OpenSL ES na Androida

Ta strona zawiera szczegółowe informacje na temat Implementacja OpenSL w ramach NDK ESTM różni się od specyfikacji referencyjnej OpenSL ES 1.0.1. Jeśli używasz przykładowego kodu ze strony specyfikacji, może być konieczna jej modyfikacja, by działała na Androidzie.

O ile nie zaznaczono inaczej, wszystkie funkcje są dostępne w Androidzie 2.3 (poziom API 9) i nowszych. Niektóre funkcje są dostępne tylko na Androidzie 4.0 (poziom API 14). Są one uwzględnione.

Uwaga: Dokument CDD (Android Compatibility Definition Document) wymienia sprzęt i oprogramowanie. zgodnego urządzenia z Androidem. Zobacz Zgodność z Androidem . CDD dla rzeczywistego dokumentu CDD.

OpenSL ES zapewnia z interfejsem w języku C++. Ukazuje funkcje podobne do tych w ścieżce audio. tych interfejsów API w Javie na Androida:

Podobnie jak w przypadku pakietu Android Native Development Kit (NDK), głównym przeznaczeniem OpenSL ES Android ułatwia implementację bibliotek udostępnionych, które można wywoływać za pomocą natywnego interfejsu Java. Interfejs (JNI ). NDK nie jest przeznaczony do tworzenia czystych aplikacji w języku C/C++. OpenSL ES to jednak w pełni funkcjonalny interfejs API i oczekujemy, że zaspokoisz większość swoich potrzeb w zakresie audio za pomocą tylko tego interfejsu API, bez wywoływania kodu działającego w środowisku wykonawczym Androida.

Uwaga: Chociaż oparty na OpenSL ES interfejs API natywnego audio (dźwięk o wysokiej wydajności) nie jest zgodna z implementacją dowolnego profilu OpenSL ES 1.0.1 (w grze, muzyce lub telefonie). Dzieje się tak, ponieważ Android nie obsługuje wszystkich funkcji wymaganych przez żaden z profili. Wszystkie znane przypadki w przypadku gdy Android działa inaczej niż jest to opisane w specyfikacji Rozszerzenia na Androida.

Funkcje odziedziczone ze specyfikacji referencyjnej

Implementacja NDK na Androida w OpenSL ES dziedziczy większość funkcji ze specyfikacją referencyjną, z pewnymi ograniczeniami.

Globalne punkty wejścia

OpenSL ES for Android obsługuje wszystkie globalne punkty wejścia zgodnie ze specyfikacją Androida. Te punkty wejścia obejmują:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Obiekty i interfejsy

W tabeli poniżej znajdziesz obiekty i interfejsy używane w implementacji NDK na Androida Obsługa OpenSL ES. Jeśli w komórce pojawi się opcja Tak, ta funkcja jest dostępna w tym implementacji.

Obsługa obiektów i interfejsów w Androidzie NDK.

Funkcja Odtwarzacz dźwięku Rejestratory dźwięku Silnik Miks wyjściowy
Wzmocnienie basów Tak Nie Nie Tak
Kolejka buforów Tak Nie Nie Nie
Lokalizator danych kolejki buforów Tak: źródło Nie Nie Nie
Dynamiczne zarządzanie interfejsem Tak Tak Tak Tak
Wysyłanie efektów Tak Nie Nie Nie
Silnik Nie Nie Tak Nie
Pogłos środowiska Nie Nie Nie Tak
Korektor Tak Nie Nie Tak
Lokalizator danych urządzeń wejścia-wyjścia Nie Tak: źródło Nie Nie
Wyodrębnianie metadanych Tak: dekoduj do PCM Nie Nie Nie
Wycisz solo Tak Nie Nie Nie
Obiekt Tak Tak Tak Tak
Lokalizator miksu wyjściowego Tak: zlew Nie Nie Nie
Odtwórz Tak Nie Nie Nie
Prędkość odtwarzania Tak Nie Nie Nie
Stan pobierania z wyprzedzeniem Tak Nie Nie Nie
Wstępnie ustawiony pogłos Nie Nie Nie Tak
Nagraj Nie Tak Nie Nie
Szukaj Tak Nie Nie Nie
Lokalizator danych URI Tak: źródło Nie Nie Nie
Wirtualizator Tak Nie Nie Tak
Głośność Tak Nie Nie Nie

