iOS錄音和播放的那些事兒:幾個奇葩的需求

來源:互聯網
上載者:User

iOS錄音和播放的那些事兒:幾個奇葩的需求

最近在做的項目中,需要在iPhone上接上帶麥耳機(蘋果叫Headset,不帶麥耳機叫Headphone),然後實現同步錄音和播放。這個功能實現之後,需要改變錄音、播放的輸入源。

對於實現同步錄音和播放功能,肯定就要使用到底層的介面,用AVAudioRecorder/AVAudioPlayer是無法實現的。

我研究了iOS聲音處理的知識之後,發現自己實現太過麻煩,需要用到至少包括AudioQueue/AudioBuffer等等,然後還有各種複雜的C Struct、回呼函數、回調處理等等,非常麻煩,一不小心就出錯,很難找到出錯的地方。於是我在網上找了一個比較著名的封閉好的庫,Novocaine。它對聲音的輸入、輸出都實現的比較好,也提供了很簡單明確的回呼函數,我只要修改一下回呼函數就可以了,這裡不表。

後面項目需要確定能否實現一種輸入/輸出方式:在插入帶麥克風的耳機時,能夠讓聲音從耳機麥克風輸入,然後同步的從手機內建擴音器播放。

在手機插入帶麥耳機後,輸入源共有2個:內建麥克風(Build-In Microphone)、耳機麥克風(Wired Microphone);輸出源有3個:打電話時用的,在上面的那個輸出(Built-In Receiver)、耳機(Wired Headphones)和放音樂時用的內建擴音器(Built-In Speaker)。

查了蘋果的文檔後發現,根據蘋果的產品策略,使用者在插入帶麥耳機後,會自動將輸入源切換到耳機麥克風,將輸出源切換到耳機。而且,在輸入源是耳機麥克風的時候,將輸出源切換到耳機是強制的。這句話比較繞,我舉個例子。假如現在輸入源是耳機麥克風,那麼輸入源只能是耳機。而如果將輸入源切換到手機內建麥克風(這是可以實現的)的時候,則可以將輸出源切換到手機。

蘋果認為,插入耳機代表使用者只想從耳機聽聲音。為了保護使用者的隱私,蘋果不允許開發人員隨便換輸出源。也就是說,雖然蘋果提供了3種方法用於切換輸出源(都比較繁瑣,後面可能會再寫一篇部落格),但在使用者插入耳機,並且我們需要輸入源是耳機麥克風的情況下,是無法將輸出源切換到內建擴音器的。這裡有更詳細的說明:http://stackoverflow.com/questions/5931799/redirecting-audio-output-to-phone-speaker-and-mic-input-to-headphones


第二個問題是,需要在耳機插入的狀態下,將輸入源調整為手機內建麥克風,而輸出源仍然保持為耳機。


在千能(不是萬能)的AVAudioSession類裡,提供了幾個很好的方法:

列印當前正在工作的輸入/輸入源:

NSArray* input = [[AVAudioSession sharedInstance] currentRoute].inputs;NSArray* output = [[AVAudioSession sharedInstance] currentRoute].outputs;NSLog(@"current intput:%@",input);NSLog(@"current output:%@",output);

列印現在可用的輸入源:

NSArray* availableInputs = [[AVAudioSession sharedInstance] availableInputs];NSLog(@"available inputs:%@",availableInputs);

AVAudioSession沒有提供可用的輸出源的列表。

將耳機插入之後,列印可用的輸入源,結果如下:

2015-01-26 17:45:40.747 PregNotice[605:6d13] available inputs:("","")
可以看出,現在可用的輸入源包括內建麥克風和耳機麥克風(Wired Microphone)。我們通過以下方法改變輸入源:

NSArray* inputArray = [[AVAudioSession sharedInstance] availableInputs];for (AVAudioSessionPortDescription* desc in inputArray) {    if ([desc.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {        NSError* error;        [[AVAudioSession sharedInstance] setPreferredInput:desc error:&error];    }}
同樣,在需要切換回來時,檢查desc.portType是不是AVAudioSessionPortHeadsetMic,如果是,調整回來。

需要注意的是,使用這個方法會觸發AVAudioSessionRouteChangeNotification通知,而插入耳機後,也會調用這個通知。我在測試的時候,為了檢查耳機插入的動作,監聽了這個通知,然後在通知回調方法裡通過上面方法修改了輸入源,導致又觸發了通知,所以插入1次耳機導致了2次調用。

關於聲音,AVAudioSession,還有很多需要瞭解的。有興趣的同學,需要搞定iOS聲音的同學,一定要好好學學。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.