【Android 高性能音频】AAudio 音频流 数据回调细节 ( 数据回调函数优先级 | 数据回调函数 | 采样率 | 采样数 | 缓冲区调整 | 线程不安全 )
文章目錄
- I . 數據回調函數優先級
- II . 數據回調函數 相關內容
- III . 采樣率 處理細節
- IV . 數據回調函數 每次 采樣個數 numFrames
- V . 數據回調函數 緩沖區 ( AAudio 內部緩沖區 ) 調整
- VI . AAudio 音頻系統的線程安全性分析
I . 數據回調函數優先級
1 . 普通線程操作 : 從普通線程中讀寫 AAudio 音頻流的 音頻數據 , 普通線程的優先級比較低 , 容易被搶占 , 或者遇到資源抖動 , 對需要連續性能的音頻流操作造成干擾 , 出現卡頓 電流 等情況 ;
2 . 增加 AAudio 內部緩沖區 : 解決上述音頻干擾的方案就是 增加 AAudio 音頻流的內部緩沖區 , 這個緩沖區在上一篇博客中有詳細介紹 , 該緩沖區是維護在音頻設備 , 增加該緩沖區大小會提高整體 AAudio 系統采樣播放的容錯率 , 采樣足夠多 , 即使某一時刻出現了采樣不足的情況 , 也能掩蓋過去 , 不會出現卡頓電流等情況 , 讓用戶無法發現 , 但是這樣音頻的延遲會增大 ;
緩沖區相關細節 : 【Android 高性能音頻】AAudio 音頻流 緩沖區 簡介 ( AAudio 音頻流內部緩沖區 | 緩沖區幀容量 | 緩沖區幀大小 | 音頻數據讀寫緩沖區 )
3 . 低延遲推薦方案 : AAudio 音頻流 提供了一個 異步的 數據回調函數 AAudioStream_dataCallback , 該函數運行在優先級很高的線程中 , 該線程的資源不容易被搶占 , 可以提供一個較穩定的性能支持 ;
AAudio 音頻流開啟播放后 , 會自動回調該異步數據回調函數 , 在該函數中執行采樣播放的過程 , 將采樣數據寫入緩沖區 , 這組數據消費完畢后 , 又會調用回調函數 , 申請新的數據 ;
數據回調函數基本工作流程 : 【Android 高性能音頻】AAudio 音頻流 PCM 采樣 的 采樣 緩沖 播放 的 連續機制 ( 數據回調機制 | 數據回調函數指針 | 實現數據回調函數 | 設置數據回調函數 )
II . 數據回調函數 相關內容
1 . 數據回調函數原型 : 由開發者實現 , 返回值 aaudio_data_callback_result_t 類型 , 參數 按照如下參數順序實現 ;
typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(AAudioStream *stream,void *userData,void *audioData,int32_t numFrames);2 . 數據回調函數注冊 : 開發者實現了 AAudioStream_dataCallback 類型的數據回調函數后 , 需要 調用 AAudioStreamBuilder_setDataCallback 函數 設置給 AAudio 音頻流 , 然后 AAudio 處于 Started 狀態后 , 就會立刻第一次回調該數據回調函數 ;
AAudioStreamBuilder_setDataCallback(builder, myCallback, myUserData);數據回調函數基本工作流程 : 【Android 高性能音頻】AAudio 音頻流 PCM 采樣 的 采樣 緩沖 播放 的 連續機制 ( 數據回調機制 | 數據回調函數指針 | 實現數據回調函數 | 設置數據回調函數 )
III . 采樣率 處理細節
1 . 采樣率 : 每秒鐘的采樣個數 , 單位是 赫茲 ( Hz ) , 一般是 44100 Hz , 或 48000 Hz ;
在 Android 手機中 , 一般是 48000 Hz , 即每秒需要處理 48000 個采樣 ;
2 . AAudio 中采樣率處理 : 在 AAudio 音頻流中 不建議設置采樣率 , 一般使用默認采樣率即可 , 每個音頻設備都有一個最佳采樣率 , 如果不設置 , 默認就按照該最佳采樣率進行工作 , 如果設置錯了 , 那么音頻流在打開時就會失敗 ;
3 . 采樣率獲取 : 如果不設置采樣率 , 那么使用默認的采樣率 , 該默認采樣率通過調用 AAudioStream_getSampleRate () 方法獲得 ;
4 . 采樣率使用 : 獲取采樣率后 , 需要準備樣本 , 這些樣本的采樣率需要轉換成指定的采樣率 , 才能向 AAudio 音頻流中讀寫 , 如果采樣率不對 , 播出來的聲音就會出問題 ;
Android 的音頻設備采樣率一般是 48000 Hz , 需要將準備的讀寫緩沖區的音頻樣本數據采樣率轉為 48000Hz 后才能向 AAudio 音頻流中讀寫 ;
IV . 數據回調函數 每次 采樣個數 numFrames
1 . 采樣個數 : 數據回調函數中有如下細節 , stream , userData , audioData 是指針類型 , 需要從外部傳入到 函數中使用這些數據 , 但是唯獨 numFrames 參數不是由用戶指定的 , 每次的采樣個數是由 AAudio 系統指定的 ;
typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(AAudioStream *stream,void *userData,void *audioData,int32_t numFrames);2 . 采樣個數實際測試值 : 這個值在不同系統 , 版本 , 硬件手機上可能不同 , 但是我測試的 三星 小米 華為等手機 , 該值是 192 , 意味著 每次采集 192 幀的數據 , 每幀的樣本數是 通道數 ;
3 . 采集的樣本緩沖區大小 :
- ① 幀 : numFrames 單位是幀 ;
- ② 樣本數 : 每幀的樣本數 等于 通道數 , 如果是單聲道 每幀有 1 個樣本 , 如果是立體聲 , 每幀有 2 個樣本 ;
- ③ 每個樣本字節數 : AAUDIO_FORMAT_PCM_I16 每個樣本 2 字節 , AAUDIO_FORMAT_PCM_FLOAT 每個樣本 4 字節 ;
- ④ 立體聲 16 位整形采樣 : AAudio 中每個樣本都有指定的個數 , 16 位整形樣本 AAUDIO_FORMAT_PCM_I16 代表 16 位采樣 , 每個樣本有 兩個字節 , 那么需要采集的樣本緩沖區大小為 numFrames×2×2numFrames \times 2 \times 2numFrames×2×2 個樣本 ;
V . 數據回調函數 緩沖區 ( AAudio 內部緩沖區 ) 調整
1 . 降低延遲 : 如果要求 AAudio 延遲盡可能低 , 需要將其內部緩沖區大小降到最低 ;
2 . 增加容錯 : 緩沖區太小 , 容錯空間也跟著變小 , 稍有風吹草動 , 就會出現卡頓 電流等播放異常的情況 , 這就需要增加緩沖區 ;
3 . 動態修改 : 上述兩個需求相互沖突 , 就必須在二者之間找到平衡 , 在不出現播放異常的情況下 , 找到能夠在當前性能下容錯的最小緩沖區 , 該值要隨著系統環境變化而動態修改 ;
4 . 調整緩沖區方法 : 在下面兩篇博客中有調整緩沖區的細節 ;
- ① 【Android 高性能音頻】AAudio 音頻流 緩沖區 簡介 ( AAudio 音頻流內部緩沖區 | 緩沖區幀容量 | 緩沖區幀大小 | 音頻數據讀寫緩沖區 )
- ② 【Android 高性能音頻】AAudio 緩沖區控制 ( XRun | 欠載 UnderRun | 超限 OverRun | 獲取緩沖區大小 | 設置緩沖區大小 )
VI . AAudio 音頻系統的線程安全性分析
1 . 線程不安全 : AAudio 的 API 大部分都是線程不安全的 ;
2 . 線程不安全原理 : 線程安全就意味著存在線程同步機制 , 線程同步就涉及到了線程的阻塞等待機制 , 在 AAudio 系統中顯然不能出現線程的阻塞 , 每秒鐘回調幾千次 , 一旦阻塞1毫秒 , 整個系統都無法正常運行 ; 此外線程阻塞后 , 其會被搶占甚至干擾 , 導致后續無法以高效率運行 ;
3 . 避免多線程操作 : 在調用 AAudio 時 , 盡量避免多線程操作 AAudio ;
- ① 等待狀態改變操作 : AAudioStream_waitForStateChange() 操作會造成線程阻塞 , 禁止在不同線程中調用該方法 ;
- ② 讀寫操作 : 禁止在 不同線程中 讀寫同一個 AAudio 音頻流 ;
4 . 線程安全的操作 :
- ① 獲取 AAudio 配置的操作 : 除 AAudioStream_getTimestamp 方法是線程不安全的之外 , 其它的 AAudioStream_get*() 類的方法 都是線程安全的 ;
- ② 創建 AAudio 音頻流構建器 : AAudio_createStreamBuilder() 方法是線程安全的 ;
- ③ 輸出 AAudio 文本 : AAudio_convert*ToText() 類的方法也是線程安全的 ;
總結
以上是生活随笔為你收集整理的【Android 高性能音频】AAudio 音频流 数据回调细节 ( 数据回调函数优先级 | 数据回调函数 | 采样率 | 采样数 | 缓冲区调整 | 线程不安全 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 高性能音频】AAudi
- 下一篇: 【Android 应用开发】Androi