W następnej sekcji opisujemy ograniczenia niektórych z tych funkcji.

Ograniczenia

Funkcje opisane w tabeli 1 mają pewne ograniczenia. Te ograniczenia przedstawiają różnice w stosunku do specyfikacji referencyjnej. Pozostała część tej sekcji zawiera więcej informacji na temat tych różnic.

Dynamiczne zarządzanie interfejsem

OpenSL ES na Androida nie obsługuje RemoveInterface ani ResumeInterface

Kombinacje efektów: pogłos środowiska i gotowy pogłos

Na tym samym mikserze wyjściowym nie można jednocześnie używać pogłosu środowiska i gotowego pogłosu.

Platforma może zignorować żądania efektu, jeśli oszacuje, że Obciążenie procesora byłoby zbyt duże.

Wysyłanie efektów

SetSendLevel() obsługuje jeden poziom wysyłania na odtwarzacz dźwięku.

Pogłos środowiska

Pogłos środowiska nie obsługuje tych dźwięków: reflectionsDelay, reflectionsLevel lub reverbDelay pól struktura SLEnvironmentalReverbSettings.

Format danych MIME

Formatu danych MIME możesz używać tylko z lokalizatorem danych URI i wyłącznie w przypadku plików audio . Nie można użyć tego formatu danych w przypadku dyktafonu.

Implementacja OpenSL ES na Androida wymaga zainicjowania pliku mimeType do NULL lub prawidłowego ciągu UTF-8. Musisz też zainicjować containerType na prawidłową wartość. ze względu na brak innych aspektów, takich jak możliwość przenoszenia danych do innych usług. implementacji lub formatów treści, których aplikacja nie może zidentyfikować za pomocą nagłówka; zalecamy ustaw mimeType na NULL i containerType do SL_CONTAINERTYPE_UNSPECIFIED.

OpenSL ES for Android obsługuje następujące formaty dźwięku, o ile Platforma Android je obsługuje również:

  • WAV – PCM.
  • WAV alaw.
  • WAV ulaw.
  • MP3 Ogg Vorbis
  • AAC LC.
  • HE-AACv1 (AAC+).
  • HE-AACv2 (rozszerzony AAC+).
  • AMR.
  • FLAC.

Uwaga: Listę formatów dźwięku obsługiwanych przez Androida znajdziesz w artykule Obsługiwane formaty multimediów.

Obsługa tych i innych formatów w tym wdrożenie OpenSL ES:

  • AAC muszą znajdować się w kontenerze MP4 lub ADTS.
  • OpenSL ES na Androida nie obsługuje MIDI
  • WMA nie należy do AOSP, nie sprawdzili jej zgodności z OpenSL ES na Androida.
  • Implementacja OpenSL ES w Androidzie NDK nie obsługuje bezpośredniego odtwarzania treści z DRM lub zaszyfrowanych treści. Aby odtworzyć chronione treści audio, musisz: odszyfrować je w aplikacji przed rozpoczęciem gry przy użyciu stosowania zabezpieczeń DRM. ograniczeń.

OpenSL ES for Android nie obsługuje następujących metod manipulowania obiektami:

  • Resume()
  • RegisterCallback()
  • AbortAsyncOperation()
  • SetPriority()
  • GetPriority()
  • SetLossOfControlInterfaces()

Format danych PCM

PCM to jedyny format danych, którego możesz używać z kolejkami buforów. Obsługiwany PCM mają następujące właściwości:

  • 8-bitowy bez znaku lub 16-bitowy ze znakiem.
  • Monochromatyczny lub stereo.
  • Sortowanie bajtów według Little-endian.
  • Częstotliwość próbkowania:
    • 8000 Hz.
    • 11 025 Hz.
    • 12 000 Hz.
    • 16 000 Hz.
    • 22 050 Hz.
    • 24 000 Hz.
    • 32 000 Hz.
    • 44 100 Hz.
    • 48 000 Hz.

