// 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);
