Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions experiments/clarinet-synth/src/audio/ClarinetProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class ClarinetProcessor {
async initialize() {
console.log(`ClarinetProcessor.initialize()`)
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
this._installIOSUnlock(this.audioContext);
await this._installIOSUnlock(this.audioContext);

// Create gain node for volume control
this.gainNode = this.audioContext.createGain();
Expand Down Expand Up @@ -80,7 +80,7 @@ export class ClarinetProcessor {
}
}

_installIOSUnlock(ctx) {
async _installIOSUnlock(ctx) {
if (!ctx) return;
let unlocked = ctx.state === 'running';
const cleanup = () => {
Expand Down Expand Up @@ -110,6 +110,9 @@ export class ClarinetProcessor {
document.addEventListener('touchstart', unlock, { capture: true, passive: true });
document.addEventListener('keydown', unlock, { capture: true });
ctx.onstatechange = () => console.log('[audio] state:', ctx.state);

// Try to unlock immediately if we're in a user gesture
await unlock();
}

noteOff() {
Expand Down
3 changes: 1 addition & 2 deletions experiments/clarinet-synth/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default defineConfig({
return 'assets/[name]-[hash][extname]';
}
}
},
watch: {},
}
}
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// clarinet-worklet.js
// AudioWorklet processor for the clarinet engine

const sampleRate = globalThis.sampleRate;

class ClarinetWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
Expand Down Expand Up @@ -73,12 +75,15 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {
if (scaled < -3) return -1;

const x2 = scaled * scaled;
return scaled * (27 + x2) / (27 + 9 * x2);
const result = scaled * (27 + x2) / (27 + 9 * x2);
console.log(`[ClarinetWorkletProcessor] reedReflection: pressureDiff=${pressureDiff.toFixed(4)}, scaled=${scaled.toFixed(4)}, result=${result.toFixed(4)}`);
return result;
}

lowpass(input, cutoff) {
const a = cutoff;
this.lpf.y1 = a * input + (1 - a) * this.lpf.y1;
console.log(`[ClarinetWorkletProcessor] lowpass: input=${input.toFixed(4)}, cutoff=${cutoff.toFixed(4)}, output=${this.lpf.y1.toFixed(4)}`);
return this.lpf.y1;
}

Expand All @@ -103,11 +108,11 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {

updateEnvelope(deltaTime) {
if (this.gate) {
const attackRate = 1.0 / (this.attackTime * this.sampleRate);
const attackRate = 1.0 / this.attackTime;
this.envelope += attackRate * deltaTime;
if (this.envelope > 1) this.envelope = 1;
} else {
const releaseRate = 1.0 / (this.releaseTime * this.sampleRate);
const releaseRate = 1.0 / this.releaseTime;
this.envelope -= releaseRate * deltaTime;
if (this.envelope < 0) {
this.envelope = 0;
Expand Down Expand Up @@ -166,10 +171,11 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {
this.delayLine[this.writePos] = newSample;
this.writePos = (this.writePos + 1) % this.delayLength;

return newSample * env * 0.5;
return newSample * env * 1.0;
}

noteOn(frequency) {
console.log(`[ClarinetWorkletProcessor] noteOn: ${frequency}`);
this.setFrequency(frequency);
this.gate = true;
this.isPlaying = true;
Expand All @@ -187,6 +193,7 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {
}

setParameter(param, value) {
console.log(`[ClarinetWorkletProcessor] setParameter: ${param}, ${value}`);
switch(param) {
case 'breath':
this.breathPressure = value * 0.8 + 0.2;
Expand All @@ -207,7 +214,7 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {
this.lpf.cutoff = 0.3 + value * 0.69;
break;
case 'brightness':
this.hpf.cutoff = value * 0.05;
this.hpf.cutoff = value * 0.5;
break;
case 'vibrato':
this.vibratoAmount = value * 0.01;
Expand All @@ -223,6 +230,10 @@ class ClarinetWorkletProcessor extends AudioWorkletProcessor {
channel[i] = this.processSample();
}

if (this.isPlaying) {
console.log(`[ClarinetWorkletProcessor] process: output[0] = ${channel[0]}`);
}

return true; // Keep processor alive
}
}
Expand Down
1 change: 1 addition & 0 deletions www/clarinet-synth/assets/index-3bg4U7-_.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading