个性化阅读
专注于IT技术分析

Web Audio API教程:为什么可以编写代码?

本文概述

Web音频API的第一版草案于2011年出现在W3C中。尽管长期以来一直支持网页中的音频, 但是直到最近才出现从Web浏览器生成音频的正确方法。我个人将其归因于Google Chrome, 因为就Google的利益而言, 浏览器开始成为计算机最重要的部分。你可能还记得, 直到Google Chrome出现, 网络浏览器的领域才开始发生很大变化。如果你这次在网页中使用声音, 那将是一个糟糕的设计决定。但是自从出现网络实验的想法以来, 网络音频又开始变得有意义。如今, Web浏览器是另一种艺术表达工具, Web浏览器中的视频和音频在其中发挥着至关重要的作用。

Web Audio API:为什么可以编写代码?

Web Audio API:为什么可以编写代码?

Web Audio API出于某种目的可能很难使用, 因为它仍在开发中, 但是已经存在许多JavaScript库以简化操作。在这种情况下, 我将向你展示如何使用名为Tone.js的库开始使用Web Audio API。这样, 你只需学习基础知识即可满足大部分浏览器声音需求。

Hello Web Audio API

入门

我们将从不使用库开始。我们的第一个实验将涉及制作三个正弦波。因为这将是一个简单的示例, 所以我们将只创建一个名为hello.html的文件, 这是一个带有少量标记的裸HTML文件。

<!DOCTYPE html>
 <html>
   <head>
<meta charset="utf‐8">
<title> Hello web audio </title> </head>
<body>
   </body>
   <script>
   </script>
</html>

Web Audio API的核心是音频上下文。音频上下文是一个对象, 它将包含与Web音频相关的所有内容。在单个项目中拥有多个音频上下文不被认为是一种好习惯。我们将按照Mozilla的Web Audio API文档给出的建议实例化音频上下文。

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

制作振荡器

实例化音频上下文后, 你已经具有一个音频组件:audioCtx.destination。这就像你的扬声器。要发出声音, 你必须将其连接到audioCtx.destination。现在要产生声音, 让我们创建一个振荡器:

var sine = audioCtx.createOscillator();

很好, 但还不够。它还需要启动并连接到我们的audioCtx.destination:

sine.start();
sine.connect(audioCtx.destination);

通过这四行, 你将拥有一个令人讨厌的网页, 播放正弦声音, 但是现在你了解了模块之间如何相互连接。在以下脚本中, 将有三个正弦形音调连接到输出, 每个音调具有不同的音调。该代码非常不言自明:

//create the context for the web audio
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
//create, tune, start and connect each oscillator sinea, sineb and sinec
var sinea = audioCtx.createOscillator();
sinea.frequency.value = 440;
sinea.type = "sine";
sinea.start();
sinea.connect(audioCtx.destination);
var sineb = audioCtx.createOscillator();
sineb.frequency.value = 523.25;
sineb.type = "sine";
sineb.start();
sineb.connect(audioCtx.destination);
var sinec = audioCtx.createOscillator();
sinec.frequency.value = 698.46;
sinec.type = "sine";
sinec.start();
sinec.connect(audioCtx.destination);

如MDN中所述, 振荡器不仅限于正弦波, 还可以是三角形, 锯齿形, 正方形和定制形状。

网络音频的修补逻辑

接下来, 我们将在Web Audio组件的乐队中添加一个增益模块。这个模块允许我们改变声音的振幅。它类似于音量旋钮。我们已经使用connect函数将振荡器连接到音频输出。我们可以使用相同的连接功能来连接任何音频组件。如果你使用的是Firefox, 并查看了Web音频控制台, 则会看到以下内容:

Web Audio API:为什么可以编写代码?2

如果要更改音量, 我们的补丁应如下所示:

Web Audio API:为什么可以编写代码?3

