AUGraph結合RemoteI/O Unit與Mixer Unit

前言

相關文章:
使用VideoToolbox硬編碼H.264
使用VideoToolbox硬解碼H.264
使用AudioToolbox編碼AAC
使用AudioToolbox播放AAC
HLS點播實現(xiàn)(H.264和AAC碼流)
HLS推流的實現(xiàn)(iOS和OS X系統(tǒng))
iOS在線音頻流播放
Audio Unit播放PCM文件
Audio Unit錄音(播放伴奏+耳返)
Audio Unit播放aac/m4a/mp3等文件
Audio Unit和ExtendedAudioFile播放音頻
前文介紹了AudioUnit的錄音/播放、AudioConvert進行音頻轉換、ExtendedAudioFile進行音頻文件的讀/寫,其中AudioUnit的初始化都是通過AudioComponentInstanceNew實現(xiàn),實際工程中更多使用的是AUGraph的方式進行AudioUnit的初始化。
本文嘗試用AUGraph來管理RemoteI/O Unit和Mixer Unit,實現(xiàn)錄音、伴奏播放、人聲和伴奏混合的功能。

基礎結構圖

正文

1、概念介紹

AUGraph連接一組 audio unit 之間的輸入和輸出,構成一張圖,同時也為audio unit 的輸入提供了回調。AUGraph抽象了音頻流的處理過程,子結構可以作為一個AUNode嵌入到更大的結構里面進行處理。AUGraph可以遍歷整個圖的信息,每個節(jié)點都是一個或者多個AUNode,音頻數(shù)據(jù)在點與點之間流通,并且每個圖都有一個輸出節(jié)點。輸出節(jié)點可以用來啟動、停止整個處理過程。

每個AudioUnit都有Input, Output 和 Global 三個域。
input輸入域是音頻流進入unit的入口,output輸出域是音頻流離開unit的出口,global全局域則代表整個unit。
輸入域和輸出域都有若干個bus/element,比如說mixer unit有多個輸入bus,只有一個輸出bus;而splitter unit則有一個輸入bus,有多個輸出的bus。

注意的是,bus和channel不是一個東西,一個是音頻流,一個是音頻流的格式。
比如說Remote I/O Unit的輸入域的inputBus是來自麥克風的音頻流,其音頻格式是雙聲道。

2、具體流程

  • 1、初始化文件流和AVAudioSession,分配buffer;
  • 2、新建AUGraph,并添加兩個AUNode,一個是RemoteI/O Unit的節(jié)點,一個是Mixer Unit的節(jié)點。
    添加AUNode的節(jié)點有兩個步驟,先通過AUGraphAddNode添加節(jié)點,再通過AUGraphNodeInfo獲取節(jié)點對應的AudioUnit。
  • 3、建立兩個AUNode的聯(lián)系,AUGraphConnectNodeInput通過把Mixer Unit的outputBus的輸出作為RemoteI/O Unit的outputBus的輸入;
    (這里需要注意,不是RemoteI/O的inputBus 的輸入,因為RemoteI/O Unit的inputBus的輸入是麥克風)
    同時設置好RemoteI/O Unit的輸入和輸出格式、Record的回調函數(shù);
  • 4、調用AUGraphInitialize初始化AUGraph,然后通過AUGraphStart開始整個AUGraph;
    在AUGraph開啟后,麥克風收到錄制數(shù)據(jù)后調用kAudioOutputUnitProperty_SetInputCallback的回調,把麥克風的數(shù)據(jù)回調給APP;
    Mixer Unit還會通過之前kAudioUnitProperty_SetRenderCallback設置好的回調,要求APP填充兩個inputBus的輸入;
    在Mixer Unit處理好數(shù)據(jù)之后,會按照之前AUGraphConnectNodeInput設置的,把數(shù)據(jù)發(fā)送給Remote I/O Unit;
    Remote I/O Unit再把數(shù)據(jù)發(fā)送給揚聲器。

3、音頻流解析

如下,是整個demo的音頻流向:



伴奏文件被讀取到內存,再被送到MixUnit的inputBus0;
麥克風錄取到音頻數(shù)據(jù),送到Remote I/O Unit的inputBus,存到內存中,再被送到MixUnit的inputBus1;
MixUnit混合兩個inputBus的數(shù)據(jù),通過outputBus輸出到Remote I/O Unit的outputBus中;
Remote I/O Unit再把outputBus的數(shù)據(jù)發(fā)送個揚聲器。

遇到的問題

1、AUGraphNodeInfo無法初始化AudioUnit

