Big matrix refactor
This commit is contained in:
parent
c9381a11f9
commit
7cf9db4872
2 changed files with 55 additions and 71 deletions
|
|
@ -650,7 +650,7 @@ export const {
|
||||||
// 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(`fm${i}${j}`);
|
registerControl(`fmi${i}${j}`, `fm${i}${j}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ export function webAudioTimeout(audioContext, onComplete, startTime, stopTime) {
|
||||||
constantNode.stop(stopTime);
|
constantNode.stop(stopTime);
|
||||||
return constantNode;
|
return constantNode;
|
||||||
}
|
}
|
||||||
const mod = (freq, range = 1, type = 'sine') => {
|
const mod = (freq, type = 'sine') => {
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
let osc;
|
let osc;
|
||||||
if (noises.includes(type)) {
|
if (noises.includes(type)) {
|
||||||
|
|
@ -321,99 +321,83 @@ const mod = (freq, range = 1, type = 'sine') => {
|
||||||
osc.type = type;
|
osc.type = type;
|
||||||
osc.frequency.value = freq;
|
osc.frequency.value = freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
osc.start();
|
osc.start();
|
||||||
const g = new GainNode(ctx, { gain: range });
|
return { osc, stop: (t) => osc.stop(t), freq };
|
||||||
osc.connect(g); // -range, range
|
|
||||||
return { fm: osc, scaled: g, stop: (t) => osc.stop(t) };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') => {
|
const fm = (frequencyparam, harmonicityRatio, modulationIndex, wave = 'sine') => {
|
||||||
const carrfreq = frequencyparam.value;
|
const carrfreq = frequencyparam.value;
|
||||||
const modfreq = carrfreq * harmonicityRatio;
|
const modfreq = carrfreq * harmonicityRatio;
|
||||||
const modgain = modfreq * modulationIndex;
|
return mod(modfreq, wave)
|
||||||
return mod(modfreq, modgain, wave);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function applyFM(param, value, begin) {
|
export function applyFM(param, value, begin) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
let target = param;
|
|
||||||
let stop = (t) => {};
|
let stop = (t) => {};
|
||||||
const targets = [param];
|
const fms = {};
|
||||||
const modulators = [];
|
|
||||||
for (let i = 0; i < 8; i++) {
|
|
||||||
const iS = `${i === 0 ? '' : i}`;
|
|
||||||
let modulator;
|
|
||||||
const fmModulationIndex = value[`fmi${iS}`];
|
|
||||||
if (fmModulationIndex) {
|
|
||||||
const fmmod = fm(target, value[`fmh${iS}`] ?? 1, fmModulationIndex, value[`fmwave${iS}`] ?? 'sine');
|
|
||||||
modulator = fmmod.scaled;
|
|
||||||
const currStop = stop;
|
|
||||||
stop = (t) => {
|
|
||||||
currStop(t);
|
|
||||||
fmmod.stop(t);
|
|
||||||
};
|
|
||||||
const adsr = ['attack', 'decay', 'sustain', 'release'].map((s) => value[`fm${s}${iS}`]);
|
|
||||||
if (!adsr.some((v) => v !== undefined)) {
|
|
||||||
// no envelope by default
|
|
||||||
modulator.connect(target);
|
|
||||||
modulators.push(modulator);
|
|
||||||
} else {
|
|
||||||
const envGain = ac.createGain();
|
|
||||||
const [attack, decay, sustain, release] = getADSRValues(adsr);
|
|
||||||
const holdEnd = begin + value.duration;
|
|
||||||
const fmEnvelopeType = value[`fmenv${iS}`] ?? 'exp';
|
|
||||||
getParamADSR(
|
|
||||||
envGain.gain,
|
|
||||||
attack,
|
|
||||||
decay,
|
|
||||||
sustain,
|
|
||||||
release,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
begin,
|
|
||||||
holdEnd,
|
|
||||||
fmEnvelopeType === 'exp' ? 'exponential' : 'linear',
|
|
||||||
);
|
|
||||||
modulator.connect(envGain);
|
|
||||||
envGain.connect(target);
|
|
||||||
modulators.push(envGain);
|
|
||||||
}
|
|
||||||
targets.push(fmmod.fm?.frequency);
|
|
||||||
if (targets[i]) {
|
|
||||||
// Cannot connect to noises, for example
|
|
||||||
target = targets[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Matrix
|
// Matrix
|
||||||
for (let i = 1; i <= 8; i++) {
|
for (let i = 1; i <= 8; i++) {
|
||||||
for (let j = 0; j <= 8; j++) {
|
for (let j = 0; j <= 8; j++) {
|
||||||
let control;
|
let control;
|
||||||
if (i === j + 1) {
|
if (i === j + 1) {
|
||||||
// Standard fm3 -> fm2 -> fm1 -> param usage
|
// Standard fm3 -> fm2 -> fm1 -> param usage
|
||||||
control = `fm${i}`;
|
const iS = i === 1 ? '' : i;
|
||||||
|
control = `fmi${iS}`;
|
||||||
} else {
|
} else {
|
||||||
control = `fm${i}${j}`;
|
control = `fmi${i}${j}`;
|
||||||
}
|
}
|
||||||
const amt = value[control];
|
const amt = value[control];
|
||||||
if (!amt) continue;
|
if (!amt) continue;
|
||||||
const source = modulators[i - 1];
|
let io = [];
|
||||||
const target = targets[j];
|
for (let [isMod, idx] of [[true, i], [false, j]]) {
|
||||||
if (!source) {
|
debugger;
|
||||||
const iS = `${i === 1 ? '' : i}`;
|
if (idx === 0) {
|
||||||
|
io.push(param);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!fms[idx]) {
|
||||||
|
const idxS = idx === 1 ? '' : idx;
|
||||||
|
const { osc, freq } = fm(param, value[`fmh${idxS}`] ?? 1, value[`fmwave${idxS}`] ?? 'sine');
|
||||||
|
const currStop = stop;
|
||||||
|
stop = (t) => {
|
||||||
|
currStop(t);
|
||||||
|
osc.stop(t);
|
||||||
|
};
|
||||||
|
const adsr = ['attack', 'decay', 'sustain', 'release'].map((s) => value[`fm${s}${idxS}`]);
|
||||||
|
if (!adsr.some((v) => v !== undefined)) {
|
||||||
|
fms[idx] = { input: osc.frequency, output: osc, freq};
|
||||||
|
} else {
|
||||||
|
const envGain = ac.createGain();
|
||||||
|
const [attack, decay, sustain, release] = getADSRValues(adsr);
|
||||||
|
const holdEnd = begin + value.duration;
|
||||||
|
const fmEnvelopeType = value[`fmenv${idxS}`] ?? 'exp';
|
||||||
|
getParamADSR(
|
||||||
|
envGain.gain,
|
||||||
|
attack,
|
||||||
|
decay,
|
||||||
|
sustain,
|
||||||
|
release,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
begin,
|
||||||
|
holdEnd,
|
||||||
|
fmEnvelopeType === 'exp' ? 'exponential' : 'linear',
|
||||||
|
);
|
||||||
|
fms[idx] = { input: osc.frequency, output: osc.connect(envGain), freq};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { input, output, freq } = fms[idx];
|
||||||
|
const g = gainNode(amt * freq);
|
||||||
|
io.push(isMod ? output.connect(g) : input);
|
||||||
|
}
|
||||||
|
if (!io[1]) {
|
||||||
logger(
|
logger(
|
||||||
`[superdough] failed to connect FM from source ${i} (due to control ${control}): source ${i} does not exist. Please use control fm${iS} to set it up`,
|
`[superdough] control ${control} failed to connect FM ${i} to target ${j} due to missing frequency parameter (likely because fm${j} is noise)`,
|
||||||
'warning',
|
'warning',
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!target) {
|
io[0].connect(io[1]);
|
||||||
logger(
|
|
||||||
`[superdough] failed to connect FM to target ${j} (due to control ${control}): target ${j} does not exist. Please use control fm${j} to set it up`,
|
|
||||||
'warning',
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
source.connect(target);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { stop };
|
return { stop };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue