2 votes

Comment convertir un AudioBuffer en fichier wav ?

J'essaie de convertir un AudioBuffer en un fichier wav que je peux télécharger. J'ai essayé deux méthodes : La première, j'enregistre tous les sons qui passent par un mediaRecorder et je fais ceci :

App.model.mediaRecorder.ondataavailable = function(evt) {
   // push each chunk (blobs) in an array
    //console.log(evt.data)
   App.model.chunks.push(evt.data);
 };

 App.model.mediaRecorder.onstop = function(evt) {
   // Make blob out of our blobs, and open it.
   var blob = new Blob(App.model.chunks, { 'type' : 'audio/wav; codecs=opus' });
   createDownloadLink(blob);

 };

Je crée une table de chunk contenant des blobs, puis je crée un nouveau Blob avec ces chunks. Ensuite, dans la fonction "createDownloadLink()", je crée un noeud audio et un lien de téléchargement :

function createDownloadLink(blob) {

  var url = URL.createObjectURL(blob);
  var li = document.createElement('li');
  var au = document.createElement('audio');
  li.className = "recordedElement";
  var hf = document.createElement('a');
  li.style.textDecoration ="none";
  au.controls = true;
  au.src = url;
  hf.href = url;
  hf.download = 'myrecording' + App.model.countRecordings + ".wav";
  hf.innerHTML = hf.download;
  li.appendChild(au);
  li.appendChild(hf);
  recordingslist.appendChild(li);

}

Le nœud audio est créé et je peux écouter le son que j'ai enregistré, donc tout semble fonctionner. Mais lorsque je télécharge le fichier, il ne peut être lu par aucun lecteur. Je pense que c'est parce qu'il n'est pas encodé en WAV et qu'il n'est donc pas compréhensible.

La deuxième méthode est la même que la précédente, à l'exception de la fonction "createDownloadLink()".

function createDownloadLink(blob) {

  var reader = new FileReader();
  reader.readAsArrayBuffer(blob);
  App.model.sourceBuffer = App.model.audioCtx.createBufferSource();

  reader.onloadend = function()
  {
      App.model.recordBuffer = reader.result;
      App.model.audioCtx.decodeAudioData(App.model.recordBuffer, function(decodedData)
                                        {
          App.model.sourceBuffer.buffer = decodedData;

      })
  }

J'obtiens ici un AudioBuffer des sons que j'ai enregistrés, mais je n'ai pas trouvé comment le convertir en fichier WAV...

0voto

Erik Points 72

Pouvez-vous utiliser une variation de ceci ? https://gist.github.com/asanoboy/3979747

Peut-être quelque chose comme ça ?

var wav = createWavFromBuffer(convertBlock(decodedData), 44100); 
// Then call wav.getBuffer or wav.getWavInt16Array() for the WAV-RIFF formatted data

L'autre fonctionne ici :

class Wav {
    constructor(opt_params) {
        this._sampleRate = opt_params && opt_params.sampleRate ? opt_params.sampleRate : 44100;
        this._channels = opt_params && opt_params.channels ? opt_params.channels : 2;
        this._eof = true;
        this._bufferNeedle = 0;
        this._buffer;
    }
    setBuffer(buffer) {
        this._buffer = this.getWavInt16Array(buffer);
        this._bufferNeedle = 0;
        this._internalBuffer = '';
        this._hasOutputHeader = false;
        this._eof = false;
    }
    getBuffer(len) {
        var rt;
        if( this._bufferNeedle + len >= this._buffer.length ){
            rt = new Int16Array(this._buffer.length - this._bufferNeedle);
            this._eof = true;
        }
        else {
            rt = new Int16Array(len);
        }
        for(var i=0; i<rt.length; i++){
            rt[i] = this._buffer[i+this._bufferNeedle];
        }
        this._bufferNeedle += rt.length;
        return  rt.buffer;
    }
    eof() {
        return this._eof;
    }
    getWavInt16Array(buffer) {

        var intBuffer = new Int16Array(buffer.length + 23), tmp;

        intBuffer[0] = 0x4952; // "RI"
        intBuffer[1] = 0x4646; // "FF"

        intBuffer[2] = (2*buffer.length + 15) & 0x0000ffff; // RIFF size
        intBuffer[3] = ((2*buffer.length + 15) & 0xffff0000) >> 16; // RIFF size

        intBuffer[4] = 0x4157; // "WA"
        intBuffer[5] = 0x4556; // "VE"

        intBuffer[6] = 0x6d66; // "fm"
        intBuffer[7] = 0x2074; // "t "

        intBuffer[8] = 0x0012; // fmt chunksize: 18
        intBuffer[9] = 0x0000; //

        intBuffer[10] = 0x0001; // format tag : 1 
        intBuffer[11] = this._channels; // channels: 2

        intBuffer[12] = this._sampleRate & 0x0000ffff; // sample per sec
        intBuffer[13] = (this._sampleRate & 0xffff0000) >> 16; // sample per sec

        intBuffer[14] = (2*this._channels*this._sampleRate) & 0x0000ffff; // byte per sec
        intBuffer[15] = ((2*this._channels*this._sampleRate) & 0xffff0000) >> 16; // byte per sec

        intBuffer[16] = 0x0004; // block align
        intBuffer[17] = 0x0010; // bit per sample
        intBuffer[18] = 0x0000; // cb size
        intBuffer[19] = 0x6164; // "da"
        intBuffer[20] = 0x6174; // "ta"
        intBuffer[21] = (2*buffer.length) & 0x0000ffff; // data size[byte]
        intBuffer[22] = ((2*buffer.length) & 0xffff0000) >> 16; // data size[byte]  

        for (var i = 0; i < buffer.length; i++) {
            tmp = buffer[i];
            if (tmp >= 1) {
                intBuffer[i+23] = (1 << 15) - 1;
            }
            else if (tmp <= -1) {
                intBuffer[i+23] = -(1 << 15);
            }
            else {
                intBuffer[i+23] = Math.round(tmp * (1 << 15));
            }
        }

        return intBuffer;
    }
}

// factory
function createWavFromBuffer(buffer, sampleRate) {
  var wav = new Wav({
      sampleRate: sampleRate,
      channels: 1
  });
  wav.setBuffer(buffer);
  return wav;
}

// ArrayBuffer -> Float32Array
var convertBlock = function(buffer) {
    var incomingData = new Uint8Array(buffer);
    var i, l = incomingData.length;
    var outputData = new Float32Array(incomingData.length);
    for (i = 0; i < l; i++) {
        outputData[i] = (incomingData[i] - 128) / 128.0;
    }
    return outputData;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X