fix: time selection click and shiftclick

This commit is contained in:
2026-07-20 19:44:23 +07:00
parent 271f0583f4
commit 85a8dc6d17
13 changed files with 1788 additions and 293 deletions
@@ -0,0 +1,77 @@
// SonicForge Studio AudioWorklet DSP Processor
// Real-time priority audio rendering thread for low-latency DSP
class SonicDSPProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
{ name: 'volumeDb', defaultValue: 0, minValue: -60, maxValue: 12 },
{ name: 'pan', defaultValue: 0, minValue: -1, maxValue: 1 }
];
}
constructor() {
super();
this.sampleCount = 0;
this.isPlaying = true;
this.port.onmessage = (event) => {
if (!event.data) return;
if (event.data.type === 'SEEK') {
this.sampleCount = Math.floor(event.data.sampleIndex || 0);
} else if (event.data.type === 'PAUSE') {
this.isPlaying = false;
} else if (event.data.type === 'PLAY') {
this.isPlaying = true;
}
};
}
process(inputs, outputs, parameters) {
const input = inputs[0];
const output = outputs[0];
if (!input || !output || input.length === 0) return true;
const numChannels = Math.min(input.length, output.length);
const blockSize = output[0].length;
const volumeDbParam = parameters.volumeDb;
const panParam = parameters.pan;
const volDb = volumeDbParam.length === 1 ? volumeDbParam[0] : 0;
const panVal = panParam.length === 1 ? panParam[0] : 0;
// Constant-Power Panning Law (21_CLIENT_PRE.md §5)
const gain = Math.pow(10, volDb / 20);
const theta = ((panVal + 1) / 2) * (Math.PI / 2);
const gainL = Math.cos(theta) * gain;
const gainR = Math.sin(theta) * gain;
const inputL = input[0] || new Float32Array(blockSize);
const inputR = input[1] || inputL;
const outputL = output[0];
const outputR = output[1] || outputL;
for (let i = 0; i < blockSize; i++) {
if (this.isPlaying) {
outputL[i] = inputL[i] * gainL;
if (output.length > 1) {
outputR[i] = inputR[i] * gainR;
}
this.sampleCount++;
} else {
outputL[i] = 0;
if (output.length > 1) outputR[i] = 0;
}
}
// Lock-free playhead position update to Main Thread
if (this.sampleCount % 512 === 0) {
this.port.postMessage({
type: 'POSITION_UPDATE',
sampleCount: this.sampleCount
});
}
return true;
}
}
registerProcessor('sonic-dsp-processor', SonicDSPProcessor);