I've been making web games for sometime now and I quickly noticed that once i use the .cloneNode(true)
to play back the same audio file multiple times to avoid re-downloading the file over and over each time I want to play an audio file, I loose control of things such as playback volume and playback rate, does anyone know how I can regain control of those parameters for each copy of the audio file?
I tried setting the parameters for the audio copies from the original file but no juice
In the HTML :
<audio src = "sight.wav" id="sight"/>
<button onclick="playSound()">Play some audio</audio>
In the Js
var get = new Function("id", "return document.getElementById(id)");
function playSound()
{
get(sight).volume = 0.30;
get(sight).playbackRate = 0.40;
get(sight).cloneNode(true).play();
};
Looks like valid code to me but like I said, no juice, the cloneNodes completely ignore the volume and playback settings and just play the normal audio. What should I do?
Node.cloneNode()
when called on an Element will create a new Element of the same sub-type with the same attributes as the original Node.
Here you are not modifying the original's attributes
, but only some IDL properties that are not reflected and thus not cloned.
const original = document.querySelector("audio");
console.log( "default", [...original.attributes].map( (att) => att.name ) ); // []
original.volume = 0.2;
console.log( "volume set", [...original.attributes].map( (att) => att.name ) ); // []
original.controls = true;
console.log( "controls set", [...original.attributes].map( (att) => att.name ) ); // [ "controls" ]
const clone = original.cloneNode();
console.log( "clone volume", clone.volume ); // 1
console.log( "clone controls", clone.controls ); // true
<audio></audio>
So you could rewrite your code so that you set the volume
and playBackRate
of your cloned element instead of setting the ones of the original node, but note that if you are really spawning several same audios, you should rather use the Web-Audio API and its AudioBuffer interface which offer far greater controls over when these media are played, and which will take far less memory than initializing DOM MediaElements.