2011-10-22 17 views
6

He escrito un script básico en Chrome que usa el nuevo API de audio web para cargar 3 archivos de sonido (a través de XMLHTTPRequest) y reproducir cada uno de ellos de forma individual. He proporcionado un botón por separado para cada sonido que permite al usuario iniciar y detener cada sonido.Web Audio API: ¿cómo puedo reiniciar la reproducción de un sonido?

La secuencia de comandos carga inmediatamente los tres archivos de sonido y, cuando termine, desactiva los botones de reproducción para que el usuario solo pueda tocar cuando los sonidos estén listos. Además, los sonidos son en bucle, por lo que la etiqueta de cada botón cambia entre "Reproducir" y "Detener" cuando se hace clic en el botón.

Todo esto funciona muy bien ... Cuando hace clic en el botón Reproducir, escucha el sonido de bucle y cuando pulsa Detener, el sonido se detiene. Sin embargo, cuando intente volver a reproducir el mismo sonido por segunda vez, el sonido no comenzará a reproducirse nuevamente. Cada vez que hace clic en el botón Reproducir/Detener, se llama a la función playSound() o stopSound() correspondiente y se pasan los parámetros apropiados, pero por alguna razón no puedo hacer que los sonidos suenen una segunda vez. ¿Estoy haciendo algo mal?

Aquí está mi código:

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

Además, es alguien al tanto de cualquier tipo de evento que podría disparar una vez un sonido no se realiza un bucle de jugar? Sería fantástico si pudiera configurar estos sonidos para que no se repitiesen y, tan pronto como se reproduzca un sonido, usa un evento así para alternar la etiqueta. No veo nada en la especificación, pero tal vez hay una mejor manera?

Gracias, Brad.

+1

¿Alguna vez solucionó esto? Estoy teniendo un problema similar. – mdm

+1

¡Estoy teniendo exactamente el mismo problema aquí! : S alguna idea? – asheinfeld

Respuesta

5

Acabo de aprender la API de Web Audio yo mismo. A primera vista, diría que es porque se supone que debes crearBufferSource cada vez que reproduces el sonido y parece que solo lo haces la primera vez. echa un vistazo a los ejemplos aquí: http://www.html5rocks.com/en/tutorials/webaudio/intro/

6

Sé que este es un año de retraso, pero tuve un problema similar, hizo algunas búsquedas rápidas y esto es lo que encontré:

En esta página: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ

A continuación, consulte las preguntas:

  • "¿Cómo puedo verificar cuando un AudioSourceNode ha terminado de reproducirse?"
  • "Tengo un AudioBufferSourceNode, que acabo de reproducir con noteOn(), y quiero volver a jugarlo, pero NoteOn() no hace nada. ¡Ayuda!"

Según tengo entendido: una fuente creada desde createBufferSource() solo se puede reproducir una vez. Una vez que lo detenga, debe crear uno nuevo. Si desea saber cuándo un sonido particular ha dejado de reproducirse, no hay ningún evento que lo despache; entonces tienes que usar un tiempo de espera.

Espero que esto ayude!

+1

Re. no tener un evento cuando una fuente termina de reproducirse: ahora hay una devolución de llamada 'activada'. Acabo de verificar que funciona en Chrome v35: audioSource.onended = function() { playingSound = false; }; Gracias a Anders Lauritsen por la sugerencia en los comentarios aquí: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ – poshaughnessy

Cuestiones relacionadas