0

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.

  • What kind of playable form? WebAudio can play out the data in getChannelData as is (roughly). – Raymond Toy Sep 30 '20 at 17:32
  • I am looking to save the audio in a wav format so that it can be used in an – WorkingOnBeingBetter Sep 30 '20 at 21:24
  • That seems kind of roundabout since you can play it out already with WebAudio. Are you trying to encode the audio and sending it to a server so it can be played somewhere else through an – Raymond Toy Sep 30 '20 at 22:48
  • Yes, I am trying to save these files to a server. I am unable to do this with the information from getChannelData(), I have noticed that consistently in the values that there are many leading 0's which may have something to do with the way that this is encoded. I agree that my earlier comment was fairly roundabout so I appreciate you understanding my intention. – WorkingOnBeingBetter Oct 01 '20 at 01:13
  • Please update your question with more details. – Raymond Toy Oct 01 '20 at 13:56
  • I have updated the question, thank you for your patience – WorkingOnBeingBetter Oct 01 '20 at 14:36

1 Answers1

1

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.

Raymond Toy
  • 5,490
  • 10
  • 13
  • Although this technically works it requires that you replay the length of the sound or video that is being grabbed. – WorkingOnBeingBetter Dec 15 '20 at 20:23
  • I don't know you can encode something without in effect replaying either in realtime or offline in some manner. Don't see how you can encode something without sending the entire clip to the encoder. Maybe WebCodecs will help you? – Raymond Toy Dec 16 '20 at 15:47