From 9066e5b1f2346a762842c978bf219551cf1705f9 Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Wed, 13 May 2026 22:17:43 +0700 Subject: [PATCH] fix: use Float32Array intermediate for AudioData.copyTo - AudioData.copyTo requires destination Float32Array, not AudioBuffer channel - Create temp Float32Array per channel, copyTo into it, then set into AudioBuffer - Properly handle 48kHz stereo Opus output to AudioContext --- public/dashboard.js | 47 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/public/dashboard.js b/public/dashboard.js index 7d717a2..277bcc8 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -485,25 +485,36 @@ const state = { } function playAudioData(audioData) { - if (!state.audioContextListen) return; - 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++) { - audioData.copyTo(audioBuffer.getChannelData(ch), { planeIndex: ch }); + if (!state.audioContextListen) { + 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(); } - 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; - audioData.close(); } function playPcm(arrayBuffer) {