前言
相關(guān)文章:
Audio Unit播放PCM文件
Audio Unit錄音(播放伴奏+耳返)
前面兩篇介紹了Audio Unit播放PCM文件和邊錄邊播,這次引入AudioConvert實(shí)現(xiàn)aac/m4a/mp3格式的播放。
正文
1、格式轉(zhuǎn)換
音頻數(shù)據(jù)的格式轉(zhuǎn)換包括采樣率改變,單聲道到多聲道的轉(zhuǎn)變、音調(diào)的升高降低等,audio unit有一個專門格式轉(zhuǎn)換unit(kAudioUnitType_FormatConverter,type of 'aufc')。
AudioUnit不支持vbr的數(shù)據(jù),也不支持從一個有損壓縮格式轉(zhuǎn)換為pcm或者pcm轉(zhuǎn)換為有損格式,對于有損格式的音頻數(shù)據(jù)轉(zhuǎn)換,需要用CoreAudio的Audio Converter API。
2、AudioFile API 和 Converter
AudioFile API提供了API對音頻文件的創(chuàng)建、打開、修改和保存;
Audio Converters 用于音頻文件的編解碼,還可以用于sample rate的改變、int到float的轉(zhuǎn)變,最常見是將音頻文件轉(zhuǎn)成pcm播放;
下面Converter的兩個格式:
Source Format
Sample Rate: 44100
Format ID: .mp3
Format Flags: 0
Bytes per Packet: 0
Frames per Packet: 1152
Bytes per Frame: 0
Channels per Frame: 2
Bits per Channel: 0
Target Format
Sample Rate: 44100
Format ID: lpcm
Format Flags: 4
Bytes per Packet: 2
Frames per Packet: 1
Bytes per Frame: 2
Channels per Frame: 1
Bits per Channel: 16
3、具體細(xì)節(jié)
1、初始化AudioFile,通過AudioFileOpenURL打開音頻文件,并讀取對應(yīng)的音頻格式(AudioStreamBasicDescription);這里和Audio Unit播放PCM文件不同的是,還需要讀取kAudioFilePropertyMaximumPacketSize和kAudioFilePropertyAudioDataPacketCount兩個屬性,分別是單個package的最大size和packet的數(shù)量,并通過緩存的大小和package的size創(chuàng)建AudioStreamPacketDescription的數(shù)組;
2、初始化AudioUnit,設(shè)置AVAudioSession的Category為AVAudioSessionCategoryPlayback;初始化AudioBufferList,設(shè)置AudioUnit的playback回調(diào);
3、在AudioUnit的playback回調(diào)中,調(diào)用AudioConvert的AudioConverterFillComplexBuffer函數(shù)并設(shè)置好回調(diào)方法lyInInputDataProc;在回調(diào)的lyInInputDataProc中,通過AudioFileReadPacketData讀取音頻數(shù)據(jù)并把讀取的AudioStreamPacketDescription回傳;
4、AudioConvert轉(zhuǎn)換后的音頻數(shù)據(jù)會填入?yún)?shù)buffList,將對應(yīng)的數(shù)據(jù)復(fù)制給AudioUnit的playback參數(shù);
遇到的問題
1、API替換
一開始用的是AudioFileReadPackets方法讀取音頻數(shù)據(jù),后面在遇到問題后發(fā)現(xiàn)AudioFileReadPackets被替換成AudioFileReadPacketData,參數(shù)類似;
2、AudioConverter的轉(zhuǎn)換函數(shù)的返回值
調(diào)用AudioConverterFillComplexBuffer后,在回調(diào)方法lyInInputDataProc中,如果設(shè)置 *ioNumberDataPackets = 0,并且返回 noErr, AudioConverter 會進(jìn)入 Finished 的狀態(tài);
返回非零的值,表示數(shù)據(jù)未完成,比如在demo中返回了
NO_MORE_DATA,NO_MORE_DATA是自定義的非零返回值;
3、AudioConverterNewSpecific返回-50
通過OSStatus,可以看到-50是AVAudioSessionErrorCodeBadParam 參數(shù)不一致;
檢查代碼,發(fā)現(xiàn)是在使用AudioConverterNewSpecific() 創(chuàng)建轉(zhuǎn)換器的時候輸入流格式與輸出流格式的聲道數(shù)設(shè)置不同;(解決方案就是聲道數(shù)改成一致)
4、AudioConverterFillComplexBuffer返回561015652
通過OSStatus,查到561015652是kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd',意思是沒有回調(diào)AudioStreamPacketDescriptions參數(shù);
對于音頻格式mBytesPerPacket=0的數(shù)據(jù),需要AudioStreamPacketDescriptions參數(shù)來輔助轉(zhuǎn)換音頻數(shù)據(jù);
解決方案就是新建AudioStreamPacketDescriptions數(shù)組,并且在讀取后賦值給outDataPacketDescription(見demo)Demo地址;
總結(jié)
AudioUnit和AudioConvert的API雖然簡單,卻是功能強(qiáng)大。
文章中的介紹更多是自己在學(xué)習(xí)過程中的一些收獲,對于知識點(diǎn)的介紹很多是不夠全面和仔細(xì)的,對此建議看看參考目錄。
Extended Audio File Services 是Audio File Services 和 Audio Converter Services 的結(jié)合,提供統(tǒng)一的接口進(jìn)行處理,下篇可能會是Extended Audio File相關(guān)。
參考
Playing a sound file using the Default Output Audio Unit
Supported Audio File and Data Formats in OS X