l-sound-demo-wisdom
Sound demo reference for the Takazudo Modular guide article system. Use PROACTIVELY when writing a guide article that explains an audio concept where hearing the difference is essential for understand...
File Structure
l-sound-demo-wisdom/
├── SKILL.md
└── references/
└── fm-ratios.md
Sound Demo Wisdom
Status: SPEC ONLY — no working component yet.
This skill documents the agreed contract for a future
<SoundDemo>Astro component. The component itself is not yet implemented. Implementation is tracked in a follow-up issue (TBD). Do not import or use<SoundDemo>in articles until that follow-up issue is resolved and the component ships.The WaveSurfer.js + build-time peaks pattern described here is the current recommendation, not an irreversible commitment. If a lighter-weight waveform library matures before implementation begins, reconsider at that point.
When to Invoke This Skill
Use a <SoundDemo> embed when all of the following are true:
- The article explains a timbral or sonic concept (FM ratios, filter cutoff changes, envelope shaping, ring mod, waveshaping, etc.)
- The audible difference between variants is the primary pedagogical point
- A diagram or prose description alone would leave readers uncertain whether they understood correctly
- Each clip is short (under ~15 seconds) and loops naturally or benefits from looping
Do NOT add a <SoundDemo> when any of the following is true:
- The article is reference-style (spec tables, module comparison grids) — link to an external audio example or a YouTube demo instead
- The audio is long-form (a full patch demo, a live performance) — embed a YouTube video instead
- The diagram already makes the concept unambiguous (e.g., a simple VCO→VCF signal flow) — trust the diagram
- No high-quality recording is available — a bad clip is worse than no clip
Decision Tree
Work through these questions in order. Stop at the first “skip” outcome.
Q1: Is there an audible difference between the variants I am trying to explain?
- Yes → continue
- No (pure structural concept) → skip; use a diagram
Q2: Would a reader who only reads the prose (no audio) likely misunderstand or remain uncertain about what the difference actually sounds like?
- Yes (e.g., “FM ratio 2 sounds more like a brass tone” — hard to imagine without hearing) → continue
- No (e.g., “adding an attenuator reduces the signal level”) → skip; prose is sufficient
Q3: Can I produce 2–5 short clips (each ≤15 seconds) that each isolate exactly one variable?
- Yes → continue
- No (concept requires a long evolving patch demo) → skip; link to YouTube instead
Q4: Will I record both .mp3 and .ogg versions?
- Yes → continue and plan the asset pipeline
- No (only one format available) → record both before writing; do not embed single-format clips
Q5 (optional check): Does each clip have a caption that names the variable value, not just the parameter name?
- Yes (“Ratio 2 — harmonically rich, minor-seventh flavor”) → good
- No (“FM ratio example 1”) → revise the caption before writing
If you reach Q5 with “yes”, the embed earns its place. Author the <SoundDemo> calls and commit the audio assets.
<SoundDemo> Component Contract Spec
Reminder: this is a specification. The component does not exist yet.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
src | string | yes | — | Path to the primary audio file, relative to static/audio/. E.g. audio/fm-ratio-1-1.mp3. The component selects .mp3 or .ogg based on browser support when both are present. |
peaks | string | no | — | Path to the precomputed peaks JSON file (see build-time peaks below). When omitted, the component renders a plain <audio controls> fallback with no waveform. |
caption | string | yes | — | Short pedagogical caption rendered below the player. Should name the variable value, not just the parameter. E.g. "FM ratio 1:1 — sine-like, pure fundamental". |
loop | boolean | no | false | Whether the audio loops automatically when it reaches the end. Use true for texture/drone clips; leave false for envelope or one-shot demos. |
duration | number | no | — | Visual hint in seconds for the waveform timeline while the audio is loading. If omitted the timeline shows placeholder until audio metadata loads. |
Example MDX usage (speculative — component not yet implemented)
<SoundDemo
src="audio/fm-ratio-2-1.mp3"
peaks="audio/fm-ratio-2-1.peaks.json"
caption="FM ratio 2:1 — octave harmonic, brass-like body"
loop={true}
duration={8}
/>
Rendering contract
- Baseline (
peaksabsent): render a native<audio controls src="...">element with an.ogg<source>sibling for Firefox. Caption renders in a<figcaption>below. - Enhanced (
peakspresent): client-hydrate a WaveSurfer.js player over the baseline. The waveform is drawn from the precomputed peaks JSON — no client-side audio decoding. The native<audio>element remains as the accessible fallback inside the WaveSurfer container. - Caption: always rendered, regardless of peaks availability. Plain text only — no MDX inside the caption prop.
- Loop: forwarded to both the
<audio>element and the WaveSurfer instance.
Build-time peaks
WaveSurfer.js’s own FAQ recommends precomputing waveform peaks server-side rather than decoding audio on the client. The workflow is:
- Record and commit the
.mp3and.oggfiles tostatic/audio/. - Run a small CLI tool (to be specified in the follow-up implementation issue) that reads the audio file and writes a peaks JSON file alongside it.
- Commit the peaks JSON file.
- Reference
peaks="audio/{filename}.peaks.json"in the<SoundDemo>call.
The peaks JSON format follows the WaveSurfer.js standard: { "data": [0.12, -0.08, 0.24, ...] } where values are normalized floats in [-1, 1]. The resolution (samples per pixel) is specified when generating; 400–800 data points is typical for a 10-second clip.
The peaks CLI is not yet defined — it will be part of the component implementation follow-up. Until then, omit peaks and accept the plain <audio> fallback.
Asset Conventions
Directory
All audio files live under static/audio/. This directory does not exist yet; create it when adding the first clip.
static/
audio/
fm-ratio-1-1.mp3
fm-ratio-1-1.ogg
fm-ratio-1-1.peaks.json
fm-ratio-2-1.mp3
fm-ratio-2-1.ogg
fm-ratio-2-1.peaks.json
filter-sweep-lpf.mp3
filter-sweep-lpf.ogg
filter-sweep-lpf.peaks.json
Naming pattern
{topic}-{variant}.{ext}
{topic}: kebab-case concept slug. Examples:fm-ratio,filter-sweep,adsr-attack,ring-mod.{variant}: distinguishes clips within the same topic. For ratios, use the ratio with-as separator (1-1,2-1,3-2). For continuous sweeps, use a short descriptor (slow,fast,deep,shallow).{ext}:mp3andoggalways produced in pairs. Peaks JSON has the same basename with.peaks.jsonsuffix.
Example set for one FM ratio comparison:
fm-ratio-1-1.mp3 ← primary audio (Chrome, Safari, Edge)
fm-ratio-1-1.ogg ← secondary audio (Firefox fallback)
fm-ratio-1-1.peaks.json ← precomputed waveform data (colocated)
Format requirements
.mp3: 128 kbps minimum, 44.1 kHz, stereo or mono as appropriate.ogg: Vorbis, quality 3–5 (approx 96–160 kbps)- Both formats are required for every clip — do not commit
.mp3without the matching.ogg - Peaks JSON: committed alongside the audio files, not gitignored
Recording guidelines
- Keep clips short: 5–15 seconds is ideal. Fade in/out at the boundaries.
- Silence is informative — if the concept requires a gap between notes, keep it.
- Normalize peak level to around −3 dBFS to avoid clipping in browser players.
- Mono is fine for most synthesis demos; stereo only when stereo image is part of the demo.
References
See references/fm-ratios.md for a worked recipe showing how to plan, name, and caption a full set of FM ratio comparison demos.