I am currently working on a project involving an IP camera that streams audio data in a unique format. Unlike common formats like MP3 or WAV, this audio is transmitted in ADPCM chunks of 544 bytes each, with a 32-byte header that needs to be removed for playback. To tackle this challenge, I am developing browser-side Javascript code with the goal of creating a browser extension that can consume this stream, strip the header, convert it to PCM, and play it seamlessly.
Below is a snippet of my code that has shown promising results in Firefox:
<script>
let form = document.forms.audioStreamSettings;
let inputAudioStreamURL = form.elements.audioStreamURL;
let inputAudioChunksLimit = form.elements.audioChunksLimit;
let btnStartStream = form.elements.startStream;
//Initiate audio playback upon clicking the "Play audio stream" button:
btnStartStream.addEventListener('click', () => {
let audioStreamURL = inputAudioStreamURL.value;
let audioChunksLimit = inputAudioChunksLimit.value;
(async () => {
let response = await fetch(audioStreamURL);
const reader = response.body.getReader();
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let receivedLength = 0;
let pcmStream = new Float32Array();
let audioDataChunks = new Uint8Array(reader.result);
for (let step = 0; step < audioChunksLimit; step++) {
const {done, value} = await reader.read();
if (done) {
break;
}
let audioChunk = new Uint8Array(value);
adpcmRawChunk = audioChunk.slice(32,544);
var pcmChunk = decodeAdpcm(adpcmRawChunk);
pcmStream = Float32Array.from([...pcmStream,...pcmChunk]);
receivedLength += audioChunk.length;
}
const audioBuffer = audioCtx.createBuffer(
1,
pcmStream.length,
8000
);
for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
const nowBuffering = audioBuffer.getChannelData(channel);
for (let i = 0; i < audioBuffer.length; i++) {
nowBuffering[i] = pcmStream[i];
}
}
const source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.start();
})()
})
</script>
While this code successfully captures and plays back a set number of audio chunks, my ultimate goal is to achieve real-time and continuous audio streaming, as well as implement a stop button for playback. I would appreciate any guidance or suggestions on how to enhance this code further to meet these objectives.