前言:
- 一直想研究一下Audio Queue Services逊彭,趁著過年這段時(shí)間有空就去研究一下先誉,首選肯定是官方文檔,下面是我讀文檔的時(shí)候翻譯過來怔匣,自己一句一句翻譯可以加深自己的理解記憶雄人,同時(shí)又能方便大家砂沛,何樂而不為谴餐!
- 由于文檔內(nèi)容較多累舷,本文會(huì)分兩篇介紹蝇摸,避免篇幅過長(zhǎng)橘洞,影響閱讀,Demo會(huì)遲點(diǎn)分享捌袜,敬請(qǐng)期待。
Audio Queue Services 解讀之 Playing Audio(下)
Playing Audio
當(dāng)你使用 Audio Queue Services 播放音頻的時(shí)候炸枣,音頻源可以是任何東西-磁盤文件虏等、基于軟件的音頻合成弄唧、內(nèi)存中的音頻對(duì)象等等,這節(jié)介紹的是播放磁盤文件
注意:本章介紹了基于ANSI-C的播放實(shí)現(xiàn)霍衫,以及一些來自Mac OS X Core Audio SDK的C ++類套才。 對(duì)于基于Objective-C的示例,請(qǐng)參閱 iOS Dev Center 中的SpeakHere示例代碼慕淡。
為你的應(yīng)用添加播放功能背伴,你通常需要實(shí)現(xiàn)下面步驟:
1、定義一個(gè)自定義的結(jié)構(gòu)體峰髓,管理音頻狀態(tài)傻寂、格式和路徑等信息。
2携兵、編寫一個(gè)音頻隊(duì)列回調(diào)函數(shù)來執(zhí)行實(shí)際播放疾掰。
3、編寫代碼以確定音頻隊(duì)列緩沖區(qū)的大小徐紧。
4静檬、打開音頻文件進(jìn)行播放并確定其音頻數(shù)據(jù)格式。
5并级、創(chuàng)建播放音頻隊(duì)列并將其配置為播放拂檩。
6、分配和入隊(duì)音頻隊(duì)列緩沖區(qū)嘲碧, 告訴音頻隊(duì)列開始播放稻励; 完成后,回調(diào)會(huì)指示音頻隊(duì)列停止愈涩。
7望抽、處理音頻隊(duì)列, 釋放資源履婉。
一煤篙、Define a Custom Structure to Manage State
開始之前,先定義一個(gè)自定義的結(jié)構(gòu)體毁腿,用來管理你的音頻樣式和音頻隊(duì)列狀態(tài)信息辑奈,例如:
static const int kNumberBuffers = 3; // 1
struct AQPlayerState {
AudioStreamBasicDescription mDataFormat; // 2
AudioQueueRef mQueue; // 3
AudioQueueBufferRef mBuffers[kNumberBuffers]; // 4
AudioFileID mAudioFile; // 5
UInt32 bufferByteSize; // 6
SInt64 mCurrentPacket; // 7
UInt32 mNumPacketsToRead; // 8
AudioStreamPacketDescription *mPacketDescs; // 9
bool mIsRunning; // 10
};
此結(jié)構(gòu)中的大多數(shù)字段與用于記錄的自定義結(jié)構(gòu)中的字段相同(或接近),如定義管理狀態(tài)的Define a Custom Structure to Manage State中的錄音音頻章節(jié)所述狸棍。 例如身害,mDataFormat
字段在此用于保存正在播放的文件的格式。 當(dāng)記錄時(shí)草戈,類似字段保存正在寫入磁盤的文件的格式塌鸯。
下面介紹一下結(jié)構(gòu)體中的字段:
1、設(shè)置audio queue buffers 音頻緩存數(shù)唐片,三個(gè)是最好的丙猬,可參考Audio Queue Buffers.
2涨颜、
AudioStreamBasicDescription
(在CoreAudioTypes.h
) 代表正在播放的音頻數(shù)據(jù)格式;mDataFormat
字段通過查詢音頻文件的kAudioFilePropertyDataFormat
屬性來填充茧球,如Obtaining a File’s Audio Data Format中所述庭瑰。
有關(guān)AudioStreamBasicDescription
結(jié)構(gòu)的詳細(xì)信息,請(qǐng)參閱Core Audio Data Types Reference3抢埋、你應(yīng)用創(chuàng)建的播放音頻隊(duì)列對(duì)象
4弹灭、存放緩沖對(duì)象 audio queue buffer 的數(shù)組
5、一個(gè)音頻文件對(duì)象揪垄,表示你的程序播放的音頻文件穷吮。
6、每個(gè)緩沖對(duì)象 audio queue buffer 的大屑⑴(以字節(jié)為單位)捡鱼,此值在這些示例中在
DeriveBufferSize
函數(shù)中計(jì)算,在音頻隊(duì)列創(chuàng)建后和啟動(dòng)之前酷愧。詳情看 Write a Function to Derive Playback Audio Queue Buffer Size7驾诈、表示要從音頻文件播放的下一個(gè)數(shù)據(jù)包的數(shù)據(jù)包索引。
8溶浴、在每次調(diào)用音頻隊(duì)列的播放回調(diào)時(shí)要讀取的數(shù)據(jù)包數(shù)乍迄。 與
bufferByteSize
字段一樣,在創(chuàng)建音頻隊(duì)列之后和啟動(dòng)音頻隊(duì)列之前戳葵,在DeriveBufferSize
函數(shù)中的這些示例中計(jì)算此值就乓。9、對(duì)于VBR(可變比特率)音頻數(shù)據(jù)拱烁,正在播放的文件的數(shù)據(jù)包描述數(shù)組。 對(duì)于CBR(恒定比特率)數(shù)據(jù)噩翠,此字段的值為NULL戏自。(VBR 和 CBR 的介紹和區(qū)別)
10、表示音頻隊(duì)列是否正在運(yùn)行
二伤锚、 Write a Playback Audio Queue Callback
下一步就是寫一個(gè)音頻隊(duì)列 Audio queue 的回調(diào)函數(shù)擅笔,這個(gè)函數(shù)做了三件事:
- 1、從音頻文件讀取指定數(shù)量的數(shù)據(jù)屯援,并將其放入音頻隊(duì)列緩沖區(qū)猛们。
- 2、將音頻隊(duì)列緩沖區(qū) buffers 加入緩沖區(qū)隊(duì)列 audio queue 中狞洋。
- 3弯淘、當(dāng)沒有更多的數(shù)據(jù)要從音頻文件讀取時(shí),告訴音頻隊(duì)列停止吉懊。
此部分顯示回調(diào)聲明示例庐橙,分別描述每個(gè)任務(wù)假勿,最后呈現(xiàn)整個(gè)回放回調(diào)。 有關(guān)回放回調(diào)的作用的說明态鳖,可以參考下圖转培。
![圖](https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Art/playback_callback_function_2x.png)
(1)、The Playback Audio Queue Callback Declaration
下面展示的 音頻隊(duì)列 播放回調(diào)實(shí)例聲明浆竭,在AudioQueue.h
頭文件中聲明為AudioQueueOutputCallback
static void HandleOutputBuffer (
void *aqData, // 1
AudioQueueRef inAQ, // 2
AudioQueueBufferRef inBuffer // 3
)
介紹一下方法參數(shù):
- 1浸须、通常,
aqData
是是包含音頻隊(duì)列的狀態(tài)信息的自定義結(jié)構(gòu)(就上面定義的結(jié)構(gòu)體)邦泄,看 Define a Custom Structure to Manage State 所述羽戒。 - 2、管理這個(gè)回調(diào)的音頻隊(duì)列
- 3虎韵、一個(gè)音頻隊(duì)列緩沖區(qū)易稠,回調(diào)將通過從音頻文件讀取來填充數(shù)據(jù)。
(2)包蓝、Reading From a File into an Audio Queue Buffer(從文件中讀取到音頻隊(duì)列緩沖區(qū))
回放音頻隊(duì)列回調(diào)的第一個(gè)動(dòng)作是從音頻文件讀取數(shù)據(jù)并將其放置在音頻隊(duì)列緩沖器中驶社。看下面代碼:
AudioFileReadPackets ( // 1
pAqData->mAudioFile, // 2
false, // 3
&numBytesReadFromFile, // 4
pAqData->mPacketDescs, // 5
pAqData->mCurrentPacket, // 6
&numPackets, // 7
inBuffer->mAudioData // 8
);
參數(shù)說明:
- 1测萎、
AudioFileReadPackets
函數(shù)聲明在AudioFile.h
頭文件中亡电,從音頻文件中讀取數(shù)據(jù)并放置到音頻隊(duì)列緩沖區(qū)中 - 2、要讀取的音頻文件
- 3硅瞧、當(dāng)讀取的時(shí)候份乒,用
false
來表示函數(shù)不緩存數(shù)據(jù) - 4、輸出時(shí)腕唧,從音頻文件讀取的音頻數(shù)據(jù)的字節(jié)數(shù)
- 5或辖、輸出時(shí),從音頻文件讀取的數(shù)據(jù)的數(shù)據(jù)包描述數(shù)組枣接。 對(duì)于CBR數(shù)據(jù)颂暇,此參數(shù)的輸入值為NULL
- 6、要從音頻文件讀取的第一個(gè)數(shù)據(jù)包的數(shù)據(jù)包索引
- 7但惶、輸入時(shí)耳鸯,從音頻文件讀取的數(shù)據(jù)包數(shù)。 輸出時(shí)膀曾,實(shí)際讀取的數(shù)據(jù)包數(shù)
- 8县爬、輸出時(shí),填充的音頻隊(duì)列緩沖器包含從音頻文件讀取的數(shù)據(jù)
(3)添谊、Enqueuing an Audio Queue Buffer (將音頻隊(duì)列緩沖區(qū) buffers 加入緩沖區(qū)隊(duì)列 audio queue 中)
現(xiàn)在财喳,已經(jīng)從音頻文件讀取數(shù)據(jù)并將其放入音頻隊(duì)列緩沖區(qū)中,回調(diào)將緩沖區(qū)排入隊(duì)列碉钠,如下面代碼所示纲缓。 一旦進(jìn)入緩沖器隊(duì)列卷拘,緩沖器中的音頻數(shù)據(jù)就可供音頻隊(duì)列發(fā)送到輸出設(shè)備
AudioQueueEnqueueBuffer ( // 1
pAqData->mQueue, // 2
inBuffer, // 3
(pAqData->mPacketDescs ? numPackets : 0), // 4
pAqData->mPacketDescs // 5
);
下面介紹一下參數(shù):
- 1、
AudioQueueEnqueueBuffer
函數(shù)將音頻隊(duì)列緩沖區(qū)添加到緩沖區(qū)隊(duì)列祝高。 - 2栗弟、管理緩沖區(qū)隊(duì)列的音頻隊(duì)列
- 3、要入隊(duì)的音頻隊(duì)列緩沖區(qū)buffers
- 4工闺、音頻隊(duì)列緩沖區(qū)數(shù)據(jù)中表示的數(shù)據(jù)包數(shù)乍赫, 對(duì)于不使用數(shù)據(jù)包描述的CBR數(shù)據(jù),使用0
- 5陆蟆、對(duì)于使用數(shù)據(jù)包描述的壓縮音頻數(shù)據(jù)格式雷厂,緩沖區(qū)中數(shù)據(jù)包的數(shù)據(jù)包描述
(4)、Stopping an Audio Queue(停止音頻隊(duì)列)
回調(diào)函數(shù)的最后一件事是檢查是否沒有更多的數(shù)據(jù)要從你正在播放的音頻文件中讀取叠殷。 一旦發(fā)現(xiàn)文件的結(jié)尾改鲫,回調(diào)就要告訴播放音頻隊(duì)列停止,看如下代碼處理:
if (numPackets == 0) { // 1
AudioQueueStop ( // 2
pAqData->mQueue, // 3
false // 4
);
pAqData->mIsRunning = false; // 5
}
介紹一下代碼:
- 1林束、通過使用函數(shù)
AudioFileReadPackets
檢查是否有數(shù)據(jù)包讀认窦(由回調(diào)早先調(diào)用) - 2、使用
AudioQueueStop
函數(shù)停止音頻隊(duì)列 - 3壶冒、要停止的音頻隊(duì)列
- 4缕题、是否馬上停止,false的話就當(dāng)所有排隊(duì)緩沖區(qū)都已播放時(shí)胖腾,異步停止音頻隊(duì)列烟零。
- 5、重置音頻隊(duì)列狀態(tài)不是正在運(yùn)行
(5)咸作、A Full Playback Audio Queue Callback(完整的回調(diào)函數(shù))
static void HandleOutputBuffer (
void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer
) {
// 官方文檔這里寫的有問題
//AQPlayerState *pAqData = (AQPlayerState *) aqData; // 1
struct AQPlayerState *pAqData = aqData;
if (pAqData->mIsRunning == 0) return; // 2
UInt32 numBytesReadFromFile; // 3
UInt32 numPackets = pAqData->mNumPacketsToRead; // 4
AudioFileReadPackets (
pAqData->mAudioFile,
false,
&numBytesReadFromFile,
pAqData->mPacketDescs,
pAqData->mCurrentPacket,
&numPackets,
inBuffer->mAudioData
);
if (numPackets > 0) { // 5
inBuffer->mAudioDataByteSize = numBytesReadFromFile; // 6
AudioQueueEnqueueBuffer (
pAqData->mQueue,
inBuffer,
(pAqData->mPacketDescs ? numPackets : 0),
pAqData->mPacketDescs
);
pAqData->mCurrentPacket += numPackets; // 7
} else {
AudioQueueStop (
pAqData->mQueue,
false
);
pAqData->mIsRunning = false;
}
}
部分代碼介紹:
- 1锨阿、在實(shí)例化時(shí)提供給音頻隊(duì)列的定制數(shù)據(jù),包括表示要播放的文件的音頻文件對(duì)象(AudioFileID類型)以及各種狀態(tài)數(shù)據(jù)性宏。 請(qǐng)參閱Define a Custom Structure to Manage State群井。
- 2、如果音頻隊(duì)列停止毫胜,則立即返回。
- 3诬辈、保存從正在播放的文件中讀取的音頻數(shù)據(jù)的字節(jié)數(shù)的變量酵使。
- 4、使用從正在播放的文件中讀取的數(shù)據(jù)包數(shù)量初始化
numPackets
變量焙糟。 - 5口渔、測(cè)試是否從文件中檢索了某些音頻數(shù)據(jù)。 如果是穿撮,則將新填充的緩沖區(qū)排入隊(duì)列缺脉。 如果不是痪欲,停止音頻隊(duì)列。
- 6攻礼、告訴音頻隊(duì)列緩沖區(qū)結(jié)構(gòu)讀取的數(shù)據(jù)的字節(jié)數(shù)业踢。
- 7、根據(jù)讀取的數(shù)據(jù)包數(shù)量增加數(shù)據(jù)包索引礁扮。
三知举、Write a Function to Derive Playback Audio Queue Buffer Size(編寫一個(gè)函數(shù)去獲取播放音頻隊(duì)列緩沖區(qū)的大小)
Audio Queue Services 希望你在應(yīng)用里面給你的音頻隊(duì)列緩沖區(qū)指定大小太伊,下面提供的代碼可以導(dǎo)出足夠大的緩沖器大小以容納給定持續(xù)時(shí)間的音頻數(shù)據(jù)雇锡。
創(chuàng)建音頻隊(duì)列后,可以通過調(diào)用 DeriveBufferSize
(下面的方法)來作為請(qǐng)求音頻隊(duì)列分配緩沖區(qū)的先決條件僚焦∶烫幔可查看 Set Sizes for a Playback Audio Queue
這里的代碼做了兩個(gè)額外的事情,對(duì)比 Write a Function to Derive Recording Audio Queue Buffer Size 類似的
- 1芳悲、導(dǎo)出每次回調(diào)調(diào)用
AudioFileReadPackets
函數(shù)時(shí)要讀取的數(shù)據(jù)包數(shù) - 2立肘、設(shè)置緩沖區(qū)大小的下限,以避免磁盤訪問頻率過高
這里的計(jì)算考慮了從磁盤讀取的音頻數(shù)據(jù)格式芭概。 格式包括可能影響緩沖區(qū)大小的所有因素赛不,如音頻通道數(shù)
void DeriveBufferSize (
// 不應(yīng)該有&
//AudioStreamBasicDescription &ASBDesc, // 1
AudioStreamBasicDescription ASBDesc,
UInt32 maxPacketSize, // 2
Float64 seconds, // 3
UInt32 *outBufferSize, // 4
UInt32 *outNumPacketsToRead // 5
) {
static const int maxBufferSize = 0x50000; // 6
static const int minBufferSize = 0x4000; // 7
if (ASBDesc.mFramesPerPacket != 0) { // 8
Float64 numPacketsForTime =
ASBDesc.mSampleRate / ASBDesc.mFramesPerPacket * seconds;
*outBufferSize = numPacketsForTime * maxPacketSize;
} else { // 9
*outBufferSize =
maxBufferSize > maxPacketSize ?
maxBufferSize : maxPacketSize;
}
if ( // 10
*outBufferSize > maxBufferSize &&
*outBufferSize > maxPacketSize
)
*outBufferSize = maxBufferSize;
else { // 11
if (*outBufferSize < minBufferSize)
*outBufferSize = minBufferSize;
}
*outNumPacketsToRead = *outBufferSize / maxPacketSize; // 12
}
代碼介紹:
- 1、音頻隊(duì)列的AudioStreamBasicDescription結(jié)構(gòu)罢洲。
- 2踢故、播放的音頻文件中數(shù)據(jù)的估計(jì)最大包大小∪敲纾可以通過調(diào)用屬性ID為
kAudioFilePropertyPacketSizeUpperBound
的AudioFileGetProperty
函數(shù)(在AudioFile.h
頭文件中聲明)來確定此值殿较。請(qǐng)參閱Set Sizes for a Playback Audio Queue。 - 3桩蓉、為每個(gè)音頻隊(duì)列緩沖區(qū)指定的大辛芨佟(以秒為單位)。
- 4院究、輸出時(shí)洽瞬,每個(gè)音頻隊(duì)列緩沖區(qū)的大小(以字節(jié)為單位)业汰。
- 5伙窃、輸出時(shí),在每次調(diào)用回放音頻隊(duì)列回調(diào)時(shí)從文件讀取的音頻數(shù)據(jù)的數(shù)據(jù)包數(shù)样漆。
- 6为障、音頻隊(duì)列緩沖區(qū)大小的上限(以字節(jié)為單位)。在此示例中,上限設(shè)置為320 KB鳍怨。這對(duì)應(yīng)于大約5秒的立體聲呻右,24位音頻,采樣率為96kHz鞋喇。
- 7声滥、音頻隊(duì)列緩沖區(qū)大小的下限(以字節(jié)為單位)。在此示例中确徙,下限設(shè)置為16 KB醒串。
- 8、對(duì)于定義每個(gè)分組固定數(shù)量的幀的音頻數(shù)據(jù)格式鄙皇,導(dǎo)出音頻隊(duì)列緩沖區(qū)大小芜赌。
- 9、對(duì)于沒有為每個(gè)分組定義固定數(shù)量的幀的音頻數(shù)據(jù)格式伴逸,基于最大分組大小和你設(shè)置的上限缠沈,導(dǎo)出合理的音頻隊(duì)列緩沖區(qū)大小。
- 10错蝴、如果導(dǎo)出的緩沖區(qū)大小高于你設(shè)置的上限洲愤,請(qǐng)根據(jù)估計(jì)的最大數(shù)據(jù)包大小調(diào)整綁定。
- 11顷锰、如果派生的緩沖區(qū)大小低于你設(shè)置的下限柬赐,請(qǐng)將其調(diào)整到綁定。
- 12官紫、計(jì)算在每次調(diào)用回調(diào)時(shí)從音頻文件讀取的數(shù)據(jù)包數(shù)肛宋。
四、Open an Audio File for Playback(打開音頻文件播放)
現(xiàn)在播放音頻文件只需要下面三個(gè)步驟:
- 1束世、獲取表示要播放的音頻文件的
CFURL
對(duì)象 - 2酝陈、打開文件
- 3、獲取文件的音頻數(shù)據(jù)格式
(1)毁涉、Obtaining a CFURL Object for an Audio File(獲取播放文件的CFURL對(duì)象)
通過下面代碼獲瘸涟铩:
CFURLRef audioFileURL =
CFURLCreateFromFileSystemRepresentation ( // 1
NULL, // 2
(const UInt8 *) filePath, // 3
strlen (filePath), // 4
false // 5
);
代碼介紹:
- 1、在
CFURL.h
頭文件中聲明的CFURLCreateFromFileSystemRepresentation
函數(shù)創(chuàng)建一個(gè)表示要播放的文件的CFURL對(duì)象贫堰。 - 2穆壕、使用
NULL
(或kCFAllocatorDefault
)來使用當(dāng)前的默認(rèn)內(nèi)存分配器。 - 3其屏、要轉(zhuǎn)換為CFURL對(duì)象的文件系統(tǒng)路徑粱檀。 在生產(chǎn)代碼中,通常從用戶獲取filePath的值漫玄。
- 4、文件系統(tǒng)路徑中的字節(jié)數(shù)。
- 5睦优、值為false表示filePath表示文件渗常,而不是目錄。
還有一種方法汗盘,我覺得是比較常用的皱碘,在我demo就使用這個(gè),這個(gè)是通過傳入一個(gè)NSString 路徑實(shí)現(xiàn)的
CFStringRef strRef = (__bridge CFStringRef)filePath;
// CFURLPathStyle 不建議使用kCFURLHFSPathStyle隐孽。 使用HFS樣式路徑的Carbon文件管理器已被棄用癌椿。 HFS樣式路徑不可靠,因?yàn)樗鼈兛梢噪S意引用多個(gè)卷(如果這些卷具有相同的卷名稱)菱阵。 您應(yīng)該盡可能使用kCFURLPOSIXPathStyle踢俄。
CFURLRef audioFileURL =
CFURLCreateWithFileSystemPath(NULL,
strRef,
kCFURLPOSIXPathStyle,
YES
);
- 其中CFURLPathStyle 不建議使用kCFURLHFSPathStyle。 使用HFS樣式路徑的Carbon文件管理器已被棄用晴及。 HFS樣式路徑不可靠都办,因?yàn)樗鼈兛梢噪S意引用多個(gè)卷(如果這些卷具有相同的卷名稱)。 官方建議應(yīng)該盡可能使用這個(gè)
(2)虑稼、Opening an Audio File(打開音頻文件)
下面示例演示怎么去打開一個(gè)音頻文件去播放
AQPlayerState aqData; // 1
OSStatus result =
AudioFileOpenURL ( // 2
audioFileURL, // 3
fsRdPerm, // 4
0, // 5
&aqData.mAudioFile // 6
);
CFRelease (audioFileURL);
代碼解釋:
- 1琳钉、創(chuàng)建一個(gè)
AQPlayerState
自定義結(jié)構(gòu)體實(shí)例(可查看 Define a Custom Structure to Manage State),當(dāng)你打開一個(gè)音頻文件播放的時(shí)候蛛倦,這個(gè)實(shí)例可以控制正在播放的音頻文件(類型是AudioFileID
) - 2歌懒、
AudioFileOpenURL
函數(shù)聲明在AudioFile.h
頭文件,打開一個(gè)你想播放的音頻文件 - 3溯壶、
CFURLRef
播放引用url - 4及皂、你播放的音頻文件所需的文件權(quán)限,可用的文件權(quán)限定義在文件管理
File Access Permission Constants
枚舉中 - 5茸塞、可選的文件類型提示躲庄。 值為0表示該示例不使用此功能
- 6、在輸出上钾虐,對(duì)音頻文件的引用被放置在自定義結(jié)構(gòu)的
mAudioFile
字段中 - 7噪窘、釋放在步驟1中創(chuàng)建的
CFURLRef
對(duì)象
(3)、Obtaining a File’s Audio Data Format(獲取文件的音頻數(shù)據(jù)格式)
上代碼:
UInt32 dataFormatSize = sizeof (aqData.mDataFormat); // 1
AudioFileGetProperty ( // 2
aqData.mAudioFile, // 3
kAudioFilePropertyDataFormat, // 4
&dataFormatSize, // 5
&aqData.mDataFormat // 6
);
- 1效扫、查詢音頻文件的音頻數(shù)據(jù)格式的時(shí)候獲取預(yù)期值
- 2倔监、
AudioFileGetProperty
函數(shù),聲明在AudioFile.h
頭文件中菌仁,獲取指定音頻文件中屬性的值 - 3浩习、你想要獲取的音頻數(shù)據(jù)格式的音頻文件對(duì)象,類型是
AudioFileID
- 4济丘、獲取音頻文件數(shù)據(jù)格式值的屬性ID
- 5谱秽、在輸入時(shí)洽蛀,描述音頻文件的數(shù)據(jù)格式的
AudioStreamBasicDescription
結(jié)構(gòu)體的預(yù)期大小疟赊;在輸出時(shí)郊供,實(shí)際大小, 播放應(yīng)用程序不需要使用此值 - 6近哟、在輸出時(shí)驮审,完整的音頻數(shù)據(jù)格式,以
AudioStreamBasicDescription
結(jié)構(gòu)體的形式吉执,從音頻文件獲得疯淫。 此行通過將文件的音頻數(shù)據(jù)格式存儲(chǔ)在音頻隊(duì)列的自定義結(jié)構(gòu)中來將其應(yīng)用于音頻隊(duì)列。
下篇將介紹 創(chuàng)建音頻播放隊(duì)列并實(shí)現(xiàn)播放戳玫,會(huì)附上Demo熙掺,前往:Audio Queue Services 解讀之 Playing Audio(下)
歡迎大家關(guān)注我,喜歡就點(diǎn)個(gè)like和star量九,你的支持將是我的動(dòng)力~
翻譯過來的可能有出入适掰,如果大家發(fā)現(xiàn)有什么問題或者寫錯(cuò)的,歡迎留言荠列,謝謝