Audio mit niedriger Latenz

Audio mit niedriger Latenz macht Spiele realistischer und reaktionsschneller.

Gehen Sie die folgende Checkliste durch, um Audio mit niedriger Latenz für Ihr Android-Spiel zu aktivieren:

  1. Oboe verwenden
  2. Leistungsmodus für Anfragen „niedrige Latenz“
  3. Freigabemodus „exklusiv“ anfordern
  4. 48.000 Hz oder Oboen-Abtastratenkonverter verwenden
  5. Nutzung auf AAUDIO_USAGE_GAME festlegen
  6. Daten-Callbacks verwenden
  7. Blockierungsvorgänge im Callback vermeiden
  8. Puffergröße auf „double buffer“ einstellen

1. Oboe-API verwenden

Die Oboe API ist ein C++-Wrapper, der AAudio unter Android 8.1 (API-Level 27) und höher aufruft. Auf früheren Android-Versionen verwendet Oboe OpenSL ES.

Oboe ist auf GitHub oder als vordefiniertes Binärprogramm verfügbar. Oboe hat auch einen QuirksManager, der Probleme auf bestimmten Geräten korrigiert, sodass Ihre App mit mehr Geräten kompatibel wird. Wenn Oboe nicht verfügbar ist, verwenden Sie AAudio direkt.

2. Modus für niedrige Latenz anfordern

Fordere mit Oboe oder AAudio den Modus mit niedriger Latenz an. Andernfalls erhalten Sie standardmäßig eine höhere Latenz.

Oboe

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

A-Audio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. Exklusiven Modus anfordern

Sie können auch exklusiven Zugriff auf den MMAP-Puffer anfordern. Ihre Anwendung erhält möglicherweise keinen exklusiven Zugriff. Falls doch, schreibt sie direkt in einen Puffer, der vom DSP gelesen wird. Dadurch wird die Latenz Ihrer Anwendung so gering wie möglich.

Oboe

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

A-Audio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. Konvertierung der Abtastrate vermeiden

Verwenden Sie die natürliche Abtastrate des Geräts. Wenn Sie keine Abtastrate angeben, erhalten Sie mit hoher Wahrscheinlichkeit 48.000 Hz. Wenn Sie eine Abtastrate angeben, sendet das Audio-Framework Ihre Daten über einen anderen Pfad, der eine viel höhere Latenz haben kann.

Wenn Sie eine andere Abtastrate verwenden müssen, verwenden Sie Oboe für die Umwandlung der Abtastrate:

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

5. Anwendungsfall korrekt deklarieren

Es ist wichtig, den Grund für die Audiowiedergabe in der App anzugeben, damit das System die richtigen Routing-, Lautstärke- und Leistungseinstellungen anwenden kann. Zum Beispiel sollte in Spielen die Verwendung AAUDIO_USAGE_GAME angegeben werden, um die Latenzoptimierungen optimal zu nutzen, insbesondere wenn sie mit Bluetooth-Headsets verbunden sind.

Oboe

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

A-Audio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. Callback-Funktion verwenden

Verwenden Sie einen Callback für den Ausgabestream. Wenn Sie blockierende Schreibvorgänge verwenden und sich auf einem Gerät befinden, das den AAudio-MMAP-Modus nicht unterstützt, kann die Latenz viel höher sein.

Oboe

builder.setDataCallback(&myCallbackObject);

A-Audio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. Blockierungen im Callback vermeiden

Wenn Sie einen Stream mit niedriger Latenz verwenden, kann die Zeit zwischen Callbacks sehr kurz sein. Sie beträgt nur wenige Millisekunden. Daher ist es sehr wichtig, im Callback nichts zu tun, was lange Zeit blockieren könnte. Wenn der Callback blockiert ist, kommt es zu Pufferuntergängen und Audiostörungen.

Vermeiden Sie Folgendes in einem Callback:

  • Arbeitsspeicher zuweisen oder freigeben
  • Datei- oder Netzwerk-E/A
  • Warten auf Mutex oder Sperre
  • Schlafen
  • Einmalige CPU-Berechnungen mit hohem Aufwand

Die Callbacks sollten Berechnungen in gleichmäßiger Geschwindigkeit durchführen, um eine reibungslose Wiedergabe ohne Störungen zu gewährleisten.

8. Puffergröße anpassen

Sobald die App den Audiostream öffnet, müssen Sie die Größe des nutzbaren Zwischenspeichers für eine optimale Latenz abstimmen. Oboe stellt die Puffergröße automatisch auf zwei Bilderserien ein. Bei AAudio ist die Standardeinstellung jedoch viel höher. Verwenden Sie eine doppelte Zwischenspeicherung. Legen Sie dazu die Puffergröße auf die doppelte Burst-Größe fest. Die Burst-Größe ist die maximale Callback-Größe.

AAudio:

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

Wenn die Puffergröße zu klein ist, kann es zu Störungen aufgrund von Pufferunterläufen kommen. Sie können die Anzahl der Pannen abrufen, indem Sie AAudioStream_getXRunCount(stream) aufrufen. Vergrößern Sie den Puffer nach Bedarf.

Eine Erläuterung der pufferbezogenen Terminologie finden Sie in den GitHub-Oboe-Dokumenten.

OpenSL Spanien

Wenn Sie ältere Android-Versionen als 8.1 unterstützen, müssen Sie OpenSL ES verwenden. Wenn Sie Oboe verwenden, können Sie Ihre App so konfigurieren, dass die Latenz verbessert wird. Siehe Optimale Latenz ermitteln in der GitHub-Dokumentation.

Ergebnisse der Checkliste

Die folgende Tabelle enthält OboeTester-Messungen der Umlauflatenz (Eingabe/Ausgabe).

Konfiguration Latenz (ms)
Alle Empfehlungen befolgen 20
Leistungsmodus, keine niedrige Latenz 205
Nicht exklusiv (GETEILT) 26
44.100 Hz (AAudio) 160
44.100 Hz (Oboe SRC) 23
Kein Ausgabe-Callback (MMAP) verwenden 21
Keine Verwendung eines Ausgabe-Callbacks (nicht MMAP) 62
Puffergröße auf Maximum eingestellt 53