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
This commit is contained in:
MythEclipse
2026-05-13 22:20:15 +07:00
parent 638d5fc005
commit 3dbe3105af

View File

@@ -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);