24

I'm getting started with the Web Audio API and just wondering if it's possible to use jQuery's $.ajax or $.load functions to make the XMLHttpRequest that receives the audio data. Do $.ajax or $.load support responseType=arrayBuffer?

EDIT:

Ok, so here's what I have so far:

function loadAudio() {
    $.ajax({
            url: sourceUrl
        }).done(function(response){
            return response;
        })
    }

but I need to return an ArrayBuffer. So how do I convert the response into an ArrayBuffer?

Oskar Eriksson
  • 2,591
  • 18
  • 32
jhnnycrvr
  • 767
  • 2
  • 7
  • 13

5 Answers5

21

About your question, it seems jQuery does not support it yet. Before using it as I suggested below, consider checking if the feature is available.

With XHTMLRequest, you can trick your server and receive a binary string representing the bytes you want from the server. It works perfectly.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/your/audio/file.wav', true);

// Here is the hack
xhr.overrideMimeType('text/plain; charset=x-user-defined');

xhr.onreadystatechange = function(event) {
  if ( this.readyState == 4 && this.status == 200 ) {
    var binaryString = this.responseText;

    for (var i = 0, len = binaryString.length; i < len; ++i) {
      var c = binaryString.charCodeAt(i);
      var byte = c & 0xff; //it gives you the byte at i
      //Do your cool stuff...

    }
  }
};

xhr.send();

It works, it's common... but... it is still a hack.

With XHTML Request Level 2, you can specify the responseType as 'arraybuffer' and receive the ArrayBuffer actually. It is much nicer. The problem is to check if your browser support this feature.

var xhr = new XMLHttpRequest();
xhr.open('GET', '/your/audio/file.wav', true);
xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
  if (this.status == 200) {
    //Do your stuff here
  }
};

xhr.send();

Hope I helped.

Walter Macambira
  • 2,574
  • 19
  • 28
6

Actually there is an easier way to do this using jQuery and the native XMLHttpRequest without having to use only the XMLHttpRequest or having to use a plugin, so you can still code in jQuery style/syntax. One of the options for $.ajax() is xhr, which the jQuery documentation describes as (emphasis mine):

xhr (default: ActiveXObject when available (IE), the XMLHttpRequest otherwise)

Type: Function()

Callback for creating the XMLHttpRequest object. Defaults to the ActiveXObject when available (IE), the XMLHttpRequest otherwise. Override to provide your own implementation for XMLHttpRequest or enhancements to the factory.

So, in order to get an ArrayBuffer as a response to a $.ajax() request, all you have to do is:

var xhrOverride = new XMLHttpRequest();
xhrOverride.responseType = 'arraybuffer';

$.ajax({
    url: '/url/of/your/binary/data',
    method: 'GET',
    xhr: function() {
        return xhrOverride;
    }
}).then(function (responseData) {

    // responseData is an ArrayBuffer!

});
Dylan Cristy
  • 916
  • 11
  • 29
  • 1
    This doesn't always work -- it breaks when the file is of a type like .json, .xml, .html, etc. To fix it, I found you can set options `dataType: "x-binary"`, and `converters: {'* x-binary'(value) {return value}}` to bypass jQuery's response data filtering. – Codesmith Feb 22 '21 at 19:40
5

I used Dylan's answer and it worked, but the resulting $.ajax request is not a full Promise anymore (I couldn't combine it with Promise.all anymore). Instead, I achieved the same by using the xhrFields setting from the documentation.

$.ajax({
    url: url,
    method: 'GET',
    xhrFields: { responseType: 'arraybuffer'}
})
dieterw
  • 151
  • 1
  • 9
1

i fetched the data from server as string(which is base64 encoded to string) using ajax get json and then on client side i decoded it to base64 and then to array buffer.

Sample code

function solution1(base64Data) {

var arrBuffer = base64ToArrayBuffer(base64Data);

// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
var newBlob = new Blob([arrBuffer], { type: "application/pdf" });

// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(newBlob);
    return;
}

// For other browsers: 
// Create a link pointing to the ObjectURL containing the blob.
var data = window.URL.createObjectURL(newBlob);

var link = document.createElement('a');
document.body.appendChild(link); //required in FF, optional for Chrome
link.href = data;
link.download = "file.pdf";
link.click();
window.URL.revokeObjectURL(data);
link.remove();

}

function base64ToArrayBuffer(data) {
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
    var ascii = binaryString.charCodeAt(i);
    bytes[i] = ascii;
}
return bytes;

};

Sajjad Ali Khan
  • 1,735
  • 2
  • 20
  • 17
  • If this fails for anyone, try https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file – Vipul Dessai Dec 15 '19 at 15:43
0

There is a simple jQuery extension for this: https://github.com/vobruba-martin/jquery.ajax.arraybuffer

$.get("https://www.website.com/image.png", function(data)
{
    console.log("received data", data);
}, "arraybuffer");
John
  • 5,942
  • 3
  • 42
  • 79