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

breakspirit picture breakspirit · Jun 10, 2014 · Viewed 23.4k times · Source

I'm using the following method to play a byte array containing wav data. The function is being called from a GWT project.

This function plays back sound, but it sounds like some kind of Hellish monster. The sample rate is definitely correct (the sound is being generated by neospeech) and I've tried all kinds of values for numberOfSamples, which just seems to represent how long the audio data is.

A value greater than 30000 for numberOfSamples will play the audio file's full length but it is garbled and horrible.

So, what am I doing wrong?

function playByteArray(byteArray, numberOfSamples) {
    sampleRate = 8000;

    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;
    }

    var audioContext = new AudioContext();

    var buffer = audioContext.createBuffer(1, numberOfSamples, sampleRate);
    var buf = buffer.getChannelData(0);
    for (i = 0; i < byteArray.length; ++i) {
        buf[i] = byteArray[i];
    }

    var source = audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(audioContext.destination);
    source.start(0);
}

Answer

breakspirit picture breakspirit · Jun 12, 2014

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