Audiolatenz

Latenz ist die Zeit, die ein Signal benötigt, um ein System zu durchlaufen. Dies sind die gängigen Arten von Latenzen bei Audio-Apps:

  • Die Latenz der Audioausgabe ist die Zeit zwischen der Erstellung eines Samples durch einen App und das Sample, das über den Kopfhöreranschluss oder den integrierten Lautsprecher abgespielt wird.
  • Die Latenz der Audioeingabe ist die Zeit, die zwischen dem Empfang eines Audiosignals durch eine die Audioeingabe des Geräts, wie das Mikrofon, und dieselben Audiodaten, die auch für ein
  • Die Umlauflatenz ist die Summe aus Eingabelatenz, Anwendungsverarbeitungszeit die Ausgabelatenz.

  • Die Berührungslatenz ist die Zeitspanne zwischen der Bildschirmberührung durch einen Nutzer und einer ein Touch-Ereignis, das von einer App empfangen wird.
  • Die Aufwärmlatenz ist die Zeit, die für den Start der Audiopipeline benötigt wird. Zeit, die Daten in einen Zwischenspeicher eingereiht werden.

Auf dieser Seite wird beschrieben, wie Sie Audio-Apps mit Ein- und Ausgabe mit niedriger Latenz entwickeln und wie Sie Aufwärmlatenz.

Latenz messen

Es ist schwierig, die Latenz von Audioein- und -ausgabe isoliert zu messen, da Sie genau wissen müssen, wenn das erste Sample an den Audiopfad gesendet wird (dies kann jedoch mit einer <ph type="x-smartling-placeholder"></ph> und einem Oszilloskop. Wenn Sie die Rundlauf-Audiolatenz kennen, Als Faustregel gilt: Die Latenz der Audioeingabe (und -ausgabe) ist halb so hoch wie die Latenz über Pfade ohne Signalverarbeitung.

Die Umlauf-Audiolatenz kann je nach Gerätemodell und Android-Build Sie können sich eine ungefähre Vorstellung der Latenz bei Nexus-Geräten veröffentlichten Messungen.

Sie können die Umlauf-Audiolatenz messen, indem Sie eine App erstellen, die ein Audiosignal erzeugt, auf dieses Signal wartet und die Zeit zwischen dem Senden und dem Empfang misst.

Da bei Audiopfaden mit minimaler Signalverarbeitung die niedrigste Latenz erreicht wird, auch ein <ph type="x-smartling-placeholder"></ph> Audio-Loopback-Dongle, mit dem der Test über den Headset-Anschluss ausgeführt werden kann.

Best Practices zur Minimierung der Latenz

Audioleistung prüfen

Im Android Compatibility Definition Document (CDD) sind die Hardware und Software eines kompatiblen Android-Geräts. Weitere Informationen finden Sie unter . Android-Kompatibilität. <ph type="x-smartling-placeholder"></ph> CDD für das eigentliche CDD-Dokument.

Im CDD wird die Umlauflatenz mit 20 ms oder weniger angegeben (obwohl Musiker normalerweise 10 ms benötigen). Das liegt daran, dass es wichtige Anwendungsfälle gibt, 20 ms.

Es gibt derzeit keine API, um die Audiolatenz in einem beliebigen Pfad auf einem Android-Gerät unter Laufzeit. Sie können jedoch die folgenden Flags für Hardwarefunktionen verwenden, um herauszufinden, dass das Gerät die Latenz garantiert:

Die Kriterien für die Meldung dieser Flags sind im CDD in Abschnitten definiert 5.6 Audiolatenz und 5.10 Professionelle Audioqualität.

So finden Sie diese Funktionen in Java:

Kotlin

val hasLowLatencyFeature: Boolean =
        packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)

val hasProFeature: Boolean =
        packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO)

Java

boolean hasLowLatencyFeature =
    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);

boolean hasProFeature =
    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);

Die android.hardware.audio.low_latency in Bezug auf die Beziehung zwischen den Audiofunktionen Funktion ist eine Voraussetzung für android.hardware.audio.pro. Ein Gerät kann android.hardware.audio.low_latency und nicht android.hardware.audio.pro, aber nicht und umgekehrt.

Keine Annahmen über die Audioleistung anstellen

