Dźwięk z małym opóźnieniem

Dźwięk o małym opóźnieniu sprawia, że gry są bardziej realistyczne i responsywne.

Wykonaj czynności z poniższej listy kontrolnej, aby włączyć dźwięk z niskim opóźnieniem w grze na Na urządzeniu z Androidem:

  1. Użyj oboju
  2. Żądanie w trybie wydajności „małe opóźnienie”
  3. Wysyłanie prośby o tryb udostępniania „Wyłączny”
  4. Używaj 48 000 Hz lub konwertera częstotliwości próbkowania obojowego
  5. Ustaw użycie na AAUDIO_USAGE_GAME
  6. Używanie wywołań zwrotnych danych
  7. Unikaj blokowania operacji w wywołaniu zwrotnym
  8. Popraw rozmiar bufora na „podwójny bufor”

1. Używanie interfejsu Oboe API

Interfejs API Oboe to kod w języku C++, który wywołuje AAudio na Androidzie 8.1 (poziom interfejsu API 27) lub nowszym. Na starszych wersjach Androida: Obój korzysta z technologii OpenSL ES.

Obój jest dostępny na GitHubie lub jako gotowym pliku binarnym. Obój ma też aplikację QuirksManager, która rozwiązuje problemy na konkretnych urządzeniach, dzięki czemu Twoja aplikacja jest zgodna z większą liczbą urządzeń. Jeśli nie możesz użyć Obój, użyj AAudio.

2. Żądanie w trybie niskiego opóźnienia

W przypadku obojów lub AAudio możesz żądać trybu niskiego opóźnienia. W przeciwnym razie uzyskasz wyższy .

Obój

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

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. Tryb na wyłączność

Możesz również poprosić o wyłączny dostęp do bufora MMAP. Aplikacja może nie otrzymać dostępu na wyłączność, ale jeśli tak, aplikacja zapisuje bezpośrednio w buforze, jest odczytywany przez platformę DSP, co zapewnia aplikacji najkrótszy możliwy czas oczekiwania.

Obój

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

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. Unikaj konwersji częstotliwości próbkowania

Używaj naturalnej częstotliwości próbkowania urządzenia. Aby to zrobić, nie podawaj parametru częstotliwość próbkowania i prawie na pewno 48 000 Hz. Jeśli podasz przykład platforma audio wysyła dane inną ścieżką, która może mieć znacznie większe opóźnienie.

Jeśli chcesz użyć innej częstotliwości próbkowania, użyj funkcji Oboe. konwersja:

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

5. Prawidłowo zadeklaruj swój przypadek użycia

Określanie powodu, dla którego aplikacja odtwarza dźwięk, ma kluczowe znaczenie dla jego zastosowania. z prawidłowymi ustawieniami routingu, głośności i wydajności. Gry powinny na przykład: wskazuje wykorzystanie AAUDIO_USAGE_GAME, aby w pełni wykorzystać czas oczekiwania zwłaszcza przy podłączeniu do zestawu słuchawkowego Bluetooth.

Obój

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

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. Korzystanie z funkcji wywołania zwrotnego

Użycie wywołania zwrotnego dla strumienia wyjściowego. Jeśli korzystasz z blokowania zapisów i masz włączone urządzenia nieobsługującego trybu AAudio MMAP, opóźnienie może być wyżej.

Obój

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. Unikaj blokowania w wywołaniu zwrotnym

Jeśli używasz strumienia o małym opóźnieniu, czas między wywołaniami zwrotnymi może być bardzo tylko kilka milisekund. Bardzo ważne jest, aby nie w wywołaniu zwrotnym cokolwiek, co mogłoby blokować reklamy na dłuższy czas. Jeśli wywołanie zwrotne to jeśli w dźwięku pojawiają się niedoskonałości bufora i zakłócenia.

W wywołaniu zwrotnym unikaj tych czynności:

  • Przydzielanie lub zwalnianie pamięci
  • I/O pliku lub sieci
  • Oczekiwanie na muteks lub blokadę.
  • Sen
  • Obliczenia związane z intensywnym jednorazowym wykorzystaniem procesora

Wywołania zwrotne powinny przeprowadzać obliczenia w równomiernym tempie, aby zapewnić płynne odtwarzanie bez lub występują błędy.

8. Dostosuj rozmiar bufora

Gdy aplikacja otworzy strumień audio, musisz dostroić rozmiar użytego bufora pod kątem optymalnego opóźnienia. Obój automatycznie ustawia rozmiar bufora na 2 serie. Ale w przypadku AAudio, wartość domyślna jest znacznie wyższa. Użyj podwójnego buforowania, ustawiając parametr dwukrotnie większy rozmiar bufora. Rozmiar serii to maksymalne wywołanie zwrotne rozmiaru.

AAudio:

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

Jeśli rozmiar bufora jest zbyt mały, mogą wystąpić problemy. poniżej założeń. Liczbę błędów możesz sprawdzić, dzwoniąc AAudioStream_getXRunCount(stream) W razie potrzeby zwiększ rozmiar bufora.

Zobacz Dokumentacja obojów na GitHubie , gdzie znajdziesz terminologię związaną z buforem.

OpenSL ES

Jeśli korzystasz z wersji Androida starszej niż 8.1, musisz użyć polecenia OpenSL ES. Jeśli używasz Obój, możesz skonfigurować aplikację, aby ulepszyć opóźnienia. Zobacz Uzyskiwanie optymalnego czasu oczekiwania w dokumentacji GitHub.

Wyniki listy kontrolnej

Poniższa tabela zawiera Tester Oboe dane dotyczące czasu oczekiwania w obie strony (od danych wejściowych do wyjścia).

Konfiguracja Czas oczekiwania (ms)
Postępuj zgodnie ze wszystkimi zaleceniami 20
Tryb wydajności nie ma małego opóźnienia 205
NIE WYJĄTKOWA (WSPÓLNA) 26
44100 Hz (AAudio) 160
44100 Hz (Oboe SRC) 23
Nieużywanie wyjściowego wywołania zwrotnego (MMAP) 21
Brak wyjściowego wywołania zwrotnego (nie MMAP) 62
Ustawiono maksymalny rozmiar bufora 53