这意味着振荡器不再连接到音频目标, 而是连接到增益模块, 并且该增益模块连接到目标。总是想像你是用吉他踏板和电缆来做到这一点的。该代码将如下所示:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)
// we create the gain module, named as volume, and connect it to our
var volume = audioCtx.createGain();
volume.connect(audioCtx.destination);
//these sines are the same, exept for the last connect statement.
//Now they are connected to the volume gain module and not to the au
var sinea = audioCtx.createOscillator();
sinea.frequency.value = 440;
sinea.type = "sine";
sinea.start();
sinea.connect(volume);
var sineb = audioCtx.createOscillator();
sineb.frequency.value = 523.25;
sineb.type = "sine";
sineb.start();
sineb.connect(volume);
var sinec = audioCtx.createOscillator();
sinec.frequency.value = 698.46;
sinec.type = "sine";
sinec.start();
sinec.connect(volume);
volume.gain.value=0.2;

你可以在https://github.com/autotel/simple-webaudioapi/找到解决方案。

GainNode是最基本的效果器, 但还有一个延迟器, 一个卷积器, 一个双二次滤波器, 一个立体声声像器, 一个波形整形器等等。你可以从Tone.js之类的库中获取新的效果。

将这些声音补丁之一存储在它们自己的对象中将使你可以根据需要重用它们, 并使用更少的代码来创建更复杂的业务流程。这可能是将来帖子的主题。

使用Tone.js简化事情

Web Audio API:为什么可以编写代码?4

现在, 我们已经简单地了解了香草Web音频模块的工作方式, 让我们看一下令人敬畏的Web音频框架:Tone.js。借助此功能(以及用于用户界面组件的NexusUI), 我们可以非常轻松地构建更有趣的合成器和声音。为了进行试验, 让我们制作一个采样器并对其应用一些用户交互效果, 然后为该采样添加一些简单的控件。

Tone.js采样器

我们可以从创建一个简单的项目结构开始:

simpleSampler
|-- js
    |-- nexusUI.js
    |-- Tone.js
|-- noisecollector_hit4.wav
|-- sampler.html

我们的JavaScript库将位于js目录中。在本演示中, 我们可以使用NoiseCollector的hit4.wav文件, 该文件可以从Freesound.org下载。

Tone.js通过Player对象提供其功能。对象的基本功能是加载样本, 然后循环播放或一次播放。我们的第一步是在sampler.html文件内的” sampler”变量中创建一个播放器对象:

<!doctype html>
<html>
    <head>
        <title> Sampler </title>
        <script type="text/javascript" src="js/nexusUI.js" ></script>
        <script type="text/javascript" src="js/Tone.js" ></script>
        <script>
            var sampler = new Tone.Player("noisecollector_hit4.wav", function() {
                console.log("samples loaded");
            });
        </script>
    </head>
    <body>
    </body>
</html>

请注意, 播放器构造函数的第一个参数是WAV文件的名称, 第二个参数是回调函数。 WAV不是唯一受支持的文件类型, 并且兼容性对Web浏览器的依赖程度大于库。播放器将样本加载到其缓冲区中完成后, 回调函数将运行。

我们还必须将采样器连接到输出。 Tone.js的实现方式是:

sampler.toMaster();

…, 其中sampler是第10行之后的Tone.Player对象。toMaster函数是connect(Tone.Master)的简写。

如果在开发人员控制台打开的情况下打开Web浏览器, 则应看到”已加载样本”消息, 表明播放器已正确创建。此时, 你可能想听示例。为此, 我们需要在网页上添加一个按钮, 并对它进行编程以在按下该按钮后播放示例。我们将在主体中使用NexusUI按钮:

<canvas nx="button"></canvas>

现在, 你应该看到在文档中呈现了一个圆形的按钮。为了对其进行编程以播放示例, 我们添加了一个NexusUI侦听器, 如下所示:

button1.on('*', function(data) {
    console.log("button pressed!");
})

