// AudioWorkletProcessor: downsample mic input to 16 kHz mono **Int16 LE** PCM.
// Qwen3-ASR streaming server (mochi-asr on i7:9000) expects Int16 LE.
//
// Browsers run AudioContext at 44.1k or 48k. We linear-resample to 16k.

const TARGET_RATE = 16000;
const CHUNK_SAMPLES = 1600; // 100 ms at 16 kHz

class AsrWorklet extends AudioWorkletProcessor {
  constructor() {
    super();
    this._ratio = sampleRate / TARGET_RATE;
    this._tail = [];
  }

  process(inputs) {
    const input = inputs[0];
    if (!input || input.length === 0 || !input[0]) return true;
    const channel = input[0];

    const outLen = Math.floor(channel.length / this._ratio);
    for (let i = 0; i < outLen; i++) {
      const srcIdx = i * this._ratio;
      const i0 = srcIdx | 0;
      const i1 = i0 + 1 < channel.length ? i0 + 1 : channel.length - 1;
      const t = srcIdx - i0;
      this._tail.push(channel[i0] * (1 - t) + channel[i1] * t);
    }

    while (this._tail.length >= CHUNK_SAMPLES) {
      const samples = this._tail.splice(0, CHUNK_SAMPLES);
      const i16 = new Int16Array(CHUNK_SAMPLES);
      for (let i = 0; i < CHUNK_SAMPLES; i++) {
        let s = samples[i];
        if (s < -1) s = -1;
        else if (s > 1) s = 1;
        i16[i] = s < 0 ? Math.round(s * 32768) : Math.round(s * 32767);
      }
      this.port.postMessage(i16.buffer, [i16.buffer]);
    }
    return true;
  }
}

registerProcessor('asr-worklet', AsrWorklet);
