How to Play Wav Audio Byte Array via JavaScript/Html5

How to play wav audio byte array via javascript/html5?

I figured out how to do what I described in my question and thought I should post it for the benefit of others. The code is below. I call playByteArray and pass it a byte array containing pcm wav data.

window.onload = init;
var context; // Audio context
var buf; // Audio buffer

function init() {
if (!window.AudioContext) {
if (!window.webkitAudioContext) {
alert("Your browser does not support any AudioContext and cannot play back this audio.");
return;
}
window.AudioContext = window.webkitAudioContext;
}

context = new AudioContext();
}

function playByteArray(byteArray) {

var arrayBuffer = new ArrayBuffer(byteArray.length);
var bufferView = new Uint8Array(arrayBuffer);
for (i = 0; i < byteArray.length; i++) {
bufferView[i] = byteArray[i];
}

context.decodeAudioData(arrayBuffer, function(buffer) {
buf = buffer;
play();
});
}

// Play the loaded file
function play() {
// Create a source node from the buffer
var source = context.createBufferSource();
source.buffer = buf;
// Connect to the final output node (the speakers)
source.connect(context.destination);
// Play immediately
source.start(0);
}

Play wav file as bytes received from server

I managed to play the bytes on browser using this method :

function playWave(byteArray) {
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var myAudioBuffer = audioCtx.createBuffer(1, byteArray.length, 8000);
var nowBuffering = myAudioBuffer.getChannelData(0);
for (var i = 0; i < byteArray.length; i++) {
nowBuffering[i] = byteArray[i];
}

var source = audioCtx.createBufferSource();
source.buffer = myAudioBuffer;
source.connect(audioCtx.destination);
source.start();
}

rewriting Java code to JS - creating an audio from bytes?

I solved it myself. I read more into the MDN docs explaining AudioBuffer and realized two important things:

  1. I didn't need to decodeAudioData (since I'm creating the data myself, there's nothing to decode). I actually took that bit from the answer I was replicating and it retrospect, it was entirely needless.
  2. Since I'm working with a 16 Bit PCM stereo, that meant I needed to use the Float32Array (2 Channels, each 16 Bit).

Granted, I still had a problem with some of my calculations that resulted in a distorted sound, but as far as producing the sound itself, I ended up doing this really simple solution:

function playBytes(bytes) {
var floats = new Float32Array(bytes.length);

bytes.forEach(function( sample, i ) {
floats[i] = sample / 32767;
});

var buffer = context.createBuffer(1, floats.length, 48000),
source = context.createBufferSource();

buffer.getChannelData(0).set(floats);
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
}

I can probably optimize it a bit further - the 32767 part should happen before this, in the part where I'm calculating the data, for example. Also, I'm creating a Float32Array with two channels, then outputting one of them cause I really don't need both. I couldn't figure out if there's a way to create one channel mono file with Int16Array, or if that's even necessary\better.

Anyway, that's essentially it. It's really just the most basic solution, with some minimal understanding on my part of how to handle my data correctly. Hope this helps anyone out there.



Related Topics



Leave a reply



Submit