Add control over phase randomization and fix a bug with supersaw
This commit is contained in:
parent
ef87f65bef
commit
e3741ae8fa
4 changed files with 22 additions and 10 deletions
|
|
@ -120,6 +120,16 @@ export const { wtWarp, wavetableWarp } = registerControl('wtWarp', 'wavetableWar
|
||||||
*/
|
*/
|
||||||
export const { wtWarpMode, wavetableWarpMode } = registerControl('wtWarpMode', 'wavetableWarpMode');
|
export const { wtWarpMode, wavetableWarpMode } = registerControl('wtWarpMode', 'wavetableWarpMode');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Amount of randomness of the initial phase of the wavetable oscillator.
|
||||||
|
*
|
||||||
|
* @name wtPhaseRand
|
||||||
|
* @param {number | Pattern} mode Warp mode: an integer
|
||||||
|
* @synonyms wavetableWarpMode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { wtPhaseRand, wavetablePhaseRand } = registerControl('wtPhaseRand', 'wavetablePhaseRand');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a custom webaudio node to use as a sound source.
|
* Define a custom webaudio node to use as a sound source.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -594,7 +594,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
|
||||||
tremolophase = 0,
|
tremolophase = 0,
|
||||||
tremoloshape,
|
tremoloshape,
|
||||||
s = getDefaultValue('s'),
|
s = getDefaultValue('s'),
|
||||||
wt,
|
|
||||||
bank,
|
bank,
|
||||||
source,
|
source,
|
||||||
gain = getDefaultValue('gain'),
|
gain = getDefaultValue('gain'),
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ async function onTriggerSynth(t, value, onended, bank, frameLen) {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
let [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
let [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
||||||
let sourceDesc, holdEnd, envEnd;
|
let sourceDesc, holdEnd, envEnd;
|
||||||
let { unison, spread, detune, wtPos, wtWarp, wtWarpMode } = value;
|
let { wtWarpMode } = value;
|
||||||
if (typeof wtWarpMode === 'string') {
|
if (typeof wtWarpMode === 'string') {
|
||||||
wtWarpMode = WarpMode[wtWarpMode.toUpperCase()] ?? WarpMode.NONE;
|
wtWarpMode = WarpMode[wtWarpMode.toUpperCase()] ?? WarpMode.NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -202,12 +202,13 @@ async function onTriggerSynth(t, value, onended, bank, frameLen) {
|
||||||
begin: t,
|
begin: t,
|
||||||
end: envEnd,
|
end: envEnd,
|
||||||
frequency,
|
frequency,
|
||||||
detune,
|
detune: value.detune,
|
||||||
position: wtPos,
|
position: value.wtPos,
|
||||||
warp: wtWarp,
|
warp: value.wtWarp,
|
||||||
warpMode: wtWarpMode,
|
warpMode: wtWarpMode,
|
||||||
voices: unison,
|
voices: value.unison,
|
||||||
spread,
|
spread: value.spread,
|
||||||
|
phaserand: value.wtPhaseRand,
|
||||||
},
|
},
|
||||||
{ outputChannelCount: [2] },
|
{ outputChannelCount: [2] },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -474,10 +474,10 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
gainR = gain1;
|
gainR = gain1;
|
||||||
}
|
}
|
||||||
// Individual voice detuning
|
// Individual voice detuning
|
||||||
freq = applySemitoneDetuneToFrequency(freq, getUnisonDetune(voices, freqspread, n));
|
const voiceFreq = applySemitoneDetuneToFrequency(freq, getUnisonDetune(voices, freqspread, n));
|
||||||
// We must wrap this here because it is passed into sawblep below which
|
// We must wrap this here because it is passed into sawblep below which
|
||||||
// has domain [0, 1]
|
// has domain [0, 1]
|
||||||
const dt = mod(freq / sampleRate, 1);
|
const dt = mod(voiceFreq / sampleRate, 1);
|
||||||
this.phase[n] = this.phase[n] ?? Math.random();
|
this.phase[n] = this.phase[n] ?? Math.random();
|
||||||
const v = waveshapes.sawblep(this.phase[n], dt);
|
const v = waveshapes.sawblep(this.phase[n], dt);
|
||||||
|
|
||||||
|
|
@ -988,6 +988,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
{ name: 'warpMode', defaultValue: 0 },
|
{ name: 'warpMode', defaultValue: 0 },
|
||||||
{ name: 'voices', defaultValue: 1, minValue: 1, maxValue: 32 },
|
{ name: 'voices', defaultValue: 1, minValue: 1, maxValue: 32 },
|
||||||
{ name: 'spread', defaultValue: 0, minValue: 0, maxValue: 1 },
|
{ name: 'spread', defaultValue: 0, minValue: 0, maxValue: 1 },
|
||||||
|
{ name: 'phaserand', defaultValue: 1, minValue: 0, maxValue: 1 },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1188,6 +1189,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
const warpAmount = pv(parameters.warp, i);
|
const warpAmount = pv(parameters.warp, i);
|
||||||
const warpMode = pv(parameters.warpMode, i);
|
const warpMode = pv(parameters.warpMode, i);
|
||||||
const voices = pv(parameters.voices, i);
|
const voices = pv(parameters.voices, i);
|
||||||
|
const phaseRand = pv(parameters.phaserand, i);
|
||||||
const gain1 = Math.sqrt(1 - spread);
|
const gain1 = Math.sqrt(1 - spread);
|
||||||
const gain2 = Math.sqrt(spread);
|
const gain2 = Math.sqrt(spread);
|
||||||
let f = pv(parameters.frequency, i);
|
let f = pv(parameters.frequency, i);
|
||||||
|
|
@ -1207,7 +1209,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
const bank = this.tables[level];
|
const bank = this.tables[level];
|
||||||
|
|
||||||
// warp phase then sample
|
// warp phase then sample
|
||||||
this.phase[n] = this.phase[n] ?? Math.random();
|
this.phase[n] = this.phase[n] ?? Math.random() * phaseRand;
|
||||||
let ph = this._warpPhase(this.phase[n], warpAmount, warpMode);
|
let ph = this._warpPhase(this.phase[n], warpAmount, warpMode);
|
||||||
const s0 = this._sampleFrame(bank[fIdx], ph);
|
const s0 = this._sampleFrame(bank[fIdx], ph);
|
||||||
const s1 = this._sampleFrame(bank[Math.min(this.numFrames - 1, fIdx + 1)], ph);
|
const s1 = this._sampleFrame(bank[Math.min(this.numFrames - 1, fIdx + 1)], ph);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue