Mostly working version
This commit is contained in:
parent
0dbca05de0
commit
19b710c401
9 changed files with 56 additions and 70 deletions
|
|
@ -2320,7 +2320,6 @@ export const { curve } = registerControl('curve');
|
||||||
export const { deltaSlide } = registerControl('deltaSlide');
|
export const { deltaSlide } = registerControl('deltaSlide');
|
||||||
export const { pitchJump } = registerControl('pitchJump');
|
export const { pitchJump } = registerControl('pitchJump');
|
||||||
export const { pitchJumpTime } = registerControl('pitchJumpTime');
|
export const { pitchJumpTime } = registerControl('pitchJumpTime');
|
||||||
export const { lfo, repeatTime } = registerControl('lfo', 'repeatTime');
|
|
||||||
// noise on the frequency or as bubo calls it "frequency fog" :)
|
// noise on the frequency or as bubo calls it "frequency fog" :)
|
||||||
export const { znoise } = registerControl('znoise');
|
export const { znoise } = registerControl('znoise');
|
||||||
export const { zmod } = registerControl('zmod');
|
export const { zmod } = registerControl('zmod');
|
||||||
|
|
|
||||||
|
|
@ -3710,7 +3710,7 @@ addConfigAlias('lfo', 'target', 't');
|
||||||
addConfigAlias('lfo', 'param', 'p');
|
addConfigAlias('lfo', 'param', 'p');
|
||||||
addConfigAlias('lfo', 'rate', 'r');
|
addConfigAlias('lfo', 'rate', 'r');
|
||||||
addConfigAlias('lfo', 'depth', 'dep', 'dp', 'd');
|
addConfigAlias('lfo', 'depth', 'dep', 'dp', 'd');
|
||||||
addConfigAlias('lfo', 'dc');
|
addConfigAlias('lfo', 'dcoffset', 'dc');
|
||||||
addConfigAlias('lfo', 'shape', 'sh');
|
addConfigAlias('lfo', 'shape', 'sh');
|
||||||
addConfigAlias('lfo', 'skew', 'sk');
|
addConfigAlias('lfo', 'skew', 'sk');
|
||||||
addConfigAlias('lfo', 'curve', 'c');
|
addConfigAlias('lfo', 'curve', 'c');
|
||||||
|
|
@ -3730,7 +3730,7 @@ addConfigAlias('send', 'depth', 'dep', 'dp', 'd');
|
||||||
addConfigAlias('send', 'dc');
|
addConfigAlias('send', 'dc');
|
||||||
addConfigAlias('send', 'offset', 'off', 'o');
|
addConfigAlias('send', 'offset', 'off', 'o');
|
||||||
|
|
||||||
Pattern.prototype.mod = function (type, config, idx) {
|
Pattern.prototype.modulate = function (type, config, idx) {
|
||||||
if (config == null || typeof config !== 'object') {
|
if (config == null || typeof config !== 'object') {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
@ -3766,7 +3766,7 @@ Pattern.prototype.mod = function (type, config, idx) {
|
||||||
* @param {string | Pattern} [config.target] Node (and parameter if specified like `lpf.frequency`) to modulate. Aliases: target, t
|
* @param {string | Pattern} [config.target] Node (and parameter if specified like `lpf.frequency`) to modulate. Aliases: target, t
|
||||||
* @param {number | Pattern} [config.rate] Modulation rate. Aliases: rate, r
|
* @param {number | Pattern} [config.rate] Modulation rate. Aliases: rate, r
|
||||||
* @param {number | Pattern} [config.depth] Modulation depth. Aliases: dep, dp, d
|
* @param {number | Pattern} [config.depth] Modulation depth. Aliases: dep, dp, d
|
||||||
* @param {number | Pattern} [config.dc] DC offset / bias for the waveform
|
* @param {number | Pattern} [config.dcoffset] DC offset / bias for the waveform. Aliases: dc
|
||||||
* @param {number | Pattern} [config.shape] Waveform shape index. Aliases: sh
|
* @param {number | Pattern} [config.shape] Waveform shape index. Aliases: sh
|
||||||
* @param {number | Pattern} [config.skew] Waveform skew amount. Aliases: sk
|
* @param {number | Pattern} [config.skew] Waveform skew amount. Aliases: sk
|
||||||
* @param {number | Pattern} [config.curve] Exponential curve amount. Aliases: c
|
* @param {number | Pattern} [config.curve] Exponential curve amount. Aliases: c
|
||||||
|
|
@ -3775,7 +3775,7 @@ Pattern.prototype.mod = function (type, config, idx) {
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.lfo = function (config, idx) {
|
Pattern.prototype.lfo = function (config, idx) {
|
||||||
return this.mod('lfo', config, idx);
|
return this.modulate('lfo', config, idx);
|
||||||
};
|
};
|
||||||
export const lfo = (config) => pure({}).lfo(config);
|
export const lfo = (config) => pure({}).lfo(config);
|
||||||
|
|
||||||
|
|
@ -3799,7 +3799,7 @@ export const lfo = (config) => pure({}).lfo(config);
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.env = function (config, idx) {
|
Pattern.prototype.env = function (config, idx) {
|
||||||
return this.mod('env', config, idx);
|
return this.modulate('env', config, idx);
|
||||||
};
|
};
|
||||||
export const env = (config) => pure({}).env(config);
|
export const env = (config) => pure({}).env(config);
|
||||||
|
|
||||||
|
|
@ -3820,6 +3820,6 @@ export const env = (config) => pure({}).env(config);
|
||||||
* @returns Pattern
|
* @returns Pattern
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.send = function (config, idx) {
|
Pattern.prototype.send = function (config, idx) {
|
||||||
return this.mod('send', config, idx);
|
return this.modulate('send', config, idx);
|
||||||
};
|
};
|
||||||
export const send = (config) => pure({}).send(config);
|
export const send = (config) => pure({}).send(config);
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ export function registerSoundfonts() {
|
||||||
node.disconnect();
|
node.disconnect();
|
||||||
onended();
|
onended();
|
||||||
};
|
};
|
||||||
return { node, stop };
|
return { node, stop, source: bufferSource };
|
||||||
},
|
},
|
||||||
{ type: 'soundfont', prebake: true, fonts },
|
{ type: 'soundfont', prebake: true, fonts },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -105,22 +105,16 @@ function getModulationShapeInput(val) {
|
||||||
return { tri: 0, triangle: 0, sine: 1, ramp: 2, saw: 3, square: 4 }[val] ?? 0;
|
return { tri: 0, triangle: 0, sine: 1, ramp: 2, saw: 3, square: 4 }[val] ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLfo(audioContext, begin, end, properties = {}) {
|
export function getEnvelope(audioContext, properties = {}) {
|
||||||
const { shape = 0, ...props } = properties;
|
return getWorklet(audioContext, 'envelope-processor', properties);
|
||||||
const { dcoffset = -0.5, depth = 1 } = properties;
|
}
|
||||||
|
|
||||||
|
export function getLfo(audioContext, properties = {}) {
|
||||||
|
// Extract some params we need for deriving other params
|
||||||
|
const { begin, shape = 0, ...props } = properties;
|
||||||
const lfoprops = {
|
const lfoprops = {
|
||||||
frequency: 1,
|
|
||||||
depth,
|
|
||||||
skew: 0.5,
|
|
||||||
phaseoffset: 0,
|
|
||||||
time: begin,
|
time: begin,
|
||||||
begin,
|
|
||||||
end,
|
|
||||||
shape: getModulationShapeInput(shape),
|
shape: getModulationShapeInput(shape),
|
||||||
dcoffset,
|
|
||||||
min: dcoffset * depth,
|
|
||||||
max: dcoffset * depth + depth,
|
|
||||||
curve: 1,
|
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||||
const stop = (endTime) => {
|
const stop = (endTime) => {
|
||||||
bufferSource.stop(endTime);
|
bufferSource.stop(endTime);
|
||||||
};
|
};
|
||||||
const handle = { node: out, bufferSource, stop };
|
const handle = { node: out, source: bufferSource, stop };
|
||||||
|
|
||||||
// cut groups
|
// cut groups
|
||||||
if (cut !== undefined) {
|
if (cut !== undefined) {
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,14 @@ import {
|
||||||
getADSRValues,
|
getADSRValues,
|
||||||
getCompressor,
|
getCompressor,
|
||||||
getDistortion,
|
getDistortion,
|
||||||
|
getEnvelope,
|
||||||
getLfo,
|
getLfo,
|
||||||
getParamADSR,
|
getParamADSR,
|
||||||
getWorklet,
|
getWorklet,
|
||||||
webAudioTimeout,
|
webAudioTimeout,
|
||||||
} from './helpers.mjs';
|
} from './helpers.mjs';
|
||||||
import { map } from 'nanostores';
|
import { map } from 'nanostores';
|
||||||
import { logger } from './logger.mjs';
|
import { errorLogger, logger } from './logger.mjs';
|
||||||
import { loadBuffer } from './sampler.mjs';
|
import { loadBuffer } from './sampler.mjs';
|
||||||
import { getAudioContext } from './audioContext.mjs';
|
import { getAudioContext } from './audioContext.mjs';
|
||||||
import { SuperdoughAudioController } from './superdoughoutput.mjs';
|
import { SuperdoughAudioController } from './superdoughoutput.mjs';
|
||||||
|
|
@ -292,18 +293,6 @@ function getSuperdoughAudioController() {
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLfo(audioContext, properties = {}) {
|
|
||||||
// Extract some params we need for deriving other params
|
|
||||||
const { begin, shape = 0, ...props } = properties;
|
|
||||||
const lfoprops = {
|
|
||||||
time: begin,
|
|
||||||
shape: getModulationShapeInput(shape),
|
|
||||||
...props,
|
|
||||||
};
|
|
||||||
|
|
||||||
return getWorklet(audioContext, 'lfo-processor', lfoprops);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function connectToDestination(input, channels) {
|
export function connectToDestination(input, channels) {
|
||||||
const controller = getSuperdoughAudioController();
|
const controller = getSuperdoughAudioController();
|
||||||
controller.output.connectToDestination(input, channels);
|
controller.output.connectToDestination(input, channels);
|
||||||
|
|
@ -445,7 +434,7 @@ function _getTargetParams(nodes, target) {
|
||||||
if (!targetNodes) {
|
if (!targetNodes) {
|
||||||
const keys = Object.keys(nodes);
|
const keys = Object.keys(nodes);
|
||||||
errorLogger(
|
errorLogger(
|
||||||
new Error(`Could not connect to target '${target}' — it does not exist. Available targets: ${keys.join(', ')}`),
|
`Could not connect to target '${target}' — it does not exist. Available targets: ${keys.join(', ')}`,
|
||||||
'superdough',
|
'superdough',
|
||||||
);
|
);
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -456,9 +445,7 @@ function _getTargetParams(nodes, target) {
|
||||||
if (!targetParam) {
|
if (!targetParam) {
|
||||||
const available = _getNodeParams(targetNode);
|
const available = _getNodeParams(targetNode);
|
||||||
errorLogger(
|
errorLogger(
|
||||||
new Error(
|
`Could not connect to parameter '${param}' on '${target}'. Available parameters: ${available.join(', ')}`,
|
||||||
`Could not connect to parameter '${param}' on '${targetName}'. Available parameters: ${available.join(', ')}`,
|
|
||||||
),
|
|
||||||
'superdough',
|
'superdough',
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
@ -472,26 +459,27 @@ function connectLFO(idx, params, nodeTracker) {
|
||||||
const { rate = 1, sync, cps, target, ...filteredParams } = params;
|
const { rate = 1, sync, cps, target, ...filteredParams } = params;
|
||||||
filteredParams['frequency'] = sync !== undefined ? sync / cps : rate;
|
filteredParams['frequency'] = sync !== undefined ? sync / cps : rate;
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
lfoNode = getLfo(ac, filteredParams);
|
const lfoNode = getLfo(ac, filteredParams);
|
||||||
nodeTracker[`lfo${idx}`] = [lfoNode];
|
nodeTracker[`lfo${idx}`] = [lfoNode];
|
||||||
_getTargetParams(target).forEach(lfoNode.connect);
|
_getTargetParams(nodeTracker, target).forEach((t) => lfoNode.connect(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectEnvelope(idx, params, nodeTracker) {
|
function connectEnvelope(idx, params, nodeTracker) {
|
||||||
const { target, ...filteredParams } = params;
|
const { target, ...filteredParams } = params;
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
envNode = getEnvelope(ac, filteredParams);
|
const envNode = getEnvelope(ac, filteredParams);
|
||||||
nodeTracker[`env${idx}`] = [envNode];
|
nodeTracker[`env${idx}`] = [envNode];
|
||||||
_getTargetParams(nodeTracker, target).forEach(envNode.connect);
|
_getTargetParams(nodeTracker, target).forEach((t) => envNode.connect(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectSendModulator(params, signal, nodeTracker, pendingConnections) {
|
function connectSendModulator(params, signal, nodeTracker, chainID) {
|
||||||
|
const ac = getAudioContext();
|
||||||
const dc = new ConstantSourceNode(ac, { offset: params.dc ?? 0 });
|
const dc = new ConstantSourceNode(ac, { offset: params.dc ?? 0 });
|
||||||
dc.start(t);
|
dc.start(params.begin);
|
||||||
const offset = new ConstantSourceNode(ac, { offset: params.offset ?? 0 });
|
const offset = new ConstantSourceNode(ac, { offset: params.offset ?? 0 });
|
||||||
offset.start(t);
|
offset.start(params.begin);
|
||||||
const raw = dc.connect(gainNode(1));
|
const raw = dc.connect(gainNode(1));
|
||||||
const modulator = post
|
const modulator = signal
|
||||||
.connect(raw)
|
.connect(raw)
|
||||||
.connect(gainNode((params.depth ?? 1) / 0.3))
|
.connect(gainNode((params.depth ?? 1) / 0.3))
|
||||||
.connect(gainNode(1));
|
.connect(gainNode(1));
|
||||||
|
|
@ -499,7 +487,7 @@ function connectSendModulator(params, signal, nodeTracker, pendingConnections) {
|
||||||
webAudioTimeout(
|
webAudioTimeout(
|
||||||
ac,
|
ac,
|
||||||
() => {
|
() => {
|
||||||
_getTargetParams(nodeTracker, params.target).forEach(signal.connect);
|
_getTargetParams(nodeTracker, params.target).forEach((t) => modulator.connect(t));
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
params.begin,
|
params.begin,
|
||||||
|
|
@ -507,12 +495,13 @@ function connectSendModulator(params, signal, nodeTracker, pendingConnections) {
|
||||||
webAudioTimeout(
|
webAudioTimeout(
|
||||||
ac,
|
ac,
|
||||||
() => {
|
() => {
|
||||||
signal.disconnect();
|
modulator.disconnect();
|
||||||
delete pendingConnections[params.id][chainID];
|
delete pendingConnections[params.id][chainID];
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
params.end + 0.05,
|
params.end + 0.05,
|
||||||
);
|
);
|
||||||
|
return modulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
let activeSoundSources = new Map();
|
let activeSoundSources = new Map();
|
||||||
|
|
@ -679,7 +668,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
if (soundHandle) {
|
if (soundHandle) {
|
||||||
sourceNode = soundHandle.node;
|
sourceNode = soundHandle.node;
|
||||||
activeSoundSources.set(chainID, new WeakRef(soundHandle)); // allow GC
|
activeSoundSources.set(chainID, new WeakRef(soundHandle)); // allow GC
|
||||||
nodes['source'] = [soundHandle.oscillator];
|
nodes['source'] = [soundHandle.source];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`sound ${s} not found! Is it loaded?`);
|
throw new Error(`sound ${s} not found! Is it loaded?`);
|
||||||
|
|
@ -761,7 +750,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
hpParams.type = 'highpass';
|
hpParams.type = 'highpass';
|
||||||
const hp1 = filt(hpParams);
|
const hp1 = filt(hpParams);
|
||||||
nodes['hpf'] = [hp1];
|
nodes['hpf'] = [hp1];
|
||||||
chain.push(hp());
|
chain.push(hp1);
|
||||||
if (ftype === '24db') {
|
if (ftype === '24db') {
|
||||||
const hp2 = filt(hpParams);
|
const hp2 = filt(hpParams);
|
||||||
nodes['hpf'].push(hp1);
|
nodes['hpf'].push(hp1);
|
||||||
|
|
@ -791,7 +780,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
const bpParams = pickAndRename(value, bpMap);
|
const bpParams = pickAndRename(value, bpMap);
|
||||||
bpParams.type = 'bandpass';
|
bpParams.type = 'bandpass';
|
||||||
const bp1 = filt(bpParams);
|
const bp1 = filt(bpParams);
|
||||||
chain.push(bp());
|
chain.push(bp1);
|
||||||
if (ftype === '24db') {
|
if (ftype === '24db') {
|
||||||
const bp2 = filt(bpParams);
|
const bp2 = filt(bpParams);
|
||||||
nodes['bpf'].push(bp2);
|
nodes['bpf'].push(bp2);
|
||||||
|
|
@ -946,7 +935,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
|
|
||||||
// finally, now that `nodes` is populated, set up modulators
|
// finally, now that `nodes` is populated, set up modulators
|
||||||
if (value.lfo) {
|
if (value.lfo) {
|
||||||
for (const [params, idx] of Object.entries(value.lfo)) {
|
for (const [idx, params] of Object.entries(value.lfo)) {
|
||||||
connectLFO(
|
connectLFO(
|
||||||
idx,
|
idx,
|
||||||
{
|
{
|
||||||
|
|
@ -955,13 +944,12 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
begin: t,
|
begin: t,
|
||||||
end: endWithRelease,
|
end: endWithRelease,
|
||||||
},
|
},
|
||||||
'lfo',
|
|
||||||
nodes,
|
nodes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.env) {
|
if (value.env) {
|
||||||
for (const [params, idx] of Object.entries(value.env)) {
|
for (const [idx, params] of Object.entries(value.env)) {
|
||||||
connectEnvelope(
|
connectEnvelope(
|
||||||
idx,
|
idx,
|
||||||
{
|
{
|
||||||
|
|
@ -969,7 +957,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
begin: t,
|
begin: t,
|
||||||
end: endWithRelease,
|
end: endWithRelease,
|
||||||
},
|
},
|
||||||
'envelope',
|
|
||||||
nodes,
|
nodes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -978,22 +965,27 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
idToNodes[value.id] = new WeakRef(nodes);
|
idToNodes[value.id] = new WeakRef(nodes);
|
||||||
}
|
}
|
||||||
if (value.send) {
|
if (value.send) {
|
||||||
for (const p of value.env) {
|
for (const p of value.send) {
|
||||||
const modNodes = idToNodes[p.id];
|
const modNodes = idToNodes[p.id];
|
||||||
if (!modNodes) {
|
if (!modNodes) {
|
||||||
logger(
|
logger(
|
||||||
`[superdough] Could not connect to pattern ${p.id} -- make sure a pattern with this name exists. Available targets: ${Object.keys(idToNodes).join(', ')}`,
|
`[superdough] Could not connect to pattern ${p.id} -- make sure a pattern with this name exists. Available targets: ${Object.keys(idToNodes).join(', ')}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
connectSendModulator(params, post);
|
const modulator = connectSendModulator({ ...p, begin: t, end: endWithRelease }, post, nodes, chainID);
|
||||||
pendingConnections[p.id] ??= {};
|
pendingConnections[p.id] ??= {};
|
||||||
pendingConnections[p.id][chainID] = new WeakRef([modulator, p.target, endWithRelease]);
|
pendingConnections[p.id][chainID] = new WeakRef([modulator, p.target, endWithRelease]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.id in pendingConnections) {
|
if (value.id in pendingConnections) {
|
||||||
for (const data of Object.values(pendingConnections[id])) {
|
for (const data of Object.values(pendingConnections[value.id])) {
|
||||||
const [modulator, target, end] = data.deref();
|
const derefData = data.deref();
|
||||||
|
if (!derefData) {
|
||||||
|
delete pendingConnections[value.id];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const [modulator, target, end] = derefData;
|
||||||
const targets = _getTargetParams(nodes, target);
|
const targets = _getTargetParams(nodes, target);
|
||||||
webAudioTimeout(
|
webAudioTimeout(
|
||||||
ac,
|
ac,
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ export function registerSynthSounds() {
|
||||||
stop(envEnd);
|
stop(envEnd);
|
||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (endTime) => {
|
stop: (endTime) => {
|
||||||
stop(endTime);
|
stop(endTime);
|
||||||
},
|
},
|
||||||
|
|
@ -141,7 +141,7 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (endTime) => {
|
stop: (endTime) => {
|
||||||
o.stop(endTime);
|
o.stop(endTime);
|
||||||
},
|
},
|
||||||
|
|
@ -208,7 +208,7 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node: envGain,
|
node: envGain,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (time) => {
|
stop: (time) => {
|
||||||
timeoutNode.stop(time);
|
timeoutNode.stop(time);
|
||||||
},
|
},
|
||||||
|
|
@ -285,7 +285,7 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node: envGain,
|
node: envGain,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (time) => {
|
stop: (time) => {
|
||||||
timeoutNode.stop(time);
|
timeoutNode.stop(time);
|
||||||
},
|
},
|
||||||
|
|
@ -363,7 +363,7 @@ export function registerSynthSounds() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node: envGain,
|
node: envGain,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (time) => {
|
stop: (time) => {
|
||||||
timeoutNode.stop(time);
|
timeoutNode.stop(time);
|
||||||
},
|
},
|
||||||
|
|
@ -409,7 +409,7 @@ export function registerSynthSounds() {
|
||||||
stop(envEnd);
|
stop(envEnd);
|
||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (endTime) => {
|
stop: (endTime) => {
|
||||||
stop(endTime);
|
stop(endTime);
|
||||||
},
|
},
|
||||||
|
|
@ -503,7 +503,7 @@ export function getOscillator(s, t, value) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node: noiseMix?.node || o,
|
node: noiseMix?.node || o,
|
||||||
oscillator: o,
|
source: o,
|
||||||
stop: (time) => {
|
stop: (time) => {
|
||||||
fmModulator.stop(time);
|
fmModulator.stop(time);
|
||||||
vibratoOscillator?.stop(time);
|
vibratoOscillator?.stop(time);
|
||||||
|
|
|
||||||
|
|
@ -964,7 +964,7 @@ class EnvelopeProcessor extends AudioWorkletProcessor {
|
||||||
{ name: 'attackCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
{ name: 'attackCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
||||||
{ name: 'decayCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
{ name: 'decayCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
||||||
{ name: 'releaseCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
{ name: 'releaseCurve', defaultValue: 0, minValue: -1, maxValue: 1 },
|
||||||
{ name: 'peak', defaultValue: 1 },
|
{ name: 'depth', defaultValue: 1 },
|
||||||
{ name: 'retrigger', defaultValue: 1, minValue: 0, maxValue: 1 },
|
{ name: 'retrigger', defaultValue: 1, minValue: 0, maxValue: 1 },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -1026,7 +1026,7 @@ class EnvelopeProcessor extends AudioWorkletProcessor {
|
||||||
const aCurve = pv(params.attackCurve, i);
|
const aCurve = pv(params.attackCurve, i);
|
||||||
const dCurve = pv(params.decayCurve, i);
|
const dCurve = pv(params.decayCurve, i);
|
||||||
const rCurve = pv(params.releaseCurve, i);
|
const rCurve = pv(params.releaseCurve, i);
|
||||||
const peak = pv(params.peak, i);
|
const depth = pv(params.depth, i);
|
||||||
const states = [
|
const states = [
|
||||||
{ time: Number.POSITIVE_INFINITY, start: 0, target: 0 }, // idle
|
{ time: Number.POSITIVE_INFINITY, start: 0, target: 0 }, // idle
|
||||||
{ time: attack, start: this.attackStart, target: 1, curve: aCurve },
|
{ time: attack, start: this.attackStart, target: 1, curve: aCurve },
|
||||||
|
|
@ -1040,7 +1040,7 @@ class EnvelopeProcessor extends AudioWorkletProcessor {
|
||||||
this.state = (this.state + 1) % states.length;
|
this.state = (this.state + 1) % states.length;
|
||||||
time = states[this.state].time;
|
time = states[this.state].time;
|
||||||
}
|
}
|
||||||
out[i] = this.val * peak;
|
out[i] = this.val * depth;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ export const getZZFX = (value, t) => {
|
||||||
source.start(t);
|
source.start(t);
|
||||||
return {
|
return {
|
||||||
node: source,
|
node: source,
|
||||||
|
source,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue