Web Audio API使用音量控制
我工作的一个简单的项目,以创建一个工具,使用网络音频API,并写了下面的代码片段(您可以按“Q”打注):Web Audio API使用音量控制
var audio = new AudioContext();
var volume = 0;
var attack = 1;
var release = 1;
var carrier = audio.createOscillator();
carrier.frequency.value = 440.00;
carrier.type = "sine";
carrier.start();
var carrier_volume = audio.createGain();
carrier_volume.gain.linearRampToValueAtTime(volume, 0);
carrier.connect(carrier_volume);
carrier_volume.connect(audio.destination);
document.addEventListener("keydown", function(e) {
if(e.keyCode == 81) {
carrier_volume.gain.linearRampToValueAtTime(1, audio.currentTime + attack);
}
});
document.addEventListener("keyup", function(e) {
if(e.keyCode == 81) {
carrier_volume.gain.linearRampToValueAtTime(0, audio.currentTime + release);
}
});
(如果你不熟悉的术语:“攻击”是它需要说明的时间才能达到它的峰值,在我的示例1秒,“释放”是一次在某人释放密钥后需要消失,本例中也为1秒)。
问题是这样的“点击”声音,你可以前后音符演奏后听到。我做了一些研究:
How can I avoid this 'clicking' sound when I stop playing a sound?
http://modernweb.com/2014/03/31/creating-sound-with-the-web-audio-api-and-oscillators/
,发现它会通过削减声波引起的,所以我应该保持音符在0dB玩和提高/根据需要降低音量。但是,它只适用于Chrome 专门只有如果我直接设置音量,就像这样:carrier_volume.gain.value = 1
。即使在Chrome中,如果我使用linearRampToValueAtTime()
函数,它也不起作用。
其他奇怪的事情发生,如果我尝试初始音量直接设置为0。通过在初始化时使用carrier_volume.gain.value = 0
,播放的第一个音符将被删除,但下一个音符将正常播放。
有没有人找到解决这个恼人的咔嗒声的方法,以及在使用gain.value
和linearRampToValueAtTime()
时都有什么延迟问题?
所以,这里的交易 - 一个linearRampToValueAtTime需要的开始时间。你打算把它当作“现在” - 当按下键时 - 但你需要明确指出,按下键时设置一个当前值。另外,您不应该在创建时使用linearRamp - 只需直接设置值。
如果您将初始体积直接设置为0(通过.value),它不应该完全切出,但第一个斜坡不会有起始点 - 所以在linearRamp的时间过去之前它将保持为零,并且然后它会跳到1
试试这个:
var audio = new AudioContext();
var volume = 0;
var attack = 1;
var release = 1;
var carrier = audio.createOscillator();
carrier.frequency.value = 440.00;
carrier.type = "sine";
carrier.start();
var carrier_volume = audio.createGain();
carrier_volume.gain.linearRampToValueAtTime(volume, 0);
carrier.connect(carrier_volume);
carrier_volume.connect(audio.destination);
// remember whether we're playing or not; otherwise the keyboard repeat will confuse us
var playing = false;
document.addEventListener("keydown", function(e) {
if((e.keyCode == 81) && !playing) {
// first, in case we're overlapping with a release, cancel the release ramp
carrier_volume.gain.cancelScheduledValues(audio.currentTime);
// now, make sure to set a "scheduling checkpoint" of the current value
carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);
// NOW, set the ramp
carrier_volume.gain.linearRampToValueAtTime(1, audio.currentTime + attack);
// Note that ideally, we would check the current value from above, and calculate
// the length of the attack based on it to keep a constant angle of the attack,
// rather than a constant time. (If we're half-way through a release when we
// start a new attack, the attack should only take 0.5s since we're already at 0.5.)
playing = true;
}
});
document.addEventListener("keyup", function(e) {
if((e.keyCode == 81) && playing) {
// first, in case we're overlapping with an attack, cancel the attack ramp
carrier_volume.gain.cancelScheduledValues(audio.currentTime);
// now, make sure to set a "scheduling checkpoint" of the current value
carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);
// NOW, set the ramp
carrier_volume.gain.linearRampToValueAtTime(0, audio.currentTime + release);
// Note that ideally, we would check the current value from above, and calculate
// the length of the release based on it to keep a constant angle of the release,
// rather than a constant time. (If we're half-way through an attack when we
// start a new release, the release should only take 0.5s since we're already at 0.5.)
playing = false;
}
});
非常感谢您!现在听起来很顺利。我也会尝试一下你的计算攻击/释放的建议。 – adrield