summaryrefslogtreecommitdiff
path: root/tools/mq_editor/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mq_editor/README.md')
-rw-r--r--tools/mq_editor/README.md44
1 files changed, 42 insertions, 2 deletions
diff --git a/tools/mq_editor/README.md b/tools/mq_editor/README.md
index 0ef2e72..78986bf 100644
--- a/tools/mq_editor/README.md
+++ b/tools/mq_editor/README.md
@@ -17,7 +17,7 @@ open tools/mq_editor/index.html
- **Top bar:** title + loaded filename
- **Toolbar:** file, extraction, playback controls and parameters
- **Main view:** log-scale time-frequency spectrogram with partial trajectories
-- **Right panel:** synthesis checkboxes (integrate phase, disable jitter, disable spread)
+- **Right panel:** per-partial mode toggle (Sinusoid / Resonator), synth params, global checkboxes
- **Mini-spectrum** (bottom-right overlay): FFT slice at mouse/playhead time
- Blue/orange gradient: original spectrum; green/yellow: synthesized
- Green bars: detected spectral peaks
@@ -49,7 +49,7 @@ open tools/mq_editor/index.html
- `editor.js` — Property panel and amplitude bezier editor for selected partials
- `fft.js` — Cooley-Tukey radix-2 FFT + STFT cache
- `mq_extract.js` — MQ algorithm: peak detection, forward tracking, backward expansion, bezier fitting
-- `mq_synth.js` — Oscillator bank synthesis from extracted partials
+- `mq_synth.js` — Oscillator bank + two-pole resonator synthesis from extracted partials
- `viewer.js` — Visualization: coordinate API, spectrogram, partials, mini-spectrum, mouse/zoom
### viewer.js coordinate API
@@ -65,6 +65,45 @@ open tools/mq_editor/index.html
| `normalizeDB(db, maxDB)` | dB → intensity [0..1] over 80 dB range |
| `partialColor(p)` | partial index → display color |
+## Resonator Synthesis Mode
+
+Each partial has a **per-partial synthesis mode** selectable in the **Synth** tab:
+
+### Sinusoid (default)
+Replica oscillator bank — direct additive sinusoids with optional spread/jitter/decay shaping.
+
+### Resonator
+Two-pole IIR bandpass resonator driven by band-limited noise:
+
+```
+y[n] = 2r·cos(ω₀)·y[n-1] − r²·y[n-2] + A(t)·√(1−r²)·noise[n]
+```
+
+- **ω₀** = `2π·f₀(t)/SR` — recomputed each sample from the freq Bezier curve (handles glides/vibrato)
+- **A(t)** — amp Bezier curve scales excitation continuously
+- **√(1−r²)** — power normalization, keeps output level ≈ sinusoidal mode at `gainComp = 1`
+- **noise[n]** — deterministic per-partial LCG (reproducible renders)
+
+**Parameters:**
+
+| Param | Default | Range | Meaning |
+|-------|---------|-------|---------|
+| `r (pole)` | 0.995 | [0, 0.9999] | Pole radius. r→1 = narrow BW / long ring. r→0 = wide / fast decay. |
+| `gain` | 1.0 | [0, ∞) | Output multiplier on top of power normalization. |
+
+**Coefficient translation from spread:**
+`r = exp(−π · BW / SR)` where `BW = f₀ · (spread_above + spread_below) / 2`.
+For a partial at 440 Hz with `spread = 0.02`: `BW ≈ 8.8 Hz`, `r ≈ exp(−π·8.8/32000) ≈ 0.9991`.
+
+**When to use:**
+- Metallic / percussive partials with natural exponential decay
+- Wide spectral peaks (large spread) where a bandpass filter is more physically accurate
+- Comparing resonator vs. sinusoidal timbre on the same partial
+
+**Note:** `RES` badge appears in the panel header when a partial is in resonator mode.
+
+---
+
## Algorithm
1. **STFT:** Overlapping Hann windows, radix-2 FFT
@@ -93,6 +132,7 @@ open tools/mq_editor/index.html
- [x] Synth params with jog sliders (decay, jitter, spread)
- [x] Auto-spread detection per partial and global
- [x] Mute / delete partials
+ - [x] Per-partial resonator synthesis mode (Synth tab toggle)
- [ ] Phase 4: Export (.spec + C++ code generation)
## See Also