低延遲音訊能讓遊戲體驗更真實靈敏。
請按照下列檢查清單完成操作,為您的 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,則可以設定應用程式來降低延遲。請參閱 GitHub 說明文件中的「取得最佳延遲時間」一節。
檢查清單結果
下表為 OboeTester 對來回 (輸入到輸出) 延遲時間的測量結果。
設定 | 延遲時間 (毫秒) |
---|---|
遵循所有建議 | 20 |
並非採用低延遲效能模式 | 205 號 |
非專屬 (共用) | 26 |
44100 Hz (AAudio) | 160 |
44100 Hz (Oboe SRC) | 23 |
不使用輸出回呼 (MMAP) | 21 |
不使用輸出回呼 (非 MMAP) | 62 |
緩衝區空間設為最大 | 53 |