diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs index 0d22b334..e9dbfb81 100644 --- a/packages/superdough/synth.mjs +++ b/packages/superdough/synth.mjs @@ -135,10 +135,10 @@ export function registerSynthSounds() { registerSound( - 'pwm', + 'pulse', (begin, value, onended) => { const ac = getAudioContext(); - let { duration, n } = value; + let { duration, n: pulsewidth = 0.5 } = value; const frequency = getFrequencyFromValue(value); const [attack, decay, sustain, release] = getADSRValues( @@ -152,12 +152,12 @@ export function registerSynthSounds() { let o = getWorklet( ac, - 'pwm-oscillator', + 'pulse-oscillator', { frequency, begin, end, - pulsewidth: 1 + pulsewidth, }, { outputChannelCount: [2], @@ -165,7 +165,7 @@ export function registerSynthSounds() { ); getPitchEnvelope(o.parameters.get('detune'), value, begin, holdend); - // const vibratoOscillator = getVibratoOscillator(o.parameters.get('detune'), value, begin); + const vibratoOscillator = getVibratoOscillator(o.parameters.get('detune'), value, begin); const fm = applyFM(o.parameters.get('frequency'), value, begin); let envGain = gainNode(1); envGain = o.connect(envGain); @@ -177,7 +177,7 @@ export function registerSynthSounds() { envGain.disconnect(); onended(); fm?.stop(); - // vibratoOscillator?.stop(); + vibratoOscillator?.stop(); }, begin, end, diff --git a/packages/superdough/worklets.mjs b/packages/superdough/worklets.mjs index acc75af7..11c20611 100644 --- a/packages/superdough/worklets.mjs +++ b/packages/superdough/worklets.mjs @@ -362,6 +362,11 @@ function getUnisonDetune(unison, detune, voiceIndex) { } return lerp(-detune * 0.5, detune * 0.5, voiceIndex / (unison - 1)); } + +function applySemitoneDetuneToFrequency(frequency, detune) { + return frequency * Math.pow(2, detune / 12) +} + class SuperSawOscillatorProcessor extends AudioWorkletProcessor { constructor() { super(); @@ -438,7 +443,8 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor { const isOdd = (n & 1) == 1; //applies unison "spread" detune in semitones - const freq = frequency * Math.pow(2, getUnisonDetune(voices, freqspread, n) / 12); + const freq = applySemitoneDetuneToFrequency(frequency, getUnisonDetune(voices, freqspread, n)) + // const freq = frequency * Math.pow(2, getUnisonDetune(voices, freqspread, n) / 12); let gainL = gain1; let gainR = gain2; // invert right and left gain @@ -649,9 +655,8 @@ class PhaseVocoderProcessor extends OLAProcessor { registerProcessor('phase-vocoder-processor', PhaseVocoderProcessor); -// SelfPMpwmWorklet.js -class PwmOscillatorProcessor extends AudioWorkletProcessor { +class PulseOscillatorProcessor extends AudioWorkletProcessor { constructor() { @@ -688,6 +693,11 @@ class PwmOscillatorProcessor extends AudioWorkletProcessor { defaultValue: 440, min: Number.EPSILON, }, + { + name: 'detune', + defaultValue: 0, + min: Number.NEGATIVE_INFINITY, + max: Number.POSITIVE_INFINITY}, { name: 'pulsewidth', defaultValue: 1, @@ -705,11 +715,14 @@ class PwmOscillatorProcessor extends AudioWorkletProcessor { return false; } const output = outputs[0]; - let env = 1, dphi; - let freq = params.frequency[0] - let pw = params.pulsewidth[0] * _PI + let env = 1, dphi; + let pw = clamp(params.pulsewidth[0], 0.01, 0.99) * _PI * 2 + let detune = params.detune[0]; + let freq = applySemitoneDetuneToFrequency(params.frequency[0], detune /100) for (let i = 0; i < (output[0].length ?? 0); i++) { + + dphi = freq * (this.pi / (sampleRate * .5)); // phase increment this.dphif += 0.1 * (dphi - this.dphif); @@ -743,4 +756,4 @@ class PwmOscillatorProcessor extends AudioWorkletProcessor { } } -registerProcessor('pwm-oscillator', PwmOscillatorProcessor); +registerProcessor('pulse-oscillator', PulseOscillatorProcessor);