您可以将一个 OscillatorNode 的频率与另一个同步/绑定吗?

Posted

技术标签:

【中文标题】您可以将一个 OscillatorNode 的频率与另一个同步/绑定吗?【英文标题】:Can you sync/bind one OscillatorNode's frequency with another? 【发布时间】:2017-10-06 05:35:40 【问题描述】:

所以,我正在使用 Web Audio API 创建两个 oscillators:

let audioCtx = new (window.AudioContext || window.webkitAudioContext)();

let o1 = audioCtx.createOscillator();
o1.type = "sawtooth";
o1.frequency.value = 220;
o1.connect(audioCtx.destination);
o1.start();

let o2 = audioCtx.createOscillator();
o2.type = "square";
o2.frequency.value = o1.frequency.value;
o2.connect(audioCtx.destination);
o2.start();

o1.frequency.setValueAtTime(392, audioCtx.currentTime + 3);

如您所见,我使用第一个振荡器的频率来设置第二个振荡器的频率。这是因为我想将这些振荡器的声音有效地结合在一起。我在 3 秒后更改了第一个振荡器的频率,但正如您所听到的,第二个振荡器的频率也没有更新。

那么 Web Audio API 是否提供了一个我可以订阅的事件(例如onfrequencychange)或其他可以让我在第一个振荡器发生变化时自动更新第二个振荡器频率的东西?也许某种绑定/连接方式 OscillatorNode.frequency(这是AudioParam)?

当然,我可以这样做:

o1.frequency.setValueAtTime(392, audioCtx.currentTime + 3);
o2.frequency.setValueAtTime(392, audioCtx.currentTime + 3);

...但是为了这个问题,让我们假设在我更新第一个振荡器的频率时,我的应用程序丢失了对第二个振荡器的引用。

基本上,我试图让两个振荡器表现得像一个。

【问题讨论】:

【参考方案1】:

目前还不清楚为什么您需要两个频率完全相同的振荡器,但可以通过一种方法来实现:

let s = new ConstantSourceNode(audioCtx, offset: 220);
s.connect(o1.frequency);
s.connect(o2.frequency);
s.start();
...
s.offset.setValueAtTime(392, audioCtx.currentTime + 3);

因此s 控制两个振荡器的频率。

而且没有onfrequencychange 事件。如果您可以自动化频率以便它改变每个样本帧,例如如果您使用 linearRampToValueAtTime 或其他自动化会发生什么,那将如何工作?

【讨论】:

谢谢!玩了这个之后,我发现每个振荡器的初始频率也应该设置为零,因为ConstantSourceNode 添加到频率,它不是简单地替换 它。 是的,很抱歉。我总是忘记将.value 添加到与AudioParam 连接的任何内容中。

以上是关于您可以将一个 OscillatorNode 的频率与另一个同步/绑定吗?的主要内容,如果未能解决你的问题,请参考以下文章

数据框 - 将每日数据减少到年度频率

如何获得 FFT 中每个值的频率?

将 X 和 Y 数组转换为频率网格

C++ 中的简单声音

跨平台音频分析库

AEJoy —— 表达式之速度和频率控制JS