AudioFileStream学习

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

参考资料:

  1. Using Audio
  2. AudioFileStream
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • AudioFileStream介绍 AudioFileStreamer时提到它的作用是用来读取采样率、码率、时长等...
    VD2012阅读 534评论 0 2
  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,650评论 0 3
  • 本篇我们介绍AudioFile和AudioFileStream。在第一篇技术栈的分析里,我们提到过AudioFil...
    anyoptional阅读 2,590评论 0 4
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,409评论 25 707
  • 有十年没有在高校迎新的销售现场来过了,新部门,新要求,让我有机会在近不惑之年重回高校看看。 繁忙之于漫步在...
    童小咪阅读 254评论 0 0