2011-10-22 14 views
6

Napisałem podstawowy skrypt w Chrome, który używa nowego Web Audio Api do załadowania 3 plików dźwiękowych (ponad XMLHTTPRequest) i odtworzenia każdego z nich z osobna. Dostarczyłem osobny przycisk dla każdego dźwięku, który pozwala użytkownikowi na rozpoczęcie i zatrzymanie każdego dźwięku.Web Audio API: Jak ponownie uruchomić odtwarzanie dźwięku?

Skrypt natychmiast ładuje wszystkie trzy pliki dźwiękowe, a po zakończeniu przycina przyciski odtwarzania, aby użytkownik mógł grać tylko wtedy, gdy dźwięki są gotowe. Ponadto, dźwięki są zapętlone, więc etykieta na każdym przycisku zmienia się pomiędzy "Play" i "Stop" po kliknięciu przycisku.

Wszystko działa świetnie ... Po kliknięciu przycisku Odtwórz usłyszysz dźwięk pętli, a po kliknięciu przycisku Zatrzymaj dźwięk zostanie zatrzymany. Jednak, gdy spróbujesz ponownie odtworzyć ten sam dźwięk po raz drugi, dźwięk nie zacznie się ponownie. Za każdym kliknięciem przycisku Play/Stop zostaje wywołana odpowiednia funkcja playSound() lub stopSound(), a odpowiednie parametry zostają przekazane, ale z jakiegoś powodu po prostu nie mogę uzyskać dźwięków, które można odtworzyć po raz drugi. czy robię coś źle?

Oto mój kod:

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

Ponadto, jest ktoś świadomy wszelkiego rodzaju imprezy, które mogłyby ogień raz dźwięk bez pętli odbywa się gra? Byłoby fajnie, gdybym mógł ustawić te dźwięki na niezwiązane z zapętleniem, a gdy tylko dźwięk zostanie odtworzony, użyj takiego zdarzenia, aby przełączyć jego etykietę. Nie widzę niczego w specyfikacji, ale może jest lepszy sposób?

Dzięki, Brad.

+1

Czy kiedykolwiek to naprawiliście? Mam podobny problem. – mdm

+1

Mam dokładnie ten sam problem tutaj! : S jakieś pomysły? – asheinfeld

Odpowiedz

5

Samą naukę interfejsu API Web Audio. Na pierwszy rzut oka powiedziałbym, że to dlatego, że masz tworzyć BufferSource za każdym razem, gdy odtwarzasz dźwięk i wygląda na to, że robisz to za pierwszym razem. zobacz przykłady tutaj: http://www.html5rocks.com/en/tutorials/webaudio/intro/

6

wiem, że jest to rok późno, ale miałem podobny problem, zrobił kilka szybkich wyszukiwań i oto co znalazłem:

Na tej stronie: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ

Następnie zapoznaj się z pytaniami:

  • "Jak mogę sprawdzić, kiedy zakończy się odtwarzanie AudioSourceNode?"
  • "Mam AudioBufferSourceNode, który właśnie odtwarzałem z noteOn(), i chcę go odtworzyć ponownie, ale noteOn() nic nie robi! Pomoc!"

Z tego co rozumiem: Źródło utworzone z createBufferSource() może być odtwarzane tylko raz. Gdy już to zrobisz, musisz utworzyć nowy. Jeśli chcesz wiedzieć, kiedy dany dźwięk przestał grać, nie ma zdarzenia, które go wywoła; więc musisz użyć limitu czasu.

Mam nadzieję, że to pomoże!

+1

Re. brak zdarzenia po zakończeniu odtwarzania źródła - występuje teraz "odświeżony" oddzwanianie. Właśnie sprawdziłem, że działa w Chrome v35: audioSource.onended = function() { playingSound = false; }; Podziękowania dla Andersa Lauritsena za napiwek w komentarzach tutaj: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ – poshaughnessy

Powiązane problemy