'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!



Solution 1:[1]

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;
}

Solution 2:[2]

I think below code is useful for you for cloning object.

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

Please note that Answer with description is given on below link. How do I correctly clone a JavaScript object?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Kaiido
Solution 2 Community