AVVISO: OpenSL ES è deprecato. Gli sviluppatori devono utilizzare la libreria Oboe open source disponibile su GitHub. Oboe è un wrapper C++ che fornisce un'API molto simile a AAudio. Oboe chiama AAudio quando è disponibile AAudio e utilizza OpenSL ES se AAudio non è disponibile.
Questa pagina fornisce dettagli su come l'implementazione di OpenSL ES ™ in NDK differisca dalla specifica di riferimento per OpenSL ES 1.0.1. Quando utilizzi il codice di esempio della specifica, potrebbe essere necessario modificarlo per il funzionamento su Android.
Se non diversamente indicato, tutte le funzionalità sono disponibili su Android 2.3 (livello API 9) e versioni successive. Alcune funzionalità sono disponibili solo per Android 4.0 (livello API 14); queste sono indicate di seguito.
Nota : il Compatibility Definition Document (CDD) di Android elenca i requisiti hardware e software di un dispositivo Android compatibile. Per ulteriori informazioni sul programma di compatibilità complessivo, consulta la sezione Compatibilità con Android e per il documento CDD effettivo consulta la sezione CDD.
OpenSL ES fornisce un'interfaccia in linguaggio C accessibile anche tramite C++. Mette a disposizione funzionalità simili alle parti audio di queste API Java per Android:
Come per tutti gli Android Native Development Kit (NDK), lo scopo principale di OpenSL ES per Android è facilitare l'implementazione di librerie condivise che devono essere chiamate utilizzando la Java Native Interface (JNI ). NDK non è destinato alla scrittura di applicazioni C/C++ pure. Tuttavia, OpenSL ES è un'API completa e prevediamo che dovresti essere in grado di soddisfare la maggior parte delle tue esigenze audio utilizzando solo questa API, senza up-call al codice in esecuzione nel runtime di Android.
Nota: anche se basata su OpenSL ES, l'API audio nativa (audio ad alte prestazioni) Android non è un'implementazione conforme di nessun profilo OpenSL ES 1.0.1 (gioco, musica o telefono). Questo accade perché Android non implementa tutte le funzionalità richieste da nessuno dei profili. Eventuali casi noti in cui Android si comporta in modo diverso rispetto alla specifica sono descritti nella pagina Estensioni Android.
Funzionalità ereditate dalla specifica di riferimento
L'implementazione di OpenSL ES in Android NDK eredita gran parte del set di funzionalità dalla specifica di riferimento, con alcune limitazioni.
Punti di ingresso globali
OpenSL ES per Android supporta tutti i punti di contatto globali nella specifica Android. Questi punti di contatto includono:
slCreateEngine
slQueryNumSupportedEngineInterfaces
slQuerySupportedEngineInterfaces
Oggetti e interfacce
La tabella seguente mostra gli oggetti e le interfacce supportati dall'implementazione di Android NDK di OpenSL ES. Se nella cella viene visualizzato Sì, la funzionalità è disponibile in questa implementazione.
Funzionalità | Lettore audio | Registratore audio | Motore | Combinazione di output |
---|---|---|---|---|
Amplificazione dei bassi | Sì | No | No | Sì |
Coda buffer | Sì | No | No | No |
Locatore dati della coda di buffer | Sì: Origine | No | No | No |
Gestione dinamica dell'interfaccia | Sì | Sì | Sì | Sì |
Invio effetto | Sì | No | No | No |
Motore | No | No | Sì | No |
Riverbero ambientale | No | No | No | Sì |
Equalizzatore | Sì | No | No | Sì |
Ricerca dati dei dispositivi di I/O | No | Sì: origine | No | No |
Estrazione di metadati | Sì: decodifica in PCM | No | No | No |
Disattiva solo l'audio | Sì | No | No | No |
Oggetto | Sì | Sì | Sì | Sì |
Ricercatore di mix di output | Sì: lavello | No | No | No |
Riproduci | Sì | No | No | No |
Velocità di riproduzione | Sì | No | No | No |
Stato del precaricamento | Sì | No | No | No |
Riverbero preimpostato | No | No | No | Sì |
Registra | No | Sì | No | No |
Cerca | Sì | No | No | No |
Locator di dati URI | Sì: Origine | No | No | No |
Virtualizzatore | Sì | No | No | Sì |
Volume | Sì | No | No | No |
La sezione successiva illustra le limitazioni di alcune di queste funzionalità.
Limitazioni
Alle funzionalità riportate nella Tabella 1 si applicano alcune limitazioni. Queste limitazioni rappresentano differenze rispetto alla specifica di riferimento. Il resto di questa sezione fornisce informazioni su queste differenze.
Gestione delle interfacce dinamiche
OpenSL ES per Android non supporta RemoveInterface
o
ResumeInterface
.
Combinazioni di effetti: riverbero ambiente e riverbero preset
Non puoi avere sia il riverbero ambientale sia il riverbero preimpostato nello stesso mix di output.
La piattaforma potrebbe ignorare le richieste di effetti se stima che il caricamento della CPU sia troppo elevato.
Invio effetto
SetSendLevel()
supporta un solo livello di invio per lettore audio.
Riverbero ambientale
Il riverbero ambientale non supporta i campi reflectionsDelay
,
reflectionsLevel
o reverbDelay
dello
struct SLEnvironmentalReverbSettings
.
Formato dei dati MIME
Puoi utilizzare il formato dei dati MIME solo con il localizzatore dei dati URI e solo per un lettore audio. Non puoi utilizzare questo formato di dati per un registratore audio.
L'implementazione di OpenSL ES per Android richiede di inizializzare mimeType
a NULL
o a una stringa UTF-8 valida. Devi anche inizializzare
containerType
con un valore valido.
In assenza di altre considerazioni, come la portabilità ad altre implementazioni o formati di contenuti che un'app non è in grado di identificare tramite l'intestazione, ti consigliamo di impostare mimeType
su NULL
e containerType
su SL_CONTAINERTYPE_UNSPECIFIED
.
OpenSL ES per Android supporta i seguenti formati audio, a condizione che siano supportati anche dalla piattaforma Android:
- WAV PCM.
- WAV alaw.
- WAV.
- MP3 Ogg Vorbis.
- LC AAC
- HE-AACv1 (AAC+).
- HE-AACv2 (AAC+ migliorato).
- AMR.
- FLAC.
Nota: per un elenco dei formati audio supportati da Android, consulta Formati multimediali supportati.
Le seguenti limitazioni si applicano alla gestione di questi e altri formati in questa implementazione di OpenSL ES:
- I formati AAC devono trovarsi all'interno di un contenitore MP4 o ADTS.
- OpenSL ES per Android non supporta MIDI.
- WMA non fa parte di AOSP e non abbiamo verificato la sua compatibilità con OpenSL ES per Android.
- L'implementazione di OpenSL ES in Android NDK non supporta la riproduzione diretta di contenuti DRM o criptati. Per riprodurre contenuti audio protetti, devi decriptarli nella tua applicazione prima della riproduzione, con l'applicazione che applica eventuali limitazioni DRM.
Metodi relativi agli oggetti
OpenSL ES per Android non supporta i seguenti metodi per la manipolazione di oggetti:
Resume()
RegisterCallback()
AbortAsyncOperation()
SetPriority()
GetPriority()
SetLossOfControlInterfaces()
Formato dei dati PCM
PCM è l'unico formato di dati che puoi utilizzare con le code del buffer. Le configurazioni di riproduzione PCM supportate hanno le seguenti caratteristiche:
- 8-bit non firmato o 16-bit firmato.
- Mono o stereo.
- Ordinamento dei byte Little-endian.
- Frequenze di campionamento di:
- 8000 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.
Le configurazioni supportate da OpenSL ES per Android per la registrazione dipendono dal dispositivo. In genere, 16.000 Hz mono/16 bit firmati sono disponibili indipendentemente dal dispositivo.
Il valore del campo samplesPerSec
è espresso in milliHz, nonostante il nome fuorviante. Per evitare di utilizzare accidentalmente il valore sbagliato, ti consigliamo di inizializzare questo campo utilizzando una delle costanti simboliche definite a questo scopo, ad esempio SL_SAMPLINGRATE_44_1
.
Android 5.0 (livello API 21) e versioni successive supportano dati in virgola mobile.
Velocità di riproduzione
La frequenza di riproduzione OpenSL ES indica la velocità con cui un oggetto presenta i dati, espressa in millesimi di velocità normale o per mille. Ad esempio, una frequenza di riproduzione pari a 1000 per mille corrisponde a 1000/1000, ovvero alla velocità normale. Un intervallo di frequenza è un intervallo chiuso che esprime una serie di possibili velocità di riproduzione.
Il supporto per gli intervalli di velocità di riproduzione e altre funzionalità può variare in base alla versione e all'implementazione della piattaforma. La tua app può determinare queste funzionalità in fase di runtime utilizzando PlaybackRate::GetRateRange()
o PlaybackRate::GetCapabilitiesOfRate()
per eseguire una query sul dispositivo.
In genere, un dispositivo supporta la stessa gamma di frequenze per un'origine dati in formato PCM e una gamma di frequenza uniforme da 1000 per mille a 1000 per mille per altri formati. In altre parole, la gamma di frequenza uniforme è effettivamente un singolo valore.
Registra
OpenSL ES per Android non supporta gli eventi SL_RECORDEVENT_HEADATLIMIT
o SL_RECORDEVENT_HEADMOVING
.
Cerca
Il metodo SetLoop()
consente il loop dell'intero file. Per attivare il loop, imposta il parametro startPos
su 0 e il parametro endPos
su SL_TIME_UNKNOWN
.
Locatore dati della coda di buffer
Un lettore audio o un registratore audio con un localizzatore di dati per una coda del buffer supporta solo il formato dati PCM.
Ricerca dati dei dispositivi di I/O
OpenSL ES per Android supporta l'utilizzo di un data locator del dispositivo di I/O solo se
hai specificato il localizzatore come origine dati per Engine::CreateAudioRecorder()
.
Inizializza il locator dei dati del dispositivo utilizzando i valori contenuti nel seguente snippet di codice:
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
Locator dati URI
OpenSL ES per Android può utilizzare il locator dati URI solo con il formato dati MIME e solo per un player audio. Non puoi utilizzare un locator di dati URI per un registratore audio. L'URI può utilizzare solo gli schemi http:
e file:
. Altri schemi, come https:
,
ftp:
o
content:
, non sono consentiti.
Non abbiamo verificato il supporto di rtsp:
con audio sulla piattaforma Android.
Strutture di dati
Android supporta le seguenti strutture di dati OpenSL ES 1.0.1:
SLDataFormat_MIME
SLDataFormat_PCM
SLDataLocator_BufferQueue
SLDataLocator_IODevice
SLDataLocator_OutputMix
SLDataLocator_URI
SLDataSink
SLDataSource
SLEngineOption
SLEnvironmentalReverbSettings
SLInterfaceID
Configurazione della piattaforma
OpenSL ES per Android è progettato per applicazioni multi-thread ed è a prova di thread. Supporta un singolo motore per applicazione e fino a 32 oggetti per motore. La memoria e la CPU disponibili del dispositivo possono limitare ulteriormente il numero di oggetti utilizzabili.
Queste opzioni del motore sono riconosciute, ma vengono ignorate da slCreateEngine
:
SL_ENGINEOPTION_THREADSAFE
SL_ENGINEOPTION_LOSSOFCONTROL
OpenMAX AL e OpenSL ES possono essere utilizzati insieme nella stessa applicazione. In questo caso, esiste un singolo oggetto motore condiviso internamente e il limite di 32 oggetti è condiviso tra OpenMAX AL e OpenSL ES. L'applicazione deve creare entrambi i motori, utilizzarli entrambi e infine distruggerli entrambi. L'implementazione mantiene un conteggio dei riferimenti al motore condiviso in modo che venga distrutto correttamente durante la seconda operazione di distruzione.
Note di programmazione
Le note di programmazione di OpenSL ES forniscono informazioni supplementari per garantire l'implementazione corretta di OpenSL ES.
Nota:
per comodità, abbiamo incluso una copia della specifica OpenSL ES 1.0.1 con l'NDK in
docs/opensles/OpenSL_ES_Specification_1.0.1.pdf
.
Problemi relativi alla piattaforma
Questa sezione descrive i problemi noti nella release iniziale della piattaforma che supporta queste API.
Gestione delle interfacce dinamiche
DynamicInterfaceManagement::AddInterface
non funziona. Specifica invece l'interfaccia nell'array che viene passato a Create()
, come mostrato nel codice di esempio per il riverbero ambientale.
Pianificare le versioni future di OpenSL ES
Le API audio ad alte prestazioni di Android si basano su Khronos Group OpenSL ES 1.0.1. Khronos ha rilasciato una versione rivista 1.1 dello standard. La versione rivista include nuove funzionalità, chiarimenti, correzioni di errori ortografici e alcune incompatibilità. La maggior parte delle incompatibilità previste sono relativamente minori o si trovano in aree di OpenSL ES non supportate da Android.
Un'applicazione sviluppata con questa versione dovrebbe funzionare sulle versioni future della piattaforma Android, a condizione che tu segua le linee guida descritte nella sezione Pianificare la compatibilità dei file binari di seguito.
Nota: la compatibilità con fonti future non è un obiettivo. In altre parole, se esegui l'upgrade a una versione più recente del NDK, potresti dover modificare il codice sorgente dell'applicazione per renderlo conforme alla nuova API. Prevediamo che la maggior parte di queste modifiche sarà di lieve entità; vedi i dettagli di seguito.
Pianifica la compatibilità binaria
Ti consigliamo di seguire queste linee guida per migliorare la compatibilità futura dei file binari della tua applicazione:
- Utilizza solo il sottoinsieme documentato delle funzionalità supportate da Android di OpenSL ES 1.0.1.
- Non fare affidamento su un determinato codice risultato per un'operazione non riuscita; preparati a gestire un codice risultato diverso.
- I gestori dei callback dell'applicazione in genere vengono eseguiti in un contesto limitato. Devono essere scritti in modo da eseguire rapidamente il proprio lavoro e tornare il prima possibile. Non eseguire operazioni complesse all'interno di un gestore di callback. Ad esempio, all'interno di un callback di completamento di una coda di buffer, puoi accodare un altro buffer, ma non creare un lettore audio.
- I gestori di callback devono essere preparati per essere chiamati più o meno spesso, per ricevere tipi di eventi aggiuntivi e devono ignorare i tipi di eventi che non riconoscono. I richiami metodi che sono configurati con una maschera di eventi composta da tipi di eventi abilitati devono essere preparati per essere chiamati con più bit di tipo di evento impostati contemporaneamente. Utilizza "&" per testare ogni bit di evento anziché una casella di switch.
- Utilizza lo stato del prefetch e i callback come indicazioni generali dell'avanzamento, ma non fare affidamento su livelli di riempimento o sequenze di callback hard-coded specifici. Potrebbero cambiare il significato del livello di riempimento dello stato di precaricamento e il comportamento per gli errori rilevati durante il precaricamento.
Nota : per ulteriori dettagli, consulta la sezione Comportamento della coda del buffer di seguito.
Pianifica la compatibilità con le origini
Come accennato, sono previste incompatibilità del codice sorgente nella prossima versione di OpenSL ES di Khronos Group. Le aree di modifica più probabili sono:
- L'interfaccia della coda del buffer dovrebbe subire modifiche significative, in particolare nelle aree di
BufferQueue::Enqueue
, nell'elenco dei parametri perslBufferQueueCallback
e nel nome del campoSLBufferQueueState.playIndex
. Ti consigliamo di utilizzare invece code di buffer semplici di Android per il codice dell'applicazione. Nel codice di esempio fornito con NDK, per questo motivo abbiamo utilizzato code di buffer semplici di Android per la riproduzione. Utilizziamo anche la coda buffer semplice di Android per la registrazione e la decodifica in PCM, ma questo accade perché OpenSL ES 1.0.1 standard non supporta la registrazione o la decodifica in un flusso di dati della coda buffer. - Ci sarà un'aggiunta di
const
ai parametri di input passati per riferimento e ai campi dello structSLchar *
utilizzati come valori di input. Non dovrebbero essere necessarie modifiche al codice. - Verrà sostituita la firma di alcuni parametri attualmente firmati con tipi non firmati.
Potresti dover modificare un tipo di parametro da
SLint32
aSLuint32
o simile oppure aggiungere un trasferimento. Equalizer::GetPresetName
copia la stringa nella memoria dell'applicazione anziché restituire un puntatore alla memoria di implementazione. Si tratta di una modifica significativa, pertanto ti consigliamo di evitare di chiamare questo metodo o di limitarne l'utilizzo.- Nei tipi di struct saranno presenti campi aggiuntivi. Per i parametri di output, questi nuovi campi possono essere ignorati, ma per i parametri di input dovranno essere inizializzati. Fortunatamente, tutti questi campi dovrebbero trovarsi in aree non supportate da Android.
- I GUID dell'interfaccia cambieranno. Fai riferimento alle interfacce in base al nome simbolico anziché al GUID per evitare una dipendenza.
- Il prezzo di
SLchar
passerà daunsigned char
achar
. Ciò riguarda principalmente il locator dei dati URI e il formato dei dati MIME. SLDataFormat_MIME.mimeType
verrà rinominatopMimeType
eSLDataLocator_URI.URI
verrà rinominatopURI
. Per isolare il codice da questa modifica, ti consigliamo di inizializzare le strutture di datiSLDataFormat_MIME
eSLDataLocator_URI
utilizzando un elenco di valori separati da virgole racchiuso tra parentesi graffe anziché per nome del campo. Questa tecnica viene utilizzata nel codice di esempio.SL_DATAFORMAT_PCM
non consente all'applicazione di specificare la rappresentazione dei dati come interi con segno, interi senza segno o in virgola mobile. L'implementazione di Android presuppone che i dati a 8 bit siano un numero intero senza segno e che i dati a 16 bit siano un numero intero con segno. Inoltre, il camposamplesPerSec
non è un nome corretto, poiché le unità effettive sono milliHz. Questi problemi dovrebbero essere risolti nella prossima versione di OpenSL ES, che introdurrà un nuovo formato di dati PCM esteso che consente all'applicazione di specificare esplicitamente la rappresentazione e corregge il nome del campo. Poiché si tratta di un nuovo formato di dati e il formato di dati PCM attuale sarà ancora disponibile (sebbene deprecato), non dovrebbe essere necessaria alcuna modifica immediata al codice.