如何获取 AudioBufferSourceNode 当前时间?
How can I get an AudioBufferSourceNode's current time?
使用音频元素 (<audio>
) 或上下文 (AudioContext
) 时,您可以检查它们的 currentTime
属性 以准确了解缓冲区的播放时间.
在我在单个 AudioContext
.
中创建多个源(或 AudioBufferSourceNode
)之前,所有这些都很好,花花公子
源可以在不同时间播放,因此我需要知道它们对应的 currentTime
,以说明:
一些供您使用的基本代码:
buffer1 = [0,1,0]; //not real buffers
buffer2 = [1,0,1];
ctx = new AudioContext();
source1 = ctx.createBufferSourceNode();
source1.buffer = buffer1;
source1.connect(ctx.destination);
source1.start(0);
source2 = ctx.createBufferSourceNode();
source2.buffer = buffer2;
source2.connect(ctx.destination);
setTimeout(1000/*some time later*/){
source2.start(0);
}
setTimeout(1500/*some more time later*/){
getCurrentTime();
}
function getCurrentTime(){
/* magic */
/* more magic */
console.log("the sources currentTime values are obviously 1500 (source1) and 500 (source2).");
}
我通常做的是为跟踪播放状态的音频源节点创建一个包装器。我尽量减少下面的代码以显示基础知识。
核心思想是跟踪声音开始的时间和声音的时间 'paused' 并使用这些值获取当前时间并从暂停位置恢复播放。
我放了一个working example on codepen
function createSound(buffer, context) {
var sourceNode = null,
startedAt = 0,
pausedAt = 0,
playing = false;
var play = function() {
var offset = pausedAt;
sourceNode = context.createBufferSource();
sourceNode.connect(context.destination);
sourceNode.buffer = buffer;
sourceNode.start(0, offset);
startedAt = context.currentTime - offset;
pausedAt = 0;
playing = true;
};
var pause = function() {
var elapsed = context.currentTime - startedAt;
stop();
pausedAt = elapsed;
};
var stop = function() {
if (sourceNode) {
sourceNode.disconnect();
sourceNode.stop(0);
sourceNode = null;
}
pausedAt = 0;
startedAt = 0;
playing = false;
};
var getPlaying = function() {
return playing;
};
var getCurrentTime = function() {
if(pausedAt) {
return pausedAt;
}
if(startedAt) {
return context.currentTime - startedAt;
}
return 0;
};
var getDuration = function() {
return buffer.duration;
};
return {
getCurrentTime: getCurrentTime,
getDuration: getDuration,
getPlaying: getPlaying,
play: play,
pause: pause,
stop: stop
};
}
旧线程 (非常有用!谢谢!),但也许值得一提的是 而不是
function update() {
window.requestAnimationFrame(update);
info.innerHTML = sound.getCurrentTime().toFixed(1) + '/' + sound.getDuration().toFixed(1);
}
update();
使用 createScriptProcessor
可能更精确,占用资源更少
就像 this post
中解释的那样
const audioBuffer = await audioContext.decodeAudioData(response.data);
const chan = audioBuffer.numberOfChannels;
const scriptNode = audioContext.createScriptProcessor(4096, chan, chan);
scriptNode.connect(audioContext.destination);
scriptNode.onaudioprocess = (e) => {
// ---> audio loop <----
};
[更新]
注意:截至 2014 年 8 月 29 日网络音频 API 规范发布,此功能已被标记为已弃用,并被 AudioWorklet 取代(请参阅 AudioWorkletNode)。 https://developers.google.com/web/updates/2017/12/audio-worklet
使用音频元素 (<audio>
) 或上下文 (AudioContext
) 时,您可以检查它们的 currentTime
属性 以准确了解缓冲区的播放时间.
在我在单个 AudioContext
.
AudioBufferSourceNode
)之前,所有这些都很好,花花公子
源可以在不同时间播放,因此我需要知道它们对应的 currentTime
,以说明:
一些供您使用的基本代码:
buffer1 = [0,1,0]; //not real buffers
buffer2 = [1,0,1];
ctx = new AudioContext();
source1 = ctx.createBufferSourceNode();
source1.buffer = buffer1;
source1.connect(ctx.destination);
source1.start(0);
source2 = ctx.createBufferSourceNode();
source2.buffer = buffer2;
source2.connect(ctx.destination);
setTimeout(1000/*some time later*/){
source2.start(0);
}
setTimeout(1500/*some more time later*/){
getCurrentTime();
}
function getCurrentTime(){
/* magic */
/* more magic */
console.log("the sources currentTime values are obviously 1500 (source1) and 500 (source2).");
}
我通常做的是为跟踪播放状态的音频源节点创建一个包装器。我尽量减少下面的代码以显示基础知识。
核心思想是跟踪声音开始的时间和声音的时间 'paused' 并使用这些值获取当前时间并从暂停位置恢复播放。
我放了一个working example on codepen
function createSound(buffer, context) {
var sourceNode = null,
startedAt = 0,
pausedAt = 0,
playing = false;
var play = function() {
var offset = pausedAt;
sourceNode = context.createBufferSource();
sourceNode.connect(context.destination);
sourceNode.buffer = buffer;
sourceNode.start(0, offset);
startedAt = context.currentTime - offset;
pausedAt = 0;
playing = true;
};
var pause = function() {
var elapsed = context.currentTime - startedAt;
stop();
pausedAt = elapsed;
};
var stop = function() {
if (sourceNode) {
sourceNode.disconnect();
sourceNode.stop(0);
sourceNode = null;
}
pausedAt = 0;
startedAt = 0;
playing = false;
};
var getPlaying = function() {
return playing;
};
var getCurrentTime = function() {
if(pausedAt) {
return pausedAt;
}
if(startedAt) {
return context.currentTime - startedAt;
}
return 0;
};
var getDuration = function() {
return buffer.duration;
};
return {
getCurrentTime: getCurrentTime,
getDuration: getDuration,
getPlaying: getPlaying,
play: play,
pause: pause,
stop: stop
};
}
旧线程 (非常有用!谢谢!),但也许值得一提的是
function update() {
window.requestAnimationFrame(update);
info.innerHTML = sound.getCurrentTime().toFixed(1) + '/' + sound.getDuration().toFixed(1);
}
update();
使用 createScriptProcessor
可能更精确,占用资源更少
就像 this post
const audioBuffer = await audioContext.decodeAudioData(response.data);
const chan = audioBuffer.numberOfChannels;
const scriptNode = audioContext.createScriptProcessor(4096, chan, chan);
scriptNode.connect(audioContext.destination);
scriptNode.onaudioprocess = (e) => {
// ---> audio loop <----
};
[更新]
注意:截至 2014 年 8 月 29 日网络音频 API 规范发布,此功能已被标记为已弃用,并被 AudioWorklet 取代(请参阅 AudioWorkletNode)。 https://developers.google.com/web/updates/2017/12/audio-worklet