Auf dieser Seite wird beschrieben, wie sich die NDK-Implementierung von OpenSL ESTM von der Referenzspezifikation für OpenSL ES 1.0.1 unterscheidet. Wenn Sie Beispielcode aus der Spezifikation verwenden, müssen Sie ihn möglicherweise ändern, damit er unter Android funktioniert.
Sofern nicht anders angegeben, sind alle Funktionen ab Android 2.3 (API-Level 9) verfügbar. Einige Funktionen sind nur unter Android 4.0 (API-Level 14) verfügbar. Diese sind vermerkt.
Hinweis : Im Android Compatibility Definition Document (CDD) sind die Hardware- und Softwareanforderungen eines kompatiblen Android-Geräts aufgeführt. Weitere Informationen zum gesamten Kompatibilitätsprogramm finden Sie unter Android-Kompatibilität. Das eigentliche CDD-Dokument finden Sie unter CDD.
OpenSL ES bietet eine C-Schnittstelle, die auch über C++ zugänglich ist. Es bietet Funktionen, die den Audioteilen dieser Android Java APIs ähneln:
Wie bei allen Android Native Development Kits (NDK) besteht der Hauptzweck von OpenSL ES für Android darin, die Implementierung gemeinsam genutzter Bibliotheken zu vereinfachen, die über die Java Native Interface (JNI ) aufgerufen werden können. NDK ist nicht zum Schreiben reiner C/C++-Anwendungen gedacht. OpenSL ES ist jedoch eine API mit vollem Funktionsumfang und wir erwarten, dass Sie die meisten Ihrer Audioanforderungen nur mit dieser API und ohne Aufrufe von Code, der in der Android-Laufzeit ausgeführt wird, ausführen können.
Hinweis : Die native Android Audio API (High Performance Audio) 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 anders als die Spezifikation verhält, werden auf der Seite Android-Erweiterungen beschrieben.
Aus der Referenzspezifikation übernommene Features
Die Android NDK-Implementierung von OpenSL ES übernimmt mit bestimmten Einschränkungen einen Großteil des Funktionssatzes aus der Referenzspezifikation.
Globale Einstiegspunkte
OpenSL ES for Android unterstützt alle globalen Einstiegspunkte in der Android-Spezifikation. Zu diesen Einstiegspunkten gehören:
slCreateEngine
slQueryNumSupportedEngineInterfaces
slQuerySupportedEngineInterfaces
Objekte und Schnittstellen
Die folgende Tabelle zeigt die Objekte und Schnittstellen, die von der Android NDK-Implementierung von OpenSL ES unterstützt werden. Wenn in der Zelle ein Ja angezeigt wird, ist die Funktion in dieser Implementierung verfügbar.
Funktion | Audio player | Audiorekorder | Modul | Ausgabemix |
---|---|---|---|---|
Bassverstärkung | Ja | Nein | Nein | Ja |
Pufferwarteschlange | Ja | Nein | Nein | Nein |
Datensuche für Zwischenspeicherwarteschlangen | Ja: Quelle | Nein | Nein | Nein |
Verwaltung dynamischer Oberflächen | Ja | Ja | Ja | Ja |
Effekt senden | Ja | Nein | Nein | Nein |
Modul | Nein | Nein | Ja | Nein |
Umwelthall | Nein | Nein | Nein | Ja |
Equalizer | Ja | Nein | Nein | Ja |
I/O Device Data Locator | Nein | Ja: Quelle | Nein | Nein |
Metadaten-Extraktion | Ja: In PCM decodieren | Nein | Nein | Nein |
Solo stummschalten | Ja | Nein | Nein | Nein |
Objekt | Ja | Ja | Ja | Ja |
Ausgabemix-Suche | Ja: Spülbecken | Nein | Nein | Nein |
Spielen | 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-Datensuche | Ja: Quelle | Nein | Nein | Nein |
Virtualizer | Ja | Nein | Nein | Ja |
Lautstärke | Ja | Nein | Nein | Nein |
Im nächsten Abschnitt werden die Einschränkungen einiger dieser Funktionen erläutert.
Einschränkungen
Für die Funktionen in Tabelle 1 gelten bestimmte Einschränkungen. Diese Einschränkungen stellen Unterschiede zur Referenzspezifikation dar. Der Rest dieses Abschnitts enthält Informationen zu diesen Unterschieden.
Verwaltung dynamischer Oberflächen
OpenSL ES für Android unterstützt weder RemoveInterface
noch ResumeInterface
.
Effektkombinationen: Umgebungs- und voreingestellter Nachhall
Es ist nicht möglich, gleichzeitig einen Umgebungs- und einen voreingestellten Nachhall in einem Ausgabemix zu verwenden.
Die Plattform ignoriert Effektanfragen möglicherweise, wenn sie die CPU-Auslastung als zu hoch schätzt.
Effekt senden
SetSendLevel()
unterstützt eine einzelne Sendestufe pro Audioplayer.
Umwelthall
Der Nachhall unterstützt die Felder reflectionsDelay
, reflectionsLevel
oder reverbDelay
der Struktur SLEnvironmentalReverbSettings
nicht.
MIME-Datenformat
Sie können das MIME-Datenformat nur mit dem URI Data Locator und nur für einen Audioplayer verwenden. Dieses Datenformat kann nicht für Audiorekorder verwendet werden.
Für die Android-Implementierung von OpenSL ES muss mimeType
entweder mit NULL
oder einem gültigen UTF-8-String initialisiert werden. Außerdem müssen Sie containerType
mit einem gültigen Wert initialisieren.
Unter Berücksichtigung anderer Aspekte, wie z. B. der Übertragbarkeit auf andere Implementierungen oder Inhaltsformate, die eine App nicht anhand des Headers erkennen kann, empfehlen wir, mimeType
auf NULL
und containerType
auf SL_CONTAINERTYPE_UNSPECIFIED
zu setzen.
OpenSL ES for Android unterstützt die folgenden Audioformate, solange die Android-Plattform sie ebenfalls unterstützt:
- 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 finden Sie unter Unterstützte Medienformate.
Für die Verarbeitung dieser und anderer Formate in dieser Implementierung von OpenSL ES gelten die folgenden Einschränkungen:
- AAC-Formate müssen sich in einem MP4- oder ADTS-Container befinden.
- OpenSL ES für Android unterstützt MIDI nicht.
- WMA ist kein Teil von AOSP und wir haben ihre Kompatibilität mit OpenSL ES for Android nicht überprüft.
- Die Android NDK-Implementierung von OpenSL ES unterstützt keine direkte Wiedergabe von DRM oder verschlüsselten Inhalten. Zur Wiedergabe geschützter Audioinhalte müssen diese vor der Wiedergabe in der App entschlüsselt werden. Dabei müssen eventuelle Einschränkungen der digitalen Rechteverwaltung erzwungen werden.
Objektbezogene Methoden
OpenSL ES for Android unterstützt die folgenden Methoden zum Bearbeiten von Objekten nicht:
Resume()
RegisterCallback()
AbortAsyncOperation()
SetPriority()
GetPriority()
SetLossOfControlInterfaces()
PCM-Datenformat
PCM ist das einzige Datenformat, das Sie für Pufferwarteschlangen verwenden können. Unterstützte PCM-Wiedergabekonfigurationen haben die folgenden Eigenschaften:
- 8-Bit, nicht signiert oder 16-Bit, signiert.
- Mono oder Stereo
- Little-Endian-Bytesortierung.
- 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 Konfigurationen, die OpenSL ES for Android für die Aufzeichnung unterstützt, sind geräteabhängig. In der Regel sind 16.000 Hz Mono/16-Bit signiert, unabhängig vom Gerät.
Der Wert des Felds samplesPerSec
wird trotz des irreführenden Namens in MilliHz-Einheiten angegeben. Damit Sie nicht versehentlich den falschen Wert verwenden, sollten Sie dieses Feld mit einer der für diesen Zweck definierten symbolischen Konstanten initialisieren, z. B. SL_SAMPLINGRATE_44_1
.
Android 5.0 (API-Level 21) und höher unterstützt Gleitkommadaten.
Wiedergabegeschwindigkeit
Die Wiedergaberate von OpenSL ES gibt die Geschwindigkeit an, mit der ein Objekt Daten darstellt, ausgedrückt in Tausendstel normaler Geschwindigkeit oder pro tausend Tausendstel. Eine Wiedergaberate von 1.000 pro 1.000 entspricht beispielsweise 1.000/1.000, also normale Geschwindigkeit. Ein Ratenbereich ist ein geschlossenes Intervall, das einen Bereich möglicher Wiedergaberaten ausdrückt.
Die Unterstützung für Wiedergaberatenbereiche und andere Funktionen kann je nach Plattformversion und Implementierung variieren. Ihre App kann diese Funktionen zur Laufzeit ermitteln, indem sie PlaybackRate::GetRateRange()
oder PlaybackRate::GetCapabilitiesOfRate()
zur Abfrage des Geräts verwendet.
Ein Gerät unterstützt in der Regel denselben Ratenbereich für eine Datenquelle im PCM-Format und einen Einheitsratenbereich von 1.000 pro 1.000 bis 1.000 pro 1.000 pro 1.000 für andere Formate. Das heißt, der Einheitsratenbereich ist effektiv ein einzelner Wert.
Aufnehmen
OpenSL ES für Android unterstützt nicht die Ereignisse SL_RECORDEVENT_HEADATLIMIT
und SL_RECORDEVENT_HEADMOVING
.
Suche
Die Methode SetLoop()
ermöglicht Schleifen von ganzen Dateien. Wenn Sie Schleifen aktivieren möchten, setzen Sie den Parameter startPos
auf 0 und den Parameter endPos
auf SL_TIME_UNKNOWN
.
Datensuche für Zwischenspeicherwarteschlangen
Ein Audioplayer oder -rekorder mit einem Datenfinder für eine Zwischenspeicherwarteschlange unterstützt nur das PCM-Datenformat.
I/O Device Data Locator
OpenSL ES for Android unterstützt die Verwendung eines E/A-Geräte-Data-Finders nur, wenn Sie ihn als Datenquelle für Engine::CreateAudioRecorder()
angegeben haben.
Initialisieren Sie den Device Data Locator mithilfe der Werte, die im folgenden Code-Snippet enthalten sind:
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
URI-Datensuche
OpenSL ES for Android kann den URI Data Locator nur mit dem MIME-Datenformat und nur für einen Audioplayer verwenden. Sie können einen URI-Datensucher nicht für einen Audiorekorder 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 für rtsp:
mit Audio auf der Android-Plattform nicht bestätigt.
Datenstrukturen
Android unterstützt die folgenden Datenstrukturen in OpenSL ES 1.0.1:
SLDataFormat_MIME
SLDataFormat_PCM
SLDataLocator_BufferQueue
SLDataLocator_IODevice
SLDataLocator_OutputMix
SLDataLocator_URI
SLDataSink
SLDataSource
SLEngineOption
SLEnvironmentalReverbSettings
SLInterfaceID
Plattformkonfiguration
OpenSL ES for Android wurde für Multithread-Anwendungen entwickelt und ist Thread-sicher. Sie unterstützt eine einzelne Suchmaschine pro Anwendung und bis zu 32 Objekte pro Suchmaschine. Der verfügbare Gerätespeicher und die CPU können die nutzbare 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 zusammen in derselben Anwendung verwendet werden. In diesem Fall gibt es intern ein einzelnes gemeinsames Engine-Objekt und das Limit von 32 Objekten wird von OpenMAX AL und OpenSL ES gemeinsam genutzt. Die Anwendung sollte beide Engines erstellen, beide Engines verwenden und schließlich beide löschen. Die Implementierung behält eine Referenzanzahl auf der gemeinsam genutzten Engine bei, sodass sie während des zweiten Löschvorgangs korrekt gelöscht wird.
Programmierhinweise
Die OpenSL ES-Programmierhinweise enthalten ergänzende Informationen zur ordnungsgemäßen Implementierung von OpenSL ES.
Hinweis : Wir haben eine Kopie der OpenSL ES 1.0.1-Spezifikation mit dem NDK in docs/opensles/OpenSL_ES_Specification_1.0.1.pdf
beigefügt.
Plattformprobleme
In diesem Abschnitt werden bekannte Probleme der ersten Plattformversion beschrieben, die diese APIs unterstützt.
Verwaltung dynamischer Oberflächen
DynamicInterfaceManagement::AddInterface
funktioniert nicht. Geben Sie stattdessen die Schnittstelle im Array an, das an Create()
übergeben wird, wie im Beispielcode für den Umgebungshall gezeigt.
Zukünftige Versionen von OpenSL ES planen
Die Hochleistungs-Audio-APIs von Android basieren auf der Khronos Group OpenSL ES 1.0.1. Khronos hat die überarbeitete Version 1.1 des Standards veröffentlicht. Die überarbeitete Version enthält neue Funktionen, Klarstellungen und Korrekturen von typografischen Fehlern und einigen Inkompatibilitäten. Die meisten der zu erwartenden Inkompatibilitäten sind relativ gering oder befinden sich in Bereichen von OpenSL ES, die von Android nicht unterstützt werden.
Eine mit dieser Version entwickelte Anwendung sollte auch auf zukünftigen Versionen der Android-Plattform funktionieren, vorausgesetzt, Sie beachten die Richtlinien im Abschnitt Kompatibilität mit Binärprogrammen planen weiter unten.
Hinweis : Die zukünftige Kompatibilität mit Quellen ist kein Ziel. Wenn Sie also ein Upgrade auf eine neuere Version des NDK durchführen, müssen Sie möglicherweise den Quellcode Ihrer Anwendung so ändern, dass er der neuen API entspricht. Wir gehen davon aus, dass die meisten Änderungen nur geringfügig sein werden. Weitere Informationen dazu finden Sie unten.
Kompatibilität mit Binärprogrammen einplanen
Wir empfehlen, für Ihre Anwendung die folgenden Richtlinien einzuhalten, 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.
- Verlassen Sie sich bei einem fehlgeschlagenen Vorgang nicht auf einen bestimmten Ergebniscode. Bereiten Sie sich auf einen anderen Ergebniscode vor.
- Callback-Handler für Anwendungen werden im Allgemeinen in einem eingeschränkten Kontext ausgeführt. Sie sollten so geschrieben werden, dass die Arbeit schnell erledigt wird, und sie dann so schnell wie möglich zurückgegeben werden. Führen Sie innerhalb eines Callback-Handlers keine komplexen Vorgänge aus. Beispielsweise können Sie in einem Callback zum Abschluss der Zwischenspeicherwarteschlange einen weiteren Puffer 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 erhalten, und Ereignistypen ignorieren, die sie nicht erkennen. Callbacks, die mit einer Ereignismaske aus aktivierten Ereignistypen konfiguriert sind, sollten so vorbereitet sein, dass sie mit mehreren Ereignistypbits gleichzeitig aufgerufen werden können. Verwenden Sie „&“ zum Testen für jedes Ereigniselement und nicht für einen Switch Case.
- Verwenden Sie den Prefetch-Status und die Callbacks als allgemeine Fortschrittsindikatoren, hängen Sie jedoch nicht von bestimmten hartcodierten Füllebenen oder Callback-Sequenzen ab. Die Bedeutung des Füllstatus für den Prefetch-Status und das Verhalten bei Fehlern, die während des Prefetch-Status erkannt werden, können sich ändern.
Hinweis: Weitere Informationen finden Sie im Abschnitt Verhalten von Puffern weiter unten.
Quellkompatibilität planen
Wie bereits erwähnt, sind Inkompatibilitäten des Quellcodes voraussichtlich in der nächsten Version von OpenSL ES der Khronos Group zu erwarten. Zu den wahrscheinlichen Bereichen für Änderungen gehören:
- An der Schnittstelle für die Zwischenspeicherwarteschlange sollten sich erhebliche Änderungen ergeben, insbesondere in den Bereichen
BufferQueue::Enqueue
, der Parameterliste fürslBufferQueueCallback
und dem Namen des FeldsSLBufferQueueState.playIndex
. Wir empfehlen, für Ihren Anwendungscode stattdessen einfache Pufferwarteschlangen für Android zu verwenden. Im Beispielcode, der mit dem NDK bereitgestellt wird, haben wir aus diesem Grund einfache Android-Pufferwarteschlangen für die Wiedergabe verwendet. (Wir verwenden auch die einfache Zwischenspeicherwarteschlange von Android zum Aufzeichnen und Decodieren in PCM. Dies liegt jedoch daran, dass das standardmäßige OpenSL ES 1.0.1 das Aufzeichnen oder Decodieren in eine Zwischenspeicherwarteschlangen-Datensenke nicht unterstützt.) - Den Eingabeparametern, die durch Verweis übergeben werden, und den als Eingabewerten verwendeten
SLchar *
-Strukturfeldern wirdconst
hinzugefügt. Dazu sollten keine Änderungen an Ihrem Code erforderlich sein. - Einige Parameter, die derzeit signiert sind, werden durch Typen ohne Vorzeichen 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 Anwendungsarbeitsspeicher, anstatt einen Zeiger an den Implementierungsspeicher zurückzugeben. Da dies eine erhebliche Änderung darstellt, empfehlen wir, den Aufruf dieser Methode entweder zu vermeiden oder ihre Verwendung zu isolieren.- Die Strukturtypen enthalten zusätzliche Felder. Bei Ausgabeparametern können diese neuen Felder ignoriert werden. Für Eingabeparameter müssen die neuen Felder jedoch initialisiert werden. Glücklicherweise sollte sich alle diese Felder in Bereichen befinden, die nicht von Android unterstützt werden.
- Die GUIDs der Schnittstelle ändern sich. Verwenden Sie Schnittstellen nach dem symbolischen Namen und nicht nach GUID, um Abhängigkeiten zu vermeiden.
- „
SLchar
“ wird von „unsigned char
“ zu „char
“ geändert. Dies betrifft vor allem die URI-Datensuche und das MIME-Datenformat. SLDataFormat_MIME.mimeType
wird inpMimeType
undSLDataLocator_URI.URI
inpURI
umbenannt. Wir empfehlen, die DatenstrukturenSLDataFormat_MIME
undSLDataLocator_URI
mit einer in Klammern gesetzten, durch Kommas getrennten Liste von Werten und nicht mit dem Feldnamen zu initialisieren, um Ihren Code von dieser Änderung zu isolieren. Diese Technik wird im Beispielcode verwendet.- Die Anwendung darf die Daten mit
SL_DATAFORMAT_PCM
nicht als vorzeichenbehaftete Ganzzahl, vorzeichenlose Ganzzahl oder als Gleitkommazahl angeben. Die Android-Implementierung geht davon aus, dass 8-Bit-Daten eine vorzeichenlose Ganzzahl und 16-Bit-Daten eine vorzeichenbehaftete Ganzzahl sind. Außerdem ist das FeldsamplesPerSec
falsch, da die tatsächlichen Einheiten MilliHz sind. Diese Probleme sollen in der nächsten OpenSL ES-Version behoben werden, 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 sein wird (obwohl verworfen wurde), sollten keine sofortigen Änderungen an Ihrem Code erforderlich sein.