Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Audio API - Cloning an audioBuffer

I have a deepClone function that I use throughout my program that clones all the properties and values of one object and returns the cloned object (see code below). I am now wanting to include an audioBuffer in the object and successfully copy it to the returning object. Is there a way to modify function to include this functionality?

TO NOTE: Not all objects passed to the deepClone function will include an audioBuffer, therefore it should be able to cope and successfully clone objects with and without them.

Edit: Can someone think of a way to combine JSON.parse(JSON.stringify(object)) with the solution provided as one of the answers? I.e. check properties of the object as the cloning is happening, if (property == 'trackBuffer') clone it differently to the rest?

deepClone function:

function deepClone (object) {
   return JSON.parse(JSON.stringify(object));
};

/**
 * Utility function for deep object cloning
 *                                                                                                                                                                               
 * @param   {object} obj  Object to be cloned
 * @returns {object}      The deep-cloned object
 */
function deepClone (object) {
    return JSON.parse(JSON.stringify(object));
};

// Create audio context
var context = new AudioContext(); 

// Create empty audio buffer
var audioBuffer = context.createBuffer(2, 22050, 44100); 

// Create object to be cloned
var track = {
  prop1: "val1",
  prop2: "val2",
  trackBuffer: audioBuffer
};

// Log before clone
console.log("before clone, track:  \n", track);

// Clone track
var clonedTrack = deepClone(track);

// Log after clone
console.log("after clone, clonedTrack: \n", clonedTrack);

As you can see from the code snippet, the clonedTrack's trackBuffer is converted to an empty object which is to be expected from JSON.parse(JSON.stringify(object));.

What is the best way to modify deepClone to successfully clone the audioBuffer but keep existing functionality?

Any help would be greatly appreciated, thanks!

like image 724
Alistair Hughes Avatar asked Sep 19 '25 14:09

Alistair Hughes


1 Answers

My suggestion is that handling AudioBuffer (de)serialization as a special case is safer. When your code must work across multiple browsers and be future-proof, you're better off to use the supported APIs of the object.

function cloneAudioBuffer(fromAudioBuffer) {
  const audioBuffer = new AudioBuffer({
    length:fromAudioBuffer.length, 
    numberOfChannels:fromAudioBuffer.numberOfChannels, 
    sampleRate:fromAudioBuffer.sampleRate
  });
  for(let channelI = 0; channelI < audioBuffer.numberOfChannels; ++channelI) {
    const samples = fromAudioBuffer.getChannelData(channelI);
    audioBuffer.copyToChannel(samples, channelI);
  }
  return audioBuffer;
}
like image 85
Erik Hermansen Avatar answered Sep 21 '25 04:09

Erik Hermansen