问题描述
我正试图模仿来自'Mozilla Web Audio API for games'Web doc的Web Audio API多轨演示。
I'm trying to mimic the Web Audio API multitrack demo from the 'Mozilla Web Audio API for games' Web doc.
我唯一需要注意的是,一旦点击了新曲目,我希望前一首曲目停止播放(而不是在彼此)。
The only caveat I have is that I want the previous track to stop, once a new track is clicked (instead of playing layered on top of each other).
一个例子是,点击鼓,鼓开始播放,然后点击吉他,鼓停止,吉他从鼓停止的地方开始。
An example would be, click drums, the drums start playing, then click guitar, the drums stop and the guitar starts right where the drums left off.
任何想法?是否有更好的工具/库来处理网络音频?
Any ideas? Are there better tools/libraries for handling web audio?
<ul>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-leadguitar.mp3">Lead Guitar</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-drums.mp3">Drums</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-bassguitar.mp3">Bass Guitar</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-horns.mp3">Horns</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-clav.mp3">Clavi</a></li>
</ul>
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var offset = 0;
var context = new AudioContext();
function playTrack(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
var audiobuffer;
// Decode asynchronously
request.onload = function() {
if (request.status == 200) {
context.decodeAudioData(request.response, function(buffer) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
console.log('context.currentTime '+context.currentTime);
if (offset == 0) {
source.start();
offset = context.currentTime;
} else {
source.start(0,context.currentTime - offset);
}
}, function(e) {
console.log('Error decoding audio data:' + e);
});
} else {
console.log('Audio didn\'t load successfully; error code:' + request.statusText);
}
}
request.send();
}
var tracks = document.getElementsByClassName('track');
for (var i = 0, len = tracks.length; i < len; i++) {
tracks[i].addEventListener('click', function(e){
console.log(this.href);
playTrack(this.href);
e.preventDefault();
});
}
推荐答案
在帮助下找出来@Kaiido
Figured it out with help from @Kaiido
同步和开始上一首曲目停止的新曲目的示例:
Example with both synchronization and starting a new track where a previous track stops:
<ul>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-leadguitar.mp3">Lead Guitar</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-drums.mp3">Drums</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-bassguitar.mp3">Bass Guitar</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-horns.mp3">Horns</a></li>
<li><a class="track" href="http://jPlayer.org/audio/mp3/gbreggae-clav.mp3">Clavi</a></li>
</ul>
let active_source = null;
let buffers = {};
const context = new(window.AudioContext || window.webkitAudioContext)();
let offset = 0;
const tempo = 3.074074076;
const tracks = document.getElementsByClassName('track');
function playTrack(url) {
let buffer = buffers[url];
let source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.loop = true;
if (offset == 0) {
source.start();
offset = context.currentTime;
active_source = source;
} else {
let relativeTime = context.currentTime - offset;
let beats = relativeTime / tempo;
let remainder = beats - Math.floor(beats);
let delay = tempo - (remainder*tempo);
let when = context.currentTime+delay;
stopActiveSource(when);
source.start(context.currentTime+delay,relativeTime+delay);
active_source = source;
source.onended = function() {
active_source = null;
};
}
}
for (var i = 0, len = tracks.length; i < len; i++) {
tracks[i].addEventListener('click', function(e) {
playTrack(this.href);
e.preventDefault();
});
getBuffer(tracks[i].href);
}
function getBuffer(url) {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function(evt) {
context.decodeAudioData(request.response, store);
};
request.send();
function store(buffer) {
buffers[url] = buffer;
}
}
function stopActiveSource(when) {
if (active_source) {
active_source.onended = null;
active_source.stop(when);
}
}
这篇关于Web Audio API - 多个同步曲目 - 在新曲目开始时停止上一曲目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!