diff options
Diffstat (limited to 'tools/mq_editor/mq_synth.js')
| -rw-r--r-- | tools/mq_editor/mq_synth.js | 26 |
1 files changed, 6 insertions, 20 deletions
diff --git a/tools/mq_editor/mq_synth.js b/tools/mq_editor/mq_synth.js index 2d4cf1b..00867a9 100644 --- a/tools/mq_editor/mq_synth.js +++ b/tools/mq_editor/mq_synth.js @@ -1,19 +1,6 @@ // MQ Synthesizer // Replica oscillator bank for sinusoidal synthesis, plus two-pole resonator mode -// Evaluate cubic bezier curve at time t -function evalBezier(curve, t) { - const dt = curve.t3 - curve.t0; - if (dt <= 0) return curve.v0; - let u = (t - curve.t0) / dt; - u = Math.max(0, Math.min(1, u)); - const u1 = 1.0 - u; - return u1*u1*u1 * curve.v0 + - 3*u1*u1*u * curve.v1 + - 3*u1*u*u * curve.v2 + - u*u*u * curve.v3; -} - // Deterministic LCG PRNG function randFloat(seed, min, max) { seed = (1664525 * seed + 1013904223) % 0x100000000; @@ -21,7 +8,7 @@ function randFloat(seed, min, max) { } // Synthesize audio from MQ partials -// partials: array of {freqCurve, ampCurve, replicas?, resonator?} +// partials: array of {freqCurve (with a0-a3 for amp), replicas?, resonator?} // replicas: {offsets, decay_alpha, jitter, spread_above, spread_below} // resonator: {enabled, r, gainComp} — two-pole resonator mode per partial // integratePhase: true = accumulate 2π*f/SR per sample (correct for varying freq) @@ -48,7 +35,6 @@ function synthesizeMQ(partials, sampleRate, duration, integratePhase = true, opt for (let p = 0; p < partials.length; ++p) { const partial = partials[p]; const fc = partial.freqCurve; - const ac = partial.ampCurve; if ((partial.resonator && partial.resonator.enabled) || options.forceResonator) { // --- Two-pole resonator mode --- @@ -63,7 +49,7 @@ function synthesizeMQ(partials, sampleRate, duration, integratePhase = true, opt const gainNorm = Math.sqrt(Math.max(0, 1.0 - r * r)); configs.push({ mode: 'resonator', - fc, ac, + fc, r, gainComp, gainNorm, y1: 0.0, y2: 0.0, noiseSeed: ((p * 1664525 + 1013904223) & 0xFFFFFFFF) >>> 0 @@ -83,7 +69,7 @@ function synthesizeMQ(partials, sampleRate, duration, integratePhase = true, opt const initPhase = randFloat(p * 67890 + r, 0.0, 1.0) * (jitter * jitterMult) * 2.0 * Math.PI; replicaData.push({ratio: offsets[r], spread, phase: initPhase}); } - configs.push({ mode: 'sinusoid', fc, ac, decay_alpha, replicaData }); + configs.push({ mode: 'sinusoid', fc, decay_alpha, replicaData }); } } @@ -93,13 +79,13 @@ function synthesizeMQ(partials, sampleRate, duration, integratePhase = true, opt for (let p = 0; p < configs.length; ++p) { const cfg = configs[p]; - const {fc, ac} = cfg; + const {fc} = cfg; if (cfg.mode === 'resonator') { if (t < fc.t0 || t > fc.t3) { cfg.y1 = 0.0; cfg.y2 = 0.0; continue; } const f0 = evalBezier(fc, t); - const A = evalBezier(ac, t); + const A = evalBezierAmp(fc, t); const omega = 2.0 * Math.PI * f0 / sampleRate; const b1 = 2.0 * cfg.r * Math.cos(omega); @@ -117,7 +103,7 @@ function synthesizeMQ(partials, sampleRate, duration, integratePhase = true, opt if (t < fc.t0 || t > fc.t3) continue; const f0 = evalBezier(fc, t); - const A0 = evalBezier(ac, t); + const A0 = evalBezierAmp(fc, t); const {decay_alpha, replicaData} = cfg; for (let r = 0; r < replicaData.length; ++r) { |
