与网络音频API音量控制 [英] Volume control with Web Audio API

查看:217
本文介绍了与网络音频API音量控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个简单的项目,以创建一个工具,使用Web API的音频,并写了下面的代码片段(您可以preSS 问:打注):

\r
\r

VAR音频=新AudioContext();\r
\r
变种体积= 0;\r
变种攻击= 1;\r
VAR发布= 1;\r
\r
变种载体= audio.createOscillator();\r
carrier.frequency.value = 440.00;\r
carrier.type =正弦波\r
carrier.start();\r
\r
变种carrier_volume = audio.createGain();\r
carrier_volume.gain.linearRampToValueAtTime(体积,0);\r
carrier.connect(carrier_volume);\r
carrier_volume.connect(audio.destination);\r
\r
document.addEventListener(的keydown功能(E){\r
  如果(e.key code == 81){\r
    carrier_volume.gain.linearRampToValueAtTime(1,audio.currentTime +攻击);\r
  }\r
});\r
\r
document.addEventListener(KEYUP功能(E){\r
  如果(e.key code == 81){\r
    carrier_volume.gain.linearRampToValueAtTime(0,+ audio.currentTime释放);\r
  }\r
});

\r

\r
\r

(如果你不熟悉的术语:攻击是它需要的注意时间才能达到它的峰值,在我的示例1秒,'放'是需要有人释放后消逝时间关键,也是1秒这个例子)。

问题是这样的点击声音,你可以前后音符演奏后听到。我做了一些研究:

<一个href=\"http://stackoverflow.com/questions/29378875/how-can-i-avoid-this-clicking-sound-when-i-stop-playing-a-sound\">How我能避免这种点击的声音时,我停止播放声音?

http://modernweb.com/2014/03/31/creating-sound-with-the-web-audio-api-and-oscillators/

和发现它会通过减少声波引起的,所以我应该保持音符若为0 dB播放,提高/根据需要调低音量。然而,它仅适用的专门的Chrome上的只有的,如果我直接设置音量,就像这样: carrier_volume.gain.value = 1 。它不工作,甚至在Chrome中,如果我用 linearRampToValueAtTime()功能。

其他奇怪的事情发生,如果我尝试初始音量直接设置为0。通过使用 carrier_volume.gain.value = 0 在初始化,打出第一个音符将被削减了,但接下来的音符都可以正常播放。

有没有人已经找到了解决这个恼人的点击声音和使用时有什么问题延迟既 gain.value linearRampToValueAtTime()


解决方案

所以,这里的交易 - 一个linearRampToValueAtTime需要的开始时间。你打算说是现在 - 当关键是pssed $ P $ - 但你需要使它明确,通过设置在最关键的是pressed的电流值。此外,你不应该在创建使用linearRamp - 只需直接设定值

如果您设置的初始音量为0,直接(通过.value的),它不应该切出完全,但第一坡道将不会有一个起点 - 因此它仍将是零,直到linearRamp的时间过去了,然后它会跳到1。

试试这个:

  VAR音频=新AudioContext();变种体积= 0;
变种攻击= 1;
VAR发布= 1;变种载体= audio.createOscillator();
carrier.frequency.value = 440.00;
carrier.type =正弦波
carrier.start();变种carrier_volume = audio.createGain();
carrier_volume.gain.linearRampToValueAtTime(体积,0);
carrier.connect(carrier_volume);
carrier_volume.connect(audio.destination);//是否还记得我们打与否;否则键盘重复会混淆我们
VAR播放= FALSE;document.addEventListener(的keydown功能(E){
  如果((e.key code == 81)及和放大器;!打){
    //首先,如果我们有一个释放重叠,取消释放斜坡
    carrier_volume.gain.cancelScheduledValues​​(audio.currentTime);    //现在,请务必将电流值的调度检查点
    carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);    //现在,设置坡道
    carrier_volume.gain.linearRampToValueAtTime(1,audio.currentTime +攻击);
    //注意理想情况下,我们将来自上述检查当前值,并计算出
    //基于它的攻击的长度,以保持该攻击的恒定角度,
    //而非恒定的时间。 (如果我们通过释放是半路上,当我们
    //启动一个新的攻击,攻击应该只需要0.5秒,因为我们在0.5是了。)    打= TRUE;
  }
});document.addEventListener(KEYUP功能(E){
  如果((e.key code == 81)及和放大器;播放){
    //首先,我们正在与攻击重叠的情况下,取消攻击坡道
    carrier_volume.gain.cancelScheduledValues​​(audio.currentTime);    //现在,请务必将电流值的调度检查点
    carrier_volume.gain.setValueAtTime(carrier_volume.gain.value,audio.currentTime);    //现在,设置坡道
    carrier_volume.gain.linearRampToValueAtTime(0,+ audio.currentTime释放);    //注意理想情况下,我们将来自上述检查当前值,并计算出
    //基于它的释放的长度,以保持中释放的恒定角度,
    //而非恒定的时间。 (如果我们通过的攻击是半路上,当我们
    //启动一个新的版本,释放应该只需要0.5秒,因为我们在0.5是了。)
    打= FALSE;
  }
});

I'm working on a simple project to create an instrument, using Web Audio API, and wrote the following snippet (you can press 'Q' to play the note):

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);
  }
});

(If you are not familiar with the terminology: 'attack' is the time it takes to the note to reach it's peak, 1 second in my example, and 'release' is the time it takes to fade away after someone releases the key, also 1 sec on this example).

The problem is this 'clicking' sound you can hear before and after the note plays. I did some research:

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/

and found that it would be caused by cutting the sound wave, so I should keep the note playing at 0 dB and raise / lower the volume as needed. However, it only works specifically on Chrome and only if I'm setting volume directly, like so: carrier_volume.gain.value = 1. It does not work, even in Chrome, if I use the linearRampToValueAtTime() function.

Other strange thing happens if I try to set the initial volume to 0 directly. By using carrier_volume.gain.value = 0 on initialization, the first note played will be cut out, but the next notes will play normally.

Does anyone have found a solution to this annoying clicking noises and what is the delay problem when using both gain.value and linearRampToValueAtTime()?

解决方案

So, here's the deal - a linearRampToValueAtTime needs a START time. You're intending that to be "now" - when the key is pressed - but you need to make it explicit, by setting a current value when the key is pressed. Also, you shouldn't use linearRamp at the creation - just set the value directly.

If you set the initial volume to 0 directly (via .value) it shouldn't cut out entirely, but the first ramp won't have a start point - so it will remain zero until the linearRamp's time passed, and then it will jump to 1.

Try this:

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;
  }
});

这篇关于与网络音频API音量控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