AudioKit Tutorial: Getting Started
作者:Colin Eberhardt on November 28, 2016
摘译:kmyhy 来自 csdn 2016-12-08 16:08
iOS devices provide rich multimedia experiences to users with vivid visual, audio and haptic interfaces. Despite the broad range of capabilities on offer, as developers we tend to focus almost exclusively on the visual design of our apps and neglect the audio side of the user experience.
iOS 设备提供了丰富的多媒体体验,比如鲜艳的视觉、声音和可以触控的界面。尽管能够使用各种各样的特性,但作为开发者,我们更多地关注了 App 的视觉设计,而忽略了用户体验的声学效果。
AudioKit is a comprehensive audio framework built by audio designers, programmers and musicians for iOS. Under the hood, AudioKit is a mixture of Swift, Objective-C, C++ and C, interfacing with Apple’s Audio Unit API. All of this fantastic (and quite complex) technology is wrapped up in a super-friendly Swift API that you can use directly within Xcode Playgrounds!
AudioKit 是一个高级音频框架,由声学设计师、程序员和音乐家为 iOS 专门打造。在底层,AudioKit 混合了 Swift、O-C、C++ 和 C,负责和苹果的声频部件 API 打交道。所有神奇的(同时十分复杂的)技术都封装成为极其友好的 Swift API,你甚至可以直接在 Xcode 的 Playground 中使用它。
This AudioKit tutorial doesn’t attempt to teach you all there is to know about AudioKit. Instead, you’ll be taken on a fun and gentle journey through the framework via the history of sound synthesis and computer audio. Along the way, you’ll learn the basic physics of sound, and how early synthesizers such as the Hammond Organ work. You’ll eventually arrive at the modern day where sampling and mixing dominate.
本文无法全面覆盖 AudioKit 的知识点。相反,我们会通过介绍声音合成和计算机声频的历史,来带你进行一次有趣和时尚的 AudioKit 之旅。通过这种方式,你会学到基本的声学物理,了解早期的合成器比如电子琴是如何工作的。最终来到现代,一个由抽样和混声统治的时代。
So pour yourself a coffee, pull up a chair and get ready for the journey!
请给自己来一杯咖啡,拖过一张椅子,开始我们的旅程!
Getting Started(开始)
作者语:该章节的原始内容使用的是AudioKit3.4.0,用的是Playground做案例,我们可以使用最新的AudioKit3.7.0,用Xcode创建的Swift项目做案例。
原始课程使用AudioKit3.4.0,我们使用AudioKit最新版本3.7.0。AudioKit3.7.0 提供了基于Playground的AudioKit文档,下载完AudioKit-master.zip之后解压,在使用官方案例是需要进入控制台输入一下代码编译文件,这个过程比较耗时:
$ cd Frameworks
$ ./build_frameworks.sh
编译完成之后 打开Examples->iOS->HelloWorld项目,将项目中ViewController中override func viewDidLoad() { }中的代码修改为:
AudioKit.output = oscillator1
AudioKit.start()
运行程序,点击播放按钮就可以听见哔哔声。
结束作者语
Create Project Journey. Drag AudioKit.framework to it
创建名称为Journey的项目,将AudioKit.framework拖入项目
T hen select the menu option Product\Build to build the AudioKit framework. There are ~700 files in the framework, so expect this to take a little time!
打开菜单 Product\Build ,编译 AudioKit 框架。这个框架大概有 700 多个文件,编译可能需要一点时间。
Once complete, click on Journey to open your playground. Replace the Xcode-generated code with the following:
编译完成后,点击 Jornery 打开你的 Playground。将 Xcode 的代码替换为:
import AudioKit
let oscillator = AKOscillator()
AudioKit.output = oscillator
AudioKit.start()
oscillator.start()
sleep(10)
Once built, you’ll hear your playground emit 10 seconds of a beeping sound. You can use the Play/Stop button at the bottom left of the playground window within the Debug Area to stop or repeat the playground.
编译时,你会听到大约 10 秒钟的蜂鸣声。你可以点击 Playground 调试窗口左下角的 Play/Stop 按钮停止或运行 Playground。
Oscillators and the Physics of Sound(振荡器和声音物理学)
Humans have been making music from physical objects — through hitting, plucking and strumming them in various ways — for thousands of years. Many of our traditional instruments, such as drums and guitars, have been around for centuries. The first recorded use of an electronic instrument, or at least the first time electronic circuitry was used to make sound, was in 1874 by Elisha Gray who worked in the field of telecommunication. Elisha discovered the oscillator, the most basic of sound synthesizers, which is where your exploration will begins.
人类通过物体制造音乐——通过击打、拖拉或者弹奏等形式——有数千年的历史。我们的许多民族乐器,比如鼓、吉他,已经发明几个世纪了。电子乐器的第一个次使用记录,或者是第一次通过电路发声,是 1874 年 Elisha Gray 创下的,他从事电信行业。Elisha 发明了振荡子,最原始的声音合成装置,你的探索将从这个东西开始。
Right click your playground, select New Playground Page, and create a new page named Oscillators.
右键点击 Playground,选择 New Playground Page,创建一个新的 Playground 文件 Oscillators。
Replace the generated code with the following:
将 Xcode 产生的代码替换为:
import AudioKit
import PlaygroundSupport
// 1. Create an oscillator
let oscillator = AKOscillator()
// 2. Start the AudioKit 'engine'
AudioKit.output = oscillator
AudioKit.start()
// 3. Start the oscillator
oscillator.start()
PlaygroundPage.current.needsIndefiniteExecution = true
The playground will emit a never-ending beep — how, er, lovely. You can press Stop if you like.
这个 Playground 将没完没了地发出哔哔声——呃,有意思。你可以按 Stop 来停止它。
This is much the same as your test playground that you created in the previous step, but this time you are going to dig into the details.
这和前面创建的测试 Playground 差不多,但这次我们将深入讨论细节。
Considering each point in turn:
- This creates an AudioKit oscillator, which subclasses AKNode. Nodes form the main building blocks of your audio pipeline.
- This associates your final output node, which is in your case your only node, with the AudioKit engine. This engine is similar to a physics or game engine: You must start it and -
keep it running in order to execute your audio pipeline. - Finally, this starts the oscillator, which causes it to emit a sound wave.
代码分成了几个步骤:
- 创建一个 AudioKit 振荡子,它是一个 AKNode 子类。节点是构成你的音频序列的主要元素。
- 将 AudioKit 引起和你最终输出的节点联系起来,在这里这个节点是你唯一的节点。音频引擎就像物理引擎或游戏引擎:你必须启动它并让它持续运转,这样你的音频序列才能被执行。
- 最后,打开振荡器,它会发出一条声波。
An oscillator creates a repeating, or periodic signal that continues indefinitely. In this playground, the AKOscillator produces a sine wave. This digital sine wave is processed by AudioKit, which directs the output to your computer’s speakers or headphones, which physically oscillate with the exact same sine wave. This sound is transmitted to your ears by compression waves in the air around you, which is how you can hear that annoyingly sharp sound!
一个振荡子会创建一个重复的、或者周期性的无限延续的信号。在这个 Playground 中,AKOscillator 发出了一个正弦波。这个数字化的正弦波经过 AudioKit 处理,直接输出到你的扬声器或者耳麦,导致真正的振荡子以同样的正弦波进行振荡。声音通过压缩你耳朵周围的空气传播到你耳中,最终你就听到了这个烦人的啸叫声!
There are two parameters that determine what the oscillator sounds like: its amplitude, which is the height of the sine wave and determines how loud it is, and its frequency, which determines the pitch.
有两个参数决定了振荡器发出的声音是什么样子:振幅,它是正弦波的高度并决定声音的大小,以及频率,它决定了音高。
Within your playground, add the following after the line where you created the AKOscillator:
在你的 Playground 中,在创建振荡子之后加入这两句:
oscillator.frequency = 300
oscillator.amplitude = 0.5
Listen closely, and you’ll hear the sound is now half as loud and much lower in pitch. The frequency, measured in hertz (or cycles per second), determines the pitch of the note. The amplitude, with a scale from 0 to 1, gives the volume.
倾听一会,你会发现现在的音量只是刚才的一半,而且音高也比刚才底了。频率单位为赫兹(即每秒周期数),决定了音符的音高。而振幅,范围从 0-1 ,决定了音量。
Elisha Gray was unfortunately beaten to the patent office by Alexander Graham Bell, narrowly missing out on going down in history as the inventor of the telephone. However, his accidental discovery of the oscillator did result in the very first patent for an electronic musical instrument.
Elisha Gray 在专利官司中输给了Alexander Graham Bell,失去了成为电话机发明者的机会。但是,他的偶然发明振荡子却导致第一个电子乐器专利的产生。
Many years later, Léon Theremin invented a slightly strange musical instrument that is still used today. With the eponymous theremin, you can change the frequency of an electronic oscillator by waving your hand above the instrument. If you have no idea what this instrument sound like, I’d recommend listening to Good Vibrations by the Beach Boys; you can’t miss the distinctive theremin sound in that track!
许多年以后, Léon Theremin 发明了一个怪异的电子乐器,至今仍然被使用着。使用特雷门琴,你可以在这个乐器上方挥舞手臂来改变电子振荡器的频率。如果你不知道怎么形容这个乐器发出的声音,我建议你听一听 The Beach Boys 演唱的 Good Vibrations, 这首歌曲中特雷门琴所发出的独特声音令人记忆深刻。
You can simulate this effect by adding the following code to the end of your playground:
你可以在 Playground 的最后加入以下代码模拟这种效果:
oscillator.rampTime = 0.2
oscillator.frequency = 500
AKPlaygroundLoop(every: 0.5) {
oscillator.frequency =
oscillator.frequency == 500 ? 100 : 500
}
The rampTime property allows the oscillator to transition smoothly between property values (e.g. frequency or amplitude). AKPlaygroundLoop is a useful little utility provided by AudioKit for periodically executing code in playgrounds. In this case, you are simply switching the oscillator frequency from 500Hz to 100Hz every 0.5 seconds.
rampTime 属性允许振荡器在属性值之间平滑过渡(比如频率或振幅)。AKPlaygroundLoop 是一个很有用的实用函数,允许周期性地执行 Playground 中的代码。在这里,你简单滴每 0.5 秒就切换一次振荡器的频率,从 500Hz 到 100 Hz。
You just built your very own theremin!
你制造了自己的特雷门琴!
Simple oscillators can create musical notes, but are not terribly pleasing to the ear. There are a number of other factors that give physical instruments, such as the piano, their distinctive sound. In the next few sections you’ll explore how these are constructed.
简单的振荡子可以发出音符,但是并不能令耳朵愉悦。真正的乐器还受许多别的因素的影响,比如钢琴,它的声音很独特。在后面几节中,你会继续探索它们是如何形成的。
Sound Envelops(声音包络)
信号处理中的包络:包络即随机过程的振幅随着时间变化的曲线
When a musical instrument plays a note, the amplitude (or loudness) varies over time, and is different from instrument to instrument. A model that can be used to simulate this effect is an Attack-Decay-Sustain-Release (ADSR) Envelope:
当乐器演奏出一个音符时,振幅(或音量)是会变化的,并且每个乐器都不相同。有一个能够模拟这个效果的模型,叫做 Attack-Decay-Sustain-Release (ADSR) 包络:
The component parts of this envelope are:
- Attack: The time taken to ramp up to full volume
- Decay: The time taken to ramp down to the sustain level
- Sustain: The level maintained after the decay has finished and before release has begun
- Release: The time taken to ramp the volume down to zero
这个封皮由几个部分构成:
- Attack 上升: 在这个阶段声音上行至最大音量。
- Decay 下行: 这个时候声音下滑到 Sustain 水平。
- Sustain 维持: 这个阶段声音会维持在退败终止时的音量,一直到开始松开。
- Release 松开: 这个阶段音量开始下滑到 0。
A piano, where strings are hit with a hammer, has a very brief attack and a rapid decay. A violin can have a longer attack, decay and sustain as the musician continues to bow the string.
一台钢琴,当琴弦被木锤敲击,会发出一个非常短促的上升音然后迅速下降。一把小提琴则会发出比较长的上升、下行和维持,因为演奏时琴弓不会离开琴弦。
One of the first electronic instruments that used an ADSR envelope was the Novachord. This instrument, built in 1939, contained 163 vacuum tubes and over 1,000 custom capacitors, and weighed in at 500 pounds (230 kg). Unfortunately, only one thousand Novachords were made and it was not a commercial success.
电子琴是第一批电子乐器中使用 ADSR 包络的乐器之一。这种乐器发明于 1939 年,由 163 个电子管和 1000 多个特制的电容器构成,重达 500 英磅(230 kg)。但不幸的是,只制造了 1000 台电子琴,它没有获得商业上的成功。
Control-click the top element in your playground, Journey, select New Playground Page and create a new page named ADSR. Replace the generated content with the following:
右键单击 Playground 中的顶层元素,Journey,选择 New Playground Page ,创建一个新的 Playground 叫做 ADSR。编辑文件内容为:
import AudioKit
import PlaygroundSupport
let oscillator = AKOscillator()
This create the oscillator that you are already familiar with. Next add the following code to the end of your playground:
创建了一个振荡器,这个你已经很熟悉了。然后继续加入代码:
let envelope = AKAmplitudeEnvelope(oscillator)
envelope.attackDuration = 0.01
envelope.decayDuration = 0.1
envelope.sustainLevel = 0.1
envelope.releaseDuration = 0.3
This creates an AKAmplitudeEnvelope which defines an ADSR envelope. The duration parameters are specified in seconds and the level is an amplitude with a range of 0 – 1.
这次创建了一个 AKAmplitudeEnvelope 并定义了一个 ADSR 包络。durantion参数用秒为单位指定,level 参数指定的是音量,取值访问 0-1 之间。
AKAmplitudeEnvelope subclasses the AKNode, just like AKOscillator. In the above code, you can see that the oscillator is passed to the envelope’s initializer, connecting the two nodes together.
AKAmplitudeEnvelope 是 AKNode 子类,同 AKOscillator 一样。在上面的代码中,你可以看到,振荡器作为参数被传递给了封皮的构造函数,两个节点连在了一起。
Next add the following:
接下来添加:
AudioKit.output = envelope
AudioKit.start()
oscillator.start()
This starts the AudioKit engine, this time taking the output from the ADSR envelope, and starts the oscillator.
AudioKit 引擎启动,这次将输出改成 ADSR 包络,然后打开振荡器。
In order to hear the effect of the envelope you need to repeatedly start then stop the node. That’s the final piece to add to your playground:
为了听到包络效果,你必须重复播放包络,然后停止包络:
AKPlaygroundLoop(every: 0.5) {
if (envelope.isStarted) {
envelope.stop()
} else {
envelope.start()
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
You will now hear the same note played repeatedly, but this time with a sound envelope that sounds a little bit like a piano.
现在你会听到同一个音符被反复播放,但这次带上了声音封皮效果,听起来有点钢琴的味道了。
The loop executes two times per second, with each iteration either starting or stopping the ADSR. When the loop starts, the rapid attack to full volume will take just 0.01 seconds, followed by a 0.1-second decay to the sustain level. This is held for 0.5 seconds, then released with a final decay of 0.3 seconds.
每秒播放两次,每个循环都以 ADSR 开始和结束。当循环开始后,快速上行到最大音量,这个过程大约 0.01 秒,紧接着是 0.1 秒的下行,到达维持水平。这个过程约 0.5 秒,然后释放 0.3 秒。
Play around with the ADSR values to try and create some other sounds. How about a violin?
修改 ADSR 值,尝试创建其他声音的效果。试试如何模拟小提琴?
The sounds you have explored so far have been based on sine waves produced by AKOscillator. While you can play musical notes with this oscillator, and use an ADSR to soften its sharp tones, you wouldn’t exactly call it musical!
从振荡器发出正弦波开始到现在,已经过去很长时间了。当你用振荡器演奏音符的同时,会使用 ADSR 去让声音更加柔和,但你仍然不能把它称之为真正的音乐!
In the next section you’ll learn how to create a richer sound.
下一节,你会学习如何创建更加丰富的声音。
Additive Sound Synthesis(加法合成)
Each musical instrument has a distinctive sound quality, known as its timbre. This is what makes a piano sound quite different from a violin, even though they’re playing exactly the same note. An important property of timbre is the sound spectrum that an instrument produces; this describes the range of frequencies that combine to produce a single note. Your current playgrounds used oscillators that emit a single frequency, which sounds quite artificial.
每种乐器都有独一无二的音质,并以其音色而得名。这就是为什么钢琴的声音和小提琴的声音截然不同的原因,哪怕它们演奏同一个音符。音色的一个重要属性是乐器所产生的声谱。声谱表示乐器发出一个单音符时所组成的频率范围。你的 Playground 当前所用的振荡器只能发出单一的频率,所以听起来非常假。
You can create a realistic synthesis of an instrument by adding together the output of a bank of oscillators to play a single note. This is known as additive synthesis, and is the subject of your next playground.
通过将一系列振荡器合并在一起作为输出并演奏同一个音符,你能够真实地模拟出一个乐器。这就是“加法合成”。这是你的下一个课题。
Right click your playground, select New Playground Page and create a new page named Additive Synthesis. Replace the generated content with the following:
右键单击 Playground,选择 New Playground Page 创建新的页,叫做 Additive Synthesis,编辑如下代码:
import AudioKit
import PlaygroundSupport
func createAndStartOscillator(frequency: Double) -> AKOscillator {
let oscillator = AKOscillator()
oscillator.frequency = frequency
oscillator.start()
return oscillator
}
For additive synthesis, you need multiple oscillators. createAndStartOscillator is a convenient way to create them.
对于加法合成,你需要使用多个振荡器。createAndStartOscillator 方法用于创建它们。
Next add the following:然后写入:
let frequencies = (1...5).map { $0 * 261.63 }
This uses the Range Operator to create a range with the numbers from 1 to 5. You then map this range by multiplying each entry by 261.53. There is a reason for this magic number: It’s the frequency of middle C on a standard keyboard. The other frequencies are multiples of this value, which are known as harmonics.
这里用了一个 Range 操作来创建一个从 1 到 5 的序列。然后对这个序列进行 map 操作,将每个数字乘以 261.63。这个数字是标注键盘上的中音 C 的音频。将其他数字乘以这个值,这就是“和声”。
Next add the following:然后继续加入:
let oscillators = frequencies.map {
createAndStartOscillator(frequency: $0)
}
This performs a further map operation to create your oscillators.
再次进行一个 map 操作,以创建多个振荡器。
The next step is to combine them together. Add the following:
然后将它们合成在一起。加入:
let mixer = AKMixer()
oscillators.forEach { mixer.connect($0) }
The AKMixer class is another AudioKit node; it takes the output of one or more nodes and combines them together.
AKMixer类是AudioKit的另一种节点.
它将 1 个或多个节点作为输出并将它们合成在一起。
Next add the following:然后加入:
let envelope = AKAmplitudeEnvelope(mixer)
envelope.attackDuration = 0.01
envelope.decayDuration = 0.1
envelope.sustainLevel = 0.1
envelope.releaseDuration = 0.3
AudioKit.output = envelope
AudioKit.start()
AKPlaygroundLoop(every: 0.5) {
if (envelope.isStarted) {
envelope.stop()
} else {
envelope.start()
}
}
The above code should be quite familiar to you; it adds an ADSR to the output of the mixer, provides it to the AudioKit engine, then periodically starts and stops it.
上述代码你已经很熟悉了;它用 mixer 创建了一个 ADSR 封皮,将它提供给 AudioKit 引擎,然后不停地播放和停止它。
To really learn how additive synthesis works, it would be nice if you could play around with the various combinations of these frequencies. The playground live-view is an ideal tool for this!
要真正能够听出加法合成的效果,你可以尝试一下将这些频率进行不同的组合。当你尝试这样做的时候,Playground 的 live-view 是一个不错的工具!
Add the following code:加入以下代码:
class PlaygroundView: AKPlaygroundView {
override func setup() {
addTitle("Harmonics")
oscillators.forEach {
oscillator in
let harmonicSlider = AKPropertySlider(
property: "\(oscillator.frequency) Hz",
value: oscillator.amplitude
) { amplitude in
oscillator.amplitude = amplitude
}
addSubview(harmonicSlider)
}
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = PlaygroundView()
AudioKit has a number of classes that make it easy for you to create interactive playgrounds; you’re using several of them here.
AudioKit 有许多类允许你轻松创建交互式的 Playground;我们在这里也使用了其中几个。
The Playground class subclasses AKPlaygoundView, which constructs a vertical stack of subviews. Within the setup method, you iterate over the oscillators, and create an AKPropertySlider for each. The sliders are initialized with the frequency and amplitude of each oscillator and invoke a callback when you interact with the slider. The trailing closure that provides this callback updates the amplitude of the respective oscillator. This is a very simple method to making your playground interactive.
PlagroundView 类是 AKPlaygroundView 的子类,它由一系列垂直排列的 subview 组成。在 setup 方法中,你遍历每个振荡器,为每个振荡器创建一个 AKPropertySlider。每个 Slider 用每个振荡器的频率和振幅进行初始化批,当遍历到一个 slider 时,都可以为它设置一个回调块,这样当你拖动 slider 时回调块被执行。尾随闭包就是这个回调块,允许你修改每个振荡器的频率。通过这种简单的方式,你可以和 Playground 进行交互。
In order to see the results of the above code, you need to ensure the live view is visible. Click the button with the linked circles icon in the top right corner to show the assistant view. Also ensure that the live view is set to the correct playground output.
为了测试上述代码,你必须开启 live view。点击右上角的双环图标,打开助手窗口。同时将 live view 设置为正确的 playground 文件。
You can alter the amplitude of each slider to change the timbre of your instrument. For a more natural sound quality, I’d suggest a configuration similar to the one pictured above.
你可以通过修改每个 Slider 的振幅来改变乐器的音色。为了获得更加自然的音质,我建议你参照上图来进行设置。
One of the earliest synthesizers to employ additive synthesis was the 200 ton (!) Teleharmonium. The immense size and weight of this instrument were almost certainly responsible for its demise. The more successful Hammond organ used a similar tonewheel technique, albeit in a smaller package, to achieve the same additive synthesis which was part of its distinctive sound. Invented in 1935, the Hammond is still well-known and was a popular instrument in the progressive rock era.
最早的一种采用加法合成的合成器是 200 吨重的电传簧风琴。如此巨大的体量,立即宣告了这种乐器的消亡。结局更好的电子管风琴使用了类似的转速脉冲轮技术,但体积更小,用同样的加法合成实现了独特的声音。电传簧风琴在 1935 年发明,在前卫摇滚时代仍然是一种广为人知的流行乐器。
Tonewheels are physical spinning disks with a number of smooth bumps on their rim, which rotate next to a pickup assembly. The Hammond organ has a whole bank of these tonewheels spinning at various different speeds. The musician uses drawbars to determine the exact mix of tones used to generate a musical note. This rather crude sounding way of creating sound is, strictly speaking, electromechanical rather than electronic!
转速脉冲轮上有旋转的轮盘,轮沿上有许多光滑的隆起,旋转轮盘附近有一个拾波器总成。电传簧风琴由许多这样的转速脉冲轮组成,它们以不同的速度旋转。音乐家通过拉杆来混合这些声音并产生一个音符。这种发声方式真的十分简陋,严格地讲,与其说是电子式的,不如说是机电式的。
There are a number of other techniques that can be used to create a more realistic sound spectrum, including Frequency Modulation (FM) and Pulse Width Modulation (PWM), both of which are available in AudioKit via the AKFMOscillator and AKPWMOscillator classes. I’d certainly encourage you to play around with both of these. Why not swap out the AKOscillator you are using in your current playgrounds for one of these?
要创建更真实的声谱有许多别的技术,比如 调频技术(FM)和脉宽调制技术(PWM),这两种在 AudioKit 中都可以通过 AKFMOscillator 和 AKPWMOscillator 类来实现。无疑,我将鼓励你去尝试这两者。为什么不在你的 Playground 中用这两者将 AKOscillator 替换掉呢?
Polyphony(复音)
The 1970s saw a shift away from modular synthesis, which uses separate oscillators, envelopes and filters, to the use of microprocessors. Rather than using analogue circuitry, sounds were instead synthesized digitally. This resulted in far cheaper and more portable sound synthesizers, with brands such as Yamaha becoming widely used by professionals and amateurs alike.
上个世纪 70 年代,出现了一种偏离模块化合成的理论,它使用单独的振荡器、封皮和过滤器,并使用了微处理器。替代模拟电路,它使用了数字合成的方式发声。它导致了价格极其低廉和便携式合成器的出现,比如著名的雅马哈电子合成器,被专业和业余音乐爱好者广泛使用。
All of your playgrounds so far have been limited a single note at a time. With many instruments, musicians are able to play more than one note simultaneously. These instruments are called polyphonic, whereas those that can only play a single note, just like your examples, are called monophonic.
你所有的 Playground 都被死死限制在只能一次演奏一个音符。如果使用多个乐器,音乐家可以同时演奏多个音符。这种演奏方式就叫做“复音”,相反,如果一次只能演奏一个音符,就像你的 Playground 一样,则叫做“单音”。
In order to create polyphonic sound, you could create multiple oscillators, each playing a different note, and feed them through a mixer node. However, there is a much easier way to create the same effect: using AudioKit’s oscillator banks.
为了制造复音,你需要创建多个振荡器,每个振荡器演奏不同的音符,并通过一个 mixer 节点播放出来。但是,我们还有一种更简单的 方法:使用 AudioKit 的振荡器 bank。
Ctrl-click your playground, select New Playground Page and create a new page named Polyphony. Replace the generated content with the following:
右键单击 Playground,选择 New Playground Page 创建一个新的 page 就叫做 Polyphony。写入以下代码:
import PlaygroundSupport
import AudioKit
let bank = AKOscillatorBank()
AudioKit.output = bank
AudioKit.start()
This simply creates the oscillator bank and sets it as the AudioKit output. If you Command-click the AKOscillatorBank class to navigate to its definition, you will find that it subclasses AKPolyphonicNode. If you follow this to its definition, you’ll find that it subclasses AKNode and adopts the AKPolyphonic protocol.
这里创建了一个振荡器 bank,并将它作为 AudioKit 的输出。如果你按下 Command 键点击 AKOscilatorBank,你将看到它的类定义,你会发现它其实继承了 AKPolyphonicNode。如果你继续深究下去,你会发现它又继承了 AKNode 并采用了AKPolyphonic 协议。
As a result, this oscillator bank is just like any other AudioKit node in that its output can be processed by mixers, envelopes and any other filters and effects. The AKPolyphonic protocol describes how you play notes on this polyphonic node, as you’ll see shortly.
因此,振荡器 bank 和其他 AudioKit 一样,它的输出也能够被 mixer、封皮和其它滤镜和效果所加工。AKPolyphonic 协议描述了你应该如何在这个复音节点上演奏音符,等下你就知道了。
In order to test this oscillator you need a way to play multiple notes in unison. That sounds a bit complicated doesn’t it?
为了测试这个振荡器,你需要设法和谐地播放多个音符。这听起来好复杂?
Add the following to the end of your playground, and ensure the live view is visible:
在 Playground 后面加入下列代码,同时打开 live view:
class PlaygroundView: AKPlaygroundView {
override func setup() {
let keyboard = AKKeyboardView(width: 440, height: 100)
addSubview(keyboard)
}
}
PlaygroundPage.current.liveView = PlaygroundView()
PlaygroundPage.current.needsIndefiniteExecution = true
Once the playground has compiled you’ll see the following:
playground编译之后就如下图所示:
How cool is that? A playground that renders a musical keyboard!
这么酷?一个 Playground 居然画出了一个音乐键盘?
The AKKeyboardView is another AudioKit utility that makes it really easy to ‘play’ with the framework and explore its capabilities. Click on the keys of the keyboard, and you’ll find it doesn’t make a sound.
AKKeyboardView 另外一个 AudioKit 提供的实用工具,它使这个框架真的容易使用和研究里面的功能。点击键盘上的键,你会发现并没有声音发出。
Time for a bit more wiring-up.
还需要做一些工作。
Update setUp of your PlaygroundView to the following:
修改你的 PlayroundView 的 setup 方法为:
let keyboard = AKKeyboardView(width: 440, height: 100)
keyboard.delegate = self
addSubview(keyboard)
This sets the keyboard view’s delegate to the PlaygroundView class. The delegate allows you to respond to these keypresses.
这样就将 keyboard view 的 delegate 属性绑定到 PlaygroundView 类。通过这个委托,你可以对按键进行处理。
Update the class definition accordingly:
修改类的定义:
class PlaygroundView: AKPlaygroundView, AKKeyboardDelegate
This adopts the AKKeyboardDelegate protocol. Finally add the following methods to the class, just after setup:
func noteOn(note: MIDINoteNumber) {
bank.play(noteNumber: note, velocity: 80)
}
func noteOff(note: MIDINoteNumber) {
bank.stop(noteNumber: note)
}
Each time you press a key, the keyboard invokes noteOn of the delegate. The implementation of this method is quite straightforward; it simply invokes play on the oscillator bank. noteOff, invokes the corresponding stop method.
当你按下一个键,键盘会调用 noteON 委托方法。方法的实现很简单,简单地播放了振荡器 bank。noteOff 方法则调用对应的 stop 方法。
Click and slide across the keyboard, and you’ll find it plays a beautiful crescendo. This oscillator bank already has ADSR capabilities built in. As a result, the decay from one note mixes with the attack, release and sustain of the next, creating quite a pleasing sound.
点击并在键盘上滑动,你会发现它演奏出了优美的音阶。振荡器 bank 内置了 ADSR 支持。因此,一个音符的下行会和另一个音符的上升、松开和保持混在了一起,发出了令人愉悦的声音。
You’ll notice that the note supplied by the keyboard is not defined as a frequency. Instead, it uses the MIDINoteNumber type. If you Command-click to view its definition, you’ll see that it is simply an integer:
你可能注意到了,键盘提供的音符不再以频率的方式提供,而是以 MIDINoteNumber 类型提供。如果你按住 Command 键并点击左鼠键,查看它的定义,你会看到它只是一个整型:
public typealias MIDINoteNumber = Int
MIDI stands for Musical Instrument Digital Interface, which is a widely adopted communication format between musical instruments. The note numbers correspond to notes on a standard keyboard. The second parameter in the play method is velocity, another standard MIDI property which details how hard a note is struck. Lower values indicate a softer strike which result in a quieter sound.
MIDI 标准全称是 Musical Instrument Digital Interface(乐器数字接口),它在乐器间进行通讯时广泛使用。 音符数字和标准键盘上的音符一一对应。play 方法的第二个参数 velocity 是另一个 MIDI 属性,用于描述一个音符的敲击力度。值越小表明敲击得越轻,会发出一个更小的声音。
The final step is to set the keyboard to polyphonic mode. Add the following to the end of the setup method:
最后一步是将键盘设置为复音模式。在 setup 方法代码最后中加入:
keyboard.polyphonicMode = true
You will find you can now play multiple notes simultaneously, just like the following:
你会发现现在可以同时演奏多个音符了,只需要这样:
…which is, incidentally, C-major.AudioKit has a long history with its foundations in the early microprocessor era. The project uses Soundpipe, and code from Csound, an MIT project that started in 1985. It’s fascinating to think that audio code you can run in a playground and add to your iPhone apps started life over 30 years ago!
……太不可思议了,C-大调。这个项目使用了 Soundpipe,代码来自于 CSound,一个起始于 1985 年的 MIT 开源项目。令人不可思议的是它可以在 Playground 中运行并添加到你的 App 中,而它竟然拥有超过 30 年的历史了!
Sampling(采样)
The sound synthesis techniques you have explored so far all try to construct realistic sounds from quite basic building blocks: oscillators, filters and mixers. In the early 1970s, the increase in computer processing power and storage gave rise to a completely different approach — sound sampling — where the aim is to create a digital copy of the sound.
你已经学习了半天的声音合成技术了,在这个过程中你尝试用非常原始的方式制造拟真的声音:振荡器、过滤器和混合器。早在上世纪 70 年代,随着计算机处理能力和存储的增长,一种完全不同的方法出现了——声音取样——目标是制造声音的数字复制品。
Sampling is a relatively simple concept and shares the same principles as digital photography. Natural sounds are smooth waveforms; the process of sampling simply records the amplitude of the soundwave at regularly spaced intervals:
采样是相对简单的概念,它和数字影像技术中的原理相同。自然声音是光滑的波形,取样只是在固定的时间间隔内简单地记录声波的震动:
There are two important factors that affect how faithfully a sound is captured:
- Bit depth: Describes the number of discrete amplitude levels a sampler can reproduce.
- Sample rate: Describes how often an amplitude measurement is taken, measured in hertz.
You’ll explore these properties with your next playground.
在取样过程中,有两个因素直接影响了记录的拟真度:
- Bit depth 位深: 表示一个取样器能够复制的离散振幅数。
- Sample rate 取样率: 表示多久进行一次振幅测量,单位是 Hz。
你将用另一个 Playground 来学习这些属性。
Right-click your playground, select New Playground Page and create a new page named Samples. Replace the generated content with the following:
在 Playground 上右键,选择 New Playground Page 并创建新的 page 名为 Samples。编辑如下代码:
import PlaygroundSupportimport AudioKitlet file = try AKAudioFile(readFileName: "climax-disco-part2.wav", baseDir: .resources)let player = try AKAudioPlayer(file: file)player.looping = true
The above loads a sound sample, creates an audio player and sets it to repeatedly loop the sample.
The WAV file for this AudioKit tutorial is available within this zip file. Unzip the contents, then drag the WAV files into the resources folder of your playground:
这段代码载入了一个示例音频,创建了一个声音播放器,并设置它的循环播放这个声音。 这个波表文件放在这个zip文件中。解压缩这个 zip 文件,将 WAV 文件拖到 Playground 的 resources 文件夹中。
Finally, add the following to the end of your playground:
然后,在 Playground 文件最后继续加入:
AudioKit.output = playerAudioKit.start()player.play()PlaygroundPage.current.needsIndefiniteExecution = true
This wires up your audio player to the AudioKit engine and starts it playing. Turn up the volume and enjoy!
这会将你的声频播放器传递给 AudioKit 引擎并开始播放。调大音量,注意听。
This brief sampled loop comprises a wide variety of sounds that would be a real challenge with the basic building blocks of oscillators.
这个简单的例子重复播放各种声音,这些声音很难用基本的振荡器来模拟。
The MP3 sound you’re using has a high bit depth and sample rate, giving it a crisp and clear sound. In order to experiment with these parameters, add the following code to your playground, just after you create your audio player:
正在使用的 MP3 有一个比较高的位深和取样率,能够产生清脆和清晰的声音。为了试验这两个参数,在创建音频播放器之后,加入如下代码:
let bitcrusher = AKBitCrusher(player)bitcrusher.bitDepth = 16bitcrusher.sampleRate = 40000
And update the AudioKit output: 并更新AudioKit输出:
AudioKit.output = bitcrusher
The output of the playground is now very different; it’s clearly the same sample, but it now sounds very tinny.
现在播放的声音就截然不同了:仍然是同一个抽样文件,但声音变得非常尖锐。
AKBitCrusher is an AudioKit effect that simulates a reduction of bit depth and sample rate. As a result, you can produce an audio output that is similar to the early samples produced by computers such as the ZX Spectrum or BBC Micro, which only had a few kilobytes of memory and processors that are millions of times slower than today’s!
AKBitCrusher 是一种 AudioKit 音效,用于模拟低位深低取样率的效果。使用它,你可以制造出这种效果,就像是早期用 ZX Spectrum 或 BBC Micro 进行抽样的声音,这些电脑仅有几 Kb 的内存和处理器,比起如今的电脑来说要慢上几百万倍!
For your final experiment, you’re going to assemble a number of nodes together to create a stereo delay effect. To start, remove the three lines of code that create and configure the bit crusher.
最后的实验,是将许多节点组合在一起,制造出立体声延迟效果。删除代码中用于创建和配置 bitcrusher 的三行代码。然后添加:
Next, add the following:继续添加代码:
let delay = AKDelay(player)delay.time = 0.1delay.dryWetMix = 1
This creates a delay effect of 0.1 seconds using your sample loop as an input. The wet/dry mix value lets you mix the delayed and non-delayed audio, in this case, a value of 1 ensures only the delayed audio is output by this node.
这会用你的抽样文件创建出大约 0.1 秒的延迟效果。干/湿混合值让你将延迟声音和未延迟的声音进行混合,设置为 1 表示只有经过延迟的声音被节点输出。
Next, add the following:然后,加入代码:
let leftPan = AKPanner(player, pan: -1)let rightPan = AKPanner(delay, pan: 1)
The AKPanner node lets you pan audio to the left, to the right, or somewhere in between. The above pans the delayed audio to the left, and the non-delayed to the right.
AKPanner 节点允许你将音频进行移动,左移、右移或者之间的某个地方。上述代码将延迟过的音频左移,为延迟的声音右移。
The final step is to mix the two together, and configure the AudioKit output by adding the following two lines to replace the old line that configured the AudioKit to use bitcrusher:
最后一个步骤是将两者混合在一起,并设置 AudioKit 的输出,用下面的代码替换掉原来设置 AudioKit 的输出为 bitcrusher 的代码:
let mix = AKMixer(leftPan, rightPan)AudioKit.output = mix
This will play the same sound sample, but with a very short delay between the left and right speaker.
这将播放同一个取样文件,但在左右扬声器之间有一个非常短的延迟。
In this AudioKit Tutorial you’ve only scratched the surface of what’s possible with AudioKit. Start exploring — try a moog filter, a pitch shifter, a reverb, or a graphic equalizer to see what effects they have.
在本教程中,你对“使用 AudioKit 能干什么”有了一个大致的理解了。开始探险吧——尝试一下穆格过滤,升降调、混响,或者图像均衡器的效果怎么样?
With a little creativity, you’ll be creating your own custom sounds, electronic instruments or game effects.
只需要一小点创意,你就可以制造出自己的声音、电子乐器或者游戏音效。
You can download the finished playground, although you’ll still have to add the AudioKit library to the workspace as described in the Getting Started section.
你可以下载完成项目。当然,你仍然还需要用“开始”一节中描述的技术将 AudioKit 库添加到工作空间中。
Finally, thanks to Aurelius Prochazka, the AudioKit project lead, for reviewing this article.
最后,感谢 AudioKit 项目的 Lead Aurelius Prochazka,审阅了本文。
If you have any questions or comments on this AudioKit tutorial, feel free to join the discussion below!
如果你有任何疑问或建议,请在下面留言。
Team
Each tutorial at www.raywenderlich.com is created by a team of dedicated developers so that it meets our high quality standards. The team members who worked on this tutorial are:
- AuthorColin Eberhardt
- Tech EditorAlexis Gallagher
- EditorChris Belanger
- Final Pass EditorEssan Parto
- Team LeadAndy Obusek