Konfiguracje obsługujące nagrywanie przez OpenSL ES na Androida to w zależności od urządzenia; zwykle 16 000 Hz mono/16-bitowe szyfrowanie jest dostępne niezależnie od urządzenia.

Wartość w polu samplesPerSec jest wyrażona w miliHz, pomimo mylących informacji imię i nazwisko. Aby uniknąć przypadkowego użycia niewłaściwej wartości, zalecamy zainicjowanie tego pola za pomocą polecenia jedną ze stałych symbolizujących zdefiniowanych w tym celu, np. SL_SAMPLINGRATE_44_1.

Obsługa Androida 5.0 (poziom interfejsu API 21) i nowszych danych zmiennoprzecinkowych.

Prędkość odtwarzania

Częstotliwość odtwarzania OpenSL ES wskazuje szybkość, z jaką przedstawia dane wyrażone w tysiącach normalnej prędkości, czyli na tysiąc. Przykład: szybkość odtwarzania 1000 na tysiąc to 1000/1000, czyli normalna szybkość. Zakres szybkości to przedział czasu określający zakres możliwych szybkości odtwarzania.

Obsługa zakresów szybkości odtwarzania i innych funkcji może się różnić w zależności od na temat wersji platformy i jej implementacji. Aplikacja może określić te możliwości w czasie działania przez przy użyciu: PlaybackRate::GetRateRange() lub PlaybackRate::GetCapabilitiesOfRate(), aby wysłać zapytanie do urządzenia.

Urządzenie zwykle obsługuje ten sam zakres częstotliwości dla źródła danych w formacie PCM i współczynnik jednostkowy zakres od 1000 na 1000 do 1000 na tysiąc w przypadku innych formatów; to znaczy, że zakres współczynnika jednostkowego jest jedną wartość.

Nagraj

OpenSL ES na Androida nie obsługuje SL_RECORDEVENT_HEADATLIMIT lub SL_RECORDEVENT_HEADMOVING zdarzenia.

Szukaj

Metoda SetLoop() umożliwia zapętlanie całego pliku. Aby włączyć zapętlenie: ustaw parametr startPos na 0, a parametr endPos do: SL_TIME_UNKNOWN.

Lokalizator danych kolejki buforów

Odtwarzacz audio lub dyktafon z lokalizatorem danych do obsługi kolejki bufora obsługuje tylko format danych PCM.

Lokalizator danych urządzeń wejścia-wyjścia

OpenSL ES for Android obsługuje lokalizator danych urządzeń wejścia-wyjścia tylko wtedy, gdy masz określił lokalizator jako źródło danych dla elementu Engine::CreateAudioRecorder(). Zainicjuj lokalizator danych urządzeń, korzystając z wartości podanych w tym fragmencie kodu:

SLDataLocator_IODevice loc_dev =
  {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};

Lokalizator danych URI

OpenSL ES for Android może używać lokalizatora danych URI tylko z formatem danych MIME. i tylko w przypadku odtwarzacza dźwięku. W rejestratorze dźwięku nie można używać lokalizatora danych URI. Identyfikator URI może mieć tylko używaj schematów http: i file:. Inne schematy, takie jak https:, ftp: lub content: są niedozwolone.

Nie zweryfikowaliśmy obsługi rtsp: z dźwiękiem na platformie Android.

Struktury danych

Android obsługuje te struktury danych OpenSL ES 1.0.1:

  • SLDataFormat_MIME
  • SLDataFormat_PCM
  • SLDataLocator_BufferQueue
  • SLDataLocator_IODevice
  • SLDataLocator_OutputMix
  • SLDataLocator_URI
  • SLDataSink
  • SLDataSource
  • SLEngineOption
  • SLEnvironmentalReverbSettings
  • SLInterfaceID

Konfiguracja platformy

OpenSL ES for Android został zaprojektowany z myślą o aplikacjach wielowątkowych i bezpieczeństwa w postaci wątków. Obsługuje jedną silnik na aplikację i maksymalnie 32 obiekty na silnik. Dostępna pamięć i CPU mogą jeszcze bardziej ogranicza liczbę obiektów.

