原文:AudioKit Tutorial: Getting Started 作者:Colin Eberhardt 同時感謝:kmyhy
近來手上有一些音訊相關的開發工作,搜搜基Hub,目前最為強大,效能屌爆,編碼炫酷的開源庫也只有AudioKit了。
Raywenderlich
也能找到相關教程,介於作者是3.0+的教程,很多程式碼都不能跑了,特此整理一趴。 本文不僅是一篇iOS開發教程,更是一篇精彩的科普文。關於程式設計與藝術的結合,聲學物理與音樂的碰撞,盡在此文。推薦所有程式設計師都好好讀一讀它,讓我們的生活除了程式碼,還有藝術,還有音樂。感謝作者Colin Eberhardt。
iOS 裝置提供了豐富的多媒體體驗,比如絢麗的視覺效果、聲音和可觸控的互動介面。儘管能夠使用各種各樣的特性,但作為開發者,我們更多地關注了應用的視覺設計,而忽略了使用者體驗的聲學效果。
AudioKit
是一個高階音訊框架,由聲學設計師、程式設計師和音樂家為 iOS 專門打造。AudioKit底層混合了Swift
、Objective-C
、C++
和C
,負責和蘋果音訊已硬體的Api打交道。所有神奇(同時十分複雜的)技術都封裝成為極其友好的 Swift Api ,你甚至可以直接在Xcode
的Playground
中使用它。
本文無法全面覆蓋 AudioKit 的知識點。相反,我們會通過介紹聲音合成和計算機聲頻的歷史,來帶你進行一次有趣和時尚的 AudioKit 之旅。通過這種方式,你會學到基本的聲學物理,瞭解早期的合成器比如電子琴是如何工作的。最終來到現代,一個大混音時代。
請給自己來一杯咖啡,拖過一張椅子,開始我們的旅程!

開始
原教程的原始內容使用的是 3.4.0 版本,用的是Playground做案例,本文使用最新的 4.3.0 ,用Xcode建立的Swift專案做案例。
港真,教程的第一步並不是特別雞凍的。為了在 Playground 中使用 AudioKit,我們必須提前進行一些準備工作。
我們需要先到AudioKit下原始碼AudioKit-4.3,或者自行clone:
git clone https://github.com/AudioKit/AudioKit.git
複製程式碼
解壓好後用Terminal
進入AudioKit-4.3
資料夾執行編譯命令:
$ cd Frameworks
$ ./build_frameworks.sh
複製程式碼
編譯時間較長(14的頂配編譯的近十分鐘吧),你闊以繼續閱讀,或者擼一把,或者雞一把。
一定要編譯完成,編譯好後進入Playgrounds
檔案,開啟下面的AudioKitPlaygrounds.xcodeproj
,這裡我們就闊以看官方為我們寫好的示例程式碼,提前體驗一把 AudioKit 的強大。體驗完了別忘了紙巾,進入正題開始教程之旅。

新建一個名為Jornery
的Playground
。錄入一下程式碼:
import AudioKitPlaygrounds
import AudioKit
let oscillator = AKOscillator()
AudioKit.output = oscillator
try? AudioKit.start()
oscillator.start()
sleep(10)
複製程式碼
編譯時,你會聽到大約 10 秒鐘的蜂鳴聲。你可以點選 Playground 除錯視窗左下角的 Play/Stop 按鈕停止或執行 Playground。
注意:建議開啟工程的時候就直接
Command + B
編譯一遍,再跑想看的程式碼。如果 Playground 執行出錯,並在 Debug 視窗中出現錯誤,你可以重啟 Xcode。不幸的是,當 Playground 和框架一起使用時,總是容易出現一些小問題,並且無法預知。 另外建議把 Run 方式改為Manually Run
,Automatically Run
太容易故障了。
振盪器和聲學基礎
人類通過物體制造音樂——通過擊打、拖拉或者彈奏等形式——有數千年的歷史。我們的許多民族樂器,比如鼓、吉他,已經發明幾個世紀了。電子樂器的第一個次使用記錄,或者是第一次通過電路發聲,是 1874 年 Elisha Gray 創下的,他從事電信行業。Elisha 發明了振盪器,最原始的聲音合成裝置,你的探索將從這個東西開始。
右鍵點選 Playground,選擇 New Playground Page,建立一個新的 Playground 檔案 Oscillators
。
將 Xcode 產生的程式碼替換為:
import AudioKitPlaygrounds
import AudioKit
// 1. Create an oscillator
let oscillator = AKOscillator()
// 2. Start the AudioKit 'engine'
AudioKit.output = oscillator
try? AudioKit.start()
// 3. Start the oscillator
oscillator.start()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼
這個 Playground 將沒完沒了地發出嗶嗶聲——呃,有意思。你可以按 Stop 來停止它。 這和前面建立的測試 Playground 差不多,但這次我們將深入討論細節。 程式碼分成了幾個步驟:
- 建立一個 AudioKit 振盪器,它是一個 AKNode 子類。節點是構成你的音訊序列的主要元素。
- 將 AudioKit 引擎和你最終輸出的節點關聯起來,在這裡這個節點是你唯一的節點。音訊引擎就像物理引擎或遊戲引擎:你必須啟動它並讓它持續運轉,這樣你的音訊序列才能被執行。
- 最後,開啟振盪器,它會發出一條聲波。
一個振盪器會建立一個重複的、或者週期性的無限延續的訊號。在這個 Playground 中,AKOscillator 發出了一個正弦波。這個數字化的正弦波經過 AudioKit 處理,直接輸出到你的揚聲器或者耳麥,導致真正的振盪器以同樣的正弦波進行振盪。聲音通過壓縮你耳朵周圍的空氣傳播到你耳中,最終你就聽到了這個煩人的嘯叫聲!

有兩個引數決定了振盪器發出的聲音是什麼樣子:amplitude - 振幅,它是正弦波的高度並決定聲音的大小,以及 frequency - 頻率,它決定了音高。 在你的 Playground 中,在建立振盪器之後加入這兩句:
oscillator.frequency = 300
oscillator.amplitude = 0.5
複製程式碼
傾聽一會,你會發現現在的音量只是剛才的一半,而且音高也比剛才低了。頻率單位為赫茲(即每秒週期數),決定了音符的音高。而振幅,範圍從 0-1 ,決定了音量。 Elisha Gray 在專利官司中輸給了Alexander Graham Bell,失去了成為電話機發明者的機會。但是,他的偶然發明振盪器卻導致第一個電子樂器專利的產生。

