1. 程式人生 > >音訊採集-AudioUnit

音訊採集-AudioUnit

AudioUnit簡介

  AudioUnit這個名字取得還是比較形象的,它的主體就是一系列的unit,不同unit能夠實現不同的功能,將一個或多個unit新增到AUGraph(Audio Processing Graph)中,並建立unit之間的連線,音訊資料順次通過各個節點即可完成我們最終需求。

   AUGraph連線一組 audio unit 之間的輸入和輸出,構成一張圖,同時也為audio unit 的輸入提供了回撥.

圖2. AudioUnit in iOS

  • Input element 和 Output element 都是 I/O unit 的一部分,可以將它們視為一個獨立的個體,單獨啟動或禁止每一個 Element,預設情況下,Element 1 禁用,Element 0 開啟。
  • 音訊輸入硬體麥克風直接連著 Element 1, Element 1 的 Input scope 對你是不可見的,你首次訪問硬體輸入的音訊資料是位於 Element 1 的 Output scope。
  • 音訊輸出硬體揚聲器直接連著 Element 0,Element 0 的 Output scope 對你是不可見的,資料從 Element 1 的 Output scope 傳遞到 Element 0 的 Input scope。

每一個 Element都有自己的 input scope 和 output scope,當描述 I/O unit 的時候可能會有困惑,相當於這樣描述,你收到收據來自 input element 的 output scope,傳送資料到 output element 的 input scope。
I/O unit 是唯一能夠在 audio processing graph 中啟動和停止音訊流的 audio unit。I/O unit 負責在音訊單元APP中的音訊流。

Audio Processing Graphs 管理 Audio Units

AUGraph 用於構建和管理 audio units 處理鏈,可以利用多個 audio units 和多個回撥函式功能,建立幾乎任何你可以想象的音訊處理解決方案。
AUGraph 增加了執行緒安全,讓你可以即時重新配置處理鏈,例如你可以安全插入一個均衡器,甚至在音訊播放時可以交換混音器輸入的其它回撥函式。實際上,AUGraph 提供了 iOS 中唯一可以在音訊應用程式中執行這種動態重新配置的 API 。
Audio Processing Graph 使用了 AUNode 表示上 graph 中 一個單獨的 audio unit ,當使用 Audio Processing Graphs,通常與包含 audio units 的代理 AUNode 互動,而不是直接使用 audio unit。
當將 graph 組合時,需要配置每一個 audio unit ,並且必須通過 audio unit API 直接與 audio unit 互動,節點單元本身是不可以配置的,通過這種方式,需要使用這兩種 API。
通常情況下,Audio Processing Graphs 通常需要三個任務,將節點新增到 Graph 中,直接配置由節點表示的 audio unit,互連節點。

#Audio Processing Graph 有一個 I/O Unit

每一個 audio processing graph 有一個 I/O unit,無論你是錄音,播放,同步 I/O。Graphs 通過 AUGraphStart 和 AUGraphStop 啟動和停止音訊流,通過函式 AudioOutputUnitStart 和 AudioOutputUnitStop 傳遞開始和停止訊息到 I/O unit。

Audio Processing Graphs 提供執行緒安全

audio processing graph 使用“待辦事項列表”提供執行緒安全,API 的一些函式新增工作單元到稍後執行的更改列表中,在你指定完整的更改好,讓 graph 實現他們。
這是一些 audio processing graph 支援的重配置函式

  • 新增或刪除音訊單元節點(AUGraphAddNode,AUGraphRemoveNode)
  • 新增或刪除節點間的連線(AUGraphConnectNodeInput,AUGraphDisconnectNodeInput)
  • 渲染回撥函式連線到 aduio unit 的輸入匯流排(AUGraphSetNodeInputCallback)

下面看一個重配置 audio processing graph 的例子,構建一個 graph 包含 Multichannel Mixer unit 和 Remote I/O unit,將聲音輸入到混頻器的兩個輸入總線上。從混合器輸出資料到 I/O unit 的 Output element 上。

