AudioFileStream介绍
AudioFileStreamer是用来读取采样率、码率、时长等基本信息以及分离音频帧。
AudioFileStreamer用在流播放中,当然不仅限于网络流,本地文件同样可以用它来读取信息和分离音频帧。
AudioFileStreamer的主要数据是文件数据,支持的文件格式有:
MPEG-1 Audio Layer 3, used for .mp3 files
MPEG-2 ADTS, used for the .aac audio data format
AIFC
AIFF
CAF
MPEG-4, used for .m4a, .mp4, and .3gp files
NeXT
WAVE
AudioFileStreamOpen
初始化AudioFileStream,创建一个音频流解析器,生成一个AudioFileStream示例。
函数示例
extern OSStatus
AudioFileStreamOpen (
void * __nullable inClientData,
AudioFileStream_PropertyListenerProc inPropertyListenerProc,
AudioFileStream_PacketsProc inPacketsProc,
AudioFileTypeID inFileTypeHint,
AudioFileStreamID __nullable * __nonnull outAudioFileStream)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
参数列表:
inClientData 上下文对象
AudioFileStream_PropertyListenerProc 歌曲信息解析的回调,每次解析出一个歌曲信息,都会执行一次回调。
AudioFileStream_PacketsProc 分离帧的回调,每解析出一部分帧就会进行一次回调
AudioFileTypeID 是文件类型的提示,创建指定文件格式的音频流解析器。AudioFileTypeID对应的枚举
enum {
kAudioFileAIFFType = 'AIFF',
kAudioFileAIFCType = 'AIFC',
kAudioFileWAVEType = 'WAVE',
kAudioFileSoundDesigner2Type = 'Sd2f',
kAudioFileNextType = 'NeXT',
kAudioFileMP3Type = 'MPG3', // mpeg layer 3
kAudioFileMP2Type = 'MPG2', // mpeg layer 2
kAudioFileMP1Type = 'MPG1', // mpeg layer 1
kAudioFileAC3Type = 'ac-3',
kAudioFileAAC_ADTSType = 'adts',
kAudioFileMPEG4Type = 'mp4f',
kAudioFileM4AType = 'm4af',
kAudioFileM4BType = 'm4bf',
kAudioFileCAFType = 'caff',
kAudioFile3GPType = '3gpp',
kAudioFile3GP2Type = '3gp2',
kAudioFileAMRType = 'amrf'
};
outAudioFileStream AudioFileStream实例对应的AudioFileStreamID,AudioFileStream其他函数需要使用。
返回值
返回值用来判断是否成功初始化(OSSStatus == noErr)
AudioFileStreamParseBytes
解析数据,在初始化完成之后,调用该方法解析文件数据。
函数示例
extern OSStatus AudioFileStreamParseBytes(AudioFileStreamID inAudioFileStream,
UInt32 inDataByteSize,
const void* inData,
UInt32 inFlags);
参数列表
inAudioFileStream 初始化成功后返回的 AudioFileStreamID
inDataByteSize 本次解析的文件长度
inData 本次解析的数据
inFlags 标志位,标识本次的解析和上一次解析是否是连续的关系,默认0表示连续,否则传入kAudioFileStreamParseFlag_Discontinuity。
返回值
OSStatus的值不是noErr则表示解析不成功,对应的错误码:
enum
{
kAudioFileStreamError_UnsupportedFileType = 'typ?',
kAudioFileStreamError_UnsupportedDataFormat = 'fmt?',
kAudioFileStreamError_UnsupportedProperty = 'pty?',
kAudioFileStreamError_BadPropertySize = '!siz',
kAudioFileStreamError_NotOptimized = 'optm',
kAudioFileStreamError_InvalidPacketOffset = 'pck?',
kAudioFileStreamError_InvalidFile = 'dta?',
kAudioFileStreamError_ValueUnknown = 'unk?',
kAudioFileStreamError_DataUnavailable = 'more',
kAudioFileStreamError_IllegalOperation = 'nope',
kAudioFileStreamError_UnspecifiedError = 'wht?',
kAudioFileStreamError_DiscontinuityCantRecover = 'dsc!'
};
每次调用成功后应该注意返回值,一旦出现错误就不必要进行后续的解析。
AudioFileStream_PropertyListenerProc
解析文件格式信息的回调,在调用AudioFileStreamParseBytes方法进行解析时会首先读取格式信息,并同步的进入AudioFileStream_PropertyListenerProc回调方法。
函数示例
typedef void (*AudioFileStream_PropertyListenerProc)(
void * inClientData,
AudioFileStreamID inAudioFileStream,
AudioFileStreamPropertyID inPropertyID,
AudioFileStreamPropertyFlags * ioFlags);
参数列表
inClientData 得到上下文
inAudioFileStream 表示当前的FileStream的AudioFileStreamID
inPropertyID 表示此次回调解析的AudioFileStreamPropertyID,
支持的AudioFileStreamPropertyID枚举:
enum
{
kAudioFileStreamProperty_ReadyToProducePackets = 'redy',
kAudioFileStreamProperty_FileFormat = 'ffmt',
kAudioFileStreamProperty_DataFormat = 'dfmt',
kAudioFileStreamProperty_FormatList = 'flst',
kAudioFileStreamProperty_MagicCookieData = 'mgic',
kAudioFileStreamProperty_AudioDataByteCount = 'bcnt',
kAudioFileStreamProperty_AudioDataPacketCount = 'pcnt',
kAudioFileStreamProperty_MaximumPacketSize = 'psze',
kAudioFileStreamProperty_DataOffset = 'doff',
kAudioFileStreamProperty_ChannelLayout = 'cmap',
kAudioFileStreamProperty_PacketToFrame = 'pkfr',
kAudioFileStreamProperty_FrameToPacket = 'frpk',
kAudioFileStreamProperty_PacketToByte = 'pkby',
kAudioFileStreamProperty_ByteToPacket = 'bypk',
kAudioFileStreamProperty_PacketTableInfo = 'pnfo',
kAudioFileStreamProperty_PacketSizeUpperBound = 'pkub',
kAudioFileStreamProperty_AverageBytesPerPacket = 'abpp',
kAudioFileStreamProperty_BitRate = 'brat',
kAudioFileStreamProperty_InfoDictionary = 'info'
};
当前PropertyID对应的信息已经解析完成信息,可以通过AudioFileStreamGetProperty接口获取PropertyID对应的值或者数据结构;
extern OSStatus AudioFileStreamGetProperty(AudioFileStreamID inAudioFileStream,
AudioFileStreamPropertyID inPropertyID,
UInt32 * ioPropertyDataSize,
void * outPropertyData);
ioFlags 表示这个property是否需要被缓存。
AudioFileStreamPropertyID解析
kAudioFileStreamProperty_BitRate 音频数据的码率,通过码率可以计算音视频的总时长
kAudioFileStreamProperty_DataOffset 表示音频数据在整个音频文件中的offset
因为大多数音频文件都会有一个文件头之后才使真正的音频数据),这个值在seek时会发挥比较大的作用,音频的seek并不是直接seek文件位置而seek时间(比如seek到2分10秒的位置),seek时会根据时间计算出音频数据的字节offset然后需要再加上音频数据的offset才能得到在文件中的真正offset
kAudioFileStreamProperty_DataFormat 表示音频文件结构信息,是一个AudioStreamBasicDescription的结构
kAudioFileStreamProperty_FormatList 作用和kAudioFileStreamProperty_DataFormat是一样的,区别在于用这个PropertyID获取到是一个AudioStreamBasicDescription的数组
kAudioFileStreamProperty_AudioDataByteCount 音频文件中音频数据的总量。这个Property的作用一是用来计算音频的总时长,二是可以在seek时用来计算时间对应的字节offset
kAudioFileStreamProperty_ReadyToProducePackets 一旦回调中这个PropertyID出现就代表解析完成,接下来可以对音频数据进行帧分离了
计算时长Duration
double duration = (audioDataByteCount * 8) / bitRate
音频数据的字节总量audioDataByteCount可以通过kAudioFileStreamProperty_AudioDataByteCount获取,
码率bitRate可以通过kAudioFileStreamProperty_BitRate获取
AudioFileStream_PacketsProc
分离音频帧回调,读取格式信息完成之后,继续调用AudioFileStreamParseBytes方法可以对帧进行分离,并同步的进入AudioFileStream_PacketsProc回调方法
函数示例
typedef void (*AudioFileStream_PacketsProc)(
void * inClientData,
UInt32 inNumberBytes,
UInt32 inNumberPackets,
const void * inInputData,
AudioStreamPacketDescription *inPacketDescriptions);
参数列表
inClientData 得到上下文
inNumberBytes 表示本次处理的数据大小
inNumberPackets 本次总共处理了多少帧AudioFileStreamPropertyID
inInputData 本次处理的所有数据
AudioStreamPacketDescription AudioStreamPacketDescription数组,存储了每一帧数据是从第几个字节开始的,这一帧总共多少字节。
AudioFileStreamSeek
seek操作
AudioFileStreamClose
AudioFileStream使用完毕后需要调用AudioFileStreamClose进行关闭
函数示例
extern OSStatus AudioFileStreamClose(AudioFileStreamID inAudioFileStream);
参数:inAudioFileStream 初始化时生成的AudioFileStreamID
参考资料: