用 JavaScript 构建合成器 什么是合成器? 构建限制

2025-05-27

使用 JavaScript 构建合成器

什么是合成器?

构建它

限制

我一直在研究WebAudio API。你可以用它来生成声音。所以我用它做了一个合成器应用,作为周末项目。这能有多难?

瑞克邀请莫蒂进入一个标有“WebAudio API”的门户,说道:“我们走吧。进去再出来。二十分钟的冒险。”

这个 API 的构建方式就像一个真正的模块化合成器。这对我来说是个惊喜。我之前一直在尝试Pure Data ,所以大致了解它的工作原理。现在我可以把这些知识运用到 JavaScript 中了。首先,我们来理清一下基础知识。

什么是合成器?

一切都始于一个振荡器 (Oscillator )。这是一种电子装置,它以特定的频率发射波形,从而产生声音。你可以把它想象成一个物理设备(因为模块化合成器就是这样的),或者按照 WebAudio API 的叫法——一个节点。该节点有一个输入和一个输出。输入是波形和频率,输出是声音信号。现在,该信号可以连接到其他设备。实际的合成器会将扬声器作为链路中的最后一个设备,但 WebAudio API 放弃了这一点。最后一个节点只是充当扬声器。

振荡器

我的振荡器非常简单。它支持四种基本波形(正弦波、方波、三角波、锯齿波)和一个频率。不同的波形会产生不同类型的音调:正弦波听起来温暖柔和,而锯齿波则更具工业感和刺耳感。频率决定了音高。440Hz 对应于音乐会音高 A。维基百科上有一个包含所有频率的完整表格

攻击、衰减、维持、释放

接下来,我需要一些控制键来进一步调整声音信号的特性。让它拥有更宽广的音调,或者弹拨感,或者增强音色。在真正的合成器上,这些控制键被称为包络线 (Envelope )、轮廓线 (Contour) 或 ADSR。它们是 Attack、Decay、Sustain 和 Release 的缩写。

图表的曲线沿 x 轴上升表示攻击,下降表示衰减,稳定表示维持,最后归零表示释放。

这是一个成熟的系统,通过操纵信号音量(y轴)随时间(x轴)的变化,赋予相对简单的信号丰富的特性。以下四个关键词分别代表一个特定的方面:

  • 起音:音调开始时音量的增强
  • 衰减:开始后音量立即下降,就像拨动吉他一样
  • 延音:只要信号到来,音符就会保持在特定的音量
  • 释放:信号消失后的音符音量,类似霍尔效应

还有一些更具体的包络,还有很多效果和方法来进一步操纵声音,但我可以用这四个基本控制来做得很好。

构建它

以下是该逻辑工作原理的粗略描述。

详细说明合成器编程的结构图。keyDown 事件触发振荡器、Attack、Decay 和 Sustain 阶段,keyUp 事件触发释放阶段并终止信号。

每个音频节点都有相应的配置选项。按下一个键会触发振荡器的声音生成,并执行后续的“Attack”(起音)、“Decay”(衰减)和“Sustain”(延音)步骤。松开一个键会触发“Release”(释放)步骤,然后终止音符。

按下某个键的实际含义取决于输入设备。理想情况下,我希望有类似这样的功能<input type="piano">,但实际上,我必须自己实现鼠标、触摸和键盘事件的处理程序。

所以我最终设计了一个功能性合成器。此外,我还添加了 PWA 常用的优雅元素,比如一个 logo,并将其命名为 JSSynth:

JSSynth 徽标

太棒了,完成了!

限制

Chrome 对同时播放的振荡器数量有所限制。在 Windows 和 macOS 上,这个数字似乎是 50,但在 Android 上则要低得多。Firefox 则完全没有这样的限制。

Safari尚未包含 AudioContext(但它在版本 14 的 TP 中),因此在它们向第三方浏览器引擎开放其操作系统之前,此合成器无法在 macOS 的 Safari 或任何 iOS 浏览器上运行。

我感觉释放键机制有点bug,因为疯狂按下按键时按键容易卡住。在我懒得修复这个问题之前,只有重新加载才能解决问题。

除此之外,我觉得这个项目还不错,而且很有趣。这是应用程序代码。我们开始吧!

文章来源:https://dev.to/iamschulz/building-a-synthesizer-in-javascript-l3l
PREV
您的投资组合是如何构建的?
NEXT
我发现的一些很酷的 VSCode 扩展