Te opcje wyszukiwarek są rozpoznawane, ale slCreateEngine ignoruje:

  • SL_ENGINEOPTION_THREADSAFE
  • SL_ENGINEOPTION_LOSSOFCONTROL

OpenMAX AL i OpenSL ES można używać razem w tej samej aplikacji. W tym przypadku jeden obiekt wyszukiwarki udostępniany wewnętrznie, a limit 32 obiektów jest wspólny dla OpenMAX AL i OpenSL ES. Aplikacja powinna utworzyć oba silniki, używać obu, a na koniec zniszczenie obu silników. Implementacja zachowuje liczbę referencji w udostępnianym silniku, jest prawidłowo zniszczony podczas drugiej operacji niszczenia.

Uwagi dotyczące programowania

Uwagi na temat programu OpenSL ES udostępnia dodatkowe informacje pozwalające zapewnić prawidłową implementację OpenSL ES.

Uwaga: Dla Twojej wygody dołączyliśmy kopię specyfikacji OpenSL ES 1.0.1 wraz z dokumentem NDK w docs/opensles/OpenSL_ES_Specification_1.0.1.pdf

Problemy z platformą

W tej sekcji opisano znane problemy występujące w początkowej wersji platformy, która obsługuje te interfejsy API.

Dynamiczne zarządzanie interfejsem

DynamicInterfaceManagement::AddInterface nie działa. Zamiast tego określ interfejs w tablica jest przekazywana do funkcji Create(), zgodnie z przykładowym kodem pogłosu środowiskowego.

Planowanie przyszłych wersji OpenSL ES

Wydajne interfejsy API audio na Androida bazują na OpenSL grupy Khronos ES 1.0.1. Khronos opublikował poprawioną wersję 1.1 standardu. poprawiona wersja zawiera nowe funkcje, wyjaśnienia, poprawki błędów typograficznych oraz i niektórych niezgodności. Większość oczekiwanych niezgodności jest stosunkowo niewielka lub znajduje się w środowisku OpenSL ES, które nie są obsługiwane przez Androida.

Aplikacja opracowanych przy użyciu tej wersji powinno działać z przyszłymi wersjami platformy Android, pod warunkiem że że przestrzegasz wytycznych podanych w sekcji Plan dla plików binarnych kompatybilności poniżej.

Uwaga: Zgodność źródeł w przyszłości nie jest celem. Oznacza to, że jeśli przejdziesz na nowszą wersję NDK, może zaistnieć konieczność zmodyfikowania kodu źródłowego aplikacji, aby dostosować ją do nowego interfejsu API. Przewidujemy, że większość takie zmiany będą niewielkie; Więcej informacji znajdziesz poniżej.

Planowanie zgodności plików binarnych

Aby poprawić zgodność aplikacji w przyszłości z plikami binarnymi, zalecamy przestrzeganie tych wytycznych:

  • Korzystaj tylko z podzbioru funkcji OpenSL ES 1.0.1 obsługiwanych na Androida.
  • nie zależą od konkretnego kodu wyniku w przypadku niepowodzenia operacji; przygotuj się na obsługę z innym kodem wyniku.
  • Moduły obsługi wywołań zwrotnych aplikacji zwykle działają w kontekście ograniczonym. Należy je napisać oraz jak najszybciej wrócili do pracy. Nie wykonuj złożonych operacji w ramach modułu obsługi wywołania zwrotnego. Na przykład w ramach wywołania zwrotnego ukończenia kolejki bufora można dodać do kolejki kolejnego bufora, ale nie tworzyć odtwarzacza dźwięku.
  • Moduły obsługi wywołań zwrotnych powinny być przygotowane do częstszego lub rzadszego wywoływania w celu dodatkowych typów zdarzeń. Ignoruj typy zdarzeń, których nie rozpozna. Wywołania zwrotne, które są skonfigurowane z maską zdarzeń z włączonych typów zdarzeń, powinny być przygotowane do wywołania z wieloma ustawionymi jednocześnie wieloma bitami typów zdarzeń. Użyj znaku „&” dla każdego fragmentu zdarzenia, a nie w skrzynce na wymianę.
  • Używaj stanu pobierania z wyprzedzeniem i wywołań zwrotnych jako ogólnych wskaźników postępu, ale nie zależą one od zakodowanych na stałe poziomów wypełnienia lub sekwencji wywołań zwrotnych. Znaczenie wypełnienia stanu pobierania z wyprzedzeniem a zachowanie błędów wykrytych podczas pobierania z wyprzedzeniem może się zmieniać.

