html5 m4a,Audio Unit播放aac/m4a/mp3等文件

穆丁雨
2023-12-01

前言

正文

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 参数不一致;

检查代码,发现是在使用AudioConverterNewSpecific() 创建转换器的时候输入流格式与输出流格式的声道数设置不同;(解决方案就是声道数改成一致)

4、AudioConverterFillComplexBuffer返回561015652

通过OSStatus,查到561015652是kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd',意思是没有回调AudioStreamPacketDescriptions参数;

对于音频格式mBytesPerPacket=0的数据,需要AudioStreamPacketDescriptions参数来辅助转换音频数据;

解决方案就是新建AudioStreamPacketDescriptions数组,并且在读取后赋值给outDataPacketDescription(见demo);

总结

AudioUnit和AudioConvert的API虽然简单,却是功能强大。

文章中的介绍更多是自己在学习过程中的一些收获,对于知识点的介绍很多是不够全面和仔细的,对此建议看看参考目录。

Extended Audio File Services 是Audio File Services 和 Audio Converter Services 的结合,提供统一的接口进行处理,下篇可能会是Extended Audio File相关。

参考

 类似资料: