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

Dzięki niewielkim opóźnieniom dźwięk w grach wydaje się bardziej realistyczny i responsywny.

Wykonaj czynności z tej listy kontrolnej, aby włączyć dźwięk z małym opóźnieniem w swojej grze na Androidzie:

  1. Obój
  2. Żądanie trybu wydajności „małe opóźnienie”
  3. Prośba o tryb udostępniania „wyłączny”
  4. Użyj przetwornika częstotliwości próbkowania 48 000 Hz lub obojowego przetwornika częstotliwości próbkowania
  5. Ustaw użycie na AAUDIO_USAGE_GAME
  6. Używanie wywołań zwrotnych danych
  7. Unikaj blokowania operacji w wywołaniu zwrotnym
  8. Dostosowanie rozmiaru bufora do opcji „podwójny bufor”

1. Korzystanie z interfejsu Oboe API

Interfejs Oboe API to kod w języku C++, który wywołuje AAudio na Androidzie 8.1 (poziom API 27) lub nowszym. We wcześniejszych wersjach Androida Oboe używa OpenSL ES.

Obój jest dostępny na GitHubie oraz jako gotowy plik binarny. Oboe ma również funkcję QuirksManager, która rozwiązuje problemy na konkretnych urządzeniach, dzięki czemu aplikacja jest zgodna z większą liczbą urządzeń. Jeżeli nie możesz skorzystać z Oboe, użyj bezpośrednio AAudio.

2. Żądanie w trybie małego opóźnienia

W przypadku obóju lub AAudio wyślij żądanie trybu niskiego opóźnienia. W przeciwnym razie domyślnie będzie korzystać z trybu większego opóźnienia.

Obój

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

Audio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. Poproś o tryb na wyłączność

Możesz też poprosić o wyłączny dostęp do bufora MMAP. Aplikacja może nie uzyskać wyłącznego dostępu, ale jeśli tak się stanie, zapisuje bezpośrednio w buforze odczytywanym przez DSP, dzięki czemu aplikacja ma najkrótszy możliwy czas oczekiwania.

Obój

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

Audio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

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

Użyj naturalnej częstotliwości próbkowania urządzenia. Aby to zrobić, nie podawaj częstotliwości próbkowania. Prawie na pewno uzyskasz 48 000 Hz. Jeśli określisz częstotliwość próbkowania, platforma audio będzie wysyłać dane inną ścieżką, która może mieć znacznie większe opóźnienie.

Jeśli musisz użyć innej częstotliwości próbkowania, użyj opcji Obój:

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

5. Prawidłowo zadeklaruj przypadek użycia

Aby system mógł zastosować odpowiednie ustawienia routingu, głośności i wydajności, musisz określić powód, dla którego aplikacja ma odtwarzać dźwięk. Na przykład gry powinny wskazywać użycie AAUDIO_USAGE_GAME, aby w pełni wykorzystać możliwości optymalizacji czasu oczekiwania, zwłaszcza gdy są podłączone do zestawów słuchawkowych Bluetooth.

Obój

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

Audio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. Korzystanie z funkcji wywołania zwrotnego

Użyj wywołania zwrotnego dla strumienia wyjściowego. Jeśli używasz blokującego zapisu i korzystasz z urządzenia, które nie obsługuje trybu AAudio MMAP, opóźnienie może być znacznie większe.

Obój

builder.setDataCallback(&myCallbackObject);

Audio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. Unikaj blokowania w wywołaniu zwrotnym

Jeśli używasz strumienia o małym czasie oczekiwania, odstępy między wywołaniami zwrotnymi mogą być bardzo krótkie – zaledwie kilka milisekund. Nie rób z nich niczego, co mogłoby blokować się na długi czas. Jeśli wywołanie zwrotne jest zablokowane, w dźwięku występują niedokładności i zakłócenia bufora.

Unikaj wykonywania tych czynności podczas wywołania zwrotnego:

  • Przydzielanie i zwalnianie pamięci
  • Wejście-wyjście pliku lub sieci
  • Czekam na muteks lub blokadę
  • Sen
  • Jednorazowe obliczenia mocy procesora

Wywołania zwrotne powinny wykonywać obliczenia w równomiernym tempie, aby zapewnić płynne odtwarzanie bez zakłóceń.

8. Dostosuj rozmiar bufora

Gdy aplikacja otworzy strumień audio, musisz dostosować rozmiar użytego bufora, aby uzyskać optymalne opóźnienie. Obój automatycznie ustawia rozmiar bufora na 2 serii. Ale przy AAudio wartość domyślna jest znacznie wyższa. Jeśli chcesz użyć podwójnego buforowania, ustaw dwukrotnie większy rozmiar serii. Rozmiar serii to maksymalny rozmiar wywołania zwrotnego.

Audio:

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

Jeśli rozmiar bufora jest zbyt mały, mogą wystąpić zakłócenia spowodowane jego niedostatecznymi rozmiarami. Liczbę usterek możesz sprawdzić, wywołując stronę AAudioStream_getXRunCount(stream). W razie potrzeby możesz zwiększyć rozmiar bufora.

Wyjaśnienie terminologii związanej z buforowaniem znajdziesz w dokumentacji obozu GitHub.

OpenSL ES

Jeśli korzystasz z wersji Androida starszych niż 8.1, musisz używać OpenSL ES. Jeśli korzystasz z Obóju, możesz skonfigurować aplikację, by zmniejszyć opóźnienie. Zapoznaj się z sekcją Uzyskiwanie optymalnego czasu oczekiwania w dokumentacji GitHuba.

Wyniki listy kontrolnej

Poniższa tabela zawiera pomiary czasu oczekiwania w metodzie OboeTester w obie strony (dane wyjściowe).

Konfiguracja Czas oczekiwania (ms)
Przestrzegaj wszystkich rekomendacji 20
Tryb wydajności nie ma małego opóźnienia 205
Nie WYKLUCZAJĄCE (UDOSTĘPNIONE) 26
44100 Hz (AAudio) 160
44100 Hz (oboe SRC) 23
Bez wyjściowego wywołania zwrotnego (MMAP) 21
Bez wyjściowego wywołania zwrotnego (nie MMAP) 62
Rozmiar bufora ustawiony na maksymalny 53