iOS音頻採集過程中的音效實現

1、背景

在移動直播中, 聲音是主播和觀衆互動的重要途徑之一, 爲了豐富直播的內容,大家都會想要在聲音上做一些文章, 在採集錄音的基礎上玩一些花樣。

比如演唱類的直播間中, 主播伴隨着背景音樂演唱. 這時有些主播就會希望能夠給自己聲音增加混響的效果, 營造出在舞臺劇場等環境下演唱的氛圍. 再比如有些搞笑類的直播間, 主播會希望給自己的聲音添加變聲的效果, 女變男,男變女或者變成機器人等等. 爲了實現這些需求我們需要對採集的聲音進行處理, 並且爲了讓主播實時聽到這些處理後的效果,以便根據效果進行調整,我們也需要提供低延時的回放,將變化後的聲音播放給主播聽.對聲音處理的方案比較多,這裏介紹一下金山雲直播SDK中所採用的基於iOS提供的AudioUnit的方案。

iOS系統提供了非常豐富的音頻相關的API,涵蓋了從採集,處理到播放等各個環節,並且按照需求的層次進行了分組。
iOS音頻採集過程中的音效實現
圖1. Core Audio Overview
其中,離底層的驅動和硬件最近的就是AudioUnit系列的API,很多其他高層的API,都是對AudioUnit的封裝. 比如AVFoundation、AudioQueue、AVAudioEngine等。

缺點:

涉及到的專有概念比較多,接口複雜

提供C風格的API

優點:

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

可以動態變更配置組合

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

  1. AudioUnit簡介

AudioUnit這個名字取得還是比較形象的,它的主體就是一系列的unit,不同unit能夠實現不同的功能,將一個或多個unit添加到AUGraph(Audio Processing Graph)中,並建立unit之間的連接,音頻數據順次通過各個節點即可完成我們最終需求。
iOS音頻採集過程中的音效實現
圖2. AudioUnit in iOS
iOS系統一共提供瞭如下4類unit。
iOS音頻採集過程中的音效實現
其中,I/O主要負責和設備打交道,比如採集和播放;Mixing負責將不同來源的音頻數據進行混合;Effect是對音頻數據進行音效處理;Format Conversion主要是進行格式轉換比如重採樣等。這裏有一個優化的點是音頻格式轉換 Multichannel Mixer 本身就能夠實現格式轉換的功能,輸入和輸出的音頻數據格式可以不同,利用這一點可以節省一個格式轉換unit。

  1. 使用AudioUnit進行音頻採集

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

  1. 實例化AUGraph,將用到units添加進去;

  2. 配置每個AudioUnit的屬性;

  3. 設置Render Callback Function;

4.將units 建立連接;

5.啓動AUGraph。

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

在直播錄製中比較關鍵的一步就是Render Callback Function。
iOS音頻採集過程中的音效實現
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丟棄數據,而出現聲音異常 。

  1. 使用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中。

iOS音頻採集過程中的音效實現
圖3 voixal voice changer

  1. 總結

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章