Android 耳返實踐 OpenSL ES AAudio Oboe

耳返概述:

耳返主要實現監聽的功能,在低延時的情況下可以給主播一個比較真實音頻的反饋,在演唱會等專業場景裏比較常用。
技術實現上來說就是要時時的把錄製進的音頻數據立刻播放出去,當然這個過程要低延遲。

AudioRecord,AudioTrack

在Android系統上做耳返,實現一個高性能的音頻錄製音頻播放是一件很痛苦的事;因爲我們並不能直接使用系統的AudioRecord,AudioTrack。這兩個函數有很大的延遲,尤其是AudioTrack,不同的系統延遲範圍在40ms到200ms之間。對於耳返來說有延遲感是不能忍受的。

那麼不使用系統API實現,要怎麼實現呢?

答案:直接和手機品牌廠商合作,拿到定製接口 hhh。
哈哈 ,如果你的公司有實力直接和各品牌廠商合作請忽略下面的內容。

OpenSL ES 和 AAudio

OpenSL ES:
OpenSL ES 是 Khronos Group 開發的 OpenSL ES™ API 規範的實現,專用於 Android。
NDK 軟件包中OpenSL ES™ API 規範 Android 特定實現。利用這個庫,不論是編寫合成器、卡拉 OK、遊戲還是其他實時應用,都可以使用 C 或 C++ 實現高性能、短延遲時間音頻。
OpenSL ES Android demo: https://github.com/googlesamples/android-ndk/tree/master/audio-echo

AAudio:
AAudio 是作爲 OpenSL ES 庫的輕量級原生 Android 替代項而開發。 與 OpenSL ES 相比,AAudio API 不僅較小,而且容易使用。
AAudio 是在 Android O 版本中引入的全新 Android C API。 此 API 是專爲需要低延遲的高性能音頻應用而設計。 應用通過讀取並將數據寫入流來與 AAudio 進行通信。
AAudio Android demo: https://github.com/googlesamples/android-audio-high-performance/tree/master/aaudio

使用android系統底層的OpenSL ES或者AAudio都可以實現一個高性能的音頻程序,尤其是AAudio更是簡單易用,性能上,功能上都更佳,但是AAudio 是在 Android O 版本中才引入的全新 Android C API,在以前的系統版本中只能使用OpenSL ES。
那麼我們需要做的是在新版本系統中使用AAudio,在不支持AAudio的系統版本中使用OpenSL ES,兩套API同時使用。不要怕困難,因爲這是一個即面向未來,又兼顧現在,歷史的good idea。不要害怕這有多麼困難,Google已經幫我們實現了——Oboe

Oboe:https://github.com/google/oboe

在這裏插入圖片描述
Oboe是一個C ++庫,可以輕鬆地在Android上構建高性能音頻應用程序。內部有OpenSL ES和AAudio兩大音頻引擎,一行代碼隨意切換使用,我們可以用JNI在android應用上使用它們。

下面提供一下Oboe使用實例:

錄製器

 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放入數據即可播放。
    
     return oboe::DataCallbackResult::Continue;
   }

我們的項目在使用Oboe做錄製和播放引擎後明顯的優化了耳返延遲問題。之前120Ms的迴路延遲設備,優化後延時在25Ms左右,對於用戶來說已經感受不到了延遲迴聲感。
很遺憾在測試了很多設備後仍發現在華爲和vivo的部分手機上耳返優化並沒有那麼明顯,還有延遲感;應該是這兩款設備在系統內部的音頻模塊上並沒有遵循Google的設計規範,待研究。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章