From 26efaa9e4d909e5f8f35ff94c9761c5aca0099b4 Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Wed, 13 May 2026 22:15:30 +0700 Subject: [PATCH] fix: correct WebCodecs AudioData.copyTo API and decoder lifecycle - AudioData.copyTo requires planeIndex parameter per channel - Check isListening state before decode to prevent closed decoder errors - Properly close decoder when leaving listen mode - Queue packets if decoder not ready yet --- public/dashboard.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/public/dashboard.js b/public/dashboard.js index 2d6091d..7d717a2 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -416,6 +416,9 @@ const state = { } else { state.audioContextListen?.close(); state.audioContextListen = null; + if (state.opusDecoder) { + state.opusDecoder.close(); + } state.opusDecoder = null; state.opusDecoderReady = false; state.opusDecodeQueue = []; @@ -456,8 +459,10 @@ const state = { } function decodeOpus(opusBuffer) { - if (!state.opusDecoderReady) { - state.opusDecodeQueue.push(opusBuffer); + if (!state.isListening || !state.opusDecoderReady) { + if (state.isListening) { + state.opusDecodeQueue.push(opusBuffer); + } return; } try { @@ -483,12 +488,15 @@ const state = { if (!state.audioContextListen) return; const sampleRate = audioData.sampleRate; const frameCount = audioData.numberOfFrames; + const numberOfChannels = audioData.numberOfChannels; const audioBuffer = state.audioContextListen.createBuffer( - audioData.numberOfChannels, + numberOfChannels, frameCount, sampleRate ); - audioData.copyTo(audioBuffer); + for (let ch = 0; ch < numberOfChannels; ch++) { + audioData.copyTo(audioBuffer.getChannelData(ch), { planeIndex: ch }); + } const source = state.audioContextListen.createBufferSource(); source.buffer = audioBuffer; source.connect(state.audioContextListen.destination);