Add release parameter, avoid clicks, some cleanup
This commit is contained in:
parent
e5fe998327
commit
4f15d681b0
2 changed files with 87 additions and 53 deletions
|
|
@ -141,8 +141,8 @@ export const { note } = registerControl(['note', 'n']);
|
||||||
*/
|
*/
|
||||||
export const { accelerate } = registerControl('accelerate');
|
export const { accelerate } = registerControl('accelerate');
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Sets the velocity from 0 to 1. Is multiplied together with gain.
|
* Sets the velocity from 0 to 1. Is multiplied together with gain.
|
||||||
|
*
|
||||||
* @name velocity
|
* @name velocity
|
||||||
* @example
|
* @example
|
||||||
* s("hh*8")
|
* s("hh*8")
|
||||||
|
|
@ -254,7 +254,7 @@ export const { fmenv } = registerControl('fmenv');
|
||||||
export const { fmattack } = registerControl('fmattack');
|
export const { fmattack } = registerControl('fmattack');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* waveform of the fm modulator
|
* Waveform of the fm modulator
|
||||||
*
|
*
|
||||||
* @name fmwave
|
* @name fmwave
|
||||||
* @param {number | Pattern} wave waveform
|
* @param {number | Pattern} wave waveform
|
||||||
|
|
@ -377,7 +377,7 @@ export const { bandf, bpf, bp } = registerControl(['bandf', 'bandq', 'bpenv'], '
|
||||||
// ['bpq'],
|
// ['bpq'],
|
||||||
export const { bandq, bpq } = registerControl('bandq', 'bpq');
|
export const { bandq, bpq } = registerControl('bandq', 'bpq');
|
||||||
/**
|
/**
|
||||||
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
|
* A pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
|
||||||
*
|
*
|
||||||
* @memberof Pattern
|
* @memberof Pattern
|
||||||
* @name begin
|
* @name begin
|
||||||
|
|
@ -438,7 +438,7 @@ export const { loopBegin, loopb } = registerControl('loopBegin', 'loopb');
|
||||||
*/
|
*/
|
||||||
export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
||||||
/**
|
/**
|
||||||
* bit crusher effect.
|
* Bit crusher effect.
|
||||||
*
|
*
|
||||||
* @name crush
|
* @name crush
|
||||||
* @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
|
* @param {number | Pattern} depth between 1 (for drastic reduction in bit-depth) to 16 (for barely no reduction).
|
||||||
|
|
@ -449,7 +449,7 @@ export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
|
||||||
// ['clhatdecay'],
|
// ['clhatdecay'],
|
||||||
export const { crush } = registerControl('crush');
|
export const { crush } = registerControl('crush');
|
||||||
/**
|
/**
|
||||||
* fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
|
* Fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
|
||||||
*
|
*
|
||||||
* @name coarse
|
* @name coarse
|
||||||
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
|
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
|
||||||
|
|
@ -460,7 +460,7 @@ export const { crush } = registerControl('crush');
|
||||||
export const { coarse } = registerControl('coarse');
|
export const { coarse } = registerControl('coarse');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* modulate the amplitude of a sound with a continuous waveform
|
* Modulate the amplitude of a sound with a continuous waveform
|
||||||
*
|
*
|
||||||
* @name tremolo
|
* @name tremolo
|
||||||
* @synonyms trem
|
* @synonyms trem
|
||||||
|
|
@ -472,7 +472,7 @@ export const { coarse } = registerControl('coarse');
|
||||||
export const { tremolo } = registerControl(['tremolo', 'tremolodepth', 'tremoloskew', 'tremolophase'], 'trem');
|
export const { tremolo } = registerControl(['tremolo', 'tremolodepth', 'tremoloskew', 'tremolophase'], 'trem');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* modulate the amplitude of a sound with a continuous waveform
|
* Modulate the amplitude of a sound with a continuous waveform
|
||||||
*
|
*
|
||||||
* @name tremolosync
|
* @name tremolosync
|
||||||
* @synonyms tremsync
|
* @synonyms tremsync
|
||||||
|
|
@ -487,7 +487,7 @@ export const { tremolosync } = registerControl(
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* depth of amplitude modulation
|
* Depth of amplitude modulation
|
||||||
*
|
*
|
||||||
* @name tremolodepth
|
* @name tremolodepth
|
||||||
* @synonyms tremdepth
|
* @synonyms tremdepth
|
||||||
|
|
@ -498,7 +498,7 @@ export const { tremolosync } = registerControl(
|
||||||
*/
|
*/
|
||||||
export const { tremolodepth } = registerControl('tremolodepth', 'tremdepth');
|
export const { tremolodepth } = registerControl('tremolodepth', 'tremdepth');
|
||||||
/**
|
/**
|
||||||
* alter the shape of the modulation waveform
|
* Alter the shape of the modulation waveform
|
||||||
*
|
*
|
||||||
* @name tremoloskew
|
* @name tremoloskew
|
||||||
* @synonyms tremskew
|
* @synonyms tremskew
|
||||||
|
|
@ -510,7 +510,7 @@ export const { tremolodepth } = registerControl('tremolodepth', 'tremdepth');
|
||||||
export const { tremoloskew } = registerControl('tremoloskew', 'tremskew');
|
export const { tremoloskew } = registerControl('tremoloskew', 'tremskew');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* alter the phase of the modulation waveform
|
* Alter the phase of the modulation waveform
|
||||||
*
|
*
|
||||||
* @name tremolophase
|
* @name tremolophase
|
||||||
* @synonyms tremphase
|
* @synonyms tremphase
|
||||||
|
|
@ -522,7 +522,7 @@ export const { tremoloskew } = registerControl('tremoloskew', 'tremskew');
|
||||||
export const { tremolophase } = registerControl('tremolophase', 'tremphase');
|
export const { tremolophase } = registerControl('tremolophase', 'tremphase');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shape of amplitude modulation
|
* Shape of amplitude modulation
|
||||||
*
|
*
|
||||||
* @name tremoloshape
|
* @name tremoloshape
|
||||||
* @param {number | Pattern} shape tri | square | sine | saw | ramp
|
* @param {number | Pattern} shape tri | square | sine | saw | ramp
|
||||||
|
|
@ -532,7 +532,7 @@ export const { tremolophase } = registerControl('tremolophase', 'tremphase');
|
||||||
*/
|
*/
|
||||||
export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
|
export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
|
||||||
/**
|
/**
|
||||||
* filter overdrive for supported filter types
|
* Filter overdrive for supported filter types
|
||||||
*
|
*
|
||||||
* @name drive
|
* @name drive
|
||||||
* @param {number | Pattern} amount
|
* @param {number | Pattern} amount
|
||||||
|
|
@ -542,7 +542,7 @@ export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* modulate the amplitude of an orbit to create a "sidechain" like effect
|
* Modulate the amplitude of an orbit to create a "sidechain" like effect
|
||||||
*
|
*
|
||||||
* @name duckorbit
|
* @name duckorbit
|
||||||
* @param {number | Pattern} orbit target orbit
|
* @param {number | Pattern} orbit target orbit
|
||||||
|
|
@ -554,7 +554,7 @@ export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
|
||||||
export const { duck } = registerControl('duckorbit', 'duck');
|
export const { duck } = registerControl('duckorbit', 'duck');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the amount of ducking applied to target orbit
|
* The amount of ducking applied to target orbit
|
||||||
*
|
*
|
||||||
* @name duckdepth
|
* @name duckdepth
|
||||||
* @param {number | Pattern} depth depth of modulation from 0 to 1
|
* @param {number | Pattern} depth depth of modulation from 0 to 1
|
||||||
|
|
@ -566,16 +566,30 @@ export const { duck } = registerControl('duckorbit', 'duck');
|
||||||
export const { duckdepth } = registerControl('duckdepth');
|
export const { duckdepth } = registerControl('duckdepth');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the attack time of the duck effect
|
* The attack time of the duck effect. Can be used to prevent clicking or for creative rhythmic effects
|
||||||
*
|
*
|
||||||
* @name duckattack
|
* @name duckattack
|
||||||
* @param {number | Pattern} time
|
* @param {number | Pattern} time
|
||||||
* @example
|
* @example
|
||||||
* stack( n(run(8)).scale("c:minor").s("sawtooth").delay(.7).orbit(2), s("bd:4!4").beat("0,4,8,11,14",16).duckorbit(2).duckattack("<0.2 0 0.4>").duckdepth(1))
|
* sound: n(run(8)).scale("c:minor").s("sawtooth").lpf(200).delay(.7).orbit(2)
|
||||||
|
* duckerWithClick: s("bd*4").duckorbit(2).duckattack(0).postgain(0)
|
||||||
|
* _duckerWithoutClick: s("bd*4").duckorbit(2).duckattack(0.003).postgain(0)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { duckattack } = registerControl('duckattack', 'duckatt');
|
export const { duckattack } = registerControl('duckattack', 'duckatt');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The release time of the duck effect
|
||||||
|
*
|
||||||
|
* @name duckrelease
|
||||||
|
* @param {number | Pattern} time
|
||||||
|
* @example
|
||||||
|
* sound: n(run(8)).scale("c:minor").s("sawtooth").delay(.7).orbit(2)
|
||||||
|
* ducker: s("bd:4!4").beat("0,4,8,11,14",16).duckorbit(2).duckrelease("<0.2 0 0.4>").duckdepth(1)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { duckrelease } = registerControl('duckrelease', 'duckrelease');
|
||||||
|
|
||||||
export const { drive } = registerControl('drive');
|
export const { drive } = registerControl('drive');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -618,7 +632,7 @@ export const { byteBeatStartTime, bbst } = registerControl('byteBeatStartTime',
|
||||||
export const { channels, ch } = registerControl('channels', 'ch');
|
export const { channels, ch } = registerControl('channels', 'ch');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controls the pulsewidth of the pulse oscillator
|
* Controls the pulsewidth of the pulse oscillator
|
||||||
*
|
*
|
||||||
* @name pw
|
* @name pw
|
||||||
* @param {number | Pattern} pulsewidth
|
* @param {number | Pattern} pulsewidth
|
||||||
|
|
@ -630,7 +644,7 @@ export const { channels, ch } = registerControl('channels', 'ch');
|
||||||
export const { pw } = registerControl(['pw', 'pwrate', 'pwsweep']);
|
export const { pw } = registerControl(['pw', 'pwrate', 'pwsweep']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controls the lfo rate for the pulsewidth of the pulse oscillator
|
* Controls the lfo rate for the pulsewidth of the pulse oscillator
|
||||||
*
|
*
|
||||||
* @name pwrate
|
* @name pwrate
|
||||||
* @param {number | Pattern} rate
|
* @param {number | Pattern} rate
|
||||||
|
|
@ -642,7 +656,7 @@ export const { pw } = registerControl(['pw', 'pwrate', 'pwsweep']);
|
||||||
export const { pwrate } = registerControl('pwrate');
|
export const { pwrate } = registerControl('pwrate');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controls the lfo sweep for the pulsewidth of the pulse oscillator
|
* Controls the lfo sweep for the pulsewidth of the pulse oscillator
|
||||||
*
|
*
|
||||||
* @name pwsweep
|
* @name pwsweep
|
||||||
* @param {number | Pattern} sweep
|
* @param {number | Pattern} sweep
|
||||||
|
|
@ -683,7 +697,7 @@ export const { phaserrate, ph, phaser } = registerControl(
|
||||||
export const { phasersweep, phs } = registerControl('phasersweep', 'phs');
|
export const { phasersweep, phs } = registerControl('phasersweep', 'phs');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The center frequency of the phaser in HZ. Defaults to 1000
|
* The center frequency of the phaser in HZ. Defaults to 1000
|
||||||
*
|
*
|
||||||
* @name phasercenter
|
* @name phasercenter
|
||||||
* @synonyms phc
|
* @synonyms phc
|
||||||
|
|
@ -711,7 +725,7 @@ export const { phasercenter, phc } = registerControl('phasercenter', 'phc');
|
||||||
export const { phaserdepth, phd, phasdp } = registerControl('phaserdepth', 'phd', 'phasdp');
|
export const { phaserdepth, phd, phasdp } = registerControl('phaserdepth', 'phd', 'phasdp');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* choose the channel the pattern is sent to in superdirt
|
* Choose the channel the pattern is sent to in superdirt
|
||||||
*
|
*
|
||||||
* @name channel
|
* @name channel
|
||||||
* @param {number | Pattern} channel channel number
|
* @param {number | Pattern} channel channel number
|
||||||
|
|
|
||||||
|
|
@ -331,18 +331,19 @@ function getDelay(orbit, delaytime, delayfeedback, t, channels) {
|
||||||
//logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`);
|
//logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`);
|
||||||
}
|
}
|
||||||
delayfeedback = clamp(delayfeedback, 0, 0.98);
|
delayfeedback = clamp(delayfeedback, 0, 0.98);
|
||||||
if (!orbits[orbit].delayNode) {
|
let delayNode = orbits[orbit].delayNode;
|
||||||
|
if (delayNode === undefined) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const dly = ac.createFeedbackDelay(1, delaytime, delayfeedback);
|
const dly = ac.createFeedbackDelay(1, delaytime, delayfeedback);
|
||||||
dly.start?.(t); // for some reason, this throws when audion extension is installed..
|
dly.start?.(t); // for some reason, this throws when audion extension is installed..
|
||||||
connectToOrbit(dly, orbit);
|
connectToOrbit(dly, orbit);
|
||||||
orbits[orbit].delayNode = dly;
|
delayNode = dly;
|
||||||
}
|
}
|
||||||
orbits[orbit].delayNode.delayTime.value !== delaytime &&
|
delayNode.delayTime.value !== delaytime &&
|
||||||
orbits[orbit].delayNode.delayTime.setValueAtTime(delaytime, t);
|
delayNode.delayTime.setValueAtTime(delaytime, t);
|
||||||
orbits[orbit].delayNode.feedback.value !== delayfeedback &&
|
delayNode.feedback.value !== delayfeedback &&
|
||||||
orbits[orbit].delayNode.feedback.setValueAtTime(delayfeedback, t);
|
delayNode.feedback.setValueAtTime(delayfeedback, t);
|
||||||
return orbits[orbit].delayNode;
|
return delayNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLfo(audioContext, begin, end, properties = {}) {
|
export function getLfo(audioContext, begin, end, properties = {}) {
|
||||||
|
|
@ -398,42 +399,59 @@ function getFilterType(ftype) {
|
||||||
return typeof ftype === 'number' ? filterTypes[Math.floor(_mod(ftype, filterTypes.length))] : ftype;
|
return typeof ftype === 'number' ? filterTypes[Math.floor(_mod(ftype, filterTypes.length))] : ftype;
|
||||||
}
|
}
|
||||||
|
|
||||||
//type orbit {
|
// type orbit {
|
||||||
// gain: number,
|
// output: GainNode,
|
||||||
// reverbNode: reverbNode
|
// reverbNode: ConvolverNode
|
||||||
// delayNode: delayNode
|
// delayNode: FeedbackDelayNode
|
||||||
//}
|
// }
|
||||||
let orbits = {};
|
let orbits = {};
|
||||||
function connectToOrbit(node, orbit) {
|
function connectToOrbit(node, orbit) {
|
||||||
if (orbits[orbit] == null) {
|
if (orbits[orbit] == null) {
|
||||||
errorLogger(new Error('target orbit does not exist'), 'superdough');
|
errorLogger(new Error('target orbit does not exist'), 'superdough');
|
||||||
}
|
}
|
||||||
node.connect(orbits[orbit].gain);
|
node.connect(orbits[orbit].output);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOrbit(audioContext, orbit, channels) {
|
function setOrbit(audioContext, orbit, channels) {
|
||||||
if (orbits[orbit] == null) {
|
if (orbits[orbit] == null) {
|
||||||
orbits[orbit] = {
|
orbits[orbit] = {
|
||||||
gain: new GainNode(audioContext, { gain: 1 }),
|
// Setup output node through which all audio filters prior to hitting
|
||||||
|
// the destination (and thus allows for global volume automation)
|
||||||
|
output: new GainNode(audioContext, { gain: 1 }),
|
||||||
};
|
};
|
||||||
connectToDestination(orbits[orbit].gain, channels);
|
connectToDestination(orbits[orbit].output, channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function duckOrbit(audioContext, targetOrbit, t, attacktime = 0.1, duckdepth = 1) {
|
|
||||||
const targetArr = [targetOrbit].flat();
|
|
||||||
|
|
||||||
targetArr.forEach((target) => {
|
function duckOrbit(audioContext, targetOrbit, t, attacktime = 0.003, releasetime = 0.1, duckdepth = 1) {
|
||||||
|
const targetArr = [targetOrbit].flat();
|
||||||
|
const attackArr = [attacktime].flat();
|
||||||
|
const releaseArr = [releasetime].flat();
|
||||||
|
const depthArr = [duckdepth].flat();
|
||||||
|
|
||||||
|
targetArr.forEach((target, idx) => {
|
||||||
if (orbits[target] == null) {
|
if (orbits[target] == null) {
|
||||||
errorLogger(new Error(`duck target orbit ${target} does not exist`), 'superdough');
|
errorLogger(new Error(`duck target orbit ${target} does not exist`), 'superdough');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const attack = attackArr[idx] ?? attackArr[0];
|
||||||
|
const release = Math.max(releaseArr[idx] ?? releaseArr[0], 0.002);
|
||||||
|
const depth = depthArr[idx] ?? depthArr[0];
|
||||||
|
const gainParam = orbits[target].output.gain;
|
||||||
webAudioTimeout(
|
webAudioTimeout(
|
||||||
audioContext,
|
audioContext,
|
||||||
() => {
|
() => {
|
||||||
orbits[target].gain.gain.cancelScheduledValues(t);
|
gainParam.cancelScheduledValues(t);
|
||||||
const currVal = orbits[target].gain.gain.value;
|
const currVal = gainParam.value;
|
||||||
orbits[target].gain.gain.linearRampToValueAtTime(clamp(1 - Math.pow(duckdepth, 0.5), 0.01, currVal), t);
|
const duckedVal = clamp(1 - Math.sqrt(depth), 0.01, currVal);
|
||||||
orbits[target].gain.gain.exponentialRampToValueAtTime(1, t + Math.max(0.002, attacktime));
|
|
||||||
|
// Guarantees the value is set to currVal at time t. This in conjunction with
|
||||||
|
// cancelScheduledValues above emulates cancelAndHoldAtTime on browsers which lack
|
||||||
|
// that method
|
||||||
|
gainParam.setValueAtTime(currVal, t);
|
||||||
|
|
||||||
|
gainParam.exponentialRampToValueAtTime(duckedVal, t + attack);
|
||||||
|
gainParam.exponentialRampToValueAtTime(1, t + attack + release);
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
t - 0.01,
|
t - 0.01,
|
||||||
|
|
@ -444,27 +462,28 @@ function duckOrbit(audioContext, targetOrbit, t, attacktime = 0.1, duckdepth = 1
|
||||||
let hasChanged = (now, before) => now !== undefined && now !== before;
|
let hasChanged = (now, before) => now !== undefined && now !== before;
|
||||||
function getReverb(orbit, duration, fade, lp, dim, ir) {
|
function getReverb(orbit, duration, fade, lp, dim, ir) {
|
||||||
// If no reverb has been created for a given orbit, create one
|
// If no reverb has been created for a given orbit, create one
|
||||||
if (!orbits[orbit].reverbNode) {
|
let reverbNode = orbits[orbit].reverbNode;
|
||||||
|
if (reverbNode === undefined) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const reverb = ac.createReverb(duration, fade, lp, dim, ir);
|
const reverb = ac.createReverb(duration, fade, lp, dim, ir);
|
||||||
connectToOrbit(reverb, orbit);
|
connectToOrbit(reverb, orbit);
|
||||||
orbits[orbit].reverbNode = reverb;
|
reverbNode = reverb;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
hasChanged(duration, orbits[orbit].reverbNode.duration) ||
|
hasChanged(duration, reverbNode.duration) ||
|
||||||
hasChanged(fade, orbits[orbit].reverbNode.fade) ||
|
hasChanged(fade, reverbNode.fade) ||
|
||||||
hasChanged(lp, orbits[orbit].reverbNode.lp) ||
|
hasChanged(lp, reverbNode.lp) ||
|
||||||
hasChanged(dim, orbits[orbit].reverbNode.dim) ||
|
hasChanged(dim, reverbNode.dim) ||
|
||||||
orbits[orbit].reverbNode.ir !== ir
|
reverbNode.ir !== ir
|
||||||
) {
|
) {
|
||||||
// only regenerate when something has changed
|
// only regenerate when something has changed
|
||||||
// avoids endless regeneration on things like
|
// avoids endless regeneration on things like
|
||||||
// stack(s("a"), s("b").rsize(8)).room(.5)
|
// stack(s("a"), s("b").rsize(8)).room(.5)
|
||||||
// this only works when args may stay undefined until here
|
// this only works when args may stay undefined until here
|
||||||
// setting default values breaks this
|
// setting default values breaks this
|
||||||
orbits[orbit].reverbNode.generate(duration, fade, lp, dim, ir);
|
reverbNode.generate(duration, fade, lp, dim, ir);
|
||||||
}
|
}
|
||||||
return orbits[orbit].reverbNode;
|
return reverbNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export let analysers = {},
|
export let analysers = {},
|
||||||
|
|
@ -562,6 +581,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
density = getDefaultValue('density'),
|
density = getDefaultValue('density'),
|
||||||
duckorbit,
|
duckorbit,
|
||||||
duckattack,
|
duckattack,
|
||||||
|
duckrelease,
|
||||||
duckdepth,
|
duckdepth,
|
||||||
// filters
|
// filters
|
||||||
fanchor = getDefaultValue('fanchor'),
|
fanchor = getDefaultValue('fanchor'),
|
||||||
|
|
@ -640,7 +660,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
setOrbit(ac, orbit, channels, t, cycle, cps);
|
setOrbit(ac, orbit, channels, t, cycle, cps);
|
||||||
|
|
||||||
if (duckorbit != null) {
|
if (duckorbit != null) {
|
||||||
duckOrbit(ac, duckorbit, t, duckattack, duckdepth);
|
duckOrbit(ac, duckorbit, t, duckattack, duckrelease, duckdepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
gain = applyGainCurve(nanFallback(gain, 1));
|
gain = applyGainCurve(nanFallback(gain, 1));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue