低延遲音訊

低延遲音訊能讓遊戲體驗更真實靈敏。

請按照下列檢查清單完成操作,為您的 Android 遊戲啟用低延遲音訊功能:

  1. 使用 Oboe
  2. 要求「低延遲」效能模式
  3. 要求「專屬」共用模式
  4. 使用 48000 Hz 或 Oboe 取樣率轉換器
  5. 設為使用 AAUDIO_USAGE_GAME
  6. 使用資料回呼
  7. 避免回呼作業遭到封鎖
  8. 將緩衝區空間調整為「雙緩衝區」

1. 使用 Oboe API

Oboe API 是 C++ 包裝函式,會在 Android 8.1 (API 級別 27) 以上版本中呼叫 AAudio。在舊版 Android 中,Oboe 是使用 OpenSL ES。

您可以在 GitHub 上或以預建二進位檔的形式取得 Oboe。Oboe 也提供 QuirksManager,用來修正特定裝置上的問題,讓應用程式與更多裝置相容。如果無法使用 Oboe,請直接使用 AAudio。

2. 要求低延遲模式

請使用 Oboe 或 AAudio 要求低延遲模式。否則根據預設,您會採用延遲時間較長的模式。

Oboe

builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. 要求專屬模式

您也可以要求 MMAP 緩衝區的專屬存取權。應用程式可能無法取得專屬存取權,但如果具備這項權限,就會直接寫入由 DSP 讀取的緩衝區,將延遲時間降至最低。

Oboe

builder.setSharingMode(oboe::SharingMode::Exclusive);

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. 避免取樣率轉換

請使用裝置的自然取樣率,如要這麼做,請不要指定取樣率,但幾乎確定得到 48000 Hz。如果您指定取樣率,音訊架構會透過其他路徑傳送資料,且該路徑的延遲時間可能較長。

如果需要採用不同的取樣率,請使用 Oboe 執行取樣率轉換作業:

builder->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium);

5. 適當宣告用途

請務必指定應用程式播放音訊的原因,這樣系統才能套用正確的轉送、音量和效能設定。舉例來說,遊戲應指示使用 AAUDIO_USAGE_GAME,藉此充分運用延遲最佳化功能,這在連線至藍牙耳機時尤其重要。

Oboe

builder.setUsage(oboe::Usage::Game);

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. 使用回呼函式

請為輸出串流使用回呼。如果您使用封鎖寫入功能,但裝置不支援 AAudio MMAP 模式,則延遲可能會高出許多。

Oboe

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. 避免回呼遭到封鎖

使用低延遲串流時,回呼之間的間隔可能非常短,只有幾毫秒。因此,請務必不要在回呼中採取任何可能長時間封鎖的回呼。如果回呼遭到封鎖,緩衝區會發生反向溢位,音訊中也會出現異常。

請避免在回呼中執行下列操作:

  • 分配或釋出記憶體
  • 檔案或網路 I/O
  • 等待互斥鎖或鎖
  • 睡覺
  • 大量一次性 CPU 計算

回呼應以均勻的速度執行運算,才能流暢播放音訊,而不會出現異常。

8. 調整緩衝區空間

應用程式開啟音訊串流後,您需要調整可用的緩衝區空間,才能最佳化延遲時間。Oboe 會自動將緩衝區空間設為兩個爆發,但使用 AAudio 時,這項預設值會高出許多。將緩衝區空間設為爆增大小的兩倍,藉此使用雙重緩衝功能。爆發大小是回呼大小上限。

AAudio:

int32_t frames = AAudioStream_getFramesPerBurst() * 2;
AAudioStream_setBufferSizeInFrames(stream, frames);

如果緩衝區空間太小,則可能因緩衝區欠載而出現異常。您可以呼叫 AAudioStream_getXRunCount(stream),瞭解異常次數。請視需要增加緩衝區空間。

如需緩衝區相關術語的說明,請參閱 GitHub Oboe 文件

OpenSL ES

如果使用 Android 8.1 以下版本,就必須使用 OpenSL ES。若是使用 Oboe,則可以設定應用程式來降低延遲。請參閱 GitHub 說明文件中的「取得最佳延遲時間」一節。

檢查清單結果

下表為 OboeTester 對來回 (輸入到輸出) 延遲時間的測量結果。

設定 延遲時間 (毫秒)
遵循所有建議 20
並非採用低延遲效能模式 205 號
非專屬 (共用) 26
44100 Hz (AAudio) 160
44100 Hz (Oboe SRC) 23
不使用輸出回呼 (MMAP) 21
不使用輸出回呼 (非 MMAP) 62
緩衝區空間設為最大 53