Audio Unit播放aac/m4a/mp3等文件
前言
相关文章: 使用VideoToolbox硬编码H.264 使用VideoToolbox硬解码H.264 使用AudioToolbox编码AAC 使用AudioToolbox播放AAC HLS点播实现(H.264和AAC码流) HLS推流的实现(iOS和OS X系统) iOS在线音频流播放 Audio Unit播放PCM文件 Audio Unit录音(播放伴奏+耳返) 前面两篇介绍了Audio Unit 播放PCM文件 和 边录边播 ,这次引入 AudioConvert 实现aac/m4a/mp3格式的播放。
正文
1、格式转换
音频数据的格式转换包括采样率改变,单声道到多声道的转变、音调的升高降低等,audio unit有一个专门格式转换unit(
kAudioUnitType_FormatConverter,type of 'aufc'
)。
AudioUnit不支持vbr的数据
,也不支持从一个有损压缩格式转换为pcm或者pcm转换为有损格式,对于有损格式的音频数据转换,需要用CoreAudio的Audio Converter API。
2、AudioFile API 和 Converter
AudioFile API提供了API对音频文件的创建、打开、修改和保存; Audio Converters 用于音频文件的编解码,还可以用于sample rate的改变、int到float的转变,最常见是将音频文件转成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、具体细节
1、初始化AudioFile,通过
AudioFileOpenURL
打开音频文件,并读取对应的音频格式(
AudioStreamBasicDescription
);这里和
Audio Unit播放PCM文件
不同的是,还需要读取
kAudioFilePropertyMaximumPacketSize
和
kAudioFilePropertyAudioDataPacketCount
两个属性,分别是单个package的最大size和packet的数量,并通过缓存的大小和package的size创建
AudioStreamPacketDescription
的数组;
2、初始化AudioUnit,设置AVAudioSession的Category为
AVAudioSessionCategoryPlayback
;初始化AudioBufferList,设置AudioUnit的playback回调;
3、在AudioUnit的playback回调中,调用AudioConvert的
AudioConverterFillComplexBuffer
函数并设置好回调方法
lyInInputDataProc
;在回调的
lyInInputDataProc
中,通过
AudioFileReadPacketData
读取音频数据并把读取的AudioStreamPacketDescription回传;
4、AudioConvert转换后的音频数据会填入参数buffList,将对应的数据复制给AudioUnit的playback参数;
遇到的问题
1、API替换
一开始用的是
AudioFileReadPackets
方法读取音频数据,后面在遇到问题后发现
AudioFileReadPackets
被替换成
AudioFileReadPacketData
,参数类似;
2、AudioConverter的转换函数的返回值
调用
AudioConverterFillComplexBuffer
后,在回调方法
lyInInputDataProc
中,如果设置
*ioNumberDataPackets = 0
,并且返回
noErr
, AudioConverter 会进入
Finished
的状态;
返回非零的值,表示数据未完成,比如在demo中返回了
NO_MORE_DATA
,NO_MORE_DATA
是自定义的非零返回值;
3、AudioConverterNewSpecific返回-50
通过
OSStatus
,可以看到-50是AVAudioSessionErrorCodeBadParam 参数不一致;