Encode Audio Back From getChannelData()

303 views Asked by At

I call getChannelData and perform some actions and remove values from the Float32Array.

How can I encode this data back into a form that can be saved?

const blob = new Blob(this.chunks, { type: audioType });
// generate audio url from blob
const audioContext = new (window.AudioContext ||
  window.webkitAudioContext)();
// reading the file with file reader using a method that uses read file in a promise 
ReadFile(blob).then((arrayBuffer) => {
  audioContext.decodeAudioData(arrayBuffer).then((audioBuffer) => {
    const audioBufferSourceNode = audioContext.createBufferSource();
    const numChannels = audioBuffer.numberOfChannels;
    const leftChannelArray = audioBuffer.getChannelData(0);
    // audioBufferSourceNode.buffer = leftChannelArray;
    let rightChannelArray;
    if (numChannels>1) {
      rightChannelArray = audioBuffer.getChannelData(1);
    }
    const monoChannelTrimmed = trimSilence(leftChannelArray, rightChannelArray) //we look on both sides for silence, we delete the array values and merge the channels
    //Now i want to turn monoChannelTrimmed into a usable audio file

Turning this channel back into something that is usable is what I have been struggling with. I have tried some suggestions from other questions in this field such as Converting Float32Array to Uint8Array while Preserving IEEE 754 Representation But nothing has worked if anyone has suggestions I would be very eager to try them.

1

There are 1 answers

2
Raymond Toy On

You can probably use the MediaStream Recording API.

Here is a small snippet of how to use it, mostly taken from the example, but modified to use a WebAudio OscillatorNode as the source. You can replace that with an AudioBufferSourceNode that is playing out your monoTrimmedChannel

let c;
let s;
let d;
let mediaRecorder;

let recordedChunks = [];

function handleDataAvailable(event) {
  console.log("data-available");
  if (event.data.size > 0) {
    recordedChunks.push(event.data);
    download();
  } else {
    // ...
  }
}

function download() {
  let blob = new Blob(recordedChunks, {
    type: "video/webm"
  });
  let url = URL.createObjectURL(blob);
  let a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  a.href = url;
  a.download = "test.mp3";
  a.click();
  window.URL.revokeObjectURL(url);
}

setTimeout(event => {
  console.log("stopping");
  mediaRecorder.stop();
}, 9000);

function start() {
  console.log("start");
  c = new AudioContext();
  s = new OscillatorNode(c);
  d = new MediaStreamAudioDestinationNode(c);
  s.connect(d);

  mediaRecorder =  new MediaRecorder(d.stream,  {
    mimeType:  "audio/webm"
  });
  mediaRecorder.ondataavailable = handleDataAvailable;

  s.start();
  mediaRecorder.start();
}

I tested this locally and it creates a test.webm file that plays a nice oscillator tone as expected. You'll probably want to tweak some things.