本篇是AudioQueue的官方文档的笔记。Audio Queue Services可以play和record以下三类任何audio data:
对于最后一种类型,我们可以在使用AudioQueue同时自己将自己需要的format转化成LPCM。AudioQueue是对mic和speaker的高度抽象,同时可以非常简单的时间音频codecs。与此同时,它也有一些高级功能,例如多个音频的同步播放,回放等等。
这章会了解到audio queue的功能,结构体,以及内部运行的机理。具体的内容包括audio queues,audio queue buffers,audio queue会使用到的callback等。还有就是audio queue的状态以及参数。
An audio queue 是iOS中play和record audio的对象.底层是AudioQueueRef
。Audio queue可以完成以下工作:
Audio queue的具体结构有以下几个部分构成:
根据我们使用audio queue的用途(record or play),具体的结构略有不同,仅仅只是callback函数函数的内容不同。
一个用于record 的audio queue,需要使用AudioQueueNewInput
方法创建,它的具体结构如图:
一个用于play的audio queue,需要使用AudioQueueNewOutput
函数创建,
audio queue buffer的数据结构如下:
typedef struct AudioQueueBuffer {
const UInt32 mAudioDataBytesCapacity;
void *const mAudioData;
UInt32 mAudioDataByteSize;
void *mUserData;
} AudioQueueBuffer;
typedef AudioQueueBuffer *AudioQueueBufferRef;
其中mAudioData字段表示这个buffer中的有用数据的地址,其他的字段用来辅助audio queue来管理使用这个buffer。一个audio queue可以使用任何数目的buffers。但是我们一般选择3个,比较好管理。
Audio queue通过下面的方式管理它们内部的buffers:
buffer queue是由audio buffers组成的,是audio queue中的buffers。我们前面介绍了audio queue是如何使用callback管理内部的buffers。不论当前是用于record或者是pleyback,将buffer放到audio queue都是需要我们在callback函数中去手动调用的。
Audio queue buffers在queue是顺序播放的,我们可以通theAudioQueueEnqueueBufferWithParameters
方法来进行控制
Audio queue在运行过程中会不断的调用callback函数,通常间隔时间和audio queue buffer的大小相关,一般是几秒一次。
audio queue callback主要任务是将audio queue buffer归还给audio queue。callback中通过AudioQueueEnqueueBuffer
方法将buffer加载到audio queue的最后。在playback中,可以使用AudioQueueEnqueueBufferWithParameters
在enqueue的过程中进行更多的控制。
如果你仅仅使用audio queue去将record的audio data写入file system,callback的方法实现的原型如下:
AudioQueueInputCallback (
void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs
);
一个recording audio queue会触发我们注册的callback,会在callback的参数中传入所有需要的关于audio data的相关信息:
这个片段会介绍如果使用playing audio queue,那么callback应该的信息:
AudioQueueOutputCallback (
void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer
);
一个playback audio queue会触发这个callback,提供一些关于audio data的有用信息:
我们日常使用Audio Queue Services时,都会使用codecs(audio data coding/decoding componets)用来在不同audio format之间进行转化。
每个audio queue都有一个audio data format,可以在AudioStreamBasicDescription
结构体中得到。当我们在ASBD中指定了mFormatID
以后,audio queue在向buffer中填充数据时候就会使用相应的codec。同样如果指定sample rate和channel count,audio queue也会同样。具体的过程见下图:
整个过程中,callback函数压根就不需要知道data fromat是什么。
在播放过程中,正好和录音过程相反,只需要在创建audio queue时候将data format告知即可。
audio queue在创建和销毁的过程有一个声明周期。app需要管理它的声明周期,控制它的状态,具体控制状态的方法如下:
AudioQueueStart
).初始化audio queue用来record或者playback。AudioQueuePrime
).对于playback,在调用AudioQueueStart
挚爱去哪调用确保数据可用,这个方法和record没有关系。AudioQueueStop
). 调用以后会重置audio queue,然后会停止record或者playback。在playback应用中,一般在没有audio data可以播放时候调用。AudioQueuePause
). 在record或者playback中调用这个方法不会影响到buffers。如果需要恢复,调用AudioQueueStart
。AudioQueueFlush
). 在enqueue最后一个audio queue buffer以后调用这个方法,确保所有的数据被record或者play(主要是在midst processing的数据)。AudioQueueReset
). 调用以后立即停止audio queue,然后将所有的buffers移除,重置所有的DSP状态等到。在调用AudioQueueStop
方法时候有两种模式:同步和异步。
当我们的record使用Audio Queue Services,存储的路径可以是磁盘上的任何地方,或者网络,或者内存中。这部分内容记录大多数的使用场景,存储在磁盘中。
具体的步骤如下:
具体的实现内容可以参考Apple官方文档:Recording Audio。
当我们使用Audio Queue Service去play audio时,音频源文件可以是任何在disk file或者memory中,这部分内容是如何用Audio Queue Service播放存储在disk上的audio file。
具体的步骤如下:
具体的实现内容可以参考Apple官方文档:Playing Audio。
请参考我的github: https://github.com/brownfeng/AudioQueueServiceDemo