summaryrefslogtreecommitdiff
path: root/tools/mq_editor/mq_synth.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mq_editor/mq_synth.js')
-rw-r--r--tools/mq_editor/mq_synth.js26
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) {