一胰默、什么是Audio Unit
iOS提供了音頻處理插件鹏漆,支持混合遵倦、均衡节吮、格式轉(zhuǎn)換和實(shí)時輸入/輸出用于錄制脖隶、播放体啰、離線渲染和實(shí)時對話如VoIP(互聯(lián)網(wǎng)協(xié)議語音)龄毡。你可以從iOS應(yīng)用動態(tài)加載和使用它赎瑰,這些強(qiáng)大和靈活的插件叫做Audio Unit薄声。
Audio units通常工作在一個封閉對象的上下文中当船,該對象為audio processing graph,如下圖默辨。在此例中德频,你的app通過一個或多個callback functions發(fā)送audio到第一個audio unit,并對每個audio unit單獨(dú)控制廓奕。I/O輸出unit抱婉,直接連接輸出硬件。
Audio units提供非常有用的個性化功能桌粉,如立體聲像蒸绩,混音,音量控制铃肯,音頻電平測量患亿。
二、Audio unit用在哪些方面
1押逼、低延遲的同時音頻I/O(輸入和輸出)步藕,例如VoIP應(yīng)用
2、響應(yīng)回放合成聲音挑格,例如用于音樂游戲或或合成樂器
3咙冗、使用特定的音頻單元功能,例如回聲消除漂彤,混音雾消,或者音調(diào)均衡
4灾搏、一種處理鏈架構(gòu),讓你靈活的將音頻處理模塊組裝起來立润,這是iOS中唯一提供此功能的音頻API
三狂窑、Audio Units in iOS
iOS根據(jù)功能提供了七種audio unit,分為四類桑腮,如下圖:
3.1 Effect Unit
iOS4提供了一個effect unit泉哈,即iPod Equalizer,與內(nèi)置iPod應(yīng)用程序使用的均衡器相同破讨。要查看該audio unit的iPod應(yīng)用程序用戶界面丛晦,請轉(zhuǎn)至Setting> iPod> EQ。 使用此audio unit時添忘,您必須提供自己的UI采呐。 該audio unit提供一組預(yù)設(shè)均衡曲線,如低音增強(qiáng)器搁骑,流行音樂和口語
3.2 Mixer Units
iOS提供兩個mixer units斧吐。3D Mixer unit是OpenAL構(gòu)建的基礎(chǔ)。在大多數(shù)情況下仲器,如果需要3D Mixer unit的功能煤率,最佳選擇是使用OpenAL,它提供更適合游戲應(yīng)用的更高級API乏冀。
Multichannel Mixer unit可以為任意數(shù)量的單聲道或立體聲流提供混音蝶糯,并帶有立體聲輸出。你可以打開或關(guān)閉每個輸入辆沦,設(shè)置其輸入增益昼捍,并設(shè)置其立體聲平移位置。
3.3 I/O Units
iOS提供三個I/O unit肢扯。Remote I/O是最常用的妒茬。它連接輸入和輸出音頻硬件,并為你提供對各個傳入和傳出音頻樣品值的低延遲訪問蔚晨。它提供硬件音頻格式和應(yīng)用程序音頻格式之間的格式轉(zhuǎn)換乍钻,通過Format Converter unit進(jìn)行格式轉(zhuǎn)換。
Voice-Processing I/O unit通過添加聲學(xué)回聲消除來擴(kuò)展遠(yuǎn)程I/O單元铭腕,以用于VoIP或語音聊天應(yīng)用程序银择。它還提供自動增益校正,語音處理質(zhì)量和靜音累舷。
Generic Output unit不連接到音頻硬件浩考,而是提供將處理鏈的輸出發(fā)送到應(yīng)用程序。通常使用Generic Output unit 進(jìn)行離線音頻處理
3.4 Format Converter Unit
iOS4提供被盈,通常通過I/O單元間接使用
五怀挠、使用兩種方式來獲取audio unit
要在運(yùn)行時查找audio unit析蝴,需要為AudioComponentDescription數(shù)據(jù)結(jié)構(gòu)指定type,subtype绿淋,manufacturer。無論是audio unit還是audio process graph API尝盼。
AudioComponentDescription audioDesc = {0};
audioDesc.componentType = kAudioUnitType_Output;
audioDesc.componentSubType = kAudioUnitSubType_RemoteIO;
audioDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
不同的audio unit的AudioComponentDescription設(shè)置如下圖表:
5.1 使用AudioComponentDescription初始化Audio Unit:
// find component
AudioComponent compoent = AudioComponentFindNext(NULL, &audioDesc);
// create new instance
AudioComponentInstanceNew(compoent, &audioUnit);
5.2 使用AUGraph來初始化audio unit:
// Declare and instantiate an audio processing graph
AUGraph processingGraph;
NewAUGraph (&processingGraph);
// Add an audio unit node to the graph, then instantiate the audio unit
AUNode ioNode;
AUGraphAddNode (processingGraph, &audioDesc, &ioNode);
AUGraphOpen (processingGraph); // indirectly performs audio unit instantiation
// Obtain a reference to the newly-instantiated I/O unit
AudioUnit ioUnit;
AUGraphNodeInfo (processingGraph, ioNode, NULL, &ioUnit);
六吞滞、使用scope和elements來指定audio units的各個部分
Audio unit的各個部分組織成scopes and element,如下圖所示盾沫。當(dāng)調(diào)用函數(shù)去配置和控制audio unit時裁赠,你可以指定scope和element以標(biāo)識函數(shù)的特點(diǎn)目標(biāo)。
scope是audio unit內(nèi)的編程上下文赴精。雖然global scope可能暗示佩捞,但這些上下文從不嵌套。一般是使用一個常量值來自AudioUnitScope枚舉蕾哟。
element是嵌套在audio unit scope中的編程上下文一忱。當(dāng)element是輸入或輸出scope的一部分時,它類似于物理音頻設(shè)備中的信號總線谭确,因此有時成為總線帘营。
global scope適用于整個audio unit,不與任何特定音頻流相關(guān)聯(lián)逐哈。它只有一個元素芬迄,即0。某些屬性昂秃,如每個切片最大幀數(shù)(kAudioUnitProperty_MaximumFramesPerSlice)禀梳,僅適用于global scope
輸入和輸出scopes直接參與通過audio unit移動一個或多個音頻流。正如你所期待的那樣肠骆,音頻輸入scope進(jìn)入從輸出scope離開算途。屬性或參數(shù)可以作為整體應(yīng)用于輸入scope或輸出scope,某些屬性只能應(yīng)用于scope特定的element
七哗戈、AudioUnitSetProperty配置audio unit
AudioUnitProperty是一個鍵值對郊艘。以下是audio unit開發(fā)中常用的一些屬性:
kAudioOutputUnitProperty_EnableIO
:用于在I/O unit上啟用和禁用input or output。默認(rèn)情況輸出已啟用唯咬,輸入已禁用
kAudioUnitProperty_ElementCount
:用于配置mixer unit上輸入elements的數(shù)量
kAudioUnitProperty_MaximumFramesPerSlice
:用于指定audio unit應(yīng)準(zhǔn)備響應(yīng)于渲染調(diào)用而產(chǎn)生的音頻數(shù)據(jù)最大幀數(shù)纱注。不需要為I/O unit設(shè)置該值,因?yàn)樗鼈円杨A(yù)先配置為處理系統(tǒng)請求的任何切片大小胆胰。對于其它audio unit狞贱,你必須將此屬性設(shè)置為4096以處理屏幕睡眠,除非設(shè)備上正在運(yùn)行音頻輸入蜀涨。當(dāng)音頻輸入運(yùn)行時瞎嬉,系統(tǒng)保持切片大小為1024
kAudioUnitProperty_StreamFormat
:用于指定特定音頻單元輸出或輸出總線的音頻流數(shù)據(jù)格式
發(fā)現(xiàn)屬性的可用性蝎毡,訪問其值以及監(jiān)聽其值的更改使用以下函數(shù)
- AudioUnitGetPropertyInfo:發(fā)現(xiàn)屬性是否可用,則為你提供其值的數(shù)據(jù)大小以及是否可以更改該值
- AudioUnitGetProperty氧枣,AudioUnitSetProperty:獲取或設(shè)置屬性的值
- AudioUnitAddPropertyListener沐兵,AudioUnitRemovePropertyListenerWithUserData:安裝或刪除回調(diào)函數(shù)以監(jiān)視屬性值的更改
八、設(shè)置和獲取parameter
audio unit parameter是用戶可調(diào)節(jié)的設(shè)置便监,可在audio unit產(chǎn)生音頻時改變扎谎。實(shí)際上,大多數(shù)parameters是在audio unit正在執(zhí)行處理時烧董,實(shí)時調(diào)整的毁靶。它也是鍵值對的形式。每個parameter的值是32位浮點(diǎn)類型逊移。使用以下函數(shù)來設(shè)置或獲取parameter的值:
- AudioUnitGetParameter
- AudioUnitSetParameter
九预吆、I/O Unit的特征
上圖I/O Unit有兩個element,但它們是獨(dú)立的胳泉,例如拐叉,你可以根據(jù)應(yīng)用程序的需要使用enable I/O屬性(kAudioOutputUnitProperty_EnableIO)來獨(dú)立啟用或禁用某個element。每個element都有Input scope和Output scope胶背。
I/O Unit的element 1
連接音頻的輸入硬件巷嚣,在上圖中由麥克風(fēng)表示。開發(fā)者只能訪問控制Output scope
I/O Unit的element 0
連接音頻的輸出硬件钳吟,在上圖中由揚(yáng)聲器表示廷粒。開發(fā)者只能訪問控制Input scope
input element is element 1(單詞Input的字母“I”,類似1)
output element is element 0 (單詞Output的字母“O”红且,類型0)
十坝茎、Auio Processing Graphs Manage Audio Units
使用數(shù)據(jù)類型AUGraph,用于構(gòu)建和管理audio unit處理鏈暇番。它可以利用多個音頻單元和多個渲染回調(diào)函數(shù)的功能嗤放,允許你創(chuàng)建幾乎任何你能想象的音頻處理解決方案。
AUGraph是線程安全的壁酬,它能夠動態(tài)地重新配置處理鏈次酌。例如,你可以安全的插入均衡器舆乔,甚至可以在播放時交換混音器輸入的不同渲染回調(diào)函數(shù)岳服。事實(shí)上AUGraph是iOS唯一提供的API,用于在音頻應(yīng)用中執(zhí)行此類動態(tài)重新配置希俩。
AUNode來表示graph上下文中的單個audio unit吊宋。當(dāng)使用graph是,你通常與node交互颜武,而不是直接與audio unit交互
當(dāng)你將graph放在一起時璃搜,你必須配置每個audio unit拖吼。為此你必須通過audio unit API直接與audio unit進(jìn)行交互。audio unit node本身是不可配置的
你還可以將AUNode實(shí)例作為復(fù)雜graph中的元素这吻,通過定義node來表示完整audio processing subgraph吊档。在這種情況下,subgraph末尾必須是Generic Output unit(一種不連接到硬件設(shè)備的I/O unit)
總而言之橘原,構(gòu)建audio processing graph需要三個任務(wù):
1籍铁、添加node到graph
2、直接配置nodes表示的audio units
3趾断、互連nodes
AUGraph提供了以下函數(shù)來重新配置:
AUGraphAddNode,AUGraphRemoveNode:添加或移除audio unit node
AUGraphConnectNodeInput吩愧,AUGraphDisconnectNodeInput:添加或移除nodes之間的connections
AUGraphSetNodeInputCallback:connecting一個渲染回調(diào)給audio unit的input bus
十一芋酌、一些設(shè)計(jì)模式
I/O Pass Through
I/O pass-through模式將傳入的音頻直接發(fā)送到硬件輸出,中間沒有處理音頻數(shù)據(jù)雁佳。
I/O Without a Render Callback Function
在Remote I/O unit的elements之間添加一個或多個其它audio unit脐帝,可以構(gòu)建出更有用的應(yīng)用,因?yàn)闆]有回調(diào)函數(shù)糖权,則無法直接操作音頻堵腹,限制了實(shí)用性。
I/O with a Render Callback Function
在Remote I/O unit之間添加一個回調(diào)函數(shù)星澳,可以在傳入音頻到達(dá)輸出硬件之前對其進(jìn)行操作疚顷。比如使用渲染回調(diào)函數(shù)調(diào)整輸出音量,添加顫音禁偎,鈴聲調(diào)制腿堤,回聲或其他效果。通過使用Accelerate框架中提供的傅立葉和卷積函數(shù)如暖,你的可能性是無窮盡的
Output-Only with a Render Callback Function
適用于游戲和音樂合成app笆檀,將渲染回調(diào)函數(shù)直接連接到Remote I/O的Output element的input scope