OpenSL ES für Android

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.

Android NDK-Unterstützung für Objekte und Schnittstellen.

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.

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ür slBufferQueueCallback und dem Namen des Felds SLBufferQueueState.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 wird const 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 in SLuint32 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 in pMimeType und SLDataLocator_URI.URI in pURI umbenannt. Wir empfehlen, die Datenstrukturen SLDataFormat_MIME und SLDataLocator_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 Feld samplesPerSec 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.