iOS系統一共提供瞭如下4類unit。

     其中,I/O主要負責和裝置打交道,比如採集和播放;Mixing負責將不同來源的音訊資料進行混合;Effect是對音訊資料進行音效處理;Format Conversion主要是進行格式轉換比如重取樣等。這裡有一個優化的點是音訊格式轉換 Multichannel Mixer 本身就能夠實現格式轉換的功能,輸入和輸出的音訊資料格式可以不同,利用這一點可以節省一個格式轉換unit。

使用AudioUnit進行音訊採集

在直播應用中,我們主要是使用Remote I/O unit來進行採集工作。 在一個AUGraph中只允許有一個I/O unit。Remote I/O需要同時負責採集和播放的功能。當用戶開啟耳返功能時,要將採集到的聲音,處理之後再送回當前節點直接播放,這樣可以將採集和播放的延時控制在50ms以內,主播才察覺不到聲音的延時。

低延時,從採集到播放回環可以到10ms的級別

可以動態變更配置組合

可以直接獲得後臺執行許可權

基本的步驟如下:

第一步:例項化AUGraph.呼叫NewAUGraph建立例項AUGraph。

第二步:建立AUNode.呼叫 AUGraphAddNode建立 AUNode。這個有以上4種類型的AUNode。

第三步:開啟AUGraph。AUGraphOpen(_auGraph)。

第四步:再通過AUGraphNodeInfo獲取節點對應的AudioUnit。

第五步:設定AUUnit 屬性AudioUnitSetProperty。配置每個AudioUnit的屬性。

第六步:設定資料回撥。Render Callback Function,呼叫AudioUnitSetProperty 設定麥克風輸出回撥

第七步:呼叫AUGraphClearConnections 連結。將units 建立連線

第八步:.啟動AUGraph。AUGraphStart

以上過程大家都可以到Apple官方的文件中找到具體的說明和程式碼示例。

在直播錄製中比較關鍵的一步就是Render Callback Function。

AudioUnit每次都是處理一段音訊資料,每次處理完成一段資料的時候,這個回撥函式就會被呼叫一次。在這個回撥函式中,通過AudioUnit的AudioUnitRender方法,可以AUGraph中的某一個節點中獲取到一段處理後的音訊PCM資料。同時,如果需要進行耳返播放,在這個回撥中也需要將取得的音訊資料送入到回撥函式的最後一個引數ioData對應的buffer中。

在設定unit的屬性時,需要注意的是一些公共的屬性。比如音訊格式屬性和MaximumFramesPerSlice。如果音訊格式設定錯誤,往往會出現AUGraph啟動失敗或者聲音異常等問題。比如,使用iOS內建的麥克風或者有線耳機時,裝置支援的取樣率比較高,44.1KHz 能正常工作,我們整條音訊通路上基本上都採用的是44.1KHz。但是當使用藍芽裝置時,一般藍芽裝置無法支援44.1KHz採集和播放,通常都是16KHz甚至更低。此時I/O Unit無法繼續使用之前的配置。需要按照實際支援的取樣率進行配置。

AudioUnit還要求兩個單元銜接處的音訊資料格式必須保持一致,當AUGraph中不同unit支援的格式不同時(比如在支援藍芽裝置或者使用回聲消除模組時,I/O unit要求的格式和其他單元的有可能不同),此時就需要分別設定格式,並通過格式轉換unit或mixer unit對格式進行轉換。

如果MaximumFramesPerSlice設定錯誤,可能會出現聲音異常的情況。 MaximumFramesPerSlice 表示的是每次回撥送入或取出的音訊資料的長度,在AUGraph的所有節點的這個屬性也需要保持一致否則會導致有的unit丟棄資料,而出現聲音異常 。

使用AudioUnit進行音效處理