實際運行時,報錯是AudioUnitSetProperty方法,返回了-50的錯誤碼。
檢查錯誤碼,是AudioUnitSetProperty的audio unit參數(shù)為空。
往上回溯,定位到AUGraphNodeInfo沒正確初始化傳入的audio unit參數(shù),導致audio unit為空,并且當時沒有報錯,直到AudioUnitSetProperty時才報錯。

經(jīng)過仔細檢查,發(fā)現(xiàn)是AUGraphOpen方法被遺漏。
必須先打開AUGraph,才進行獲取AudioUnit的操作。

2、AUGraphSetNodeInputCallback給RemoteI/O Unit設置回調無效

如下,給RemoteI/O Unit設置回調可以用AudioUnitSetProperty方法修改kAudioOutputUnitProperty_SetInputCallback設置回調,但嘗試用AUGraphSetNodeInputCallback對RemoteI/O Unit節(jié)點添加回調的時候,發(fā)現(xiàn)沒法正常調用回調函數(shù)。

    AURenderCallbackStruct recordCallback;
    recordCallback.inputProc = RecordCallback;
    recordCallback.inputProcRefCon = (__bridge void *)self;
    
//    CheckError(AUGraphSetNodeInputCallback(auGraph, outputNode, INPUT_BUS, &recordCallback), "record callback set fail");  // 這個不行,因為scope不一致
    CheckError(AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Output, INPUT_BUS, &recordCallback, sizeof(recordCallback)), "set property fail");

AUGraphSetNodeInputCallback 默認是inputScope,如果在input bus的inputScope修改屬性,會造成異?,F(xiàn)象;

3、kAudioOutputUnitProperty_SetInputCallback 和 kAudioUnitProperty_SetRenderCallback 混淆

  • kAudioUnitProperty_SetRenderCallback 是audio unit需要數(shù)據(jù),向Host請求數(shù)據(jù);
  • kAudioOutputUnitProperty_SetInputCallback是audio unit通知Host數(shù)據(jù)已經(jīng)就緒,可以通過AudioUnitRender拉取數(shù)據(jù);

AudioUnitRender的解釋是:Initiates a rendering cycle for an audio unit.
下圖闡釋了AudioUnit是如何通過AudioUnitRender去Pull音頻流數(shù)據(jù)

4、AUGraphConnectNodeInput的BUS參數(shù)設置錯誤

AUGraphConnectNodeInput(auGraph, mixNode, OUTPUT_BUS, outputNode, OUTPUT_BUS),從字面看是把mixNode的輸出作為outputNode的輸入。
但是在bus的參數(shù)設置上,為什么Remote I/O Unit的bus不是inputBus?
因為Remote I/O Unit有輸入域有兩個Bus,inputBus對應的是麥克風的輸入,outputBus對應的是app發(fā)送給Remote I/O Unit的數(shù)據(jù)。
這里Mixer Unit是把人聲和伴奏混合后,輸出給Remote I/O Unit,相當于app發(fā)送數(shù)據(jù)給Remote I/O Unit,所以這里應該填outputBus。

總結

demo中仍然存在問題,因為兩個unit結構混亂:
麥克風=>I/O Unit=>APP=>MixUnit
文件=>APP=>MixUnit
然后再是MixUnit=>I/O Unit=>揚聲器
其中,I/O Unit既指向MixUnit,同時MixUnit又指向I/O Unit。
更好的實現(xiàn)方案,用一個Unit來實現(xiàn)錄音,再用另外一個Unit進行播放,形成 RecordUnit=>MixUnit=>PlayUnit這樣的結構會更加漂亮。
這個設想就交由你去實現(xiàn)了!
demo的代碼點擊這里書寫不易,不如來個喜歡支持下↓↓

附錄

Core Audio Tips
Audio Unit Properties Reference PDF
Audio Unit Hosting Guide for iOS

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容

  • 本例需求:將Mic采集的PCM轉成AAC,可得到兩種不同數(shù)據(jù),本例采用AudioQueue/AudioUnit兩種...
    小東邪啊閱讀 18,963評論 67 54
  • 一、Audio Unit綜述1.1、Audio Unit 概念點1.2、 AuidoUnit類型二、構建Audio...
    _羊羽_閱讀 6,965評論 3 17
  • 前言 相關文章:使用VideoToolbox硬編碼H.264使用VideoToolbox硬解碼H.264使用Aud...
    落影l(fā)oyinglin閱讀 13,370評論 21 39
  • 國人一直都在改變世人看法,提高全民素質,但意識不該談何容易。 環(huán)保在中國,剛剛起步。實行困難重重的,一個塑料袋引發(fā)...
    19號淡然閱讀 411評論 0 0
  • 俺覺得有些同學,是青翠的故事 記憶泛黃了,不影響 他們是樹,是草,是花,是鳥 是一片茂密森林 他們隨風搖動百家姓中...
    喬橋閱讀 319評論 3 4