Simplify declarations via globalThis; fix cleanup/stop
This commit is contained in:
parent
ac3f477f30
commit
654c1a86f0
2 changed files with 44 additions and 108 deletions
|
|
@ -468,7 +468,8 @@ export const { attack, att } = registerControl('attack', 'att');
|
||||||
* ._scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerMultiControl(['fmh', 'fmi'], 8, 'fmh');
|
Object.assign(globalThis, registerMultiControl(['fmh', 'fmi'], 8, 'fmh'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the Frequency Modulation of the synth.
|
* Sets the Frequency Modulation of the synth.
|
||||||
* Controls the modulation index, which defines the brightness of the sound.
|
* Controls the modulation index, which defines the brightness of the sound.
|
||||||
|
|
@ -491,8 +492,8 @@ export const { fmh, fmh1, fmh2, fmh3, fmh4, fmh5, fmh6, fmh7, fmh8 } = registerM
|
||||||
* .fmh(1.06).fmh2(10).fmh3(0.1)
|
* .fmh(1.06).fmh2(10).fmh3(0.1)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmi, fmi1, fmi2, fmi3, fmi4, fmi5, fmi6, fmi7, fmi8, fm, fm1, fm2, fm3, fm4, fm5, fm6, fm7, fm8 } =
|
Object.assign(globalThis, registerMultiControl(['fmi', 'fmh'], 8, 'fm'));
|
||||||
registerMultiControl(['fmi', 'fmh'], 8, 'fm');
|
|
||||||
// fm envelope
|
// fm envelope
|
||||||
/**
|
/**
|
||||||
* Ramp type of fm envelope. Exp might be a bit broken..
|
* Ramp type of fm envelope. Exp might be a bit broken..
|
||||||
|
|
@ -511,10 +512,8 @@ export const { fmi, fmi1, fmi2, fmi3, fmi4, fmi5, fmi6, fmi7, fmi8, fm, fm1, fm2
|
||||||
* ._scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmenv, fmenv1, fmenv2, fmenv3, fmenv4, fmenv5, fmenv6, fmenv7, fmenv8 } = registerMultiControl(
|
Object.assign(globalThis, registerMultiControl('fmenv', 8));
|
||||||
'fmenv',
|
|
||||||
8,
|
|
||||||
);
|
|
||||||
/**
|
/**
|
||||||
* Attack time for the FM envelope: time it takes to reach maximum modulation
|
* Attack time for the FM envelope: time it takes to reach maximum modulation
|
||||||
*
|
*
|
||||||
|
|
@ -531,26 +530,7 @@ export const { fmenv, fmenv1, fmenv2, fmenv3, fmenv4, fmenv5, fmenv6, fmenv7, fm
|
||||||
* ._scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const {
|
Object.assign(globalThis, registerMultiControl('fmattack', 8, 'fmatt'));
|
||||||
fmattack,
|
|
||||||
fmattack1,
|
|
||||||
fmattack2,
|
|
||||||
fmattack3,
|
|
||||||
fmattack4,
|
|
||||||
fmattack5,
|
|
||||||
fmattack6,
|
|
||||||
fmattack7,
|
|
||||||
fmattack8,
|
|
||||||
fmatt,
|
|
||||||
fmatt1,
|
|
||||||
fmatt2,
|
|
||||||
fmatt3,
|
|
||||||
fmatt4,
|
|
||||||
fmatt5,
|
|
||||||
fmatt6,
|
|
||||||
fmatt7,
|
|
||||||
fmatt8,
|
|
||||||
} = registerMultiControl('fmattack', 8, 'fmatt');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waveform of the fm modulator
|
* Waveform of the fm modulator
|
||||||
|
|
@ -566,10 +546,7 @@ export const {
|
||||||
* n("0 1 2 3".fast(4)).chord("<Dm Am F G>").voicing().s("sawtooth").fmwave("brown").fm(.6)
|
* n("0 1 2 3".fast(4)).chord("<Dm Am F G>").voicing().s("sawtooth").fmwave("brown").fm(.6)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { fmwave, fmwave1, fmwave2, fmwave3, fmwave4, fmwave5, fmwave6, fmwave7, fmwave8 } = registerMultiControl(
|
Object.assign(globalThis, registerMultiControl('fmwave', 8));
|
||||||
'fmwave',
|
|
||||||
8,
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decay time for the FM envelope: seconds until the sustain level is reached after the attack phase.
|
* Decay time for the FM envelope: seconds until the sustain level is reached after the attack phase.
|
||||||
|
|
@ -588,26 +565,8 @@ export const { fmwave, fmwave1, fmwave2, fmwave3, fmwave4, fmwave5, fmwave6, fmw
|
||||||
* ._scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const {
|
Object.assign(globalThis, registerMultiControl('fmdecay', 8, 'fmdec'));
|
||||||
fmdecay,
|
|
||||||
fmdecay1,
|
|
||||||
fmdecay2,
|
|
||||||
fmdecay3,
|
|
||||||
fmdecay4,
|
|
||||||
fmdecay5,
|
|
||||||
fmdecay6,
|
|
||||||
fmdecay7,
|
|
||||||
fmdecay8,
|
|
||||||
fmdec,
|
|
||||||
fmdec1,
|
|
||||||
fmdec2,
|
|
||||||
fmdec3,
|
|
||||||
fmdec4,
|
|
||||||
fmdec5,
|
|
||||||
fmdec6,
|
|
||||||
fmdec7,
|
|
||||||
fmdec8,
|
|
||||||
} = registerMultiControl('fmdecay', 8, 'fmdec');
|
|
||||||
/**
|
/**
|
||||||
* Sustain level for the FM envelope: how much modulation is applied after the decay phase
|
* Sustain level for the FM envelope: how much modulation is applied after the decay phase
|
||||||
*
|
*
|
||||||
|
|
@ -625,26 +584,8 @@ export const {
|
||||||
* ._scope()
|
* ._scope()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const {
|
Object.assign(globalThis, registerMultiControl('fmsustain', 8, 'fmsus'));
|
||||||
fmsustain,
|
|
||||||
fmsustain1,
|
|
||||||
fmsustain2,
|
|
||||||
fmsustain3,
|
|
||||||
fmsustain4,
|
|
||||||
fmsustain5,
|
|
||||||
fmsustain6,
|
|
||||||
fmsustain7,
|
|
||||||
fmsustain8,
|
|
||||||
fmsus,
|
|
||||||
fmsus1,
|
|
||||||
fmsus2,
|
|
||||||
fmsus3,
|
|
||||||
fmsus4,
|
|
||||||
fmsus5,
|
|
||||||
fmsus6,
|
|
||||||
fmsus7,
|
|
||||||
fmsus8,
|
|
||||||
} = registerMultiControl('fmsustain', 8, 'fmsus');
|
|
||||||
/**
|
/**
|
||||||
* Release time for the FM envelope: how much modulation is applied after the note is released
|
* Release time for the FM envelope: how much modulation is applied after the note is released
|
||||||
*
|
*
|
||||||
|
|
@ -656,31 +597,12 @@ export const {
|
||||||
* @param {number | Pattern} time release time
|
* @param {number | Pattern} time release time
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const {
|
Object.assign(globalThis, registerMultiControl('fmrelease', 8, 'fmrel'));
|
||||||
fmrelease,
|
|
||||||
fmrelease1,
|
|
||||||
fmrelease2,
|
|
||||||
fmrelease3,
|
|
||||||
fmrelease4,
|
|
||||||
fmrelease5,
|
|
||||||
fmrelease6,
|
|
||||||
fmrelease7,
|
|
||||||
fmrelease8,
|
|
||||||
fmrel,
|
|
||||||
fmrel1,
|
|
||||||
fmrel2,
|
|
||||||
fmrel3,
|
|
||||||
fmrel4,
|
|
||||||
fmrel5,
|
|
||||||
fmrel6,
|
|
||||||
fmrel7,
|
|
||||||
fmrel8,
|
|
||||||
} = registerMultiControl('fmrelease', 8, 'fmrel');
|
|
||||||
|
|
||||||
// FM Matrix
|
// FM Matrix
|
||||||
for (let i = 0; i <= 8; i++) {
|
for (let i = 0; i <= 8; i++) {
|
||||||
for (let j = 0; j <= 8; j++) {
|
for (let j = 0; j <= 8; j++) {
|
||||||
registerControl(`fmi${i}${j}`, `fm${i}${j}`);
|
Object.assign(globalThis, registerControl(`fmi${i}${j}`, `fm${i}${j}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,7 @@ export function webAudioTimeout(audioContext, onComplete, startTime, stopTime) {
|
||||||
constantNode.stop(stopTime);
|
constantNode.stop(stopTime);
|
||||||
return constantNode;
|
return constantNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = (freq, type = 'sine') => {
|
const mod = (freq, type = 'sine') => {
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
let osc;
|
let osc;
|
||||||
|
|
@ -349,10 +350,10 @@ const mod = (freq, type = 'sine') => {
|
||||||
osc.frequency.value = freq;
|
osc.frequency.value = freq;
|
||||||
}
|
}
|
||||||
osc.start();
|
osc.start();
|
||||||
return { osc, stop: (t) => osc.stop(t), freq };
|
return { osc, freq };
|
||||||
};
|
};
|
||||||
|
|
||||||
const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') => {
|
const fm = (frequencyparam, harmonicityRatio, wave = 'sine') => {
|
||||||
const carrfreq = frequencyparam.value;
|
const carrfreq = frequencyparam.value;
|
||||||
const modfreq = carrfreq * harmonicityRatio;
|
const modfreq = carrfreq * harmonicityRatio;
|
||||||
return mod(modfreq, wave);
|
return mod(modfreq, wave);
|
||||||
|
|
@ -360,7 +361,7 @@ const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') =>
|
||||||
|
|
||||||
export function applyFM(param, value, begin) {
|
export function applyFM(param, value, begin) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
let stop = (t) => {};
|
const toStop = []; // fm oscillators we will expose `stop` for
|
||||||
const fms = {};
|
const fms = {};
|
||||||
// Matrix
|
// Matrix
|
||||||
for (let i = 1; i <= 8; i++) {
|
for (let i = 1; i <= 8; i++) {
|
||||||
|
|
@ -377,8 +378,8 @@ export function applyFM(param, value, begin) {
|
||||||
if (!amt) continue;
|
if (!amt) continue;
|
||||||
let io = [];
|
let io = [];
|
||||||
for (let [isMod, idx] of [
|
for (let [isMod, idx] of [
|
||||||
[true, i],
|
[true, i], // source
|
||||||
[false, j],
|
[false, j], // target
|
||||||
]) {
|
]) {
|
||||||
if (idx === 0) {
|
if (idx === 0) {
|
||||||
io.push(param);
|
io.push(param);
|
||||||
|
|
@ -387,15 +388,11 @@ export function applyFM(param, value, begin) {
|
||||||
if (!fms[idx]) {
|
if (!fms[idx]) {
|
||||||
const idxS = idx === 1 ? '' : idx;
|
const idxS = idx === 1 ? '' : idx;
|
||||||
const { osc, freq } = fm(param, value[`fmh${idxS}`] ?? 1, value[`fmwave${idxS}`] ?? 'sine');
|
const { osc, freq } = fm(param, value[`fmh${idxS}`] ?? 1, value[`fmwave${idxS}`] ?? 'sine');
|
||||||
const currStop = stop;
|
toStop.push(osc);
|
||||||
stop = (t) => {
|
const toCleanup = [osc]; // nodes we want to cleanup after oscillator `stop`
|
||||||
currStop(t);
|
|
||||||
osc.stop(t);
|
|
||||||
};
|
|
||||||
const adsr = ['attack', 'decay', 'sustain', 'release'].map((s) => value[`fm${s}${idxS}`]);
|
const adsr = ['attack', 'decay', 'sustain', 'release'].map((s) => value[`fm${s}${idxS}`]);
|
||||||
if (!adsr.some((v) => v !== undefined)) {
|
let output = osc;
|
||||||
fms[idx] = { input: osc.frequency, output: osc, freq };
|
if (adsr.some((v) => v !== undefined)) {
|
||||||
} else {
|
|
||||||
const envGain = ac.createGain();
|
const envGain = ac.createGain();
|
||||||
const [attack, decay, sustain, release] = getADSRValues(adsr);
|
const [attack, decay, sustain, release] = getADSRValues(adsr);
|
||||||
const holdEnd = begin + value.duration;
|
const holdEnd = begin + value.duration;
|
||||||
|
|
@ -412,12 +409,16 @@ export function applyFM(param, value, begin) {
|
||||||
holdEnd,
|
holdEnd,
|
||||||
fmEnvelopeType === 'exp' ? 'exponential' : 'linear',
|
fmEnvelopeType === 'exp' ? 'exponential' : 'linear',
|
||||||
);
|
);
|
||||||
fms[idx] = { input: osc.frequency, output: osc.connect(envGain), freq };
|
toCleanup.push(envGain);
|
||||||
|
output = osc.connect(envGain);
|
||||||
}
|
}
|
||||||
|
fms[idx] = { input: osc.frequency, output, freq, toCleanup };
|
||||||
|
osc.onended = () => cleanupNodes(fms[idx].toCleanup);
|
||||||
}
|
}
|
||||||
const { input, output, freq } = fms[idx];
|
const { input, output, freq, toCleanup } = fms[idx];
|
||||||
const g = gainNode(amt * freq);
|
const g = gainNode(amt * freq);
|
||||||
io.push(isMod ? output.connect(g) : input);
|
io.push(isMod ? output.connect(g) : input);
|
||||||
|
toCleanup.push(g);
|
||||||
}
|
}
|
||||||
if (!io[1]) {
|
if (!io[1]) {
|
||||||
logger(
|
logger(
|
||||||
|
|
@ -429,7 +430,9 @@ export function applyFM(param, value, begin) {
|
||||||
io[0].connect(io[1]);
|
io[0].connect(io[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { stop };
|
return {
|
||||||
|
stop: (t) => toStop.forEach((m) => m?.stop(t)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saturation curves
|
// Saturation curves
|
||||||
|
|
@ -549,3 +552,14 @@ export const destroyAudioWorkletNode = (node) => {
|
||||||
node.disconnect();
|
node.disconnect();
|
||||||
node.parameters.get('end')?.setValueAtTime(0, 0);
|
node.parameters.get('end')?.setValueAtTime(0, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const cleanupNode = (node, time) => {
|
||||||
|
if (node == null) return;
|
||||||
|
node.disconnect?.();
|
||||||
|
node.parameters?.get('end')?.setValueAtTime(0, 0);
|
||||||
|
node.stop?.(time);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cleanupNodes = (nodes, time) => {
|
||||||
|
nodes.forEach((n) => cleanupNode(n, time));
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue