2011-10-22 7 views
6

Ho scritto uno script di base in Chrome che utilizza il nuovo Web Audio Api per caricare 3 file audio (su XMLHTTPRequest) e riprodurli singolarmente. Ho fornito un pulsante separato per ogni suono che consente all'utente di avviare e interrompere ogni suono.API Web Audio: come posso riavviare la riproduzione di un suono?

Lo script carica immediatamente tutti e tre i file audio e al termine deseleziona i pulsanti di riproduzione in modo che l'utente possa eseguire la riproduzione solo quando i suoni sono pronti. Inoltre, i suoni sono in loop, quindi l'etichetta su ciascun pulsante cambia tra "Play" e "Stop" quando si fa clic sul pulsante.

Tutto funziona alla grande ... Quando si fa clic su un pulsante Riproduci si sente il suono in loop e quando si preme Stop il suono si interrompe. Tuttavia, quando si tenta di riprodurre nuovamente lo stesso suono per una seconda volta, il suono non riprenderà a suonare. Ogni volta che fai clic sul pulsante Riproduci/Ferma, viene richiamata la funzione playSound() o stopSound() appropriata e passano i parametri appropriati, ma per qualche motivo non riesco a riprodurre i suoni una seconda volta. Sto facendo qualcosa di sbagliato?

Ecco il mio codice:

<body> 

<label for="playBtn1">Moog:</label> 
<input id="playBtn1" type="button" value="Play" disabled /> 
<label for="playBtn1">Drums:</label> 
<input id="playBtn2" type="button" value="Play" disabled /> 
<label for="playBtn1">Choir:</label> 
<input id="playBtn3" type="button" value="Play" disabled /> 

<script> 
    var playBtn1 = document.getElementById("playBtn1"); 
    var playBtn2 = document.getElementById("playBtn2"); 
    var playBtn3 = document.getElementById("playBtn3"); 

    var context = new webkitAudioContext(); 

    var soundBuffer1 = null; 
    var soundBuffer2 = null; 
    var soundBuffer3 = null; 

    var soundBufferSourceNode1 = context.createBufferSource(); 
    soundBufferSourceNode1.looping = true; 
    var soundBufferSourceNode2 = context.createBufferSource(); 
    soundBufferSourceNode2.looping = true; 
    var soundBufferSourceNode3 = context.createBufferSource(); 
    soundBufferSourceNode3.looping = true; 

    loadSound('micromoog.wav', 1); 
    loadSound('breakbeat-drum-loop.wav', 2); 
    loadSound('choir.wav', 3); 

    playBtn1.addEventListener("click", function(e) { 
    if(this.value == "Play") { 
     this.value = "Stop"; 
     playSound(soundBuffer1, soundBufferSourceNode1); 
    } else if(this.value == "Stop") { 
     this.value = "Play"; 
     stopSound(soundBufferSourceNode1); 
    } 
    }, false); 
    playBtn2.addEventListener("click", function(e) { 
    if(this.value == "Play") { 
     this.value = "Stop"; 
     playSound(soundBuffer2, soundBufferSourceNode2); 
    } else if(this.value == "Stop") { 
     this.value = "Play"; 
     stopSound(soundBufferSourceNode2); 
    } 
    }, false); 
    playBtn3.addEventListener("click", function(e) { 
    if(this.value == "Play") { 
     this.value = "Stop"; 
     playSound(soundBuffer3, soundBufferSourceNode3); 
    } else if(this.value == "Stop") { 
     this.value = "Play"; 
     stopSound(soundBufferSourceNode3); 
    } 
    }, false); 

    function loadSound(url, bufferNum) { 
    var request = new XMLHttpRequest(); 
    request.open('GET', url, true); 
    request.responseType = 'arraybuffer'; 

    // Decode asynchronously 
    request.onload = function() { 
     var successCallback = function(buffer) { 
     switch(bufferNum) { 
      case 1: 
      soundBuffer1 = buffer; 
      playBtn1.disabled = false; 
      break; 
      case 2: 
       soundBuffer2 = buffer; 
      playBtn2.disabled = false; 
      break; 
      case 3: 
      soundBuffer3 = buffer; 
      playBtn3.disabled = false; 
      break; 
     } 
     } 
     var errorCallback = function(e) { 
     console.log(e); 
     } 
     context.decodeAudioData(request.response, successCallback, errorCallback); 
    } 

    request.send(); 
    } 

    function playSound(buffer, bufferSourceNode) { 
    bufferSourceNode.buffer = buffer; 
    bufferSourceNode.connect(context.destination); 
    bufferSourceNode.noteOn(0); 
    } 

    function stopSound(bufferSourceNode) { 
    bufferSourceNode.noteOff(0); 
    } 
</script> 

</body> 

Inoltre, è qualcuno a conoscenza di qualsiasi tipo di evento che potrebbe sparare una volta un suono non-loop è finito di giocare? Sarebbe bello se potessi impostare questi suoni su non-loop e non appena un suono è terminato, usa un evento del genere per cambiare la sua etichetta. Non vedo nulla nelle specifiche ma forse c'è un modo migliore?

Grazie, Brad.

+1

Hai mai sistemato questo? Sto avendo un problema simile. – mdm

+1

Sto avendo lo stesso identico problema qui! : Qualche idea? – asheinfeld

risposta

6

So che questo è un anno di ritardo, ma ho avuto un problema simile, ha fatto un paio di ricerche rapide ed ecco cosa ho trovato:

In questa pagina: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ

Quindi fare riferimento alle domande:

  • "Come posso controllare quando un AudioSourceNode ha finito di suonare?"
  • "Ho un AudioBufferSourceNode, che ho appena riprodotto con noteOn(), e voglio riprodurlo di nuovo, ma noteOn() non fa nulla! Aiuto!"

Da quello che ho capito: una fonte creata da createBufferSource() può essere riprodotta solo una volta. Una volta che lo interrompi, devi crearne uno nuovo. Se volevi sapere quando un suono particolare ha smesso di suonare, non c'è nessun evento che lo invii; quindi devi usare un timeout.

Spero che questo aiuti!

+1

Re. non avendo un evento quando una fonte finisce di giocare - ora c'è un callback 'onended'. Ho appena verificato che funzioni in Chrome v35: audioSource.onended = function() { playingSound = false; }; Grazie a Anders Lauritsen per il suggerimento nei commenti qui: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ – poshaughnessy

Problemi correlati