Beachten Sie die folgenden Annahmen, um Latenzprobleme zu vermeiden:

  • Gehen Sie nicht davon aus, dass die Lautsprecher und Mikrofone von Mobilgeräten für die Akustik. Aufgrund ihrer geringen Größe ist die Akustik in der Regel schlecht, sodass die Signalverarbeitung um die Klangqualität zu verbessern. Diese Signalverarbeitung führt zu Latenz.
  • Gehen Sie nicht davon aus, dass die Eingabe- und Ausgabe-Callbacks synchronisiert werden. Für gleichzeitige Eingabe Für jede Seite werden separate Handler zum Abschluss von Pufferwarteschlangen verwendet. Es gibt keine Garantie der relativen Reihenfolge dieser Callbacks oder der Synchronisierung der Audiouhren, auch wenn beide Seiten dieselbe Abtastrate verwenden. Die Anwendung sollte die Daten mit Puffersynchronisierung.
  • Gehen Sie nicht davon aus, dass die tatsächliche Stichprobenrate genau mit der Nominalrate übereinstimmt. Für Beträgt die Nennabtastrate beispielsweise 48.000 Hz, ist es normal, dass der Audiotakt voranschreitet mit einer etwas anderen Geschwindigkeit als das Betriebssystem CLOCK_MONOTONIC. Das liegt daran, können Audio- und Systemuhren von verschiedenen Kristallen abgeleitet werden.
  • Gehen Sie nicht davon aus, dass die tatsächliche Wiedergabe-Abtastrate genau mit dem tatsächlichen Erfassungsbeispiel übereinstimmt. insbesondere wenn sich die Endpunkte auf separaten Pfaden befinden. Wenn Sie beispielsweise des On-Device-Mikrofons bei einer Nennabtastrate von 48.000 Hz und Wiedergabe über USB-Audio bei einer Nominalabtastrate von 48.000 Hz weichen die tatsächlichen Abtastraten wahrscheinlich leicht voneinander ab voneinander zu lernen.

Eine Folge potenziell unabhängiger Audiouhren ist die Notwendigkeit einer asynchronen Abtastrate. Conversion. Ein einfaches (aber nicht ideal für die Audioqualität) Verfahren für die asynchrone Abtastrate Conversion besteht darin, Stichproben nach Bedarf nahe einem Punkt zu duplizieren oder zu verwerfen. Mehr komplexe Konvertierungen sind möglich.

Eingabelatenz minimieren

In diesem Abschnitt finden Sie Vorschläge dazu, wie Sie die Latenz der Audioeingabe bei Aufnahmen mit einem integriertes Mikrofon oder externes Headsetmikrofon verwenden.

  • Wenn deine App den Eingang überwacht, empfehle Nutzern, ein Headset zu verwenden. z. B. durch Aufrufen des Bildschirms Beste Kopfhörer mit Kopfhörern bei der ersten Ausführung. Hinweis dass die Nutzung des Headsets nicht automatisch die geringstmögliche Latenz garantiert. Möglicherweise musst du weitere Schritte ausführen, um unerwünschte Signalverarbeitungen aus dem Audiopfad zu entfernen, z. B. mithilfe der VOICE_RECOGNITION bei der Aufnahme.
  • Auf die Verarbeitung von Nominalabtastraten von 44.100 und 48.000 Hz vorbereitet sein, wie in den <ph type="x-smartling-placeholder"></ph> getProperty(String) für <ph type="x-smartling-placeholder"></ph> PROPERTY_OUTPUT_SAMPLE_RATE festgelegt werden. Andere Stichprobenraten sind möglich, werden aber selten.
  • Sie müssen auf die Verarbeitung der Puffergröße vorbereitet sein, die von <ph type="x-smartling-placeholder"></ph> getProperty(String) für <ph type="x-smartling-placeholder"></ph> PROPERTY_OUTPUT_FRAMES_PER_BUFFER festgelegt werden. Typische Puffergrößen sind 96, 128, 160, 192, 240, 256, oder 512 Frames aufnehmen, aber andere Werte sind möglich.

Ausgabelatenz minimieren

Optimale Stichprobenrate verwenden wenn Sie Ihren Audioplayer erstellen

Um die niedrigste Latenz zu erzielen, müssen Sie Audiodaten bereitstellen, die dem optimalen Wert des Geräts entsprechen. Stichprobenrate und Puffergröße. Weitere Informationen finden Sie unter <ph type="x-smartling-placeholder"></ph> Geringere Latenz bei der Entwicklung berücksichtigen.

In Java lässt sich die optimale Abtastrate im AudioManager abrufen, wie im Folgenden gezeigt: Codebeispiel:

Kotlin

val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val sampleRateStr: String? = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
var sampleRate: Int = sampleRateStr?.let { str ->
    Integer.parseInt(str).takeUnless { it == 0 }
} ?: 44100 // Use a default value if property not found

Java

AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
String sampleRateStr = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
int sampleRate = Integer.parseInt(sampleRateStr);
if (sampleRate == 0) sampleRate = 44100; // Use a default value if property not found

Sobald Sie die optimale Abtastrate kennen, können Sie sie bei der Erstellung Ihres Players angeben. In diesem Beispiel wird OpenSL ES verwendet:

// create buffer queue audio player
void Java_com_example_audio_generatetone_MainActivity_createBufferQueueAudioPlayer
        (JNIEnv* env, jclass clazz, jint sampleRate, jint framesPerBuffer)
{
   ...
   // specify the audio source format
   SLDataFormat_PCM format_pcm;
   format_pcm.numChannels = 2;
   format_pcm.samplesPerSec = (SLuint32) sampleRate * 1000;
   ...
}

Hinweis: samplesPerSec bezieht sich auf die Abtastrate pro Kanal in Millihertz (1 Hz = 1.000 mHz).

Optimale Zwischenspeichergröße verwenden, um Audiodaten in die Warteschlange zu stellen

