AVVISO: OpenSL ES è deprecato. Gli sviluppatori dovrebbero usare l'open source Libreria di oboe disponibile su GitHub. Oboe è un wrapper C++ che fornisce un'API molto simile a AAudio. Oboe chiama AAudio quando AAudio disponibile e torna a OpenSL ES se AAudio non è disponibile.
OpenSL ES per Android estende la specifica OpenSL ES di riferimento per renderlo compatibile con e sfruttare la potenza e la flessibilità della piattaforma Android.
La definizione dell'API per le estensioni Android si trova in OpenSLES_Android.h
e nei file di intestazione che include. Per maggiori dettagli su queste estensioni, consulta OpenSLES_Android.h
. Questo file si trova nella radice di installazione, nella
Directory sysroot/usr/include/SLES
. Salvo diversa indicazione
tutte le interfacce sono esplicite.
Queste estensioni limitano la portabilità della tua applicazione
altre implementazioni OpenSL ES, in quanto sono specifiche per Android. Per limitare il problema, puoi
evitando di utilizzare estensioni o utilizzando #ifdef
per escluderle al momento della compilazione.
La tabella seguente mostra le interfacce e i locator di dati specifici per Android supportati da Android OpenSL ES per ciascun tipo di oggetto. I valori Sì nelle celle indicano le interfacce e i locatori di dati disponibili per ogni tipo di oggetto.
Funzionalità | Lettore audio | Registratore audio | Motore | Mix di output |
---|---|---|---|---|
Coda di buffer di Android | Sì: sorgente (decodifica) | No | No | No |
Configurazione Android | Sì | Sì | No | No |
Effetto Android | Sì | No | No | Sì |
Funzionalità degli effetti Android | No | No | Sì | No |
Invio di effetti su Android | Sì | No | No | No |
Coda del buffer semplice di Android | Sì: sorgente (riproduzione) o destinazione (decodifica) | Sì | No | No |
Data locator della coda di buffer di Android | Sì: sorgente (decodifica) | No | No | No |
Data locator del descrittore file di Android | Sì: Origine | No | No | No |
Data locator della coda di buffer semplice di Android | Sì: origine (riproduzione) o sink (decodifica) | Sì: sink | No | No |
Interfaccia di configurazione Android
L'interfaccia di configurazione di Android fornisce un mezzo per impostare parametri specifici della piattaforma per gli oggetti. Questa interfaccia è diversa dalle altre interfacce OpenSL ES 1.0.1 in quanto la tua app può utilizzarla prima di creare l'oggetto corrispondente; pertanto, puoi configurare l'oggetto prima di crearlo. La
OpenSLES_AndroidConfiguration.h
file di intestazione, che si trova all'indirizzo
/sysroot/usr/include/SLES
,
documenta le seguenti chiavi e valori di configurazione disponibili:
- Tipo di stream per i lettori audio (valore predefinito:
SL_ANDROID_STREAM_MEDIA
). - Registra profilo per registratori audio (valore predefinito:
SL_ANDROID_RECORDING_PRESET_GENERIC
).
Il seguente snippet di codice mostra un esempio di come impostare il tipo di stream audio Android su un media player:
// CreateAudioPlayer and specify SL_IID_ANDROIDCONFIGURATION // in the required interface ID array. Do not realize player yet. // ... SLAndroidConfigurationItf playerConfig; result = (*playerObject)->GetInterface(playerObject, SL_IID_ANDROIDCONFIGURATION, &playerConfig); assert(SL_RESULT_SUCCESS == result); SLint32 streamType = SL_ANDROID_STREAM_ALARM; result = (*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)); assert(SL_RESULT_SUCCESS == result); // ... // Now realize the player here.
Puoi utilizzare un codice simile per configurare il preset per un registratore audio:
// ... obtain the configuration interface as the first four lines above, then: SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION; result = (*playerConfig)->SetConfiguration(playerConfig, RECORDING_PRESET, &presetValue, sizeof(SLuint32));
Interfacce degli effetti Android
Le interfacce di effetti, invio di effetti e funzionalità di effetti di Android forniscono un meccanismo generico per consentire a un'applicazione di eseguire query e utilizzare effetti audio specifici del dispositivo. I produttori di dispositivi devono documentare tutti gli effetti audio specifici del dispositivo disponibili che forniscono.
Le applicazioni portatili devono utilizzare le API OpenSL ES 1.0.1 per gli effetti audio anziché le estensioni di effetti Android.
Localizzatore dati descrittore file Android
Il locator dei dati del descrittore file Android ti consente di specificare l'origine di un media player come descrittore file aperto con accesso in lettura. Il formato dei dati deve essere MIME.
Questa estensione è particolarmente utile in combinazione con il gestore di asset nativo, perché l'app legge gli asset dall'APK tramite un descrittore file.
Interfaccia e locator di dati della coda di buffer semplice di Android
Nella specifica di riferimento OpenSL ES 1.0.1, le code buffer possono essere usate solo per i lettori audio e sono compatibili con PCM e altri formati di dati. Le specifiche dell'interfaccia e del locator dei dati della coda di buffer semplice di Android sono identiche alle specifiche di riferimento, con due eccezioni:
- Puoi utilizzare le code di buffer semplici di Android con registratori audio e lettori audio.
- Puoi utilizzare il formato dati PCM solo con queste code.
Per la registrazione, la tua app dovrebbe accodare i buffer vuoti. Quando viene inviato un callback registrato una notifica che informa che il sistema ha terminato di scrivere i dati in un buffer, l'app può leggere dal buffer.
La riproduzione funziona allo stesso modo. Per il codice sorgente futuro compatibilità, tuttavia, suggeriamo che le applicazioni utilizzino Android semplici code di buffer invece di code di buffer OpenSL ES 1.0.1.
Comportamento coda buffer
L'implementazione di Android non include
il requisito della specifica di riferimento che il cursore di riproduzione ritorni all'inizio
del buffer attualmente in riproduzione quando la riproduzione entra nel valore SL_PLAYSTATE_STOPPED
stato. Questa implementazione può essere conforme a questo comportamento o può lasciare invariata la posizione del cursore di riproduzione.
Di conseguenza, la tua app non può presumere che si verifichi uno di questi comportamenti. Pertanto,
devi chiamare esplicitamente il metodo BufferQueue::Clear()
dopo una transizione a
SL_PLAYSTATE_STOPPED
. In questo modo, la coda del buffer viene impostata su uno stato noto.
Allo stesso modo, non esiste una specifica che stabilisca se il trigger per un callback di coda di buffer debba
una transizione a SL_PLAYSTATE_STOPPED
o l'esecuzione di
BufferQueue::Clear()
. Pertanto, ti consigliamo di non creare una dipendenza
l'uno o l'altro; la tua app dovrebbe
essere in grado di gestire entrambe le cose.
Interfacce dinamiche alla creazione degli oggetti
Per praticità, l'implementazione Android di OpenSL ES 1.0.1
Consente alla tua app di specificare interfacce dinamiche quando crea un'istanza di un oggetto.
Questa è un'alternativa all'utilizzo di DynamicInterfaceManagement::AddInterface()
per aggiungere queste interfacce dopo la creazione dell'istanza.
Report sulle estensioni
Esistono tre metodi per verificare se la piattaforma supporta le estensioni Android. Questi sono:
Engine::QueryNumSupportedExtensions()
Engine::QuerySupportedExtension()
Engine::IsExtensionSupported()
Qualsiasi di questi metodi restituisce ANDROID_SDK_LEVEL_<API-level>
,
dove API-level
è il livello API della piattaforma; ad esempio, ANDROID_SDK_LEVEL_23
.
Un livello API della piattaforma pari o superiore a 9 indica che la piattaforma supporta le estensioni.
Decodifica l'audio in PCM
Questa sezione descrive un'estensione deprecata specifica di Android a OpenSL ES 1.0.1 per decodificare uno stream codificato in PCM senza riproduzione immediata. La seguente tabella fornisce consigli per l'uso di questa estensione e delle alternative.
Livello API | Alternative |
---|---|
Fino a 15 anni | Un codec open source con una licenza appropriata. |
Da 16 a 20 |
La classe MediaCodec o un codec open source con una licenza appropriata
|
21 e successive |
NDK MediaCodec nei file di intestazione <media/NdkMedia*.h> ,
MediaCodec o un codec open source con una licenza appropriata
|
Nota:
Al momento non esiste alcuna documentazione per la versione NDK dell'API MediaCodec
. Tuttavia,
puoi fare riferimento al codice di esempio
native-codec per un esempio.
Un lettore audio standard viene riprodotto su un dispositivo audio e specifica il mix di output come sink di dati. L'estensione per Android è diversa per il fatto che un audio player agisce da decoder se l'app ha specificato l'origine dati come URI o come Android del descrittore di file, descritto utilizzando il formato dei dati MIME. In tal caso, il data sink viene un localizzatore di dati su una coda di buffer semplice Android che utilizza il formato di dati PCM.
Questa funzionalità è pensata principalmente per consentire ai giochi di precaricare gli asset audio quando passano a una
un nuovo livello di gioco, simile alla funzionalità SoundPool
offerti dal corso.
Inizialmente, l'applicazione dovrebbe accodare un set di buffer vuoti in una coda di buffer. Successivamente, l'app riempie i buffer con i dati PCM. La semplicità di Android Il callback della coda di buffer viene attivato dopo che ogni buffer è stato riempito. Il gestore del callback elabora i dati PCM, ripete la coda del buffer ora vuoto e quindi restituisce. L'applicazione è responsabile del monitoraggio dei buffer decodificati; l'elenco dei parametri di callback non include informazioni sufficienti per indicare il buffer contenente i dati o il buffer che deve essere inserito in coda successivamente.
L'origine dati segnala implicitamente la fine del flusso (EOS) fornendo una
SL_PLAYEVENT_HEADATEND
evento alla fine dello stream. Dopo che l'app è stata decodificata
tutti i dati ricevuti, non effettua altre chiamate al semplice callback della coda del buffer di Android.
Il formato dei dati PCM del sink in genere corrisponde a quello dell'origine dati codificata in termini di frequenza di campionamento, numero di canali e profondità in bit. Tuttavia, puoi decodificare in un altro frequenza di campionamento, numero di canali o profondità di bit. Per informazioni su un provisioning per rilevare l'effettivo formato PCM, consulta Determinare il formato dei dati PCM decodificati tramite i metadati.
La funzionalità di decodifica PCM di OpenSL ES per Android supporta la messa in pausa e la ricerca iniziale, ma non il controllo del volume, gli effetti, il looping o la velocità di riproduzione.
A seconda dell'implementazione della piattaforma, la decodifica potrebbe richiedere risorse che non possono essere lasciate inattive. Pertanto, ti consigliamo di assicurarti di fornire un numero sufficiente di buffer PCM vuoti, altrimenti il decodificatore non funziona. Ciò può accadere, ad esempio, se l'app ritorna dal callback della coda di buffer semplice di Android senza mettere in coda un altro buffer vuoto. Il risultato dell'inerzia dei decoder è non specificato, ma può includere: eliminazione del valore decodificato dati PCM, messa in pausa del processo di decodifica o terminazione del decoder.
Nota: per decodificare uno stream codificato in PCM, ma non riprodurlo immediatamente, per le app in esecuzione su Android 4.x (livelli API 16-20), consigliamo di utilizzare la classe MediaCodec
.
Per le nuove app con Android 5.0 (livello API 21) o versioni successive, ti consigliamo di usare l'NDK
equivalente, <NdkMedia*.h>
. Questi file di intestazione risiedono
nella directory media/
nella directory radice di installazione.
Decodifica lo streaming da ADTS AAC in PCM
Un lettore audio agisce da decoder per lo streaming se l'origine dati è un Localizzatore di dati della coda del buffer Android che utilizza il formato dei dati MIME e i dati il sink è un semplice localizzatore di dati di coda del buffer Android che utilizza il formato di dati PCM. Configura il formato dati MIME nel seguente modo:
- Container:
SL_CONTAINERTYPE_RAW
- Stringa di tipo MIME:
SL_ANDROID_MIME_AACADTS
Questa funzionalità è destinata principalmente alle applicazioni multimediali di streaming che gestire l'audio AAC, ma dover eseguire l'elaborazione audio personalizzata prima della riproduzione. La maggior parte delle applicazioni che devono decodificare l'audio in PCM deve utilizzare il metodo descritto in Decodifica dell'audio in PCM, poiché questo metodo è più semplice e gestisce più formati audio. La tecnica descritta qui è un approccio più specializzato, da utilizzare solo se si applicano entrambe queste condizioni:
- L'origine audio compressa è uno stream di frame AAC contenuti nelle intestazioni ADTS.
- L'applicazione gestisce questo flusso. I dati non si trovano all'interno di una risorsa di rete il cui identificatore è un URI o di un file locale il cui identificatore è un descrittore di file.
Inizialmente, l'applicazione deve accodare un insieme di buffer pieni nella coda di buffer Android. Ogni buffer contiene uno o più frame ADTS AAC completi. Il callback della coda del buffer Android viene attivato dopo che ogni buffer è stato svuotato. Il gestore di callback deve riempire e aggiungere nuovamente il buffer, per poi tornare. L'applicazione non deve tenere traccia dei buffer codificati; il parametro callback include informazioni sufficienti per indicare il buffer che dovrebbe essere accodato successivamente. La fine del flusso viene contrassegnata esplicitamente inserendo in coda un elemento EOS. Dopo la versione EOS, non sono più consentite le code.
Ti consigliamo di assicurarti di fornire buffer ADTS AAC completi per evitare di bloccare il decodificatore. Questo può accadere, ad esempio, se la tua app restituisce il callback della coda del buffer Android senza accodare un altro buffer pieno. Il risultato dell'abbandono del decoder non è specificato.
Sotto tutti gli aspetti, tranne che per l'origine dati, il metodo di decodifica in streaming è lo stesso descritto in Decodificare l'audio in PCM.
Nonostante la somiglianza dei nomi, una coda di buffer di Android non è uguale a una coda di buffer semplice di Android. Il decodificatore in streaming utilizza entrambi i tipi di code buffer: una coda buffer Android per l'origine dati ADTS AAC e una coda buffer semplice Android per la destinazione dati PCM. Per ulteriori informazioni sull'API Simple buffer Queue di Android, consulta Android
semplice localizzatore di dati e interfaccia della coda di buffer.
Per ulteriori informazioni sull'API Android Buffer Queue, consulta il file index.html
nella directory docs/Additional_library_docs/openmaxal/
nella home directory dell'installazione.
Determinare il formato dei dati PCM decodificati mediante metadati
L'interfaccia SLMetadataExtractionItf
fa parte della specifica di riferimento.
Tuttavia, le chiavi dei metadati che indicano il formato effettivo dei dati PCM decodificati sono specifiche per
Android. Il file di intestazione OpenSLES_AndroidMetadata.h
definisce queste chiavi dei metadati.
Questo file di intestazione si trova nella radice di installazione, nella
Directory /sysroot/usr/include/SLES
.
Gli indici chiave dei metadati sono disponibili subito dopo
termina l'esecuzione del metodo Object::Realize()
. Tuttavia, i valori associati non sono disponibili fino a quando l'app non decodifica i primi dati codificati. Una buona prassi è eseguire una query per gli indici delle chiavi nel thread principale dopo aver chiamato il metodo Object::Realize
e leggere i valori dei metadati del formato PCM nel gestore di callback della coda del buffer semplice di Android quando lo chiami per la prima volta. Consulta il codice di esempio nel pacchetto NDK per esempi di utilizzo di questa interfaccia.
I nomi delle chiavi dei metadati sono stabili, ma gli indici delle chiavi non sono documentati e sono soggetti a modifiche. Un'applicazione non deve presumere che gli indici siano permanenti in più esecuzioni e non deve presumere che più istanze di oggetti condividano gli indici all'interno della stessa esecuzione.
Dati a virgola mobile
Un'app in esecuzione su Android 5.0 (livello API 21) e versioni successive può fornire dati a un AudioPlayer in formato a virgola mobile a precisione singola.
Nel seguente codice di esempio, il metodo Engine::CreateAudioPlayer()
crea un player audio
che utilizza dati a virgola mobile:
#include <SLES/OpenSLES_Android.h> ... SLAndroidDataFormat_PCM_EX pcm; pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; pcm.numChannels = 2; pcm.sampleRate = SL_SAMPLINGRATE_44_1; pcm.bitsPerSample = 32; pcm.containerSize = 32; pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT; ... SLDataSource audiosrc; audiosrc.pLocator = ... audiosrc.pFormat = &pcm;