iphone linepcm audio unit play archictecture.docx
《iphone linepcm audio unit play archictecture.docx》由会员分享,可在线阅读,更多相关《iphone linepcm audio unit play archictecture.docx(21页珍藏版)》请在冰点文库上搜索。
![iphone linepcm audio unit play archictecture.docx](https://file1.bingdoc.com/fileroot1/2023-4/30/896fc0aa-92ba-4ed8-9668-4a8c57167429/896fc0aa-92ba-4ed8-9668-4a8c571674291.gif)
iphonelinepcmaudiounitplayarchictecture
1audioqueue:
Anaudioqueuedoestheworkof:
Connectingtoaudiohardware
Managingmemory
Employingcodecs,asneeded,forcompressedaudioformats
Mediatingrecordingorplayback
2audioqueuearchitecture:
Allaudioqueueshavethesamegeneralstructure,consistingoftheseparts:
Asetof audioqueuebuffers,eachofwhichisatemporaryrepositoryforsomeaudiodata
A bufferqueue,anorderedlistfortheaudioqueuebuffers
An audioqueuecallback function,whichyouwrite
3buffqueueenqueue
由callback自己实现音频缓冲的入队、出队
4ControllingthePlaybackProcess
AudioQueueInputCallback(
void*inUserData,
AudioQueueRefinAQ,
AudioQueueBufferRefinBuffer,
constAudioTimeStamp*inStartTime,
UInt32inNumberPacketDescriptions,
constAudioStreamPacketDescription*inPacketDescs
);
UsingCodecsandAudioDataFormats
AudioQueueServicesemployscodecs(audiodatacoding/decodingcomponents)asneededforconvertingbetweenaudioformats.Yourrecordingorplaybackapplicationcanuseanyaudioformatforwhichthereisaninstalledcodec.Youdonotneedtowritecustomcodetohandlevariousaudioformats.Specifically,yourcallbackdoesnotneedtoknowaboutdataformats.
Here’showthisworks.Eachaudioqueuehasanaudiodataformat,representedinan AudioStreamBasicDescription structure.Whenyouspecifytheformat—inthe mFormatID fieldofthestructure—theaudioqueueusestheappropriatecodec.Youthenspecifysamplerateandchannelcount,andthat’sallthereistoit.You'llseeexamplesofsettingaudiodataformatin “RecordingAudio” and “PlayingAudio.”
Arecordingaudioqueuemakesuseofaninstalledcodecasshownin Figure1-5.
Figure1-5 Audioformatconversionduringrecording
Instep1of Figure1-5,yourapplicationtellsanaudioqueuetostartrecording,andalsotellsitthedataformattouse.Instep2,theaudioqueueobtainsnewaudiodataandconvertsit,usingacodec,accordingtotheformatyou’vespecified.Theaudioqueuetheninvokesthecallback,handingitabuffercontainingappropriatelyformatedaudiodata.Instep3,yourcallbackwritestheformattedaudiodatatodisk.Again,yourcallbackdoesnotneedtoknowaboutthedataformats.
Aplaybackaudioqueuemakesuseofaninstalledcodecasshownin Figure1-6.
Figure1-6 Audioformatconversionduringplayback
Instep1of Figure1-6,yourapplicationtellsanaudioqueuetostartplaying,andalsotellsitthedataformatcontainedintheaudiofiletobeplayed.Instep2,theaudioqueueinvokesyourcallback,whichreadsdatafromtheaudiofile.Thecallbackhandsoffthedata,initsoriginalformat,totheaudioqueue.Instep3,theaudioqueueusestheappropriatecodecandthensendstheaudioalongtothedestination.
Anaudioqueuecanmakeuseofanyinstalledcodec,whethernativetoMacOSXorprovidedbyathirdparty.Todesignateacodectouse,yousupplyitsfour-charactercodeIDtoanaudioqueue’s AudioStreamBasicDescription structure.You’llseeanexampleofthisin “RecordingAudio.”
MacOSXincludesawiderangeofaudiocodecs,aslistedintheformatIDsenumerationinthe CoreAudioTypes.h headerfileandasdocumentedin CoreAudioDataTypesReference.Youcandeterminethecodecsavailableonasystembyusingtheinterfacesinthe AudioFormat.h headerfile,intheAudioToolboxFramework.YoucandisplaythecodecsonasystemusingtheFiendishthngsapplication,availableassamplecodeat
5使用audioqueue录音
Defineacustomstructuretomanagestate,format,andpathinformation.
Writeanaudioqueuecallbackfunctiontoperformtheactualrecording.
Optionallywritecodetodetermineagoodsizefortheaudioqueuebuffers.Writecodetoworkwithmagiccookies,ifyou’llberecordinginaformatthatusescookies.
Fillthefieldsofthecustomstructure.Thisincludesspecifyingthedatastreamthattheaudioqueuesendstothefileit’srecordinginto,aswellasthepathtothatfile.
Createarecordingaudioqueueandaskittocreateasetofaudioqueuebuffers.Alsocreateafiletorecordinto.
Telltheaudioqueuetostartrecording.
Whendone,telltheaudioqueuetostopandthendisposeofit.Theaudioqueuedisposesofitsbuffers.
1)DefineaCustomStructuretoManageState
2)writeaRecordingaudioqueuecallback
Writinganaudioqueuebuffertodiskcallback’sfirsttask
Enqueueanaudioqueue
录制音频相关开发步骤:
1定义一个结构体:
用来存储音频格式、状体、文件路径
2写回调函数执行实际的record操作
3(可选)写段代码决定audioqueue缓冲区的大小;写段代码与magiccookies配合工作(在aac格式时会用到),
4填充1中定义的结构体,包括制定数据流用于存储的,文件路径。
5生成一个audioqueue及audioqueuebuffer,生成一个存储文件句柄。
6通过audioqueue启动录音
7录音结束时通知audioqueue结束录音,audioqueue本身会完成后续动作,例如其所申请的各种资源的释放。
以下是其实施步骤:
A:
定义定制结构体:
结构体各成员说明:
1设置audioqueue缓冲大小
2设置录音所需的各种参数格式
AudioStreamBasicDescriptionstructfromCoreAudioTypes.h代表音频数据格式。
被mQueue(3)使用
//---------------------------------------------------
structAudioStreamBasicDescription{
Float64mSampleRate;
UInt32mFormatID;
UInt32mFormatFlags;
UInt32mBytesPerPacket;
UInt32mFramesPerPacket;
UInt32mBytesPerFrame;
UInt32mChannelsPerFrame;
UInt32mBitsPerChannel;
UInt32mReserved;
};
typedefstructAudioStreamBasicDescriptionAudioStreamBasicDescription;
//---------------------------------------------------
3通过自己写代码生成的Audioqueue
4指针数组,指向audioqueue的管理的缓冲区
5audiofileproject指向存储文件的路径
6每个audioqueuebuffer的大小,单位Byte
7audioqueuebuffer(应写入文件的)下标
8audioqueue的状态指示标志。
B:
编写Recordingaudioqueue回调函数:
**这个函数有两个主要功能:
将从读取的音频缓冲存入音频文件
将已经存入文件的buff入队
//---------------------------
typedefvoid(*AudioQueueInputCallback)(
void*inUserData,
AudioQueueRefinAQ,
AudioQueueBufferRefinBuffer,
constAudioTimeStamp*inStartTime,
UInt32inNumberPacketDescriptions,
constAudioStreamPacketDescription*inPacketDescs
);
参数解释:
inUserData:
A中定义的,见上页
inAQ:
调用本回调函数的audioqueue
inBuffer:
存储待保存的录音的buff
inStartTime:
auidoqueue中一个缓冲的采样时间。
inNumberPacketDescriptioins:
packetdescriptions数量
inPacketDescs:
由编码器产生的针对压缩音频的相关信息
//---------------------------
&&将读取的音频缓冲数据写入音频文件:
//-------------------------
OSStatusAudioFileWritePackets(
AudioFileIDinAudioFile,
BooleaninUseCache,
UInt32inNumBytes,
constAudioStreamPacketDescription*inPacketDescriptions,
SInt64inStartingPacket,
UInt32*ioNumPackets,
constvoid*inBuffer
);
参数解释:
AudioFileWritePackets:
definedinAudioFile.husedtowritebufftofile
inAudioFile:
inUseCache:
true:
useuser’scache;false:
donotuseusercache;
inNumBytes:
将写入的缓存大小,以Byte为单位。
inPacketDescritions:
PacketDescriptiionarray
inStartingPacket:
Thepacketindexforthefirstpackettobewritten.
ioNumPackets:
Oninput,thenumberofpacketstowrite.Onoutput,thenumberofpacketsactuallywritten.
inBuffer:
Thenewaudiodatatowritetotheaudiofile
//-------------------------
&&入队已用的缓冲:
//-------------------------
OSStatusAudioQueueEnqueueBuffer(
AudioQueueRefinAQ,
AudioQueueBufferRefinBuffer,
UInt32inNumPacketDescs,
constAudioStreamPacketDescription*inPacketDescs
);
参数解释:
The AudioQueueEnqueueBuffer functionaddsanaudioqueuebuffertoanaudioqueue’sbufferqueue.
inAQ:
Theaudioqueuetoaddthedesignatedaudioqueuebufferto
inBuffer:
Theaudioqueuebuffertoenqueue.
inNumPacketDescs:
Thenumberofpacketdescriptionsintheaudioqueuebuffer'sdata.Setto 0 becausethisparameterisunusedforrecording.
inPacketDescs:
Thearrayofpacketdescriptionsdescribingtheaudioqueuebuffer’sdata.Setto NULL becausethisparameterisunusedforrecording.
//-------------------------
一个完整的回调函数:
staticvoidHandleInputBuffer(
void*aqData,
AudioQueueRefinAQ,
AudioQueueBufferRefinBuffer,
constAudioTimeStamp*inStartTime,
UInt32inNumPackets,
constAudioStreamPacketDescription*inPacketDesc
){
AQRecorderState*pAqData=(AQRecorderState*)aqData;//1
if(inNumPackets==0&&//2
pAqData->mDataFormat.mBytesPerPacket!
=0)
inNumPackets=
inBuffer->mAudioDataByteSize/pAqData->mDataFormat.mBytesPerPacket;
if(AudioFileWritePackets(//3
pAqData->mAudioFile,
false,
inBuffer->mAudioDataByteSize,
inPacketDesc,
pAqData->mCurrentPacket,
&inNumPackets,
inBuffer->mAudioData
)==noErr){
pAqData->mCurrentPacket+=inNumPackets;//4
}
if(pAqData->mIsRunning==0)//5
return;
AudioQueueEnqueueBuffer(//6
pAqData->mQueue,
inBuffer,
0,
NULL
);
}
C:
setamagiccookiesforanaudiofile
一些已编码音频格式例如:
MPEG4AAC利用这个数据机构保存该音频元数据(格式信息),这个结构体被称作magiccookies,在录制这种格式音频之前首先要获取这个数据并用接口函数存储到文件中位置不确定。
当录音结束后再存储一次,有些编码器会在录音结束后更新这个结构体。
//-----------------------------------------
OSStatusAudioFileSetProperty(
AudioFileIDinAudioFile,
AudioFilePropertyIDinPropertyID,
UInt32inDataSize,
constvoid*inPropertyData
);
………………………………………………………………………………………
OSStatusSetMagicCookieForFile(
AudioQueueRefinQueue,//1
AudioFileIDinFile//2
){
OSStatusresult=noErr;//3
UInt32cookieSize;//4
if(
AudioQueueGetPropertySize(//5
inQueue,
kAudioQueueProperty_MagicCookie,
&cookieSize
)==noErr
){
char*magicCookie=
(char*)malloc(cookieSize);//6
if(
AudioQueueGetProperty(//7
inQueue,
kAudioQueueProperty_MagicCookie,
magicCookie,
&cookieSize
)==noErr
)
result=AudioFileSetProperty(//8
inFile,
kAudioFilePropertyMagicCookieData,
cookieSize,
magicCookie
);
free(magicCookie);//9
}
returnresult;//10
}
………………………………………………………………………………………
//-----------------------------------------
D:
设置录音参数:
Tosetupanaudiodataformat,youspecify: