The mighty stylophone. One of the greatest musical instruments ever created. Used by the likes of David Bowie, Kraftwerk and pretty much no-one else inbetween, I’ll show you how to make this fantastic invention using the Web Audio API.
强大的手提电话。 有史以来最伟大的乐器之一。 由David Bowie,Kraftwerk之类的人使用,几乎没有其他人使用过,我将向您展示如何使用Web Audio API进行这项出色的发明。
Please note: this is highly experimental and only works as intended in browsers that support the Web Audio API.
请注意:这是高度实验性的,仅在支持Web Audio API的浏览器中可正常使用。
Web Audio API (The Web Audio API)
The Web Audio API is a relatively new invention. It’s a high-level way of processing and manipulating sound in a web browser.
Web Audio API是一个相对较新的发明。 这是在Web浏览器中处理和处理声音的高级方法。
Because it’s so new, it’s currently only supported by Chrome and Safari, but Mozilla are working hard on making sure it works in Firefox. As such, this tutorial will only work on said browsers.
由于它太新了,因此目前仅受Chrome和Safari支持,但是Mozilla一直在努力确保它在Firefox中能正常工作。 因此,本教程仅适用于所述浏览器。
We use JavaScript to interact with the API using what is known as a Node Graph. This allows us to control the flow and relationship of different audio components. Imagine strumming an electric guitar. The audio signal would travel down a cable then into an amplifier. If you wanted to change the sound of the guitar, you might take the end of the cable and plug it into an effects unit, like a distortion pedal. You would then connect another cable from the effects unit to the amplifier. When activated, the distortion pedal would alter the sound and pass it on to the amplifier. This idea of chaining things together is the core concept of the Web Audio API.
我们使用JavaScript通过称为“节点图”的API与API进行交互。 这使我们可以控制不同音频组件的流向和关系。 想象一下弹奏电吉他。 音频信号将通过电缆传输,然后进入放大器。 如果要更改吉他的声音,则可以将电缆的一端接好并将其插入效果器(如失真踏板)。 然后,您需要将另一根电缆从效果器连接到放大器。 激活后,失真踏板会改变声音并将其传递给放大器。 将事物链接在一起的想法是Web Audio API的核心概念。
留声机 (The Stylophone)
A very clever man called Brian Jarvis invented the Stylophone in 1967. It consists of a little metal keyboard which is played, as its name suggests, using a stylus. If you’re not familiar with it, have a look at some of the various videos online to get an idea of what we’re making. It’s monophonic, meaning that it can only play one note at a time. This makes it a perfect choice for a first web audio project.
1967年,一个名叫Brian Brianvis的非常聪明的人发明了Stylophone 。它由一个小金属键盘组成,顾名思义,它使用手写笔进行演奏。 如果你不熟悉它,看看一些不同的视频在网上获得,我们正在做什么的想法。 它是单音的,这意味着它一次只能演奏一个音符。 这使其成为第一个Web音频项目的理想选择。
让气氛更热烈 (Make Some Noise)
The Web Audio API uses a “context” similar to the way the <canvas> tag does. In fact you can think of your context as the world in which your musical creation is going to exist. Well, the audio part of it at least. It’s easy to create. You can follow along by opening up your browser’s JavaScript console.
Web Audio API使用类似于<canvas>标记的“上下文”。 实际上,您可以将上下文视为音乐创作将存在的世界。 好吧,至少是音频部分。 创建起来很容易。 您可以打开浏览器JavaScript控制台进行后续操作。
var context = new webkitAudioContext(); // webkit prefixed for now.
Simple.
简单。
波浪 (Waves)
We’re not going to delve into the ins and outs of how sound works, but it’s important to know that sound travels in waves. You’ve probably seen visual representations of these waves if you’ve ever recorded audio onto your computer, or played a song using SoundCloud. Essentially, different sounding waves look different. The most basic of waves, the sine wave, has a nice round sound. A square wave, however, has a much harsher sound. An oscillator generating a square wave at different frequencies is how a stylophone produces different notes. Traditionally, an oscillator is a piece of electronic circuitry that produces a repetitive oscillating frequency; in our case, the square wave. Luckily, the wonderful Web Audio API has us covered. It has its very own built-in method for creating sound waves.
我们不会深入研究声音的工作原理,但重要的是要知道声音会以波浪的形式传播。 如果您曾经将音频录制到计算机上或使用SoundCloud播放过歌曲,则可能已经看到了这些波形的视觉表示。 本质上,不同的声波看起来不同。 最基本的正弦波具有良好的圆形声音。 但是,方波的声音更刺耳。 震荡器如何产生不同的音符,因此振荡器会以不同的频率产生方波。 传统上,振荡器是产生重复振荡频率的电子电路。 在我们的例子中,方波。 幸运的是,我们涵盖了出色的Web Audio API。 它具有自己的内置方法来创建声波。
var oscillator = context.createOscillator();
Great! We now have a working oscillator. Although, by default it produces a sine wave. Let’s change that.
大! 我们现在有一个工作的振荡器。 虽然默认情况下会产生一个正弦波。 让我们改变它。
oscillator.type = oscillator.SQUARE; // Change oscillator to produce a square wave.
There are other values you can change the oscillator to, such as ‘SAWTOOTH’ and ‘TRIANGLE’. You may want to customize your stylophone by using a different type of wave.
您可以将振荡器更改为其他值,例如“ SAWTOOTH”和“ TRIANGLE”。 您可能想通过使用其他类型的wave来定制您的风格电话。
建立连接 (Making a connection)
Using our guitar analogy from earlier, if you were to play an electric guitar without it being connected to an amplifier you wouldn’t hear anything. The exact same thing would happen here. If we were to start our oscillator, we wouldn’t hear anything as we haven’t connected it to our speakers. With the Web Audio API, our speakers are represented by “context.destination”. To connect our oscillator to the speakers we do the following:
使用之前的吉他类比,如果您在未连接放大器的情况下弹奏电吉他,您将听不到任何声音。 完全相同的事情将在这里发生。 如果要启动振荡器,则因为未将其连接到扬声器,所以不会听到任何声音。 使用Web Audio API,我们的发言人以“ context.destination”表示。 要将振荡器连接到扬声器,请执行以下操作:
oscillator.connect(context.destination); // Connect our oscillator to the speakers.
Super. We’ve got a square wave oscillator ready to go! Ready? Let’s start it off.
超。 我们已经准备好一个方波振荡器! 准备? 让我们开始吧。
oscillator.noteOn(0); // Start the oscillator playing after 0 seconds.
Beautiful. Similarly, the oscillator can be stopped by doing
美丽。 同样,可以通过以下方式停止振荡器
oscillator.noteOff(0); // Stop the oscillator after 0 seconds.
You should be aware that these methods have been recently renamed to start() and stop() in the Web Audio API spec, but Safari hasn’t implemented these changes yet, so we’ll keep using noteOn/Off in the meantime.
您应该知道,这些方法最近在Web Audio API规范中已重命名为start()和stop(),但是Safari尚未实现这些更改,因此在此期间我们将继续使用noteOn / Off。
If you find these oscillators a bit loud, don’t worry, you can control the volume of pretty much anything you want with the Web Audio API. All we have to do is add a Gain Node to our chain.
如果您发现这些振荡器有点大声,请放心,您可以使用Web Audio API控制几乎任何您想要的音量。 我们要做的就是向我们的链中添加一个增益节点。
var gainNode = context.createGainNode();gainNode.value = 0.25;oscillator.connect(gainNode); // Connect our oscillator to the Gain Node.
gainNode.connect(context.destination); // Connect the Gain Node to the speakers.
As you can see, we’ve taken a lead from our oscillator, connected it to a Gain Node then taken another lead to the speakers (context.destination).A Gain Node multiplies the volume coming into it and sends that result on to the next node in the chain. So in our case, we’re multiplying it by 0.25, making the volume a quarter of the amplitude it was when it entered the node.
如您所见,我们从振荡器获得一根导线,将其连接到一个增益节点,然后再将另一根导线连接到扬声器(context.destination)。一个增益节点乘以进入的音量并将其结果发送到链中的下一个节点。 因此,在本例中,我们将其乘以0.25,从而使音量成为进入节点时振幅的四分之一。
不同人的不同注解 (Different Notes for Different Folks)
In order for the user to interact with these oscillators, we’re going to need a keyboard. Luckily, I’ve written a little script called Qwerty Hancock, which makes it easy to create an interactive vector keyboard in the browser. It relies on the vector drawing library Raphaël, so after you’ve downloaded them both, include them like so:
为了使用户与这些振荡器进行交互,我们将需要一个键盘。 幸运的是,我编写了一个名为Qwerty Hancock的小脚本,可以轻松在浏览器中创建交互式矢量键盘。 它依赖于矢量绘图库Raphaël ,因此,在下载它们两者之后,请像这样包含它们:
<script src="js/raphael-min.js"></script>
<script src="js/qwerty-hancock.js"></script>
We’ll need an empty element in our html for the keyboard to go, so let’s make one, and give it an id of “keyboard”.
我们需要在html中添加一个空元素以供键盘使用,因此让我们做一个,并为其指定一个ID“键盘”。
<div id="keyboard"><div>
Next, we instantiate the keyboard.
接下来,我们实例化键盘。
// Create keyboard using Qwerty Hancock.
var keyboard = qwertyHancock(
{
id: 'keyboard',
height: 100,
width: 568,
startNote: 'A2',
octaves: 1.7,
whiteKeyColour: '#eee',
blackKeyColour: '#ddd',
blackKeyWidth: 40,
blackKeyHeight: 60,
hoverColour: 'silver',
keyboardLayout: 'en'
}
);
These parameters are fairly self-explanatory, but further documentation is available on the Qwerty Hancock site. Qwerty Hancock also gives us access to two callback functions. The first one is called when the user presses a key on the keyboard, the second when she takes her finger off a key. Let’s put these callbacks with what we’ve got so far so we can see what it all looks like.
这些参数是不言自明的,但是在Qwerty Hancock网站上可以找到更多文档。 Qwerty Hancock还使我们可以访问两个回调函数。 当用户按下键盘上的一个键时,第一个被调用,而当用户将手指从一个键上移开时,第二个被调用。 让我们将这些回调与到目前为止的内容一起放置,以便我们可以看到它们的全部外观。
<!doctype html>
<html>
<body>
<div id="keyboard"><div><script src="js/raphael-min.js"></script>
<script src="js/qwerty-hancock.js"></script><script>
// our script (see below)
</script>
</body>
<html>
// Create Web Audio Context.
var context = new webkitAudioContext();// Create keyboard using Qwerty Hancock.
var keyboard = qwertyHancock(
{
id: 'keyboard',
height: 100,
width: 568,
startNote: 'A2',
octaves: 1.7,
whiteKeyColour: '#eee',
blackKeyColour: '#ddd',
blackKeyWidth: 40,
blackKeyHeight: 60,
hoverColour: 'silver',
keyboardLayout: 'en'
}
);keyboard.keyDown(function (note, frequency) {
// Key on keyboard has been pressed.
});keyboard.keyUp(function (note, frequency) {
// Key on keyboard has been depressed.
});
Creating oscillators using the Web Audio API is cheap, that is to say they don’t take up a lot of memory or processing power to instantiate them. Also, after you call the noteOff() method, they are no longer usable. You can’t just call noteOn() again. This means that we should create an oscillator each time a key is pressed, and then destroy it once the user lets go of it. The best thing to do is stick our code for creating the oscillator into a convenient function, while keeping a reference to it so we can refer to it when we need to stop it later.
使用Web Audio API创建振荡器很便宜,也就是说,它们不需要占用大量内存或实例化它们的处理能力。 同样,在调用noteOff()方法之后,它们将不再可用。 您不能只再次调用noteOn()。 这意味着我们应该在每次按键时创建一个振荡器,然后在用户放开它时销毁它。 最好的办法是将用于创建振荡器的代码粘贴到一个方便的函数中,同时保留对其的引用,以便在以后需要停止它时可以引用它。
var currentOscillator;var playNote = function () {
var oscillator = context.createOscillator(),
gainNode = context.createGainNode();oscillator.type = oscillator.SQUARE; // Set volume of the oscillator.
gainNode.gain.value = 0.3;// Route oscillator through gain node to speakers.
oscillator.connect(gainNode);
gainNode.connect(context.destination);oscillator.noteOn(0);currentOscillator = oscillator;
};var stopNote = function () {
currentOscillator.noteOff(0); // Stop oscillator after 0 seconds.
currentOscillator.disconnect();
}
The best thing to do after you stop an oscillator is to disconnect it. This way it will get picked up by the browser’s garbage collector. Let’s call these functions when a key on the keyboard is pressed and depressed respectively.
停止振荡器后,最好的办法是断开振荡器。 这样,它将被浏览器的垃圾收集器拾取。 让我们分别按下和按下键盘上的一个键时调用这些功能。
keyboard.keyDown(function (note, frequency) {
playNote();
});keyboard.keyUp(function (note, frequency) {
stopNote();
});
OK, refresh your browser and you should now have a working stylophone! Ah. Not quite. All the notes have the same pitch. We need to change the frequency of the oscillator depending on what note is pressed. As you may have noticed, Qwerty Hancock passes back the note and frequency of the key on the keyboard that was pressed. This makes things a lot easier. We can use this to set the frequency of the oscillator. We’ll need to pass the frequency to the playNote function first, then use that value to set the frequency of the oscillator.
OK,刷新您的浏览器,您现在应该可以使用手写笔了! 啊。 不完全的。 所有音符具有相同的音高。 我们需要根据按下的音符来改变振荡器的频率。 您可能已经注意到,Qwerty Hancock会传回所按下键盘上的音符和键的频率。 这使事情变得容易得多。 我们可以使用它来设置振荡器的频率。 我们需要先将频率传递给playNote函数,然后使用该值来设置振荡器的频率。
var playNote = function (frequency) {
var oscillator = context.createOscillator(),
gainNode = context.createGainNode();oscillator.type = oscillator.SQUARE;
oscillator.frequency.value = frequency;// Set volume of the oscillator.
gainNode.gain.value = 0.3;// Route oscillator through gain node to speakers.
oscillator.connect(gainNode);
gainNode.connect(context.destination);oscillator.noteOn(0);currentOscillator = oscillator;
};var stopNote = function () {
currentOscillator.noteOff(0); // Stop oscillator after 0 seconds.
currentOscillator.disconnect();
}keyboard.keyDown(function (note, frequency) {
playNote(frequency);
});keyboard.keyUp(function (note, frequency) {
stopNote();
});
You should now (hopefully) have a working stylophone! Let’s make it look a bit nicer before we show it off.
现在,您应该(希望)有一个工作中的手提电话! 在炫耀之前,让它看起来更好一些。
.stylophone {
margin: auto;
width: 576px;
border: 4px solid black;
}.stylophone h1 {
background-color: black;
color: white;
font-size: 1.2em;
line-height: 1.4em;
margin: 0;
padding: 2px 10px 2px;
}.stylophone .speaker {
height: 154px;
background: -webkit-linear-gradient(black 50%, #462e16 50%);
background-size: 10px 10px;
border-bottom: 4px solid black;
}
Beautiful! Hope you’ve enjoyed this tutorial and are ready to conquer the world with your new skills. If you’re interested, check out some of the more complicated things I’ve made with the Web Audio API.
美丽! 希望您喜欢本教程,并准备以新技能征服世界。 如果您有兴趣,请查看我使用Web Audio API所做的一些更复杂的事情。
翻译自: https://tympanus.net/codrops/2013/06/10/web-audio-stylophone/