NexusUI的杰出之处在于, 它为每个NexusUI元素创建了一个全局变量。你可以将NexusUI设置为不执行此操作, 而是通过将nx.globalWidgets设置为false来仅在nx.widgets []中使用这些变量。在这里, 我们将只创建几个元素, 因此我们将坚持这一行为。

与jQuery中一样, 我们可以将这些.on事件放置在其中, 第一个参数将是事件名称。在这里, 我们只是将功能分配给对按钮所做的任何操作。不论写为” *”。你可以在NexusUI API中了解有关每个元素的事件的更多信息。要播放示例而不是在按下按钮时记录消息, 我们应该运行采样器的启动功能。

nx.onload = function() {
    button1.on('*', function(data) {
    console.log("button pressed!");
        sampler.start();
    });
}

还要注意, 侦听器位于onload回调中。 NexusUI元素是在画布中绘制的, 直到nx调用onload函数, 你才能引用它们。就像你在jQuery中处理DOM元素一样。

该事件在鼠标按下和释放时触发。如果希望仅在按下时触发它, 则必须评估event.press是否等于1。

这样, 你应该有一个按钮, 可以在每次按下时播放样本。如果将sampler.retrigger设置为true, 则无论你是否在播放样本, 都可以播放该样本。否则, 你必须等到样本完成后才能重新触发它。

应用效果

借助Tone.js, 我们可以轻松创建延迟:

var delay= new Tone.FeedbackDelay("16n", 0.5).toMaster();

第一个参数是延迟时间, 可以用音乐符号表示, 如下所示。第二个是湿声, 表示原始声音和对其产生影响的声音之间的混合。对于延迟, 你通常不希望100%浸湿, 因为延迟对于原始声音而言很有趣, 而且单独浸湿并没有那么吸引人。

下一步是将采样器从主机上拔下, 然后插入延迟器。调整采样器连接到主机的线路:

sampler.connect(delay);

现在再次尝试该按钮, 看看有什么不同。

接下来, 我们将两个转盘添加到文档正文中:

<canvas nx="dial"></canvas>
<canvas nx="dial"></canvas>

然后, 我们使用NexusUIlistener将转盘的值应用于延迟效果:

dial1.on('*', function(data) {
    delay.delayTime.value=data.value;
})
dial2.on('*', function(data) {
    delay.feedback.value=data.value;
})

你可以在每个事件上调整的参数可以在Tone.js文档中找到。为了延迟, 它在这里。现在你可以尝试使用示例, 并使用NexusUI拨盘调整延迟参数。每个NexusUI元素都可以轻松完成此过程, 而不仅限于效果。例如, 还可以尝试添加另一个拨号盘, 并添加其侦听器, 如下所示:

dial3.on('*', function(data) {
    sampler.playbackRate=data.value;
})

你可以在github.com/autotel/simpleSampler中找到这些文件

总结

当我浏览这些API时, 我开始对我想到的所有可能性和想法感到不知所措。音频的这种实现与数字音频的传统实现之间的最大区别不在于音频本身, 而在于上下文。这里没有新的合成方法。相反, 创新之处在于音频和音乐制作正在满足网络技术的要求。

我个人从事电子音乐制作, 并且在这一领域一直存在着实际演奏音乐和仅按播放已录制曲目之间的歧义的悖论。如果你想真正制作现场电子音乐, 则必须能够创建自己的表演工具或”音乐制作机器人”以进行现场即兴演奏。但是, 如果电子音乐的演奏变得只是在预先准备的音乐制作算法中调整参数, 那么听众也可以参与此过程。我一直在进行一些有关将网络和音频集成到众包音乐中的实验, 也许不久以后我们将参加派对, 音乐通过听众的智能手机来自听众。毕竟, 这与我们在洞穴时代可能喜欢的有节奏的果酱没什么不同。

相关:MIDI教程:创建由MIDI硬件控制的基于浏览器的音频应用程序

赞(0)
未经允许不得转载:srcmini » Web Audio API教程:为什么可以编写代码?

评论 抢沙发

评论前必须登录!