許多年以後,Léon Theremin 發明了一個怪異的電子樂器,至今仍然被使用著。使用特雷門琴,你可以在這個樂器上方揮舞手臂來改變電子振盪器的頻率。如果你不知道怎麼形容這個樂器發出的聲音,我建議你聽一聽 The Beach Boys 演唱的 Good Vibrations, 這首歌曲中特雷門琴所發出的獨特聲音令人記憶深刻。
你可以在 Playground 的最後加入以下程式碼模擬這種效果:
oscillator.rampDuration = 0.2
oscillator.frequency = 500
import AudioKitUI
AKPlaygroundLoop(every: 0.5) {
oscillator.frequency = (oscillator.frequency == 500 ? 100 : 500)
}
複製程式碼
rampDuration 屬性允許振盪器在屬性值之間平滑過渡(比如頻率或振幅)。AKPlaygroundLoop 是一個很有用的實用函式,允許週期性地執行 Playground 中的程式碼。在這裡,你簡單滴每 0.5 秒就切換一次振盪器的頻率,從 500Hz 到 100 Hz。
你製造了自己的特雷門琴!
簡單的振盪器可以發出音符,但是並不能令耳朵愉悅。真正的樂器還受許多別的因素的影響,比如鋼琴,它的聲音很獨特。在後面幾節中,你會繼續探索它們是如何形成的。 完整程式碼:
import AudioKitPlaygrounds
import AudioKit
let oscillator = AKOscillator()
oscillator.frequency = 300
oscillator.amplitude = 0.5
AudioKit.output = oscillator
try? AudioKit.start()
oscillator.start()
oscillator.rampDuration = 0.2
oscillator.frequency = 500
import AudioKitUI
AKPlaygroundLoop(every: 0.5) {
oscillator.frequency = (oscillator.frequency == 500 ? 100 : 500)
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼
聲音封包
當樂器演奏出一個音符時,振幅(或音量)是會變化的,並且每個樂器都不相同。有一個能夠模擬這個效果的模型,叫做 Attack-Decay-Sustain-Release (ADSR) 封包:

這個封包由幾個部分構成:
- Attack - 上行: 在這個階段聲音上行至最大音量。
- Decay - 下行: 這個時候聲音下滑到 Sustain 水平。
- Sustain - 維持: 這個階段聲音會維持在釋放終止時的音量,一直到開始 Release。
- Release - 釋放: 這個階段音量開始下滑到 0。
一臺鋼琴,當琴絃被木錘敲擊,會發出一個非常短促的上行音然後迅速下降。一把小提琴則會發出比較長的上行、下行和維持,因為演奏時琴弓不會離開琴絃。 電子琴是第一批電子樂器中使用 ADSR 封包的樂器之一。這種樂器發明於 1939 年,由 163 個電子管和 1000 多個特製的電容器構成,重達 500 英磅(230 kg)。但不幸的是,只製造了 1000 臺電子琴,它沒有獲得商業上的成功。

右鍵單擊 Playground 中的頂層元素,Journey,選擇 New Playground Page ,建立一個新的 Playground 叫做ADSR
。編輯檔案內容為:
import AudioKitPlaygrounds
import AudioKit
let oscillator = AKOscillator()
複製程式碼
建立了一個振盪器,這個你已經很熟悉了。然後繼續加入程式碼:
let envelope = AKAmplitudeEnvelope(oscillator)
envelope.attackDuration = 0.01
envelope.decayDuration = 0.1
envelope.sustainLevel = 0.1
envelope.releaseDuration = 0.3
複製程式碼
這次建立了一個 AKAmplitudeEnvelope 並定義了一個 ADSR 封包。durantion 引數用秒為單位指定,level 引數指定的是音量,取值訪問 0-1 之間。 AKAmplitudeEnvelope 是 AKNode 子類,同 AKOscillator 一樣。在上面的程式碼中,你可以看到,振盪器作為引數被傳遞給了封包的建構函式,兩個節點連在了一起。 接著:
AudioKit.output = envelope
try? AudioKit.start()
oscillator.start()
複製程式碼
AudioKit 引擎啟動,這次將輸出改成 ADSR 封包,然後開啟振盪器。

為了聽到封包效果,你必須重複播放封包,然後停止封包:
import AudioKitUI
AKPlaygroundLoop(every: 0.5) {
if (envelope.isStarted) {
envelope.stop()
} else {
envelope.start()
}
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼
現在你會聽到同一個音符被反覆播放,但這次帶上了聲音封包效果,聽起來有點鋼琴的味道了。 每秒播放兩次,每個迴圈都以 ADSR 開始和結束。當迴圈開始後,快速上行到最大音量,這個過程大約 0.01 秒,緊接著是 0.1 秒的下行,到達維持水平。這個過程約 0.5 秒,然後釋放 0.3 秒。 修改 ADSR 值,嘗試建立其他聲音的效果。試試如何模擬小提琴? 從振盪器發出正弦波開始到現在,已經過去很長時間了。當你用振盪器演奏音符的同時,會使用 ADSR 去讓聲音更加柔和,但你仍然不能把它稱之為真正的音樂! 下一節,你會學習如何建立更加豐富的聲音。 完整程式碼:
import AudioKitPlaygrounds
import AudioKit
let oscillator = AKOscillator()
let envelope = AKAmplitudeEnvelope(oscillator)
envelope.attackDuration = 0.01
envelope.decayDuration = 0.1
envelope.sustainLevel = 0.1
envelope.releaseDuration = 0.3
AudioKit.output = envelope
try? AudioKit.start()
oscillator.start()
import AudioKitUI
AKPlaygroundLoop(every: 0.5) {
if (envelope.isStarted) {
envelope.stop()
} else {
envelope.start()
}
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼
聲音疊加合成
每種樂器都有獨一無二的音質,並以其音色而得名。這就是為什麼鋼琴的聲音和小提琴的聲音截然不同的原因,哪怕它們演奏同一個音符。音色的一個重要屬性是樂器所產生的聲譜。聲譜表示樂器發出一個單音符時所組成的頻率範圍。你的 Playground 當前所用的振盪器只能發出單一的頻率,所以聽起來非常假。 通過將一系列振盪器合併在一起作為輸出並演奏同一個音符,你能夠真實地模擬出一個樂器。這就是“疊加合成”。這是你的下一個課題。
右鍵單擊 Playground,選擇 New Playground Page 建立新的頁,叫做Additive Synthesis
,編輯如下程式碼:
import AudioKitPlaygrounds
import AudioKit
func createAndStartOscillator(frequency: Double) -> AKOscillator {
let oscillator = AKOscillator()
oscillator.frequency = frequency
return oscillator
}
複製程式碼
對於疊加合成,你需要使用多個振盪器。createAndStartOscillator 方法用於建立它們。 然後寫入:
let frequencies = (1...5).map { $0 * 261.63 }
複製程式碼
這裡用了一個 Range 操作來建立一個從 1 到 5 的序列。然後對這個序列進行 map 操作,將每個數字乘以 261.63。這個數字是標註鍵盤上的中音 C 的音訊。將其他數字乘以這個值,這就是“和聲”。
然後繼續加入:
let oscillators = frequencies.map {
createAndStartOscillator(frequency: $0)
}
複製程式碼
再次進行一個 map 操作,以建立多個振盪器。 然後將它們合成在一起。加入:
let mixer = AKMixer()
oscillators.forEach { mixer.connect(input: $0) }
複製程式碼
AKMixer 類也是 AudioKit 中的節點; 它將 1 個或多個節點作為輸出並將它們合成在一起。 然後:
let envelope = AKAmplitudeEnvelope(mixer)
envelope.attackDuration = 0.01
envelope.decayDuration = 0.1
envelope.sustainLevel = 0.1
envelope.releaseDuration = 0.3
AudioKit.output = envelope
try? AudioKit.start()
oscillators.map { $0.start() }
import AudioKitUI
AKPlaygroundLoop(every: 0.5) {
if (envelope.isStarted) {
envelope.stop()
} else {
envelope.start()
}
}
複製程式碼
上述程式碼你已經很熟悉了;它用 mixer 建立了一個 ADSR 封包,將它提供給 AudioKit 引擎,然後不停地播放和停止它。 要真正能夠聽出合成的效果,你可以嘗試一下將這些頻率進行不同的組合。當你嘗試這樣做的時候,Playground 的 live-view 是一個不錯的工具! 加入下列程式碼:
class LiveView: AKLiveViewController {
override func viewDidLoad() {
addTitle("Mixer")
oscillators.forEach { oscillator in
let slider = AKSlider(property: "\(oscillator.frequency) Hz", value: oscillator.amplitude) { amplitude in
oscillator.amplitude = amplitude
}
addView(slider)
}
}
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = LiveView()
複製程式碼
AudioKit 有許多類允許你輕鬆建立互動式的 Playground;我們在這裡也使用了其中幾個。 LiveView 類是 AKLiveViewController 的子類,它由一系列垂直排列的 subview 組成。在 viewDidLoad 方法中,你遍歷每個振盪器,為每個振盪器建立一個 AKSlider。每個 Slider 用每個振盪器的頻率和振幅進行初始化,當遍歷到一個 slider 時,都可以為它設定一個回撥塊,這樣當你拖動 slider 時回撥塊被執行。尾隨閉包就是這個回撥塊,允許你修改每個振盪器的頻率。通過這種簡單的方式,你可以和 Playground 進行互動。
為了測試上述程式碼,你必須開啟 live view。點選右上角的雙環圖示,開啟助手視窗。同時將 live view 設定為正確的 playground 檔案。

你可以通過修改每個 Slider 的振幅來改變樂器的音色。為了獲得更加自然的音質,我建議你參照上圖來進行設定。
最早的一種採用疊加合成的合成器是 200 噸重的電傳簧風琴。如此巨大的體量,立即宣告了這種樂器的消亡。結局更好的電子管風琴使用了類似的轉速脈衝輪技術,但體積更小,用同樣的加法合成實現了獨特的聲音。電傳簧風琴在 1935 年發明,在前衛搖滾時代仍然是一種廣為人知的流行樂器。

C3 電傳簧風琴 – 圖片來自 public domain image。
轉速脈衝輪上有旋轉的輪盤,輪沿上有許多光滑的隆起,旋轉輪盤附近有一個拾波器總成。電傳簧風琴由許多這樣的轉速脈衝輪組成,它們以不同的速度旋轉。音樂家通過拉桿來混合這些聲音併產生一個音符。這種發聲方式真的十分簡陋,嚴格地講,與其說是電子式的,不如說是機電式的。
要建立更真實的聲譜有許多別的技術,比如 調頻技術(FM)和脈寬調製技術(PWM),這兩種在 AudioKit 中都可以通過AKFMOscillator
和AKPWMOscillator
類來實現。無疑,我將鼓勵你去嘗試這兩者。為什麼不在你的 Playground 中用這兩者將 AKOscillator 替換掉呢?
複音
上個世紀 70 年代,出現了一種偏離模組化合成的理論,它使用單獨的振盪器、封包和過濾器,並使用了微處理器。替代類比電路,它使用了數字合成的方式發聲。它導致了價格極其低廉和行動式合成器的出現,比如著名的雅馬哈電子合成器,被專業和業餘音樂愛好者廣泛使用。

1983 年的 Yamaha DX7 – 圖片來自public domain image
你所有的 Playground 都被死死限制在只能一次演奏一個音符。如果使用多個樂器,音樂家可以同時演奏多個音符。這種演奏方式就叫做“複音”,相反,如果一次只能演奏一個音符,就像你的 Playground 一樣,則叫做“單音”。 為了製造複音,你需要建立多個振盪器,每個振盪器演奏不同的音符,並通過一個 mixer 節點播放出來。但是,我們還有一種更簡單的 方法:使用 AudioKit 的振盪器 bank。
右鍵單擊 Playground,選擇 New Playground Page 建立一個新的 page 就叫做Polyphony
。寫入以下程式碼:
import AudioKitPlaygrounds
import AudioKit
let bank = AKOscillatorBank()
AudioKit.output = bank
try? AudioKit.start()
複製程式碼
這裡建立了一個振盪器 bank,並將它作為 AudioKit 的輸出。如果你按下 Command 鍵點選 AKOscilatorBank,你將看到它的類定義,你會發現它其實繼承了 AKPolyphonicNode。如果你繼續深究下去,你會發現它又繼承了 AKNode 並採用了AKPolyphonic 協議。
因此,振盪器 bank 和其他 AudioKit 一樣,它的輸出也能夠被 mixer、封包和其它濾鏡和效果所加工。AKPolyphonic 協議描述了你應該如何在這個複音節點上演奏音符,等下你就知道了。
為了測試這個振盪器,你需要設法和諧地播放多個音符。這聽起來好複雜? 在 Playground 後面加入下列程式碼,同時開啟 live view:
import AudioKitUI
class LiveView: AKLiveViewController, AKKeyboardDelegate {
override func viewDidLoad() {
addTitle("Keyboard")
let keyboard = AKKeyboardView(width: 440, height: 100)
keyboard.delegate = self
keyboard.polyphonicMode = true
addView(keyboard)
}
func noteOn(note: MIDINoteNumber) {
bank.play(noteNumber: note, velocity: 80)
}
func noteOff(note: MIDINoteNumber) {
bank.stop(noteNumber: note)
}
}
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = LiveView()
複製程式碼
當 Playground 編譯成功,你會看到這個:

這麼酷?一個 Playground 居然畫出了一個音樂鍵盤? AKKeyboardView 另外一個 AudioKit 提供的實用工具,它使這個框架真的容易使用和研究裡面的功能。 當你按下一個鍵,鍵盤會呼叫 noteON 委託方法。方法的實現很簡單,簡單地播放了振盪器 bank。noteOff 方法則呼叫對應的 stop 方法。 點選並在鍵盤上滑動,你會發現它演奏出了優美的音階。振盪器 bank 內建了 ADSR 支援。因此,一個音符的下行會和另一個音符的上升、鬆開和保持混在了一起,發出了令人愉悅的聲音。
你可能注意到了,鍵盤提供的音符不再以頻率的方式提供,而是以 MIDINoteNumber 型別提供。如果你按住 Command 鍵並點選左鼠鍵,檢視它的定義,你會看到它只是一個整型:
public typealias MIDINoteNumber = Int
複製程式碼
MIDI 標準全稱是 Musical Instrument Digital Interface(樂器數字介面),它在樂器間進行通訊時廣泛使用。 音符數字和標準鍵盤上的音符一一對應。play 方法的第二個引數 velocity 是另一個 MIDI 屬性,用於描述一個音符的敲擊力度。值越小表明敲擊得越輕,會發出一個更小的聲音。
最後一步是將鍵盤設定為複音模式。在 setup 方法程式碼最後中加入:
keyboard.polyphonicMode = true
複製程式碼
你會發現現在可以同時演奏多個音符了,只需要這樣:

……太不可思議了,C-大調。這個專案使用了 Soundpipe,程式碼來自於 CSound,一個起始於 1985 年的 MIT 開源專案。令人不可思議的是它可以在 Playground 中執行並新增到你的 App 中,而它竟然擁有超過 30 年的歷史了!
抽樣
你已經學習了半天的聲音合成技術了,在這個過程中你嘗試用非常原始的方式製造擬真的聲音:振盪器、過濾器和混合器。早在上世紀 70 年代,隨著計算機處理能力和儲存的增長,一種完全不同的方法出現了——聲音取樣——目標是製造聲音的數字複製品。
取樣是相對簡單的概念,它和數字影像技術中的原理相同。自然聲音是光滑的波形,取樣只是在固定的時間間隔內簡單地記錄聲波的震動:

在抽樣過程中,有兩個因素直接影響了記錄的擬真度:
- Bit depth - 位深: 表示一個取樣器能夠複製的離散振幅數。
- Sample rate - 速率: 表示多久進行一次振幅測量,單位是 Hz。
你將用另一個 Playground 來學習這些屬性。
在 Playground 上右鍵,選擇 New Playground Page 並建立新的 page 名為Samples
。編輯如下程式碼:
import AudioKitPlaygrounds
import AudioKit
let file = try AKAudioFile(readFileName: "climax-disco-part2.wav", baseDir: .resources)
let player = try AKAudioPlayer(file: file)
player.looping = true
複製程式碼
這段程式碼載入了一個示例音訊,建立了一個聲音播放器,並設定它的迴圈播放這個聲音。 這個波表檔案放在這個zip檔案中。解壓縮這個 zip 檔案,將 WAV 檔案拖到 Playground 的 resources 資料夾中。
然後,在 Playground 檔案最後繼續加入:
AudioKit.output = player
try? AudioKit.start()
player.play()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼
這會將你的聲頻播放器傳遞給 AudioKit 引擎並開始播放。調大音量,注意聽。 這個簡單的例子重複播放各種聲音,這些聲音很難用基本的振盪器來模擬。 正在使用的音訊有一個比較高的位深和取樣率,能夠產生清脆和清晰的聲音。為了試驗這兩個引數,在建立音訊播放器之後,加入如下程式碼:
let bitcrusher = AKBitCrusher(player)
bitcrusher.bitDepth = 16
bitcrusher.sampleRate = 40000
AudioKit.output = bitcrusher
複製程式碼
現在播放的聲音就截然不同了:仍然是同一個抽樣檔案,但聲音變得非常尖銳。 AKBitCrusher 是一種 AudioKit 音效,用於模擬低位深低取樣率的效果。使用它,你可以製造出這種效果,就像是早期用 ZX Spectrum 或 BBC Micro 進行抽樣的聲音,這些電腦僅有幾 Kb 的記憶體和處理器,比起如今的電腦來說要慢上幾百萬倍!
最後的實驗,是將許多節點組合在一起,製造出立體聲延遲效果。刪除程式碼中用於建立和配置 bitcrusher 的三行程式碼。然後新增:
let delay = AKDelay(player)
delay.time = 0.1
delay.dryWetMix = 1
複製程式碼
這會用你的抽樣檔案建立出大約 0.1 秒的延遲效果。幹/溼混合值讓你將延遲聲音和未延遲的聲音進行混合,設定為 1 表示只有經過延遲的聲音被節點輸出。 然後,加入程式碼:
let leftPan = AKPanner(player, pan: -1)
let rightPan = AKPanner(delay, pan: 1)
複製程式碼
AKPanner 節點允許你將音訊進行移動,左移、右移或者之間的某個地方。上述程式碼將延遲過的音訊左移,為延遲的聲音右移。 最後一個步驟是將兩者混合在一起,並設定 AudioKit 的輸出,用下面的程式碼替換掉原來設定 AudioKit 的輸出為 bitcrusher 的程式碼:
let mix = AKMixer(leftPan, rightPan)
AudioKit.output = mix
複製程式碼
這將播放同一個檔案,但在左右揚聲器之間有一個非常短的延遲。 完整程式碼:
import AudioKitPlaygrounds
import AudioKit
let file = try AKAudioFile(readFileName: "climax-disco-part2.wav", baseDir: .resources)
let player = try AKAudioPlayer(file: file)
player.looping = true
//let bitcrusher = AKBitCrusher(player)
//bitcrusher.bitDepth = 16
//bitcrusher.sampleRate = 40000
//AudioKit.output = bitcrusher
let delay = AKDelay(player)
delay.time = 0.1
delay.dryWetMix = 1
let leftPan = AKPanner(player, pan: -1)
let rightPan = AKPanner(delay, pan: 1)
let mix = AKMixer(leftPan, rightPan)
AudioKit.output = mix
try? AudioKit.start()
player.play()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
複製程式碼

結語
在本教程中,你對“使用 AudioKit 能幹什麼”有了一個大致的理解了。開始探險吧——嘗試一下穆格過濾,升降調、混響,或者影象均衡器的效果怎麼樣? 只需要一小點創意,你就可以製造出自己的聲音、電子樂器或者遊戲音效。
你可以下載最終專案。當然,你仍然還需要像最開始那樣編譯動態庫,並將最終程式碼拖入進去即可。
最後,感謝 AudioKit 專案的Lead,Aurelius Prochazka,審閱了本文。