【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )
文章目錄
- I . AAudio 音頻流 創(chuàng)建 配置 使用 銷毀 流程
- II . AAudio 音頻流 穩(wěn)定狀態(tài) 與 過(guò)渡狀態(tài)
- III . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng)
- IV . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng) 實(shí)例 ( 暫停操作 )
- V . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng) 注意事項(xiàng)
I . AAudio 音頻流 創(chuàng)建 配置 使用 銷毀 流程
紅色標(biāo)題是本博客講解的內(nèi)容 , 黑色是前幾篇講過(guò)的內(nèi)容 ;
使用 AAudio 音頻庫(kù) , 首先需要導(dǎo)入 AAudio.h 頭文件 ;
#include <AAudio.h>創(chuàng)建 AAudio 音頻流 , 需要先創(chuàng)建 AAudio 音頻流構(gòu)建器 , 然后在通過(guò)該構(gòu)建器創(chuàng)建音頻流 ;
//創(chuàng)建構(gòu)建器 , AAudio 音頻流通過(guò)該構(gòu)建器創(chuàng)建//聲明 AAudio 音頻流構(gòu)建器 指針AAudioStreamBuilder *builder = nullptr;//創(chuàng)建 AAudio 音頻流構(gòu)建器 , 注意傳入二維指針aaudio_result_t result = AAudio_createStreamBuilder(&builder);設(shè)置音頻設(shè)備 ID ;
// 設(shè)置音頻流設(shè)備 IDAAudioStreamBuilder_setDeviceId(builder, playbackDeviceId_);設(shè)置音頻流方向 ;
// 設(shè)置音頻流方向AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);設(shè)置音頻設(shè)備共享模式 ;
// 設(shè)置共享模式 , 獨(dú)占模式性能更高 , 延遲更低 ; 如果 該音頻設(shè)備正在被使用 , 設(shè)置失敗會(huì)自動(dòng)設(shè)置成 共享模式AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);設(shè)置性能模式 ;
// 設(shè)置性能模式AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);設(shè)置 AAudio 音頻流通道數(shù) :
// 設(shè)置通道個(gè)數(shù)AAudioStreamBuilder_setChannelCount(builder, sampleChannels_);設(shè)置 AAudio 音頻流樣本格式 :
// 設(shè)置音頻格式AAudioStreamBuilder_setFormat(builder, sampleFormat_);設(shè)置 AAudio 音頻流緩沖區(qū)大小 : 這里的緩沖區(qū)是播放器的緩沖區(qū) , 單位是幀 , 每幀的采樣數(shù)就是通道數(shù) , 單聲道 每幀 1 個(gè)采樣, 雙聲道立體聲每幀 2 個(gè)采樣 , 分別對(duì)應(yīng)左右聲道的采樣 ;
// 設(shè)置每幀的緩沖區(qū)大小 , 可以通過(guò)該設(shè)置達(dá)到盡可能低的延遲AAudioStream_setBufferSizeInFrames(playStream_, framesPerBurst_);創(chuàng)建 AAudio 音頻流 : 創(chuàng)建 AAudio 音頻流 , 就是打開(kāi)音頻流 , 注意要在音頻流參數(shù)設(shè)置完畢后才能打開(kāi)音頻流 ;
// 打開(kāi)音頻流 ( 該步驟就是創(chuàng)建音頻流 )aaudio_result_t result = AAudioStreamBuilder_openStream(builder, &playStream_);銷毀 AAudio 音頻流構(gòu)建器 : 在音頻流創(chuàng)建 ( 打開(kāi) ) 完畢后 , 應(yīng)該馬上銷毀 AAudio 音頻流構(gòu)建器 ;
//銷毀音頻流構(gòu)建器AAudioStreamBuilder_delete(builder);使用 AAudio 音頻流 進(jìn)行 錄音 或 播放操作 , 使用完畢后需要 銷毀 AAudio 音頻流 ;
停止 AAudio 音頻流 : 如果 AAudio 音頻流不再使用 , 需要馬上銷毀 AAudio 音頻流 , 銷毀前需要先將音頻流停止 , 然后才能銷毀 ;
//先停止音頻流 , 然后才能關(guān)閉aaudio_result_t result = AAudioStream_requestStop(playStream_);關(guān)閉 AAudio 音頻流 : 如果 AAudio 音頻流不再使用 , 需要馬上銷毀 AAudio 音頻流 , 該流會(huì)占據(jù)音頻設(shè)備資源 , 不用應(yīng)馬上銷毀 ;
//關(guān)閉音頻流 , 關(guān)閉后 , 該音頻流就徹底釋放了 , 如果在使用 , 必須重新創(chuàng)建result = AAudioStream_close(playStream_);II . AAudio 音頻流 穩(wěn)定狀態(tài) 與 過(guò)渡狀態(tài)
1 . AAudio 音頻流有 6 種穩(wěn)定狀態(tài) :
- ① Open : 音頻流打開(kāi)后的狀態(tài) , 就是 Open 狀態(tài) , 該狀態(tài)時(shí)間很短 , 馬上回自動(dòng)轉(zhuǎn)到下一狀態(tài) ;
- ② Started : 音頻流打開(kāi)后 , 會(huì)自動(dòng)從 Open 狀態(tài)轉(zhuǎn)為 Started 狀態(tài) , 該狀態(tài)下音頻流的音頻數(shù)據(jù) , 處于流動(dòng)狀態(tài) , 這個(gè)過(guò)程占生命周期的 99.999% 的時(shí)間 ;
- ③ Paused : 暫停狀態(tài) , 在 Started 狀態(tài)下 , 如果調(diào)用 AAudioStream_requestPause() 方法 , 就會(huì)進(jìn)入該狀態(tài) ; 此時(shí)播放器是暫停的 , 可以隨時(shí)恢復(fù)播放 , 調(diào)用 AAudioStream_requestStart() 方法 , 可以恢復(fù)播放 , 進(jìn)入 Started 狀態(tài) ;
- ④ Flushed : 刷寫(xiě)狀態(tài) , 在 Paused 狀態(tài)下 , 調(diào)用 AAudioStream_requestFlush() 方法 , 就會(huì)進(jìn)入該狀態(tài) , 這是將播放器緩沖區(qū)中的數(shù)據(jù)播放完畢 , 可以清空緩沖區(qū) ; 調(diào)用 AAudioStream_requestStart() 方法 , 可以恢復(fù)播放 , 進(jìn)入 Started 狀態(tài) ;
- ⑤ Stopped : 停止?fàn)顟B(tài) , 在 Started 狀態(tài)下 , 如果調(diào)用 AAudioStream_requestStop() 方法 , 就會(huì)進(jìn)入該狀態(tài) ; 此時(shí)如果要恢復(fù)成 Started 狀態(tài) , 需要調(diào)用 AAudioStream_requestStart() 方法 ;
- ⑥ Closed : 關(guān)閉狀態(tài) , 在 Stopped 狀態(tài)下 , 如果調(diào)用 AAudioStream_close() 方法 , 就會(huì)進(jìn)入 Closed 狀態(tài) ; 該狀態(tài)意味著 AAudio 音頻流被銷毀 , 無(wú)法再繼續(xù)使用 ;
總結(jié) :
處于 暫停 ( Paused ) , 停止 ( Stopped ) , 刷寫(xiě) ( Flushed ) 狀態(tài)下 , 可以調(diào)用 AAudioStream_requestStart() 方法 , 恢復(fù)成 Started 狀態(tài) ;
刷寫(xiě) ( Flushed ) 狀態(tài) 必須 有前置狀態(tài) 暫停狀態(tài) ( Paused ) 才能進(jìn)入該狀態(tài) , 其它狀態(tài)下是無(wú)法進(jìn)入 刷寫(xiě)狀態(tài)的 ;
2 . AAudio 音頻流有 5 種 過(guò)渡狀態(tài) : 過(guò)渡狀態(tài)是兩種穩(wěn)定狀態(tài)之間的狀態(tài) ;
- ① Starting 狀態(tài) : Open 狀態(tài) 與 Started 狀態(tài) 之間的 過(guò)渡狀態(tài) ;
- ② Pausing 狀態(tài) : Started 狀態(tài) 與 Paused 狀態(tài)之間的 過(guò)渡狀態(tài) ;
- ③ Flushing 狀態(tài) : Paused 狀態(tài) 與 Flushed 狀態(tài)之間的 過(guò)渡狀態(tài) ;
- ④ Stopping 狀態(tài) : Started 狀態(tài) 與 Stopped 狀態(tài) 之間的過(guò)渡狀態(tài) ;
- ⑤ Closing 狀態(tài) : Stopped 狀態(tài) 與 Closed 狀態(tài) 之間的過(guò)渡狀態(tài) ;
3 . 11 個(gè)狀態(tài)之間的狀態(tài)機(jī)轉(zhuǎn)化關(guān)系如下圖 :
III . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng)
1 . AAudio 音頻流狀態(tài)監(jiān)聽(tīng)簡(jiǎn)介 :
- ① 沒(méi)有回調(diào)函數(shù) : AAudio 沒(méi)有提供 監(jiān)聽(tīng) 音頻流狀態(tài)的 回調(diào)函數(shù) ;
- ② 等待變更方法 : 目前只能使用 AAudioStream_waitForStateChange() 方法 , 該方法調(diào)用后 , 開(kāi)始阻塞 , 等待 AAudio 音頻流變更成 不同于 開(kāi)發(fā)者指定的狀態(tài) 的 其它狀態(tài)后 , 繼續(xù)執(zhí)行下面的代碼 ;
2 . AAudioStream_waitForStateChange 方法簡(jiǎn)介 :
- ① 函數(shù)原型 : 調(diào)用該函數(shù)時(shí) , 當(dāng)前狀態(tài)應(yīng)該是 inputState 狀態(tài) , 之后一直阻塞 , 該函數(shù)會(huì)等待 當(dāng)前狀態(tài) , 不是 inputState 狀態(tài)時(shí) , 接觸阻塞 , 繼續(xù)執(zhí)行下面的代碼 ;
- ② 參數(shù) 1 AAudioStream *stream : 狀態(tài)機(jī)所屬的 AAudio 音頻流 ;
- ③ 參數(shù) 2 aaudio_stream_state_t inputState : 初始狀態(tài) , 調(diào)用該方法時(shí)的狀態(tài) ; 當(dāng) AAudio 音頻流狀態(tài)不是該狀態(tài)時(shí) , 方法阻塞解除 ;
- ④ 參數(shù) 3 aaudio_stream_state_t *nextState : 下一個(gè)狀態(tài)的指針 , 指向一個(gè)狀態(tài)值 , 該值是 解除阻塞的時(shí)刻的 AAudio 音頻流狀態(tài) ; 用于在后續(xù)執(zhí)行時(shí)獲取當(dāng)前是什么狀態(tài) ;
- ⑤ 參數(shù) 4 int64_t timeoutNanoseconds : 超時(shí)時(shí)間 , 該方法不可能一直阻塞代碼執(zhí)行 , 當(dāng)超過(guò)一定時(shí)間后 , 繼續(xù)執(zhí)行后續(xù)的代碼 ;
- ⑥ 返回值 aaudio_result_t : 如果成功 , 返回 AAUDIO_OK , 如果失敗會(huì)返回對(duì)應(yīng)的錯(cuò)誤碼 ;
IV . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng) 實(shí)例 ( 暫停操作 )
1 . 監(jiān)聽(tīng)暫停操作 : 在 Started 狀態(tài)下 , 調(diào)用 AAudioStream_requestPause() 方法 , 設(shè)置 AAudio 音頻流暫停操作 ;
2 . 理論上的狀態(tài)改變 : 方法調(diào)用后 , AAudio 音頻流 會(huì)立刻進(jìn)入 Pausing 過(guò)渡狀態(tài) , 然后處理過(guò)渡操作 , 處理完畢后 , 進(jìn)入 Paused 狀態(tài) ;
3 . 代碼實(shí)現(xiàn) :
- ① 申請(qǐng)暫停 : 調(diào)用 AAudioStream_requestPause() 方法之后 ;
- ② 當(dāng)前狀態(tài) : 申請(qǐng)暫停后 , 當(dāng)前狀態(tài)馬上切換成了 Pausing 狀態(tài) ;
- ③ 阻塞程序 : 此時(shí) 立刻調(diào)用 AAudioStream_waitForStateChange() 方法 , 其中的 第二個(gè)參數(shù) inputState 設(shè)置成 Pausing 狀態(tài) , 該方法阻塞了程序運(yùn)行 ;
- ④ 解除阻塞 : 當(dāng)狀態(tài)由 Pausing 轉(zhuǎn)為其它狀態(tài) ( 一般是 Paused 狀態(tài) ) , 或者超時(shí) , 阻塞解除 , 繼續(xù)執(zhí)行下面的代碼 ;
V . AAudio 音頻流 狀態(tài)改變 監(jiān)聽(tīng) 注意事項(xiàng)
1 . 申請(qǐng)關(guān)閉 操作 無(wú)法監(jiān)聽(tīng)狀態(tài) : 當(dāng)前如果是 Stopped 狀態(tài) , 調(diào)用 AAudioStream_close() 方法后 AAudio 音頻流會(huì)直接被刪除 , 無(wú)法調(diào)用 AAudioStream_waitForStateChange 方法監(jiān)聽(tīng) 音頻流 狀態(tài) ;
2 . 監(jiān)聽(tīng)時(shí)不要關(guān)閉流 : 如果調(diào)用了 AAudioStream_waitForStateChange () 方法監(jiān)聽(tīng) AAudio 音頻流 狀態(tài) , 當(dāng)前線程雖然在阻塞狀態(tài) , 無(wú)法操作 , 但是不要在另外的線程中關(guān)閉該 AAudio 音頻流 ;
總結(jié)
以上是生活随笔為你收集整理的【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Android 高性能音频】AAudi
- 下一篇: 【Android 高性能音频】AAudi