WARNUNG: OpenSL ES wurde eingestellt. Entwickler sollten die Open-Source-Oboe-Bibliothek verwenden, die auf GitHub verfügbar ist. Oboe ist ein C++-Wrapper, der eine API bietet, die AAudio sehr ähnelt. Oboe ruft AAudio auf, wenn AAudio verfügbar ist, und wechselt zu OpenSL ES, wenn AAudio nicht verfügbar ist.
Auf dieser Seite erfahren Sie, inwiefern sich die NDK-Implementierung von OpenSL ES™ von der Referenzspezifikation für OpenSL ES 1.0.1 unterscheidet. Wenn Sie Beispielcode aus der Spezifikation verwenden, müssen Sie ihn möglicherweise so ändern, dass er auf Android-Geräten funktioniert.
Sofern nicht anders angegeben, sind alle Funktionen ab Android 2.3 (API-Level 9) verfügbar. Einige Funktionen sind nur für Android 4.0 (API-Level 14) verfügbar. Diese sind entsprechend gekennzeichnet.
Hinweis : Im Android Compatibility Definition Document (CDD) werden die Hardware- und Softwareanforderungen eines kompatiblen Android-Geräts aufgeführt. Weitere Informationen zum allgemeinen Kompatibilitätsprogramm finden Sie unter Android-Kompatibilität und das eigentliche CDD-Dokument unter CDD.
OpenSL ES bietet eine C-Programmierschnittstelle, auf die auch mit C++ zugegriffen werden kann. Sie bietet ähnliche Audiobereiche wie diese Android Java APIs:
Wie bei allen Elementen des Android Native Development Kit (NDK) besteht der Hauptzweck von OpenSL ES für Android darin, die Implementierung gemeinsam genutzter Bibliotheken zu erleichtern, die über die Java Native Interface (JNI ) aufgerufen werden. Das NDK ist nicht für das Schreiben reiner C/C++-Anwendungen gedacht. OpenSL ES ist jedoch eine API mit umfassender Funktionalität und wir gehen davon aus, dass Sie die meisten Ihrer Audioanforderungen nur mit dieser API erfüllen können, ohne Upcalls zu Code ausführen zu müssen, der in der Android-Laufzeit ausgeführt wird.
Hinweis : Die native Audio-API (High-Performance Audio) von Android basiert zwar auf OpenSL ES, ist aber keine konforme Implementierung eines OpenSL ES 1.0.1-Profils (Spiel, Musik oder Smartphone). Das liegt daran, dass Android nicht alle Funktionen implementiert, die für eines der Profile erforderlich sind. Alle bekannten Fälle, in denen sich Android von der Spezifikation unterscheidet, werden auf der Seite Android-Erweiterungen beschrieben.
Aus der Referenzspezifikation übernommene Features
Die Android NDK-Implementierung von OpenSL ES übernimmt einen Großteil des Feature-Sets aus der Referenzspezifikation mit bestimmten Einschränkungen.
Globale Einstiegspunkte
OpenSL ES für Android unterstützt alle globalen Einstiegspunkte in der Android-Spezifikation. Zu diesen Einstiegspunkten gehören:
slCreateEngine
slQueryNumSupportedEngineInterfaces
slQuerySupportedEngineInterfaces
Objekte und Oberflächen
In der folgenden Tabelle sind die Objekte und Schnittstellen aufgeführt, die von der Android NDK-Implementierung von OpenSL ES unterstützt werden. Wenn in der Zelle Ja angezeigt wird, ist die Funktion in dieser Implementierung verfügbar.
Funktion | Audio player | Audiorekorder | Motor | Ausgabemix |
---|---|---|---|---|
Bassverstärkung | Ja | Nein | Nein | Ja |
Pufferwarteschlange | Ja | Nein | Nein | Nein |
Datensuche für Pufferwarteschlangen | Ja: Quelle | Nein | Nein | Nein |
Dynamische Benutzeroberflächenverwaltung | Ja | Ja | Ja | Ja |
Effekt gesendet | Ja | Nein | Nein | Nein |
Motor | Nein | Nein | Ja | Nein |
Umgebungshall | Nein | Nein | Nein | Ja |
Equalizer | Ja | Nein | Nein | Ja |
Daten-Locator für E/A-Geräte | Nein | Ja: Quelle | Nein | Nein |
Metadaten extrahieren | Ja: In PCM decodieren | Nein | Nein | Nein |
Solo stummschalten | Ja | Nein | Nein | Nein |
Objekt | Ja | Ja | Ja | Ja |
Output-Mix-Locator | Ja: Spülbecken | Nein | Nein | Nein |
Wiedergeben | Ja | Nein | Nein | Nein |
Wiedergabegeschwindigkeit | Ja | Nein | Nein | Nein |
Prefetch-Status | Ja | Nein | Nein | Nein |
Voreingestellter Hall | Nein | Nein | Nein | Ja |
Aufnehmen | Nein | Ja | Nein | Nein |
Suche | Ja | Nein | Nein | Nein |
URI-Daten-Locator | Ja: Quelle | Nein | Nein | Nein |
Virtualizer | Ja | Nein | Nein | Ja |
Lautstärke | Ja | Nein | Nein | Nein |
Im nächsten Abschnitt werden die Einschränkungen für einige dieser Funktionen erläutert.
Beschränkungen
Für die Funktionen in Tabelle 1 gelten bestimmte Einschränkungen. Diese Einschränkungen stellen Unterschiede zur Referenzspezifikation dar. Im Rest dieses Abschnitts finden Sie Informationen zu diesen Unterschieden.
Dynamische Benutzeroberflächenverwaltung
OpenSL ES für Android unterstützt weder RemoveInterface
noch ResumeInterface
.
Effektkombinationen: Raumhall und voreingestellter Hall
Für denselben Ausgabemix können nicht gleichzeitig Raumhall und vordefinierter Hall verwendet werden.
Die Plattform ignoriert möglicherweise Effektanfragen, wenn die CPU-Auslastung voraussichtlich zu hoch ist.
Effekt gesendet
SetSendLevel()
unterstützt eine einzelne Sendeebene pro Audioplayer.
Umgebungshall
Der Raumhall unterstützt die Felder reflectionsDelay
, reflectionsLevel
und reverbDelay
des SLEnvironmentalReverbSettings
-Structs nicht.
MIME-Datenformat
Sie können das MIME-Datenformat nur mit dem URI-Datensucher und nur für einen Audioplayer verwenden. Dieses Datenformat kann nicht für einen Audiorekorder verwendet werden.
Für die Android-Implementierung von OpenSL ES musst du mimeType
entweder mit NULL
oder einem gültigen UTF-8-String initialisieren. Außerdem müssen Sie containerType
mit einem gültigen Wert initialisieren.
Wenn keine anderen Aspekte zu berücksichtigen sind, z. B. die Portabilität zu anderen Implementierungen oder Inhaltsformate, die eine App nicht anhand des Headers identifizieren kann, empfehlen wir, mimeType
auf NULL
und containerType
auf SL_CONTAINERTYPE_UNSPECIFIED
festzulegen.
OpenSL ES für Android unterstützt die folgenden Audioformate, sofern sie auch von der Android-Plattform unterstützt werden:
- WAV PCM.
- WAV alaw.
- WAV ulaw.
- MP3 Ogg Vorbis.
- AAC LC.
- HE-AACv1 (AAC+).
- HE-AACv2 (erweitertes AAC+).
- AMR.
- FLAC.
Hinweis : Eine Liste der von Android unterstützten Audioformate findest du unter Unterstützte Medienformate.
Für die Verarbeitung dieses und anderer Formate in dieser OpenSL ES-Implementierung gelten die folgenden Einschränkungen:
- AAC-Formate müssen sich in einem MP4- oder ADTS-Container befinden.
- OpenSL ES für Android unterstützt kein MIDI.
- WMA ist nicht Teil von AOSP und wir haben die Kompatibilität mit OpenSL ES für Android nicht überprüft.
- Die Android NDK-Implementierung von OpenSL ES unterstützt keine direkte Wiedergabe von DRM- oder verschlüsselten Inhalten. Wenn Sie geschützte Audioinhalte abspielen möchten, müssen Sie sie vor der Wiedergabe in Ihrer App entschlüsseln. Dabei müssen alle DRM-Einschränkungen durch Ihre App erzwungen werden.
Objektbezogene Methoden
OpenSL ES für Android unterstützt die folgenden Methoden zur Manipulation von Objekten nicht:
Resume()
RegisterCallback()
AbortAsyncOperation()
SetPriority()
GetPriority()
SetLossOfControlInterfaces()
PCM-Datenformat
PCM ist das einzige Datenformat, das du mit Pufferwarteschlangen verwenden kannst. Unterstützte PCM-Wiedergabekonfigurationen haben die folgenden Eigenschaften:
- 8-Bit-vorzeichenlos oder 16-Bit-mit Vorzeichen.
- Mono oder Stereo.
- Little-Endian-Bytereihenfolge.
- Abtastraten:
- 8.000 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
Die von OpenSL ES für Android unterstützten Konfigurationen für die Aufzeichnung sind geräteabhängig. Normalerweise ist unabhängig vom Gerät 16.000 Hz Mono/16-Bit signiert verfügbar.
Der Wert des Felds samplesPerSec
wird trotz des irreführenden Namens in Millihertz angegeben. Um versehentlich den falschen Wert zu verwenden, empfehlen wir, dieses Feld mit einer der zu diesem Zweck definierten symbolischen Konstanten zu initialisieren, z. B. SL_SAMPLINGRATE_44_1
.
Android 5.0 (API-Level 21) und höher unterstützen Gleitkommadaten.
Wiedergabegeschwindigkeit
Eine OpenSL ES-Wiedergaberate gibt die Geschwindigkeit an, mit der ein Objekt Daten darstellt, ausgedrückt in Tausendstel der normalen Geschwindigkeit oder Pro Mille. Eine Wiedergaberate von 1.000 pro Mille entspricht beispielsweise 1.000/1.000, also der normalen Geschwindigkeit. Ein Taktfrequenzbereich ist ein geschlossenes Intervall, das einen Bereich möglicher Wiedergaberaten angibt.
Die Unterstützung für Wiedergabegeschwindigkeitsbereiche und andere Funktionen kann je nach Plattformversion und Implementierung variieren. Ihre App kann diese Funktionen zur Laufzeit ermitteln. Dazu wird das Gerät mit PlaybackRate::GetRateRange()
oder PlaybackRate::GetCapabilitiesOfRate()
abgefragt.
Ein Gerät unterstützt in der Regel denselben Ratenbereich für eine Datenquelle im PCM-Format und einen Einheitsratebereich von 1.000 promille bis 1.000 promille für andere Formate. Das bedeutet, dass der Einheitsratebereich effektiv ein einzelner Wert ist.
Aufnehmen
OpenSL ES für Android unterstützt die Ereignisse SL_RECORDEVENT_HEADATLIMIT
und SL_RECORDEVENT_HEADMOVING
nicht.
Suche
Mit der SetLoop()
-Methode kann die gesamte Datei wiederholt werden. Wenn du das Looping aktivieren möchtest, setze den Parameter startPos
auf 0 und den Parameter endPos
auf SL_TIME_UNKNOWN
.
Daten-Locator für Buffer-Warteschlange
Ein Audioplayer oder -rekorder mit einem Datenlocator für eine Pufferwarteschlange unterstützt nur das PCM-Datenformat.
Daten-Locator für E/A-Geräte
OpenSL ES für Android unterstützt die Verwendung eines Datenlocators für E/A-Geräte nur, wenn Sie den Locator als Datenquelle für Engine::CreateAudioRecorder()
angegeben haben.
Initialisieren Sie den Gerätedaten-Locator mit den Werten im folgenden Code-Snippet:
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
URI-Daten-Locator
OpenSL ES für Android kann den URI-Daten-Locator nur mit dem MIME-Datenformat und nur für einen Audioplayer verwenden. Sie können für einen Audiorekorder keinen URI-Datenfinder verwenden. Der URI kann nur die Schemas http:
und file:
verwenden. Andere Schemas wie https:
, ftp:
oder content:
sind nicht zulässig.
Wir haben die Unterstützung von rtsp:
mit Audio auf der Android-Plattform nicht überprüft.
Datenstrukturen
Android unterstützt die folgenden OpenSL ES 1.0.1-Datenstrukturen:
SLDataFormat_MIME
SLDataFormat_PCM
SLDataLocator_BufferQueue
SLDataLocator_IODevice
SLDataLocator_OutputMix
SLDataLocator_URI
SLDataSink
SLDataSource
SLEngineOption
SLEnvironmentalReverbSettings
SLInterfaceID
Plattformkonfiguration
OpenSL ES für Android ist für mehrstufige Anwendungen konzipiert und threadsicher. Es unterstützt eine einzelne Engine pro Anwendung und bis zu 32 Objekte pro Engine. Der verfügbare Arbeitsspeicher und die verfügbare CPU des Geräts können die verwendbare Anzahl von Objekten weiter einschränken.
Diese Engine-Optionen werden erkannt, aber von slCreateEngine
ignoriert:
SL_ENGINEOPTION_THREADSAFE
SL_ENGINEOPTION_LOSSOFCONTROL
OpenMAX AL und OpenSL ES können in derselben Anwendung zusammen verwendet werden. In diesem Fall gibt es intern ein einziges gemeinsames Engine-Objekt und das Limit von 32 Objekten wird zwischen OpenMAX AL und OpenSL ES aufgeteilt. Die Anwendung sollte beide Engines erstellen, beide Engines verwenden und schließlich beide löschen. Die Implementierung führt eine Referenzzählung für die freigegebene Engine, damit sie beim zweiten Löschvorgang korrekt gelöscht wird.
Programmhinweise
Die OpenSL ES-Programmierhinweise enthalten zusätzliche Informationen, die für eine ordnungsgemäße Implementierung von OpenSL ES erforderlich sind.
Hinweis : Wir haben eine Kopie der Spezifikation von OpenSL ES 1.0.1 mit dem NDK in docs/opensles/OpenSL_ES_Specification_1.0.1.pdf
beigefügt.
Plattformprobleme
In diesem Abschnitt werden bekannte Probleme in der ersten Plattformversion beschrieben, die diese APIs unterstützt.
Dynamische Benutzeroberflächenverwaltung
DynamicInterfaceManagement::AddInterface
funktioniert nicht. Geben Sie die Benutzeroberfläche stattdessen im Array an, das an Create()
übergeben wird, wie im Beispielcode für den Umgebungsreverb gezeigt.
Für zukünftige Versionen von OpenSL ES planen
Die leistungsstarken Audio-APIs von Android basieren auf Khronos Group OpenSL ES 1.0.1. Khronos hat eine überarbeitete Version 1.1 des Standards veröffentlicht. Die überarbeitete Version enthält neue Funktionen, Klarstellungen, Korrekturen von Tippfehlern und einige Inkompatibilitäten. Die meisten der erwarteten Inkompatibilitäten sind relativ geringfügig oder betreffen Bereiche von OpenSL ES, die von Android nicht unterstützt werden.
Eine mit dieser Version entwickelte Anwendung sollte auf zukünftigen Versionen der Android-Plattform funktionieren, sofern Sie die im Abschnitt Binäre Kompatibilität planen beschriebenen Richtlinien einhalten.
Hinweis : Die zukünftige Kompatibilität von Quellen wird nicht angestrebt. Wenn Sie also auf eine neuere Version des NDK umstellen, müssen Sie möglicherweise den Quellcode Ihrer Anwendung so ändern, dass er der neuen API entspricht. Wir gehen davon aus, dass die meisten dieser Änderungen geringfügig sind. Weitere Informationen finden Sie unten.
Binärkompatibilität planen
Wir empfehlen, dass Ihre Anwendung diesen Richtlinien entspricht, um die zukünftige Binärkompatibilität zu verbessern:
- Verwenden Sie nur die dokumentierte Teilmenge der von Android unterstützten Funktionen aus OpenSL ES 1.0.1.
- Verlasse dich nicht auf einen bestimmten Ergebniscode für einen fehlgeschlagenen Vorgang. Sei darauf vorbereitet, mit einem anderen Ergebniscode umzugehen.
- Callback-Handler von Anwendungen werden in der Regel in einem eingeschränkten Kontext ausgeführt. Sie sollten so geschrieben sein, dass sie ihre Arbeit schnell erledigen und dann so schnell wie möglich zurückkehren können. Führen Sie keine komplexen Vorgänge innerhalb eines Callback-Handlers aus. Sie können beispielsweise in einem Callback für den Abschluss der Zwischenspeicherwarteschlange einen weiteren Zwischenspeicher in die Warteschlange stellen, aber keinen Audioplayer erstellen.
- Callback-Handler sollten darauf vorbereitet sein, häufiger oder seltener aufgerufen zu werden, um zusätzliche Ereignistypen zu empfangen, und sollten Ereignistypen ignorieren, die sie nicht erkennen. Callbacks, die mit einer Ereignismaske aus aktivierten Ereignistypen konfiguriert sind, sollten so vorbereitet sein, dass sie mit mehreren gleichzeitig festgelegten Ereignistyp-Bits aufgerufen werden können. Verwenden Sie „&“, um für jedes Ereignisbit anstelle eines Switch-Case-Vorgangs zu testen.
- Verwende den prefetch-Status und Callbacks als allgemeine Hinweise auf den Fortschritt, aber verlasse dich nicht auf bestimmte hartcodierte Füllstände oder Callback-Sequenzen. Die Bedeutung des Füllstands des prefetch-Status und das Verhalten bei Fehlern, die während des Prefetch erkannt werden, können sich ändern.
Hinweis : Weitere Informationen finden Sie unten im Abschnitt Verhalten von Pufferwarteschlangen.
Quellkompatibilität planen
Wie bereits erwähnt, sind in der nächsten Version von OpenSL ES von der Khronos Group Inkompatibilitäten mit dem Quellcode zu erwarten. Zu den wahrscheinlichen Änderungsbereichen gehören:
- An der Schnittstelle der Zwischenspeicherwarteschlange sind erhebliche Änderungen zu erwarten, insbesondere in Bezug auf
BufferQueue::Enqueue
, die Parameterliste fürslBufferQueueCallback
und den Namen des FeldsSLBufferQueueState.playIndex
. Wir empfehlen, im Anwendungscode stattdessen einfache Android-Pufferwarteschlangen zu verwenden. Im Beispielcode, der mit dem NDK geliefert wird, haben wir aus diesem Grund einfache Android-Pufferwarteschlangen für die Wiedergabe verwendet. Wir verwenden auch die einfache Pufferwarteschlange von Android zum Aufzeichnen und Decodieren in PCM, da OpenSL ES 1.0.1 das Aufzeichnen oder Decodieren in eine Pufferwarteschlange nicht unterstützt. - Den per Verweis übergebenen Eingabeparametern und den
SLchar *
-Strukturfeldern, die als Eingabewerte verwendet werden, wirdconst
hinzugefügt. Dies sollte keine Änderungen an Ihrem Code erfordern. - Einige Parameter, die derzeit signiert sind, werden durch signaturlose Typen ersetzt.
Möglicherweise müssen Sie einen Parametertyp von
SLint32
inSLuint32
oder ähnlich ändern oder eine Umwandlung hinzufügen. Equalizer::GetPresetName
kopiert den String in den Anwendungsspeicher, anstatt einen Zeiger in den Implementierungsspeicher zurückzugeben. Dies ist eine erhebliche Änderung. Wir empfehlen Ihnen daher, diese Methode entweder nicht aufzurufen oder ihre Verwendung einzuschränken.- Die Strukturtypen enthalten zusätzliche Felder. Bei Ausgabeparametern können diese neuen Felder ignoriert werden. Bei Eingabeparametern müssen sie jedoch initialisiert werden. Glücklicherweise befinden sich alle diese Felder voraussichtlich in Bereichen, die von Android nicht unterstützt werden.
- Die GUIDs der Benutzeroberfläche ändern sich. Verweise auf Schnittstellen anhand des symbolischen Namens anstelle der GUID, um Abhängigkeiten zu vermeiden.
- Der Preis für
SLchar
ändert sich vonunsigned char
inchar
. Dies betrifft hauptsächlich den URI-Datenlocator und das MIME-Datenformat. SLDataFormat_MIME.mimeType
wird inpMimeType
umbenannt undSLDataLocator_URI.URI
wird inpURI
umbenannt. Wir empfehlen, die DatenstrukturenSLDataFormat_MIME
undSLDataLocator_URI
mit einer in Klammern gesetzten, durch Kommas getrennten Liste von Werten anstatt nach Feldnamen zu initialisieren, um Ihren Code von dieser Änderung zu isolieren. Diese Technik wird im Beispielcode verwendet.SL_DATAFORMAT_PCM
erlaubt es der Anwendung nicht, die Darstellung der Daten als signierte Ganzzahl, als ungesignierte Ganzzahl oder als Gleitkommazahl anzugeben. Bei der Android-Implementierung wird davon ausgegangen, dass 8-Bit-Daten vorzeichenlose Ganzzahlen und 16-Bit-Daten vorzeichenbehaftete Ganzzahlen sind. Außerdem ist das FeldsamplesPerSec
falsch, da die tatsächlichen Einheiten in MilliHz angegeben werden. Diese Probleme werden voraussichtlich in der nächsten OpenSL ES-Version behoben, die ein neues erweitertes PCM-Datenformat einführt, mit dem die Anwendung die Darstellung explizit angeben und den Feldnamen korrigieren kann. Da es sich um ein neues Datenformat handelt und das aktuelle PCM-Datenformat weiterhin verfügbar (wenn auch nicht mehr empfohlen) sein wird, sollten keine sofortigen Änderungen an deinem Code erforderlich sein.