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:
- <ph type="x-smartling-placeholder"></ph>
android.hardware.audio.low_latency
gibt eine kontinuierliche Ausgabelatenz von 45 ms an oder weniger. - <ph type="x-smartling-placeholder"></ph>
android.hardware.audio.pro
gibt eine kontinuierliche Umlauflatenz von 20 ms an oder weniger.
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:
- Starten Sie die App und führen Sie den folgenden Befehl aus:
- Notieren Sie sich die Prozess-ID Ihrer App.
- Spielen Sie jetzt Audioinhalte aus Ihrer App ab. Sie haben ungefähr drei Sekunden Zeit, folgenden Befehl vom Terminal aus:
- 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).
adb shell ps | grep your_app_name
adb shell dumpsys media.audio_flinger
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
- <ph type="x-smartling-placeholder"></ph> Audiolatenz für App-Entwickler
- <ph type="x-smartling-placeholder"></ph> Trägt zur Audiolatenz bei
- <ph type="x-smartling-placeholder"></ph> Audiolatenz messen
- <ph type="x-smartling-placeholder"></ph> Audioaufwärmphase
- <ph type="x-smartling-placeholder"></ph> Latenz (Audio)
- <ph type="x-smartling-placeholder"></ph> Umlaufzeit