Split the single ASR gateway into app/main.py (entrypoint) + app/core (shared env helpers) + app/asr (all existing ASR logic, unchanged behavior) + app/tts (placeholder router/config, no engine yet), so a real TTS backend can be dropped in later without reshuffling ASR code. API moved under /asr/* and /tts/* prefixes; UI gained a top-level ASR/TTS tab switcher built on a reusable nested .tab-group mechanism, with JS split into common.js/asr.js/tts.js. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
30 lines
802 B
JavaScript
30 lines
802 B
JavaScript
// AudioWorklet processor — accumulates 4096 samples (~256ms at 16kHz) before sending
|
|
class PCMProcessor extends AudioWorkletProcessor {
|
|
constructor() {
|
|
super();
|
|
this._chunks = [];
|
|
this._total = 0;
|
|
this._target = 4096;
|
|
}
|
|
|
|
process(inputs) {
|
|
const ch = inputs[0] && inputs[0][0];
|
|
if (ch && ch.length > 0) {
|
|
this._chunks.push(ch.slice());
|
|
this._total += ch.length;
|
|
|
|
if (this._total >= this._target) {
|
|
const out = new Float32Array(this._total);
|
|
let offset = 0;
|
|
for (const c of this._chunks) { out.set(c, offset); offset += c.length; }
|
|
this._chunks = [];
|
|
this._total = 0;
|
|
this.port.postMessage(out.buffer, [out.buffer]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
registerProcessor('pcm-processor', PCMProcessor);
|