Uwaga: zapoznaj się z Działanie kolejki buforów poniżej.

Planowanie pod kątem zgodności źródła

Jak już wspomnieliśmy, w następnej wersji OpenSL ES należy spodziewać się niezgodności kodu źródłowego Grupa Chronos. Możliwe obszary zmian:

  • Interfejs kolejki bufora prawdopodobnie ulegnie istotnym zmianom, szczególnie w obszarach BufferQueue::Enqueue, listę parametrów funkcji slBufferQueueCallback oraz nazwa pola SLBufferQueueState.playIndex. Zalecamy użycie kodu aplikacji Są to proste kolejki buforowe w Androidzie. W tym przykładzie dołączonego do pakietu NDK, użyliśmy prostych kolejek buforowych w Androidzie do odtwarzania z tego powodu. (Do nagrywania i dekodowania w PCM używamy również prostej kolejki buforowej na Androidzie, ale jest to, że standard OpenSL ES 1.0.1 nie obsługuje rejestrowania ani dekodowania danych w kolejce bufora. ujście).
  • Do parametrów wejściowych przekazywanych przez odwołanie zostanie dodana wartość const. do SLchar * pól struktury wykorzystywanych jako wartości wejściowe. Nie powinno to wymagać żadnych zmian w kod.
  • Niektóre obecnie podpisane parametry zostaną zastąpione typami niepodpisanymi. Może być konieczna zmiana typu parametru z SLint32 na SLuint32 lub podobnego. dodać obsadę.
  • Equalizer::GetPresetName kopiuje ciąg znaków do pamięci aplikacji zamiast zwracać dane i wskazuje pamięć o implementacji. To znaczna zmiana, dlatego zalecamy uniknąć wywoływania tej metody lub odizolować jej użycie.
  • W typach struct będą dostępne dodatkowe pola. Dla parametrów wyjściowych te nowe pola może być ignorowana, ale w przypadku parametrów wejściowych należy zainicjować nowe pola. Na szczęście Wszystkie te pola powinny znajdować się na obszarach, które nie są obsługiwane przez Androida.
  • Interfejs Zmienią się identyfikatory GUID. Używaj interfejsu, używając nazwy symbolicznej, a nie identyfikatora GUID, aby uniknąć błędu zależności.
  • SLchar zmieni się z unsigned char na char. Dotyczy to głównie lokalizator danych URI i format danych MIME.
  • Nazwa SLDataFormat_MIME.mimeType zostanie zmieniona na pMimeType, Nazwa SLDataLocator_URI.URI zostanie zmieniona na pURI. Zalecamy zainicjowanie struktur danych SLDataFormat_MIME i SLDataLocator_URI za pomocą w nawiasach klamrowych, rozdzielana przecinkami lista wartości zamiast według nazwy pola w celu wyodrębnienia kodu przed tą zmianą. Technika ta została użyta w przykładowym kodzie.
  • SL_DATAFORMAT_PCM nie zezwala aplikacji na określenie reprezentacji dane w postaci liczby całkowitej ze znakiem, liczby całkowitej bez znaku lub liczby zmiennoprzecinkowej. Implementacja na Androidzie zakłada, że 8-bitowe dane są liczbą całkowitą bez znaku, a 16-bitowa liczba całkowita ze znakiem. Ponadto pole Parametr samplesPerSec jest błędny, ponieważ rzeczywiste jednostki to miliHz. Te problemy są oczekiwane , które zostaną uwzględnione w następnej wersji OpenSL ES, w ramach której zostaną wprowadzone nowe rozszerzone dane PCM. który pozwala aplikacji na wyraźne określenie oświadczenia i koryguje nazwę pola. Będzie to nowy format danych, a obecny format danych PCM nadal będzie (chociaż zostało wycofane), nie powinno się wymagać żadnych natychmiastowych zmian w kodzie.