Audio latensi rendah

Audio latensi rendah membuat game terasa lebih realistis dan responsif.

Selesaikan checklist berikut untuk mengaktifkan audio latensi rendah di game Anda di Android:

  1. Menggunakan Oboe
  2. Meminta mode performa "latensi rendah"
  3. Meminta mode berbagi "eksklusif"
  4. Menggunakan 48.000 Hz atau pengonversi frekuensi sampel Oboe
  5. Menyetel penggunaan ke AAUDIO_USAGE_GAME
  6. Menggunakan callback data
  7. Menghindari operasi pemblokiran di callback
  8. Menyesuaikan ukuran buffer menjadi "buffer ganda"

1. Menggunakan Oboe API

Oboe API adalah wrapper C++ yang memanggil AAudio di Android 8.1 (level API 27) atau yang lebih baru. Pada versi Android sebelumnya, Oboe menggunakan OpenSL ES.

Oboe tersedia di GitHub atau sebagai biner bawaan. Oboe juga memiliki QuirksManager yang dapat mengatasi masalah di perangkat tertentu sehingga membuat aplikasi Anda kompatibel dengan lebih banyak perangkat. Jika Anda tidak dapat menggunakan Oboe, gunakan AAudio secara langsung.

2. Meminta mode latensi rendah

Dengan Oboe atau AAudio, minta mode latensi rendah. Jika tidak, Anda akan mendapatkan mode latensi yang lebih tinggi secara default.

Oboe

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

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. Meminta mode eksklusif

Anda juga dapat meminta akses eksklusif ke buffer MMAP. Aplikasi Anda mungkin tidak mendapatkan akses eksklusif, tetapi jika mendapatkannya, aplikasi Anda akan menulis secara langsung ke buffer yang dibaca oleh DSP, yang memberi aplikasi Anda latensi serendah mungkin.

Oboe

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

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. Menghindari konversi frekuensi sampel

Gunakan frekuensi sampel alami perangkat. Anda dapat melakukannya dengan tidak menentukan frekuensi sampel, dan biasanya Anda akan mendapatkan 48.000 Hz. Jika Anda menentukan frekuensi sampel, framework audio akan mengirimkan data Anda di jalur berbeda yang dapat memiliki latensi yang jauh lebih tinggi.

Jika Anda perlu menggunakan frekuensi sampel yang berbeda, gunakan Oboe untuk melakukan konversi frekuensi sampel:

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

5. Menyatakan kasus penggunaan Anda dengan benar

Menentukan alasan aplikasi Anda memutar audio sangat penting bagi sistem untuk menerapkan setelan pemilihan rute, volume, dan performa yang tepat. Misalnya, game harus menunjukkan penggunaan AAUDIO_USAGE_GAME untuk memanfaatkan sepenuhnya pengoptimalan latensi, terutama saat terhubung ke headset Bluetooth.

Oboe

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

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. Menggunakan fungsi callback

Gunakan callback untuk streaming output. Jika Anda menggunakan operasi tulis yang memblokir dan menggunakan perangkat yang tidak mendukung mode MMAP AAudio, latensi mungkin jauh lebih tinggi.

Oboe

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. Menghindari pemblokiran dalam callback

Jika Anda menggunakan streaming latensi rendah, waktu antar-callback dapat menjadi sangat singkat, hanya beberapa milidetik. Jadi, sangat penting bagi Anda untuk tidak melakukan hal apa pun dalam callback yang dapat memblokir untuk waktu yang lama. Jika callback diblokir, underflow dan gangguan buffer akan terjadi di audio.

Hindari melakukan hal berikut dalam callback:

  • Mengalokasikan atau mengosongkan memori
  • I/O file atau jaringan
  • Menunggu mutex atau kunci
  • Tidur
  • Perhitungan CPU satu kali yang berat

Callback harus melakukan perhitungan dengan kecepatan yang merata untuk pemutaran yang lancar tanpa gangguan.

8. Menyesuaikan ukuran buffer

Setelah aplikasi membuka streaming audio, Anda perlu menyesuaikan ukuran buffer yang dapat digunakan untuk mendapatkan latensi optimal. Oboe secara otomatis menyetel ukuran buffer menjadi dua burst. Namun, nilai defaultnya jauh lebih tinggi dengan AAudio. Gunakan buffering ganda dengan menyetel ukuran buffer menjadi dua kali ukuran burst. Ukuran burst adalah ukuran callback maksimum.

AAudio:

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

Jika ukuran buffer terlalu kecil, Anda mungkin akan mengalami gangguan yang disebabkan oleh underrun buffer. Anda bisa mendapatkan jumlah gangguan dengan memanggil AAudioStream_getXRunCount(stream). Tingkatkan ukuran buffer sesuai kebutuhan.

Lihat dokumen GitHub Oboe untuk mendapatkan penjelasan tentang terminologi terkait buffer.

OpenSL ES

Jika Anda mendukung versi Android sebelum 8.1, Anda harus menggunakan OpenSL ES. Jika menggunakan Oboe, Anda dapat mengonfigurasi aplikasi untuk meningkatkan latensi. Lihat Mendapatkan latensi optimal di dokumen GitHub.

Hasil checklist

Tabel berikut berisi pengukuran OboeTester untuk latensi bolak-balik (input ke output).

Konfigurasi Latensi (md)
Ikuti semua rekomendasi 20
Mode performa tanpa latensi rendah 205
Tidak EKSKLUSIF (DIBAGIKAN) 26
44.100 Hz (AAudio) 160
44.100 Hz (Oboe SRC) 23
Tidak menggunakan callback output (MMAP) 21
Tidak menggunakan callback output (bukan MMAP) 62
Ukuran buffer ditetapkan ke maksimum 53