Audio latensi rendah membuat game terasa lebih realistis dan responsif.
Selesaikan checklist berikut untuk mengaktifkan audio latensi rendah di game Anda di Android:
- Menggunakan Oboe
- Meminta mode performa "latensi rendah"
- Meminta mode berbagi "eksklusif"
- Menggunakan 48.000 Hz atau pengonversi frekuensi sampel Oboe
- Menyetel penggunaan ke AAUDIO_USAGE_GAME
- Menggunakan callback data
- Menghindari operasi pemblokiran di callback
- 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 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 |