From 3efc298cd15111f94a11aaab7cf65a64d0fce816 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Sat, 4 Apr 2026 03:53:39 -0700 Subject: [PATCH] =?UTF-8?q?perf(pcm-player):=20=E2=9A=A1=20Optimize=20PCM?= =?UTF-8?q?=20audio=20processing=20for=20better=20playback=20efficiency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- @applications/web/src/worklets/pcm-player.js | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/@applications/web/src/worklets/pcm-player.js b/@applications/web/src/worklets/pcm-player.js index 8e3b8f2..a3d5e97 100644 --- a/@applications/web/src/worklets/pcm-player.js +++ b/@applications/web/src/worklets/pcm-player.js @@ -21,8 +21,9 @@ */ const INPUT_SAMPLE_RATE = 22050; -/** Ring buffer capacity in samples (≈1.5 seconds at 22050Hz) */ -const RING_CAPACITY = 32768; // must be power of 2 +/** Ring buffer capacity in samples (≈5.95 seconds at 22050Hz). + * Must be a power of 2. Sized to hold a full TTS segment (typically 2–4s). */ +const RING_CAPACITY = 131072; // 2^17 class PcmPlayerProcessor extends AudioWorkletProcessor { constructor() { @@ -59,20 +60,25 @@ class PcmPlayerProcessor extends AudioWorkletProcessor { const int16 = new Int16Array(buffer); const incoming = int16.length; - // Check for overrun — drop oldest samples to make room + // If the incoming chunk is larger than the ring, keep only the last RING_CAPACITY samples + // (i.e. drop the oldest part of a very long chunk rather than corrupting state). + const srcOffset = incoming > RING_CAPACITY ? incoming - RING_CAPACITY : 0; + const writeCount = incoming - srcOffset; + + // Drop oldest buffered samples to make room — never go below zero const freeSpace = RING_CAPACITY - this._available; - if (incoming > freeSpace) { - const drop = incoming - freeSpace; + if (writeCount > freeSpace) { + const drop = Math.min(writeCount - freeSpace, this._available); this._readHead = (this._readHead + drop) & (RING_CAPACITY - 1); this._available -= drop; } // Write Int16 → Float32 into ring - for (let i = 0; i < incoming; i++) { - this._ring[this._writeHead] = int16[i] / 32768.0; + for (let i = 0; i < writeCount; i++) { + this._ring[this._writeHead] = int16[srcOffset + i] / 32768.0; this._writeHead = (this._writeHead + 1) & (RING_CAPACITY - 1); } - this._available += incoming; + this._available += writeCount; } /**