Sie können die optimale Puffergröße auf ähnliche Weise wie die optimale Stichprobenrate erhalten, indem Sie die AudioManager-API:

Kotlin

val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val framesPerBuffer: String? = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
var framesPerBufferInt: Int = framesPerBuffer?.let { str ->
    Integer.parseInt(str).takeUnless { it == 0 }
} ?: 256 // Use default

Java

AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
int framesPerBufferInt = Integer.parseInt(framesPerBuffer);
if (framesPerBufferInt == 0) framesPerBufferInt = 256; // Use default

Die <ph type="x-smartling-placeholder"></ph> Die Eigenschaft PROPERTY_OUTPUT_FRAMES_PER_BUFFER gibt die Anzahl der Audioframes an die der HAL-Zwischenspeicher (Hardware Abstraktionsschicht) enthalten kann. Sie sollten Ihre Audio- puffern, sodass sie ein exaktes Vielfaches dieser Zahl enthalten. Wenn Sie die richtige Nummer verwenden von Audioframes werden in regelmäßigen Abständen Callbacks vorgenommen, wodurch der Jitter reduziert wird.

Es ist wichtig, die Puffergröße mit der API zu bestimmen, anstatt einen hartcodierten Wert zu verwenden. da die HAL-Puffergrößen je nach Gerät und Android-Build unterschiedlich sind.

Keine Ausgabeschnittstellen hinzufügen bei denen Signalverarbeitung

Nur diese Oberflächen werden vom Schnellmixer unterstützt:

  • SL_IID_ANDROIDSIMPLEBUFFERQUEUE
  • SL_IID-VOLUMEN
  • SL_IID_MUTESOLO

Diese Schnittstellen sind nicht zulässig, da sie eine Signalverarbeitung erfordern und Ihren Antrag auf die Ablehnung eines Schnellverfahrens:

  • SL_IID_BASSBOOST
  • SL_IID_EFFEKTEEND
  • SL_IID_UMWELTREVERB
  • SL_IID_EQUALIZER
  • SL_IID_WIEDERGABERATE
  • SL_IID_PRESETREVERB
  • SL_IID_VIRTUALIZER
  • SL_IID_ANDROIDEFFEKT
  • SL_IID_ANDROID-EFFEKTEEND

Achte bei der Erstellung des Players darauf, nur schnelle Oberflächen hinzuzufügen, wie in den im folgenden Beispiel:

const SLInterfaceID interface_ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };

Prüfen, ob Sie einen Track mit niedriger Latenz verwenden

Führe die folgenden Schritte aus, um zu überprüfen, ob du erfolgreich einen Titel mit niedriger Latenz abgerufen hast:

  1. Starten Sie die App und führen Sie den folgenden Befehl aus:
  2. adb shell ps | grep your_app_name
    
  3. Notieren Sie sich die Prozess-ID Ihrer App.
  4. Spielen Sie jetzt Audioinhalte aus Ihrer App ab. Sie haben ungefähr drei Sekunden Zeit, folgenden Befehl vom Terminal aus:
  5. adb shell dumpsys media.audio_flinger
    
  6. Suchen Sie nach Ihrer Prozess-ID. Wenn Sie in der Spalte Name ein F sehen, ist es auf einer mit niedriger Latenz (das F steht für Fast Track).

Aufwärmlatenz minimieren

Wenn Sie Audiodaten zum ersten Mal in die Warteschlange stellen, sind zum Aufwärmen des Audiokreises des Geräts. Um diese Aufwärmlatenz zu vermeiden, können Sie enQueue-Zwischenspeicher von Audiodaten, die Stille enthalten, wie im folgenden Codebeispiel gezeigt:

#define CHANNELS 1
static short* silenceBuffer;
int numSamples = frames * CHANNELS;
silenceBuffer = malloc(sizeof(*silenceBuffer) * numSamples);
    for (i = 0; i<numSamples; i++) {
        silenceBuffer[i] = 0;
    }

Sobald Audio produziert sein sollte, kannst du zur Aufnahme von Puffern wechseln, die echte Audiodaten.

Hinweis:Wenn ständig Audio ausgegeben wird, verursacht dies einen erheblichen Stromverbrauch. Achten Sie darauf, Ausgabe im onPause(). Sie können die stille Ausgabe auch nach einer gewissen Zeit der Nutzerinaktivität pausieren.

Zusätzlicher Beispielcode

Eine Beispiel-App zur Darstellung der Audiolatenz findest du unter NDK-Beispiele.

Weitere Informationen

  1. <ph type="x-smartling-placeholder"></ph> Audiolatenz für App-Entwickler
  2. <ph type="x-smartling-placeholder"></ph> Trägt zur Audiolatenz bei
  3. <ph type="x-smartling-placeholder"></ph> Audiolatenz messen
  4. <ph type="x-smartling-placeholder"></ph> Audioaufwärmphase
  5. <ph type="x-smartling-placeholder"></ph> Latenz (Audio)
  6. <ph type="x-smartling-placeholder"></ph> Umlaufzeit