低延遲音訊可提高遊戲的真實感,為玩家提供即時回應。
請完成以下檢查清單所列步驟,為 Android 遊戲啟用低延遲音訊:
- 使用 Oboe
- 要求「低延遲」效能模式
- 要求「專屬」共用模式
- 使用 48000 Hz 或 Oboe 取樣率轉換器
- 設定用途為 AAUDIO_USAGE_GAME
- 使用資料回呼
- 避免封鎖回呼作業
- 將緩衝區空間調整為「雙緩衝區」
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,可以設定應用程式來縮短延遲時間。詳情請見 取得最佳延遲時間 。
檢查清單結果
下表為 OboeTester 對來回 (從輸入到輸出) 延遲時間的測量結果。
設定 | 延遲時間 (毫秒) |
---|---|
依循所有建議 | 20 |
未採用低延遲效能模式 | 205 |
非專屬 (共用) | 26 |
44100 Hz (AAudio) | 160 |
44100 Hz (Oboe SRC) | 23 |
未使用輸出回呼 (MMAP) | 21 |
未使用輸出回呼 (非 MMAP) | 62 |
緩衝區空間設為最大 | 53 |