重排音频节点能保证无缝播放吗?
Is seamless playback guaranteed when re-arranging audio nodes?
当我用 AudioBufferSourceNode
播放音频时,我可以在它之前添加其他节点(增益或声相器或可能的其他节点)播放时没有任何间隙或跳跃?这在规范中有提到吗?有人有这方面的经验吗?
// Play audio
var source = context.createBufferSource();
source.buffer = someBuffer;
source.connect(context.destination);
source.start();
// Later, when source is still playing, is this safe?
source.disconnect();
source.connect(gain);
gain.connect(context.destination);
// And removing nodes is safe too?
gain.disconnect();
source.disconnect();
source.connect(context.destination);
我知道我可以按照自己的意愿重新排列节点,但我的问题是关于在实际播放过程中重新排列。
我没有检查规格,但从测试来看,实现确实有所不同...
当完全断开连接时 Chrome,Safari 将暂停 AudioBufferSourceNode 的播放,而 Firefox 将保留它 运行。
const ctx = new(window.AudioContext || window.webkitAudioContext);
let source;
let connected = true;
btn.onclick = e => {
btn.textContent = 'loading...';
btn.disabled = true;
fetch('https://upload.wikimedia.org/wikipedia/commons/2/23/Turdus_fuscater_-_Great_Thrush_XC243229.mp3')
.then(r => r.arrayBuffer())
.then(buf => ctx.decodeAudioData(buf))
.then(audioBuf => {
source = ctx.createBufferSource();
source.buffer = audioBuf;
source.onended = e => console.log('done');
source.connect(ctx.destination);
btn.onclick = e => {
source.start(0);
btn.onclick = switchConnect;
btn.textContent = 'switch connection';
};
btn.textContent = 'play';
btn.disabled = false;
});
};
function switchConnect() {
if (connected)
source.disconnect();
else
source.connect(ctx.destination);
connected = !connected;
}
<script src="https://cdn.jsdelivr.net/gh/mohayonao/promise-decode-audio-data@eb4b1322113b08614634559bc12e6a8163b9cf0c/build/promise-decode-audio-data.min.js"></script>
<button id="btn">fetch</button>
现在,即使播放没有暂停,您也可能会遇到一些咔哒声和爆裂声。这甚至是 AudioNode.disconnect()
has been extended to allow for a destination
parameter 的原因,它允许我们微调我们想要断开连接的目的地,而不是从所有地方断开连接。
这样做,您只需先将您的节点连接到新目的地,然后再将其与之前的目的地断开连接即可。这应该消除明显的咔哒声和爆裂声,以及 webkit 在播放时的暂停。
但是,请注意,所有浏览器仍然不支持此选项,从我测试的浏览器来看,Chrome 和 Firefox 支持,Safari 不支持。由于在不支持的浏览器中调用 disconnect(destination)
实际上会断开它与 所有 目的地的连接,因此我们必须在代码中处理这两种情况。
let supportFineDisconnect = false;
const ctx = new(window.AudioContext || window.webkitAudioContext);
const osc = ctx.createOscillator();
const gain = ctx.createGain();
// lazy checks support for AudioNode.disconnect(destination)
try {
osc.disconnect(osc);
} catch (e) {
supportFineDisconnect = "maybe";
}
btn1.onclick = begin;
onchange = switchRoute;
function begin(){
osc.connect(gain);
gain.connect(ctx.destination);
gain.gain.value = 1;
osc.start(0);
btn1.textContent = 'stop';
btn1.onclick = e => osc.stop(0);
}
function switchRoute() {
if (!supportFineDisconnect) { // might click
osc.disconnect(); // disconnect from all
}
if (+document.querySelector('input:checked').value) {
connectDirect();
} else {
connectGain();
}
}
function connectDirect() {
// first connect to new dest
osc.connect(ctx.destination);
if (supportFineDisconnect) {
osc.disconnect(gain); // then disconnect only from gain
}
}
function connectGain() {
// first connect to new dest
osc.connect(gain);
if (supportFineDisconnect) {
osc.disconnect(ctx.destination); // then disconnect only from main
}
}
<button id="btn1">start playing a 440hz osc</button>
switch: <input type="radio" checked value="0" name="switch"><label>through gain</label>
<input type="radio" value="1" name="switch"><label>direct</label>
但是,当然,这仍然不能阻止其他因素引起的咔哒声或爆裂声(比如增益或其他变化)。
当我用 AudioBufferSourceNode
播放音频时,我可以在它之前添加其他节点(增益或声相器或可能的其他节点)播放时没有任何间隙或跳跃?这在规范中有提到吗?有人有这方面的经验吗?
// Play audio
var source = context.createBufferSource();
source.buffer = someBuffer;
source.connect(context.destination);
source.start();
// Later, when source is still playing, is this safe?
source.disconnect();
source.connect(gain);
gain.connect(context.destination);
// And removing nodes is safe too?
gain.disconnect();
source.disconnect();
source.connect(context.destination);
我知道我可以按照自己的意愿重新排列节点,但我的问题是关于在实际播放过程中重新排列。
我没有检查规格,但从测试来看,实现确实有所不同...
当完全断开连接时 Chrome,Safari 将暂停 AudioBufferSourceNode 的播放,而 Firefox 将保留它 运行。
const ctx = new(window.AudioContext || window.webkitAudioContext);
let source;
let connected = true;
btn.onclick = e => {
btn.textContent = 'loading...';
btn.disabled = true;
fetch('https://upload.wikimedia.org/wikipedia/commons/2/23/Turdus_fuscater_-_Great_Thrush_XC243229.mp3')
.then(r => r.arrayBuffer())
.then(buf => ctx.decodeAudioData(buf))
.then(audioBuf => {
source = ctx.createBufferSource();
source.buffer = audioBuf;
source.onended = e => console.log('done');
source.connect(ctx.destination);
btn.onclick = e => {
source.start(0);
btn.onclick = switchConnect;
btn.textContent = 'switch connection';
};
btn.textContent = 'play';
btn.disabled = false;
});
};
function switchConnect() {
if (connected)
source.disconnect();
else
source.connect(ctx.destination);
connected = !connected;
}
<script src="https://cdn.jsdelivr.net/gh/mohayonao/promise-decode-audio-data@eb4b1322113b08614634559bc12e6a8163b9cf0c/build/promise-decode-audio-data.min.js"></script>
<button id="btn">fetch</button>
现在,即使播放没有暂停,您也可能会遇到一些咔哒声和爆裂声。这甚至是 AudioNode.disconnect()
has been extended to allow for a destination
parameter 的原因,它允许我们微调我们想要断开连接的目的地,而不是从所有地方断开连接。
这样做,您只需先将您的节点连接到新目的地,然后再将其与之前的目的地断开连接即可。这应该消除明显的咔哒声和爆裂声,以及 webkit 在播放时的暂停。
但是,请注意,所有浏览器仍然不支持此选项,从我测试的浏览器来看,Chrome 和 Firefox 支持,Safari 不支持。由于在不支持的浏览器中调用 disconnect(destination)
实际上会断开它与 所有 目的地的连接,因此我们必须在代码中处理这两种情况。
let supportFineDisconnect = false;
const ctx = new(window.AudioContext || window.webkitAudioContext);
const osc = ctx.createOscillator();
const gain = ctx.createGain();
// lazy checks support for AudioNode.disconnect(destination)
try {
osc.disconnect(osc);
} catch (e) {
supportFineDisconnect = "maybe";
}
btn1.onclick = begin;
onchange = switchRoute;
function begin(){
osc.connect(gain);
gain.connect(ctx.destination);
gain.gain.value = 1;
osc.start(0);
btn1.textContent = 'stop';
btn1.onclick = e => osc.stop(0);
}
function switchRoute() {
if (!supportFineDisconnect) { // might click
osc.disconnect(); // disconnect from all
}
if (+document.querySelector('input:checked').value) {
connectDirect();
} else {
connectGain();
}
}
function connectDirect() {
// first connect to new dest
osc.connect(ctx.destination);
if (supportFineDisconnect) {
osc.disconnect(gain); // then disconnect only from gain
}
}
function connectGain() {
// first connect to new dest
osc.connect(gain);
if (supportFineDisconnect) {
osc.disconnect(ctx.destination); // then disconnect only from main
}
}
<button id="btn1">start playing a 440hz osc</button>
switch: <input type="radio" checked value="0" name="switch"><label>through gain</label>
<input type="radio" value="1" name="switch"><label>direct</label>
但是,当然,这仍然不能阻止其他因素引起的咔哒声或爆裂声(比如增益或其他变化)。