From 3dbe3105afc889b6eb13aa4070d8e8e2a6a4a5db Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Wed, 13 May 2026 22:20:15 +0700 Subject: [PATCH] fix: simplify AudioData playback with direct copyTo approach - Rename playAudioData to playAudioDataDirect for clarity - Remove duplicate playAudioData function with debug logging - Use direct copyTo into temp Float32Array per channel - Check isListening state in output callback --- public/dashboard.js | 68 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/public/dashboard.js b/public/dashboard.js index f756d99..557c709 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -437,7 +437,7 @@ const state = { } try { state.opusDecoder = new AudioDecoder({ - output: (audioData) => playAudioData(audioData), + output: (audioData) => playAudioDataDirect(audioData), error: (error) => { console.error('Opus decode error:', error); showError(`Opus decode error: ${error.message}`); @@ -458,6 +458,39 @@ const state = { } } + function playAudioDataDirect(audioData) { + if (!state.audioContextListen || !state.isListening) { + audioData.close(); + return; + } + try { + const sampleRate = audioData.sampleRate; + const frameCount = audioData.numberOfFrames; + const numberOfChannels = audioData.numberOfChannels; + const audioBuffer = state.audioContextListen.createBuffer( + numberOfChannels, + frameCount, + sampleRate + ); + for (let ch = 0; ch < numberOfChannels; ch++) { + const channelData = audioBuffer.getChannelData(ch); + const tempArray = new Float32Array(frameCount); + audioData.copyTo(tempArray, { planeIndex: ch }); + channelData.set(tempArray); + } + const source = state.audioContextListen.createBufferSource(); + source.buffer = audioBuffer; + source.connect(state.audioContextListen.destination); + const startAt = Math.max(state.nextStartTime, state.audioContextListen.currentTime); + source.start(startAt); + state.nextStartTime = startAt + audioBuffer.duration; + } catch (error) { + console.error('Play audio error:', error); + } finally { + audioData.close(); + } + } + function decodeOpus(opusBuffer) { if (!state.isListening || !state.opusDecoderReady) { if (state.isListening) { @@ -484,39 +517,6 @@ const state = { } } - function playAudioData(audioData) { - if (!state.audioContextListen) { - audioData.close(); - return; - } - try { - const sampleRate = audioData.sampleRate; - const frameCount = audioData.numberOfFrames; - const numberOfChannels = audioData.numberOfChannels; - console.log(`AudioData: ${frameCount} frames, ${numberOfChannels} ch, ${sampleRate}Hz`); - const audioBuffer = state.audioContextListen.createBuffer( - numberOfChannels, - frameCount, - sampleRate - ); - for (let ch = 0; ch < numberOfChannels; ch++) { - const channelData = audioBuffer.getChannelData(ch); - console.log(`Channel ${ch}: copyTo into ${channelData.length} samples`); - audioData.copyTo(channelData, { planeIndex: ch }); - } - const source = state.audioContextListen.createBufferSource(); - source.buffer = audioBuffer; - source.connect(state.audioContextListen.destination); - const startAt = Math.max(state.nextStartTime, state.audioContextListen.currentTime); - source.start(startAt); - state.nextStartTime = startAt + audioBuffer.duration; - } catch (error) { - console.error('Play audio error:', error); - } finally { - audioData.close(); - } - } - function playPcm(arrayBuffer) { if (!state.audioContextListen) return; const bytes = new Uint8Array(arrayBuffer);