日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

使用Android高性能音频--OpenSL ES和AAudio

發(fā)布時(shí)間:2024/4/15 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Android高性能音频--OpenSL ES和AAudio 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

AAudio的概念介紹:

AAudio 是作為 OpenSL ES 庫(kù)的輕量級(jí)原生 Android 替代項(xiàng)而開發(fā)。 與 OpenSL ES 相比,AAudio API 不僅較小,而且容易使用。

AAudio 是在 Android O 版本中引入的全新 Android C API。

因此 API 是專為需要低延遲的高性能音頻應(yīng)用而設(shè)計(jì)。 應(yīng)用通過讀取并將數(shù)據(jù)寫入流來(lái)與 AAudio 進(jìn)行通信。

GitHub :AAudio Android demo地址http:// https://github.com/googlesamples/android-audio-high-performance/tree/master/aaudio

使用Android系統(tǒng)底層的OpenSL ES或者AAudio都可以實(shí)現(xiàn)一個(gè)高性能的音頻程序,尤其是AAudio更是簡(jiǎn)單易用,性能上,功能上都更佳,但是AAudio 是在 Android O 版本中才引入的全新 Android C API,在以前的系統(tǒng)版本中只能使用OpenSL ES。

  • 那么我們需要做的是在新版本系統(tǒng)中使用AAudio
  • 在不支持AAudio的系統(tǒng)版本中使用OpenSL ES,兩套 API 同時(shí)使用。

不要怕困難,因?yàn)檫@是一個(gè)即面向未來(lái),又兼顧現(xiàn)在的優(yōu)秀方案。不要害怕這有多么困難,Google已經(jīng)幫我們實(shí)現(xiàn)了——Oboe。

OpenSL ES 谷歌使用文檔介紹如下:

注意:開發(fā)者應(yīng)考慮使用開源 Oboe 庫(kù),這個(gè)庫(kù)可在?GitHub?上獲得。Oboe 是一個(gè) C++ 封裝容器,提供與?AAudio?非常相似的 API。Oboe 在 AAudio 可用時(shí)對(duì)其進(jìn)行調(diào)用,并在 AAudio 不可用時(shí)回退到 OpenSL ES。

?OpenSL ES?? API 規(guī)范的 Android 專用實(shí)現(xiàn)。利用這個(gè)庫(kù),不論您是編寫合成器、數(shù)字音頻工作站、卡拉 OK 應(yīng)用、游戲還是其他實(shí)時(shí)應(yīng)用,都可以使用 C 或 C++ 實(shí)現(xiàn)高性能、低延遲的音頻。

  • OpenSL ES 與 Android Java 框架中的?MediaPlayer?和?MediaRecorder?API 提供類似的音頻功能。
  • OpenSL ES 提供 C 語(yǔ)言接口和 C++ 綁定,讓您可以從使用任意一種語(yǔ)言編寫的代碼中調(diào)用 API。

OpenSL ES API 可以幫助您開發(fā)和提升應(yīng)用的音頻性能。


如何使用oboe?


官方指導(dǎo)文檔在這里,可以通過兩種方式使用oboe,這里是把源碼拉下來(lái)編譯到項(xiàng)目。

1. 下載oboe庫(kù)->https://github.com/google/oboe

Oboe GitHub 主頁(yè) : GitHub/Oboe

① 簡(jiǎn)單使用 : Getting Started

② Oboe 全指南 :?Full Guide To Oboe

③ Oboe API 參考 : API reference

④ Android 音頻框架發(fā)展 : Android audio history


OpenSL 的生命周期如下:

為 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ò) ;


使用總結(jié):


第一步:導(dǎo)入oboe頭文件

第二步:創(chuàng)建builder并設(shè)置參數(shù)

第三步:設(shè)置回調(diào)接口

第四步:播放音頻

第五步:關(guān)閉音頻流


下面提供一下Oboe使用實(shí)例:

錄制器:

setupCommonStreamParameters(oboe::AudioStreamBuilder *builder) {builder->setAudioApi(mAudioApi)->setSharingMode(oboe::SharingMode::Exclusive)->setPerformanceMode(oboe::PerformanceMode::LowLatency);return builder;setupRecordingStreamParameters(oboe::AudioStreamBuilder *builder ,bool isCallBack) {builder->setCallback(this)->setDirection(oboe::Direction::Input)return setupCommonStreamParameters(builder);oboe::AudioStream *mRecordingStream = nullptr;oboe::AudioStreamBuilder builder;setupRecordingStreamParameters(&builder);oboe::Result result = builder.openStream(&mRecordingStream);if (result == oboe::Result::OK && mRecordingStream) {oboe::Result result = mRecordingStream->requestStart(); //開始錄制。}

播放器:

setupCommonStreamParameters(oboe::AudioStreamBuilder *builder) {builder->setAudioApi(mAudioApi)->setSharingMode(oboe::SharingMode::Exclusive)->setPerformanceMode(oboe::PerformanceMode::LowLatency);return builder;setupPlayStreamParameters(oboe::AudioStreamBuilder *builder ,bool isCallBack) {builder->setCallback(this)->setDirection(oboe::Direction::output)return setupCommonStreamParameters(builder);oboe::AudioStream *mPlayStream = nullptr;oboe::AudioStreamBuilder builder;setupPlayStreamParameters(&builder);oboe::Result result = builder.openStream(&mPlayStream);if (result == oboe::Result::OK && mPlayStream) {oboe::Result result = mPlayStream->requestStart(); //開始播放。}oboe::DataCallbackResult LiveEffectEngine::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {render(audioData,numFrames); //audioData放入數(shù)據(jù)即可播放。return oboe::DataCallbackResult::Continue;}

?


總結(jié)

以上是生活随笔為你收集整理的使用Android高性能音频--OpenSL ES和AAudio的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。