Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web audio api misreporting length of buffer?

I'm doing some web audio stuff on chrome and i noticed the buffer.length property does not match what I see in Sonar. Web audio claims my file is 1391324 samples long, or ~31.6 seconds. Sonar is showing me 1278279 samples, or ~29 seconds. The file properties in windows confirm Sonar's numbers as well. Its a normal 16-bit, 44.1k wav file. Whats could be going on here?

Edit: It appears chrome resamples the audio to 48k. Why??? I want my same wav file, thanks. Firefox does not do this and gives me the correct length.

Try it on chrome and firefox using this fiddle: http://jsfiddle.net/kV7aV/2/ and use this file: https://dl.dropboxusercontent.com/u/75652364/amp.wav

Fiddle code to make SO happy:

html:

<input type="file" id="audio_file" accept="audio/wav" multiple />
<p id="output"></p>
<p id="output2"></p>

js:

var fileInput = document.getElementById("audio_file");
var output = document.getElementById("output");
var output2 = document.getElementById("output2");

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var context = new AudioContext();

fileInput.onchange = function (evt) {

    var files = evt.target.files; // FileList object

    for (var f = 0; f < files.length; f++) {

        var reader = new FileReader();

        reader.onload = function (e) {
            context.decodeAudioData(e.target.result, function (buffer) {
                console.log(buffer.length);
                output.innerHTML = buffer.length;

                var data = buffer.getChannelData(0);

                // undefined in firefox
                console.log(data[1391323]);
                output2.innerHTML = data[1391323];

            });

        };

        reader.readAsArrayBuffer(files[f]);

    }

};
like image 309
Rob Allsopp Avatar asked Mar 20 '26 08:03

Rob Allsopp


1 Answers

It appears web audio may or may not resample your audio depending on your browser, the audio file's sample rate, and your sound card's sample rate. See step 4 here. My sound card is set to 48k, and it looks like chrome went ahead and and resampled to match my sound card. I'm not sure why firefox didn't. Currently, there appears to be no way to force decodeAudioData to decode into the original sample rate, but there is a discussion on the subject here. As a temporary fix in the meantime, I've written a simple function for resampling audio:

// takes a Float32Array of audio data and resamples it
function resample( signal, oldSR, newSR ) {

    var ratio =  oldSR / newSR;

    var newLength = Math.round((newSR / oldSR) * signal.length);

    var signalNew = new Float32Array(newLength);

    var sampCount;
    var m;
    var weight;

    if ( ratio > 1.0 ) {

        for ( var n = 0; n < newLength; n++ ) {

            sampCount = n * ratio;
            m = Math.floor(sampCount);
            weight = sampCount - m;

            signalNew[n] = (signal[m] * (1-weight)) + (signal[m+1] * weight);

        }

    } else {

        for ( var n = 0; n < newLength; n++ ) {

            m = Math.round(n * ratio);

            signalNew[n] = signal[m];

        }

    }

    return signalNew;

}
like image 123
Rob Allsopp Avatar answered Mar 21 '26 20:03

Rob Allsopp