API веб-аудио: как я могу возобновить воспроизведение звука?
Я написал базовый скрипт в Chrome, который использует новый Web Audio Api для загрузки 3 звуковых файлов (через XMLHTTPRequest) и воспроизведения каждого из них по отдельности. Я предоставил отдельную кнопку для каждого звука, которая позволяет пользователю запускать и останавливать каждый звук.
Сценарий немедленно загружает все три звуковых файла и, когда это будет сделано, отменяет приглушение кнопок воспроизведения, чтобы пользователь мог нажать кнопку воспроизведения, только когда звук будет готов. Кроме того, звуки зацикливаются, поэтому при нажатии кнопки метка на каждой кнопке изменяется между "Play" и "Stop".
Все это прекрасно работает... Когда вы нажимаете кнопку Play, вы слышите зацикленный звук, а когда вы нажимаете кнопку Stop, звук останавливается. Однако, если вы попытаетесь повторно воспроизвести один и тот же звук во второй раз, звук не начнет воспроизводиться снова. Каждый раз, когда вы нажимаете кнопку Play/Stop, вызывается соответствующая функция playSound() или stopSound() и передаются соответствующие параметры, но по какой-то причине я просто не могу заставить звуки воспроизводиться во второй раз. Я делаю что-то неправильно?
Вот мой код:
<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>
Кроме того, кто-нибудь знает о каком-либо событии, которое может сработать, когда воспроизводится звук без петель? Было бы здорово, если бы я мог установить эти звуки нецикличными, и как только звук закончится, используйте такое событие, чтобы переключить его метку. Я не вижу ничего в спецификации, но, может быть, есть лучший способ?
Спасибо, Брэд.
2 ответа
Я знаю, что это год с опозданием, но у меня была похожая проблема, я сделал несколько быстрых поисков, и вот что я нашел:
На этой странице: http://updates.html5rocks.com/2012/01/Web-Audio-FAQ
Тогда обратитесь к вопросам:
- "Как я могу проверить, когда AudioSourceNode закончил играть?"
- "У меня есть AudioBufferSourceNode, который я только что воспроизвел с помощью noteOn(), и я хочу воспроизвести его снова, но noteOn () ничего не делает! Помогите!"
Из того, что я понимаю: источник, созданный из createBufferSource(), может быть воспроизведен только один раз. Как только вы остановите это, вы должны создать новый. Если вы хотите знать, когда конкретный звук перестал воспроизводиться, нет события, которое отправляет его; поэтому вы должны использовать тайм-аут.
Надеюсь это поможет!
Просто изучаю API Web Audio. На первый взгляд я бы сказал, что это потому, что вы должны создавать BufferSource каждый раз, когда проигрываете звук, и кажется, что вы делаете это только в первый раз. посмотрите примеры здесь: http://www.html5rocks.com/en/tutorials/webaudio/intro/