Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloning audio source without having to download it again

I'm creating a piano in the browser using javascript. In order for me to play the same key multiple times simultaneously, instead of just playing the Audio object, I clone it and play the clone, otherwise I'd have to wait for the audio to finish or to restart it, which I don't want.

I've done something like this:

var audioSrc = new Audio('path/');
window.onkeypress = function(event) {
    var currentAudioSrc = audioSrc.cloneNode();
    currentAudioSrc.play();
}

The problem is, I was checking chrome's inspector, and I noticed that every time I clone the object, the browser download it again

enter image description here

I checked some people who wanted to achieve similar things, and noticed that most of them have the same problem that I do, they redownload the file. The only example I found that can play the same audio source multiple times simultaneously is SoundJs http://www.createjs.com/SoundJS

I tried checking the source could but couldn't figure out how it was done. Any idea?


like image 329
Daniel Ortiz Avatar asked May 25 '15 07:05

Daniel Ortiz


1 Answers

With the webAudioAPI you could do something like that :

  • Download once the file via XMLHttpRequest.
  • Append the response to a buffer
  • Create a new bufferSource and play it on each call
  • Fallback to your first implementation if webAudioAPI is not supported (IE)

window.AudioContext = window.AudioContext||window.webkitAudioContext;
if(!window.AudioContext)
  yourFirstImplementation();
else{
var buffer,
ctx = new AudioContext(),
gainNode = ctx.createGain();
gainNode.connect(ctx.destination);
var vol = document.querySelector('input');
vol.value = gainNode.gain.value;
vol.addEventListener('change', function(){
    gainNode.gain.value = this.value;
  }, false);

function createBuffer(){
  ctx.decodeAudioData(this.response, function(b) {
    buffer = b;
    }, function(e){console.warn(e)});
  var button = document.querySelector('button');
  button.addEventListener('click', function(){playSound(buffer)});
  button.className = 'ready';
  }

var file = 'https://dl.dropboxusercontent.com/s/agepbh2agnduknz/camera.mp3',
xhr = new XMLHttpRequest();
xhr.onload = createBuffer;
xhr.open('GET', file, true);
xhr.responseType = 'arraybuffer';
xhr.send();

function playSound(buf){
  var source = ctx.createBufferSource();
  source.buffer = buf;
  source.connect(gainNode);
  source.onended = function(){if(this.stop)this.stop(); if(this.disconnect)this.disconnect();}
  source.start(0);
  }
}

function yourFirstImplementation(){
  alert('webAudioAPI is not supported by your browser');
  }
button{opacity: .2;}
button.ready{opacity: 1};
<button>play</button>
<input type="range" max="5" step=".01" title="volume"/>
like image 74
Kaiido Avatar answered Oct 21 '22 12:10

Kaiido