這裡所謂的音效處理,主要是指對原本的聲音進行一些改變,比如混響效果,變聲效果等。用到手段主要是數字訊號處理提供的一系列時間和頻域的工具,將輸入的PCM資料經過運算後得到變化後的聲音。

4.1 混響效果(reverberation)

我們在音樂廳,劇院,禮堂等比較空曠的室內說話或唱歌時,往往能聽到和平時不一樣的聲音,主要是聲音在牆壁上多次反射後疊加在一起,聽起來就有了混響的效果。在聲音處理中,我們可以人為的將聲音快取起來,延時一定時間後,和原聲音疊加,就能夠模擬出混響的效果。AudioUnit提供了kAudioUnitSubType_Reverb2來實現混響效果的生成。將該unit接入到AUGraph中之後,配置引數即可實現混響的效果。雖然混響原理是比較簡單,但實際上為了模擬自然界中實際的音效,計算過程還是相當複雜的,要模擬出不同的大小的空間,不同材質的牆壁,障礙物的多少,需要輸入比較多的引數來參與運算。iOS的reverb unit提供了7個引數。我們在直播應用中提供了4個不同場景的模擬(錄音棚,演唱會,KTV,小舞臺),主要是通過調整如下引數實現的:

kReverb2Param_DryWetMix混響效果聲的大小與空間大小無關,而只與空間內雜物的多少以及牆壁及物體的材質有關;

kReverb2Param_DecayTimeAt0Hz / kReverb2Param_DecayTimeAtNyquist衰減時間,整個混響的總長度,與空間大小比較相關,越空曠越長。

4.2 變聲效果

變聲效果主要是在頻域上對人的聲音進行一定的處理,我們知道男聲一般比較低沉,女聲比較尖銳,這個主要說的是音調。通過對聲音音調的調整,可以讓低沉的男聲聽上去像尖銳女聲。iOS提供了kAudioUnitSubType_NewTimePitch的unit來實現音調的調整。值得注意的是kAudioUnitSubType_NewTimePitch不是輸入Effect類的,而是屬於FormatConverter類的。通過設定TimePitch unit的kNewTimePitchParam_Pitch屬性即可。

/// pitchShift為具體數值(0表示不變,負數表明調低沉,正數調尖銳)AudioUnitSetParameter(pitchUnit, kNewTimePitchParam_Pitch, kAudioUnitScope_Global, 0, pitchShift, 0);

變男聲,需要強化突出低沉的特點,將音調調低,設定負數引數即可;

變女聲,需要強化突出尖銳的特點,將音調調高,設定正數即可;

機器人音效,機器人的音效是一個組合效果,我們印象中的機器人音效都是老電影中的那種,音調比較高,而且有重音。所以我們採用的是TimePitch unit + Delay unit的方式。Delay unit也是iOS提供的一個將聲音延時疊加的unit,但是比混音要簡單很多,只有單次疊加;

莊嚴巨集大音效,想象一下佛祖之類的聲音,一般都是自帶回聲,而且比較男性化,所以我們選擇的是TimePitch unit + Reverb unit的方式來實現。

這裡推薦一個自己調音效的參考軟體voxal voice changer。大家可以在這個軟體上自己將不同的工具元件組合起來,除錯引數,實時聽到引數對應的結果。當效果滿意後再移植到AudioUnit中。

圖3 voixal voice changer

總結

以上大概介紹了怎麼用AudioUnit來實現iOS直播中的音訊採集,怎麼使用AudioUnit中的音效元件來實現混響和變聲效果。但是AudioUnit的潛力還遠沒有挖掘完,比如還可以將背景音樂播放,混音,回聲消除等其他移動多媒體音訊相關的功能納入到這個框架中。

文章https://www.jianshu.com/p/5d18180c69b8作者講解比較詳細



作者:泥孩兒0107
連結:https://www.jianshu.com/p/dd6f312b0c2b