AudioUnit是什麼? 它是ios端進行音視訊採集的框架,最全,最屌的!但是缺點就是學習成本大,但是大沒關係,既然您已經看到這裡,想必就是想搞音視訊,這點小的困難應該能克服的。
我這邊就先看怎麼用,用完在講講具體的是什麼東西比較好,這也是我一向學習新東西的習慣和方法,這個世界上的理論很多,真理也很多,我們可以選擇接收和不接受,如果你看看下面的實現結果如果不滿意就可以直接關閉,如果有興趣可以歡迎一直看下去咯!
廢話不多說了,我也沒時間了,直接介紹:
操作流程:
no1: 描述音訊元件: kAudioUnitType_Output。kAudioUnitSubType_RemoteIO/kAudioUnitManufacturerApple 這個知道就行,不需要了解
no2: 使用AudioComponentFindNext : 這個就當作是生產AudioUnit 的工廠
no3 : AudioComponentInstanceNew: 顧名思義,就是Audio Unit 的例項
no4: AudioUnitSetProperty函式為錄製和回放開啟IO
no5: 使用 AudioStreamBasicDescription 結構體描述音訊格式,並使用AudioUnitSetProperty進行設定
no6: 使用 AudioUnitSetProperty 設定音訊錄製與放播的回撥函式
no7: 分配緩衝區
no8: 初始化Audio Unit
no9: 啟動Audio Unit
理論:
Core Audio
數字音訊處理的基礎設施,它是應用程式用來處理音訊的一組軟體框架,所有關於iOS音訊開發的介面都是由Core Audio來提供或者經過它提供的介面來進行封裝的。Apple官方對Core Audio的框架分層圖示如下:
![音視訊系列之iOS: 音訊採集 AudioUnit](https://i.iter01.com/images/f046fa67844a5d068e5d035d64c3bb658b1b74c8cf035b53df488b303517c4fb.png)
![音視訊系列之iOS: 音訊採集 AudioUnit](https://i.iter01.com/images/b841efec4ad35594248d4971a02942abc5259cfcb7fb64efe551392cdcb8c96a.png)
OutputOnlyWithRenderCallback_2x.png
較複雜的構建
輸入端有兩路音訊流,都是通過rendercallback方式抓取資料,其中一路音訊流直接給入到Mixer Unit中,另一路先經過EQ Unit處理後給入到Mixer Unit中,
![音視訊系列之iOS: 音訊採集 AudioUnit](https://i.iter01.com/images/e494b53c489a937f10032c17b9940fa03cab4f1d8909dc81ccdac2c80616f296.png)
OutputOnlyWithRenderCallbackExtended_2x.png
Tips
1. 多執行緒及記憶體管理
儘可能的避免render callback方法內做加鎖及處理耗時較高的操作,這樣可以最大限度的提升實時效能,如果播放資料或者採集資料存在不同執行緒讀寫的情況,必需要加鎖保護,推薦pthread相關lock方法效能比其它鎖要高
音訊的輸入輸出一般都是一個持續的過程,在採集與播放的callback中,應儘量複用buffer及避免多次buffer拷貝,而不是每次回撥都重新申請和釋放,在適當的位置加上@autoreleasepool避免長時間執行記憶體不斷上漲
2. 格式
Core Audio Type中定義了AudioStreamBasicDescription結構,Audio Unit及其它很多音訊API對格式的配置都需要用到它,根據需要將該結構的資訊填充正確,下面是44.1K,stereo,16bit的填充例子
audioDescription.mSampleRate = 44100;
audioDescription.mChannelsPerFrame = 2;
audioDescription.mBitsPerChannel = 16;
audioDescription.mFramesPerPacket = 1;
audioDescription.mFormatID = kAudioFormatLinearPCM;
audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;
audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame ;
蘋果官方建議在整個Audio Processing Graph或者Unit之間儘量以相同的音訊格式流通,儘管Audio Unit的輸入輸出可以不同。另外在Unit之間輸入輸出連線點要保持一致。
3. 音質
在使用過程中,Audio Unit的format是可以動態改變的,但存在一種情況,Unit在銷燬前最好恢復到預設建立時的format,否則在銷燬後再重建Unit後,可能出現播放音質變差(音量變小,聲音粗糙)的情況。
在使用VoiceProcessing I/O Unit過程,遇到在有些iphone上開啟揚聲器後,Unit從Mic採集過來的資料為空或者噪音的情況,從APP STORE中下載了其它的VOIP型別的APP也同樣存在該問題,後來將AudioUnitSubType改成RemoteIO型別後,問題消失,懷疑蘋果在VoiceProcessing Unit上對回聲消除功能的處理上有bug
4. AudioSession
既然使用了音訊特性,就會用到AudioSession,隨著功能需求跟進,與它相關的問題也瞞多的,比如路由管理(聽筒揚聲器、線控耳機、藍芽耳機),打斷處理(interruption、iphone call)等,這裡以Audio Unit為主,就不對它進行詳細描述了,需要注意的是
音訊的路由變更(使用者挺拔耳機,或者程式碼呼叫強制切換)涉及到iOS硬體上輸入和輸出裝置的改變,I/O型別Unit的採集和播放執行緒在切換過程中會阻塞一定時間(200ms左右),如果是語音對講類對實時性要求較高的應用場景要考慮丟包策略。
在APP前臺工作時,iPhone來電或者使用者主動切換到其它音訊類APP後,要及時處理音訊的打斷機制,在恰當的時機停止及恢復Unit的工作,由於iOS平臺對資源的獨佔方式,iPhone在通話等操作時,APP中的Unit是無法初始化或者繼續工作的。
作者:MasonFu
連結:http://www.jianshu.com/p/5d18180c69b8
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。