OSTRZEŻENIE: OpenSL ES został wycofany. Deweloperzy powinni używać biblioteki Oboe typu open source, która jest dostępna na GitHubie. Oboe to kod w języku C++ zapewniający interfejs API podobny do AAudio. Oboe wywołuje AAudio, gdy jest ono dostępne, a gdy nie jest, używa OpenSL ES.
Ta sekcja zawiera informacje potrzebne do rozpoczęcia korzystania z interfejsów OpenSL ES API.
Dodawanie biblioteki OpenSL ES do aplikacji
Funkcje OpenSL ES można wywoływać z kodu C i C++. Aby dodać do aplikacji podstawowy zestaw funkcji OpenSL ES, dołącz plik nagłówka OpenSLES.h
:
#include <SLES/OpenSLES.h>
Aby dodać rozszerzenia OpenSL ES na Androida, dołącz plik nagłówka OpenSLES_Android.h
:
#include <SLES/OpenSLES_Android.h>
Gdy dodasz plik nagłówka OpenSLES_Android.h
, automatycznie zostaną uwzględnione te nagłówki:
#include <SLES/OpenSLES_AndroidConfiguration.h> #include <SLES/OpenSLES_AndroidMetadata.h>
Uwaga: te nagłówki nie są wymagane, ale są wyświetlane jako pomoc w poznawaniu interfejsu API.
Kompilacja i debugowanie
Możesz włączyć OpenSL ES do kompilacji, określając go w pliku Android.mk
, który służy jako jeden z plików Maker systemu kompilacji NDK. Dodaj do Android.mk
ten wiersz:
LOCAL_LDLIBS += -lOpenSLES
Aby zapewnić niezawodne debugowanie, zalecamy sprawdzenie wartości SLresult
, którą zwraca większość interfejsów OpenSL ES API. Do debugowania możesz użyć assertów lub bardziej zaawansowanej logiki obsługi błędów. Żadna z tych metod nie zapewnia przewagi w pracy z OpenSL ES, ale jedna z nich może być bardziej odpowiednia w danym przypadku użycia.
W naszych przykładach używamy asercji, ponieważ pomagają one wykrywać nierealistyczne warunki, które wskazują na błąd w programowaniu. W przypadku innych warunków, które prawdopodobnie wystąpią w wersji produkcyjnej, użyliśmy jawnego przetwarzania błędów.
Wiele błędów interfejsu API powoduje wpis w logu oprócz kodu wyniku innego niż 0. Takie wpisy w dzienniku mogą zawierać dodatkowe szczegóły, które są szczególnie przydatne w przypadku stosunkowo złożonych interfejsów API, takich jak
Engine::CreateAudioPlayer
.
Możesz wyświetlić log z wiersza poleceń lub z Android Studio. Aby sprawdzić dziennik z poziomu wiersza poleceń, wpisz:
$ adb logcat
Aby przejrzeć logi w Android Studio, kliknij Widok > Okna narzędzi > Logcat. Więcej informacji znajdziesz w artykule Zapisywanie i wyświetlanie logów za pomocą narzędzia Logcat.
Przykładowy kod
Zalecamy użycie obsługiwanego i przetestowanego przykładowego kodu, który można wykorzystać jako model dla własnego kodu. Znajduje się on w folderach audio-echo i native-audio w repozytorium GitHub android-ndk.
Uwaga: specyfikacja OpenSL ES 1.0.1 zawiera w załącznikach przykładowy kod (więcej informacji znajdziesz w rejestrze Khronos OpenSL ES). Przykłady w Załączniku B: przykładowy kod i Załączniku C: przykładowy kod do zastosowania korzystają jednak z funkcji, które nie są obsługiwane przez Androida. Niektóre przykłady zawierają też błędy typograficzne lub korzystają z interfejsów API, które prawdopodobnie ulegną zmianie. Posługiwać się nimi należy z ostrożnością. Chociaż kod może być przydatny do zrozumienia pełnego standardu OpenSL ES, nie należy go używać w postaci domyślnej w przypadku Androida.
Treść audio
Oto niektóre z wielu sposobów łączenia treści audio w pakiety:
- Zasoby: gdy umieścisz pliki audio w folderze
res/raw/
, powiązane interfejsy APIResources
będą miały do nich łatwy dostęp. Nie ma jednak bezpośredniego dostępu do zasobów, więc musisz napisać kod w języku programowania Java, aby skopiować je przed użyciem. - Zasoby: umieszczenie plików audio w folderze
assets/
powoduje, że są one bezpośrednio dostępne dla interfejsów API do zarządzania zasobami natywnej aplikacji na Androida. Więcej informacji o tych interfejsach API znajdziesz w plikach nagłówkowychandroid/asset_manager.h
iandroid/asset_manager_jni.h
. Przykładowy kod znajdujący się w repozytorium GitHub android-ndk używa tych interfejsów API do obsługi natywnego menedżera zasobów w połączeniu z lokalizatorem danych w plikach opisów Androida. - Sieć: możesz użyć lokalizatora danych URI, aby odtwarzać treści audio bezpośrednio z sieci. Pamiętaj jednak, aby zapoznać się z artykułem Zabezpieczenia i uprawnienia.
- Lokalny system plików: identyfikator danych URI obsługuje schemat
file:
w przypadku plików lokalnych, o ile są one dostępne dla aplikacji. Pamiętaj, że framework zabezpieczeń Androida ogranicza dostęp do plików za pomocą mechanizmów identyfikatora użytkownika i identyfikatora grupy systemu Linux. - Nagranie: aplikacja może nagrywać dane audio z wejścia mikrofonu, a potem przechowywać i odtwarzać je później. Przykładowy kod korzysta z tej metody w przypadku klipu odtwarzanego.
- Zkompilowany i połączony w ramach inline: możesz połączyć zawartość audio bezpośrednio z zasobami wspólnymi, a potem odtworzyć ją za pomocą odtwarzacza audio z lokalizatorem danych kolejki buforowej. Ta opcja najlepiej sprawdza się w przypadku krótkich klipów w formacie PCM. Ten przykładowy kod korzysta z tej techniki w klipach Hello i Android. Dane PCM zostały przekonwertowane na ciągi szesnastkowe za pomocą narzędzia
bin2c
(nie użyto). - Synteza w czasie rzeczywistym: aplikacja może syntetyzować dane PCM na bieżąco, a następnie odtwarzać je za pomocą odtwarzacza audio z lokalizatorem danych kolejki buforowej. Jest to stosunkowo zaawansowana technika, a szczegóły syntezy dźwięku wykraczają poza zakres tego artykułu.
Uwaga: ten artykuł nie dotyczy znajdowania ani tworzenia przydatnych treści audio do aplikacji. Aby znaleźć więcej informacji, możesz użyć w wyszukiwarce internetowej takich haseł jak interaktywne audio, audio do gier, projektowanie dźwięku i programowanie dźwięku.
Uwaga: Twoim obowiązkiem jest upewnić się, że możesz legalnie odtwarzać i nagrywać treści. W przypadku nagrywania treści mogą mieć zastosowanie kwestie prywatności.
Przykłady kodu
Te przykładowe aplikacje są dostępne na naszej stronie GitHub:
- audio-echo tworzy pętlę ruchu w obie strony między wejściami i wyjściami.
- native-audio to prosty dyktafon/odtwarzacz dźwięku.
Implementacja OpenSL ES w Android NDK różni się w pewnych aspektach od specyfikacji referencyjnej OpenSL ES 1.0.1. Te różnice są ważnym powodem, dla którego kod przykładowy skopiowany bezpośrednio ze specyfikacji referencyjnej OpenSL ES może nie działać w aplikacji na Androida.
Więcej informacji o różnicach między specyfikacją referencyjną a implementacją na Androidzie znajdziesz w artykule OpenSL ES na Androida.