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
This commit is contained in:
MythEclipse
2026-05-13 22:15:30 +07:00
parent 25dbd8413b
commit 26efaa9e4d

View File

@@ -416,6 +416,9 @@ const state = {
} else { } else {
state.audioContextListen?.close(); state.audioContextListen?.close();
state.audioContextListen = null; state.audioContextListen = null;
if (state.opusDecoder) {
state.opusDecoder.close();
}
state.opusDecoder = null; state.opusDecoder = null;
state.opusDecoderReady = false; state.opusDecoderReady = false;
state.opusDecodeQueue = []; state.opusDecodeQueue = [];
@@ -456,8 +459,10 @@ const state = {
} }
function decodeOpus(opusBuffer) { function decodeOpus(opusBuffer) {
if (!state.opusDecoderReady) { if (!state.isListening || !state.opusDecoderReady) {
state.opusDecodeQueue.push(opusBuffer); if (state.isListening) {
state.opusDecodeQueue.push(opusBuffer);
}
return; return;
} }
try { try {
@@ -483,12 +488,15 @@ const state = {
if (!state.audioContextListen) return; if (!state.audioContextListen) return;
const sampleRate = audioData.sampleRate; const sampleRate = audioData.sampleRate;
const frameCount = audioData.numberOfFrames; const frameCount = audioData.numberOfFrames;
const numberOfChannels = audioData.numberOfChannels;
const audioBuffer = state.audioContextListen.createBuffer( const audioBuffer = state.audioContextListen.createBuffer(
audioData.numberOfChannels, numberOfChannels,
frameCount, frameCount,
sampleRate sampleRate
); );
audioData.copyTo(audioBuffer); for (let ch = 0; ch < numberOfChannels; ch++) {
audioData.copyTo(audioBuffer.getChannelData(ch), { planeIndex: ch });
}
const source = state.audioContextListen.createBufferSource(); const source = state.audioContextListen.createBufferSource();
source.buffer = audioBuffer; source.buffer = audioBuffer;
source.connect(state.audioContextListen.destination); source.connect(state.audioContextListen.destination);