Czas oczekiwania to czas potrzebny na przesłanie sygnału przez system. Są to najczęstsze typy opóźnień związanych z aplikacjami audio:
- Opóźnienie na wyjściu audio to czas upływający między wygenerowaniem próbki audio przez a próbkę odtwarzaną przez gniazdo słuchawek lub wbudowany głośnik.
- Opóźnienie wejścia audio to czas upływający między odebraniem sygnału audio przez wejścia urządzenia audio, np. mikrofonu, oraz tych samych danych dźwiękowych dostępnych dla .
Opóźnienie w obie strony to suma czasu oczekiwania na sygnał wejściowe, czasu przetwarzania aplikacji oraz opóźnienia na wyjściu.
- Opóźnienie dotknięcia to czas, jaki upływa od momentu, gdy użytkownik dotknie ekranu zdarzenie dotknięcia odebrane przez aplikację.
- Czas oczekiwania na rozgrzewanie to czas potrzebny na pierwsze uruchomienie potoku audio. czas umieszczenia danych w kolejce w buforze.
Na tej stronie dowiesz się, jak opracować aplikację audio z wejściem i wyjściem o małym opóźnieniu oraz jak tego uniknąć czas oczekiwania na rozgrzewkę.
Mierz czas oczekiwania
Pomiar wejścia audio i opóźnienia wyjściowego dźwięku w izolacji jest trudny, ponieważ wymaga dokładnej wiedzy. gdy do ścieżki audio wysyłana jest pierwsza próbka (chociaż można to zrobić za pomocą metody obwód świetlny i oscyloskop). Jeśli znasz opóźnienie dźwięku w obie strony, możesz użyj ogólnej zasady: opóźnienie wejścia (i wyjścia) dźwięku jest o połowę mniejsze od opóźnienia dźwięku w obie strony. w ścieżkach bez przetwarzania sygnału.
Opóźnienie dźwięku w obie strony jest bardzo różne w zależności od modelu urządzenia i Kompilacja Androida. Możesz uzyskać ogólne pojęcie o podróży w obie strony, na urządzeniach Nexus. opublikowanych pomiarów.
Możesz zmierzyć opóźnienie dźwięku w obie strony, tworząc aplikację, która generuje sygnał audio. nasłuchuje tego sygnału, a potem mierzy czas między jego wysłaniem a odebraniem.
Najmniejsze opóźnienie jest osiągane na ścieżkach dźwiękowych z minimalnym przetwarzaniem sygnału, też użyć funkcji Wtyczka audio sprzężenia zwrotnego audio, która umożliwia przeprowadzenie testu przez złącze zestawu słuchawkowego.
Sprawdzone metody minimalizowania opóźnień
Sprawdzanie wydajności reklam audio
Dokument CDD (Android Compatibility Definition Document) wymienia sprzęt i oprogramowanie. zgodnego urządzenia z Androidem. Zobacz zgodności z Androidem, aby uzyskać więcej informacji o ogólnym programie zgodności. CDD dla rzeczywistego dokumentu CDD.
Zgodnie z dokumentem CDD opóźnienie w obie strony wynosi 20 ms lub mniej (mimo że muzycy zwykle wymagają 10 ms). Wynika to z faktu, że istnieją ważne przypadki użycia, które są włączone przez 20 ms.
Obecnie nie ma interfejsu API do określania opóźnienia dźwięku na dowolnej ścieżce na urządzeniu z Androidem w środowisku wykonawczym. Możesz jednak użyć poniższych flag funkcji sprzętowych, aby sprawdzić, czy urządzenie gwarantuje opóźnienia:
-
android.hardware.audio.low_latency
oznacza ciągłe opóźnienie wyjściowe wynoszący 45 ms lub mniej. -
android.hardware.audio.pro
oznacza ciągłe opóźnienie w obie strony wynoszące 20 ms lub mniej.
Kryteria zgłaszania tych zgłoszeń są określone w CDD w sekcjach 5.6 Opóźnienie dźwięku oraz 5.10 Profesjonalna ścieżka dźwiękowa.
Aby sprawdzić te funkcje w Javie:
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);
Jeśli chodzi o relację funkcji audio, android.hardware.audio.low_latency
jest wymagany do korzystania z android.hardware.audio.pro
. Urządzenie może zaimplementować
android.hardware.audio.low_latency
, a nie android.hardware.audio.pro
, ale nie
i na odwrót.
Nie należy przyjmować żadnych założeń dotyczących wydajności audio.
Pamiętaj o tych założeniach, aby uniknąć problemów z opóźnieniami:
- Nie zakładaj, że głośniki i mikrofony używane w urządzeniach mobilnych zwykle działają dobrze. akustykę. Ze względu na niewielki rozmiar akustyka jest ogólnie słaba, więc przetwarzanie sygnału jest aby poprawić jakość dźwięku. Przetwarzanie sygnału zwiększa opóźnienie.
- Nie zakładaj, że wywołania zwrotne wejściowe i wyjściowe są zsynchronizowane. Do jednoczesnego wprowadzania danych dla każdej strony są używane oddzielne moduły obsługi kolejki bufora i dane wyjściowe. Brak gwarancja względnej kolejności wywołań zwrotnych lub synchronizacji zegarów audio, nawet wtedy, gdy obie strony używają tej samej częstotliwości próbkowania. Aplikacja powinna buforować dane za pomocą: prawidłową synchronizację bufora.
- Nie zakładaj, że rzeczywista częstotliwość próbkowania jest dokładnie taka sama jak nominalna częstotliwość próbkowania. Dla:
Jeśli na przykład nominalna częstotliwość próbkowania wynosi 48 000 Hz, to normalne, że zegar audio przesuwa się szybciej.
z nieco inną szybkością niż system operacyjny
CLOCK_MONOTONIC
. Dzieje się tak, ponieważ zegary dźwiękowe i zegary systemowe mogą pochodzić z różnych kryształów. - Nie zakładaj, że rzeczywista częstotliwość próbkowania podczas odtwarzania jest taka sama jak zwłaszcza wtedy, gdy punkty końcowe znajdują się w osobnych ścieżkach. Na przykład jeśli przechwytujesz z mikrofon na urządzeniu z nominalną częstotliwością próbkowania 48 000 Hz i odtwarzany przez USB przy nominalnej częstotliwości próbkowania 48 000 Hz rzeczywiste częstotliwości próbkowania mogą się nieznacznie różnić od siebie nawzajem.
Konsekwencją potencjalnie niezależnych zegarów audio jest konieczność stosowania asynchronicznej częstotliwości próbkowania. konwersji. Prosta technika (choć nie idealna dla jakości audio) umożliwiająca asynchroniczną częstotliwość próbkowania konwersji polega na duplikowaniu lub usuwaniu próbek w miarę potrzeb w pobliżu punktu przecięcia. Więcej i bardziej złożone konwersje.
Minimalizuj opóźnienie sygnału wejściowego
W tej sekcji znajdziesz sugestie, które pomogą Ci zmniejszyć opóźnienie sygnału wejściowego dźwięku podczas nagrywania z użyciem wbudowany mikrofon lub zewnętrzny zestaw słuchawkowy z mikrofonem.
- Jeśli aplikacja monitoruje wejście, zasugeruj użytkownikom korzystanie z zestawu słuchawkowego
(np. przez wyświetlanie ekranu Najlepsze ze słuchawkami przy pierwszym uruchomieniu). Notatka
że samo użycie zestawu słuchawkowego nie gwarantuje najniższego możliwego opóźnienia. Może być konieczne
wykonaj inne czynności, by usunąć przetwarzanie niechcianych sygnałów ze ścieżki audio, np. przez
za pomocą funkcji
VOICE_RECOGNITION
gotowe podczas nagrywania. - Przygotuj się na obsługę nominalnych częstotliwości próbkowania 44 100 i 48 000 Hz według raportu getproperty(String) dla PROPERTY_OUTPUT_SAMPLE_RATE. Inne częstotliwości próbkowania są możliwe, ale są one rzadkie.
- Przygotuj się na obsługę rozmiaru bufora zgłaszanego przez getproperty(String) dla PROPERTY_OUTPUT_FRAMES_PER_BUFFER. Typowe rozmiary bufora to 96, 128, 160, 192, 240, 256, lub 512, ale możliwe są też inne wartości.
Minimalizowanie opóźnienia wyjściowego
Użyj optymalnej częstotliwości próbkowania podczas tworzenia odtwarzacza dźwięku
Aby uzyskać jak najkrótszy czas oczekiwania, należy dostarczyć dane audio pasujące do optymalnej częstotliwości próbkowania i rozmiaru bufora. Więcej informacji: Projektowanie z myślą o krótszym czasie oczekiwania.
W Javie można uzyskać optymalną częstotliwość próbkowania z modułu AudioManager: przykładowy kod:
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
Po ustaleniu optymalnej częstotliwości próbkowania możesz ją podać podczas tworzenia odtwarzacza. W tym przykładzie użyto OpenSL ES:
// 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; ... }
Uwaga: samplesPerSec
dotyczy częstotliwości próbkowania na kanał w
ms (1 Hz = 1000 mHz).
Użyj optymalnego rozmiaru bufora do umieszczania danych audio w kolejce
Optymalny rozmiar bufora można uzyskać w podobny sposób jak optymalną częstotliwość próbkowania, stosując metodę Interfejs API AudioManager:
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
Właściwość PROPERTY_OUTPUT_FRAMES_PER_BUFFER
wskazuje liczbę klatek dźwięku.
który może przechowywać bufor HAL (Hardware Abstraction Layer). Musisz utworzyć dźwięk
jest buforowana tak, aby zawierała dokładną wielokrotność tej liczby. Jeśli użyjesz prawidłowego numeru
klatek audio, wywołania zwrotne występują w regularnych odstępach czasu, co pozwala zmniejszyć zakłócenia.
Do określenia rozmiaru bufora należy używać interfejsu API, a nie wartości zakodowanej na stałe, bo rozmiar bufora HAL różni się w zależności od urządzenia i wersji Androida.
Nie dodawaj interfejsów wyjściowych obejmujące przetwarzanie sygnałów
Szybki mikser obsługuje tylko te interfejsy:
- SL_IID_ANDROIDSIMPLEBUFFERQUEUE
- SL_IID_VOLUME
- SL_IID_MUTESOLO
Te interfejsy są niedozwolone, ponieważ wymagają przetwarzania sygnałów i powodują prośba o skrócenie czasu do odrzucenia:
- SL_IID_BASSBOOST
- SL_IID_SKUSEND
- SL_IID_ENVIRONMENTALREVERB
- SL_IID_EQUALIZER
- SL_IID_PLAYBACKRATE
- SL_IID_PRESETREVERB
- SL_IID_VIRTUALIZER
- SL_IID_ANDROID
- SL_IID_ANDROIDSEND
Podczas tworzenia odtwarzacza pamiętaj, aby dodawać tylko szybkie interfejsy, jak pokazano w następujący przykład:
const SLInterfaceID interface_ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };
Sprawdź, czy używasz ścieżki niskiego opóźnienia
Wykonaj te czynności, aby sprawdzić, czy udało Ci się pobrać ścieżkę o małym opóźnieniu:
- Uruchom aplikację, a następnie uruchom to polecenie:
- Zanotuj identyfikator procesu aplikacji.
- Teraz włącz dźwięk z aplikacji. Masz około 3 sekund na uruchomienie następujące polecenie z terminala:
- Zeskanuj, aby znaleźć identyfikator procesu. Jeśli w kolumnie Nazwa widzisz literę F, oznacza to, że znajduje się ona na ścieżka z małym opóźnieniem (F oznacza szybki utwór).
adb shell ps | grep your_app_name
adb shell dumpsys media.audio_flinger
Minimalizuj czas oczekiwania na rozgrzewkę
Dodanie danych dźwiękowych do kolejki po raz pierwszy zajmuje niewiele, czas na rozgrzanie obwodu audio urządzenia. Aby uniknąć tego opóźnienia na rozgrzewkę, możesz: do umieszczenia w kolejce buforów danych audio zawierających ciszę, jak widać w tym przykładowym kodzie:
#define CHANNELS 1 static short* silenceBuffer; int numSamples = frames * CHANNELS; silenceBuffer = malloc(sizeof(*silenceBuffer) * numSamples); for (i = 0; i<numSamples; i++) { silenceBuffer[i] = 0; }
W momencie, gdy chcesz nagrać dźwięk, możesz przełączyć się na bufory kolejki zawierające prawdziwych danych dźwiękowych.
Uwaga: ciągłe odtwarzanie dźwięku wiąże się ze znacznym zużyciem energii. Pamiętaj, by zatrzymać w funkcji onPause(). Rozważ też wstrzymanie cichych wyników po określonym czasie bezczynności użytkownika.
Dodatkowy przykładowy kod
Aby pobrać przykładową aplikację, która pokazuje opóźnienie dźwięku, zobacz Próbki NDK.
Więcej informacji
- Opóźnienie dźwięku dla deweloperów aplikacji
- Opóźnienie dźwięku
- Mierzenie opóźnienia dźwięku
- Rozgrzewka dźwiękowa
- Czas oczekiwania (dźwięk)
- Czas opóźnienia w obie strony