【Android 高性能音频】Oboe 播放器开发 ( 为 OpenSL ES 配置参数以获得最佳延迟 | Oboe 音频流 | Oboe 音频设备 )
文章目錄
- 一、獲得最佳延遲
- 二、Oboe 音頻流
- 三、Oboe 音頻設(shè)備
Oboe GitHub 主頁 : GitHub/Oboe
-
① 簡單使用 : Getting Started
-
② Oboe 全指南 : Full Guide To Oboe
-
③ Oboe API 參考 : API reference
-
④ Android 音頻框架發(fā)展 : Android audio history
在 【Android 高性能音頻】Oboe 開發(fā)流程 ( 導(dǎo)入 Oboe 庫 | 使用預(yù)構(gòu)建的二進(jìn)制庫和頭文件 | 編譯 Oboe 源碼 ) 博客中介紹了 如何導(dǎo)入 Oboe 函數(shù)庫到項(xiàng)目中 , 本博客中在導(dǎo)入 Oboe 函數(shù)庫的基礎(chǔ)上 , 進(jìn)行 Oboe 播放器功能開發(fā) ;
在 【Android 高性能音頻】Oboe 開發(fā)流程 ( 包含頭 Oboe 頭文件 | 創(chuàng)建音頻流 | 設(shè)置音頻流 | 音頻流回調(diào)類 AudioStreamCallback ) 介紹了如何創(chuàng)建 AudioStreamBuilder , 以及 創(chuàng)建 AudioStreamCallback 回調(diào) ;
在 【Android 高性能音頻】Oboe 開發(fā)流程 ( 創(chuàng)建并設(shè)置 AudioStreamCallback 對(duì)象 | 打開 Oboe 音頻流 | 日志封裝 logging_macros.h ) 博客中介紹了 設(shè)置 AudioStreamCallback 對(duì)象 , 打開 Oboe 音頻流 操作 , 以及 Google 官方提供的日志封裝有文件 ;
在 【Android 高性能音頻】Oboe 開發(fā)流程 ( 檢查 Oboe 音頻流屬性 | 開始播放 | 停止播放 | 關(guān)閉 Oboe 音頻流 | 重新配置 Oboe 音頻流屬性 ) 博客中介紹了 如何開始 Oboe 音頻流播放 , 以及 播放完畢后的收尾工作 ;
在 【Android 高性能音頻】Oboe 開發(fā)流程 ( Oboe 完整代碼示例 ) 博客中 , 介紹了 一個(gè)最簡單的 Oboe 播放器開發(fā)流程 , 所有代碼及應(yīng)用配置 ;
一、獲得最佳延遲
Oboe 庫的目標(biāo)是 提供低延遲音頻流 ;
如果當(dāng)前手機(jī)是 Android 8.0 Oreo( API Level 26 ) 及以上系統(tǒng) , 就會(huì)自動(dòng)選擇 AAudio 打開音頻流 , 系統(tǒng)會(huì)自動(dòng)選擇最佳配置 , framesPerBurst 也由 AAudio 提供 ;
如果當(dāng)前手板版本 低于 Android 8.0 Oreo( API Level 26 ) , 此時(shí)會(huì)調(diào)用 OpenSL ES , OpenSL ES 播放器的參數(shù)需要完全由手動(dòng)進(jìn)行設(shè)置 ;
為 OpenSL ES 播放器設(shè)置 采樣率 與 采樣緩沖區(qū)參數(shù) :
( 1 ) 在 Java 層獲取采樣率與采樣緩沖區(qū)大小 :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){AudioManager myAudioMgr = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);// 獲取采樣率String sampleRateStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);int defaultSampleRate = Integer.parseInt(sampleRateStr);// 獲取采樣緩沖區(qū)String framesPerBurstStr = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);int defaultFramesPerBurst = Integer.parseInt(framesPerBurstStr);// 調(diào)用 Native 方法傳入本地層 native_setDefaultStreamValues(defaultSampleRate, defaultFramesPerBurst); }( 2 ) 在 C++ 代碼中設(shè)置 OpenSL ES 的參數(shù) :
JNIEXPORT void JNICALL Java_com_google_sample_oboe_hellooboe_MainActivity_native_1setDefaultStreamValues(JNIEnv *env,jclass type,jint sampleRate,jint framesPerBurst) {oboe::DefaultStreamValues::SampleRate = (int32_t) sampleRate;oboe::DefaultStreamValues::FramesPerBurst = (int32_t) framesPerBurst; }上述的采樣率 和 緩沖區(qū)大小是用于 設(shè)置 Android 設(shè)備內(nèi)置音頻設(shè)備 的 , 如 內(nèi)置揚(yáng)聲器 , 聽筒 ;
外置設(shè)備 , 如耳機(jī) , 藍(lán)牙音箱 需要設(shè)置更大的緩沖區(qū) ;
二、Oboe 音頻流
Oboe 的主要作用是在 Android 應(yīng)用 和 Android 設(shè)備中的 音頻 輸入 / 輸出 設(shè)備 之間 操作移動(dòng)音頻數(shù)據(jù) ;
Android 應(yīng)用 輸入 / 輸出 數(shù)據(jù) 方案 :
- 通過使用 回調(diào)函數(shù) 實(shí)現(xiàn)
- 直接從 音頻流 中 讀取 / 寫出 數(shù)據(jù)
音頻數(shù)據(jù)讀寫調(diào)用 , 可以是 阻塞的 ( 同步 ) , 也可以是 非阻塞的 ( 異步 ) ;
- 阻塞 : 調(diào)用后 , 阻塞等待回應(yīng) , 回應(yīng)收到后 , 才往下執(zhí)行 ;
- 非阻塞 : 調(diào)用后 , 不等待回應(yīng) , 直接向后執(zhí)行后續(xù)代碼 ;
音頻流根據(jù)如下屬性定義 :
- 音頻流方向 : 音頻設(shè)備作為 數(shù)據(jù)源 或 流數(shù)據(jù)接收器 ( 數(shù)據(jù)目的地 ) ;
- 共享模式 : 獨(dú)占模式 / 共享模式 ; 獨(dú)占模式 下音頻流獨(dú)占該設(shè)備 , 其它音頻流不允許訪問該設(shè)備 , 性能高 ; 共享模式 , 多個(gè)音頻流可以同時(shí)訪問該設(shè)備 , 性能低 ;
- 采樣格式 : 音頻流數(shù)據(jù)的采樣格式 ;
三、Oboe 音頻設(shè)備
音頻設(shè)備與音頻流對(duì)應(yīng)關(guān)系 : 每個(gè) Oboe 音頻流都需要關(guān)聯(lián)一個(gè)單獨(dú)的音頻設(shè)備 ; 注意對(duì)應(yīng)關(guān)系 , 一個(gè)音頻設(shè)備可以關(guān)聯(lián)多個(gè)音頻流 , 但是 一個(gè)音頻流只能關(guān)聯(lián)一個(gè)音頻設(shè)備 ;
音頻設(shè)備作用 : 音頻設(shè)備是一個(gè)硬件接口或者虛擬端口 , 一般作為 連續(xù)的數(shù)字音頻數(shù)據(jù)流的 源端 或 目的端 ; 音頻設(shè)備作為 數(shù)據(jù)源 或 流數(shù)據(jù)接收器 ( 數(shù)據(jù)目的地 ) ;
音頻設(shè)備舉例 : Android 設(shè)備的 內(nèi)置麥克風(fēng) , 揚(yáng)聲器 , 電話聽筒 , 或外接的耳機(jī) , 藍(lán)牙音箱 等 ;
獲取音頻設(shè)備 : Android 6.0 Marshmallow( API Level 23 ) 及以上的版本 , 可以通過調(diào)用 AudioManager 的 getDevices() 方法 , 獲取當(dāng)前的可用音頻設(shè)備 , 該方法會(huì)返回設(shè)備的類型和信息 ;
音頻設(shè)備 ID : 每個(gè)音頻設(shè)備都有一個(gè) 唯一的 ID 標(biāo)識(shí) , 使用該標(biāo)識(shí) , 可以實(shí)現(xiàn)將 音頻流 與 指定的 音頻設(shè)備進(jìn)行綁定 ; 多數(shù)情況下 , 用戶不需要自己設(shè)置音頻設(shè)備 , Oboe 會(huì)自動(dòng)選擇主設(shè)備 , 推薦讓 Oboe 自動(dòng)選擇 , 不要進(jìn)行手動(dòng)干預(yù) ;
音頻流方向 : 音頻設(shè)備 可以 決定該音頻流是 輸入流 還是 輸出流
- 輸入流 : 麥克風(fēng) , 采集音頻數(shù)據(jù) ; 設(shè)備 -> 內(nèi)存 ;
- 輸出流 : 揚(yáng)聲器 , 播放音頻數(shù)據(jù) ; 內(nèi)存 -> 設(shè)備 ;
打開 Oboe 音頻流時(shí) , 系統(tǒng)會(huì)檢查音頻流方向 , 如果你設(shè)置的是麥克風(fēng) , 但是音頻流方向設(shè)置成了輸出方向 , 那么打開音頻流操作就會(huì)出錯(cuò) ;
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【Android 高性能音频】Oboe 播放器开发 ( 为 OpenSL ES 配置参数以获得最佳延迟 | Oboe 音频流 | Oboe 音频设备 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【组合数学】组合数学简介 ( 组合思想
- 下一篇: 【组合数学】组合存在性定理 ( 三个组合