OpenSL ES per Android

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 , la funzionalità è disponibile in questa implementazione.

Supporto di Android NDK per oggetti e interfacce.

Funzionalità Lettore audio Registratore audio Motore Combinazione di output
Amplificazione dei bassi No No
Coda buffer No No No
Locatore dati della coda di buffer Sì: Origine No No No
Gestione dinamica dell'interfaccia
Invio effetto No No No
Motore No No No
Riverbero ambientale No No No
Equalizzatore No No
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 No No No
Oggetto
Ricercatore di mix di output Sì: lavello No No No
Riproduci No No No
Velocità di riproduzione No No No
Stato del precaricamento No No No
Riverbero preimpostato No No No
Registra No No No
Cerca No No No
Locator di dati URI Sì: Origine No No No
Virtualizzatore No No
Volume 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.

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 per slBufferQueueCallback e nel nome del campo SLBufferQueueState.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 struct SLchar * 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 a SLuint32 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à da unsigned char a char. Ciò riguarda principalmente il locator dei dati URI e il formato dei dati MIME.
  • SLDataFormat_MIME.mimeType verrà rinominato pMimeType e SLDataLocator_URI.URI verrà rinominato pURI. Per isolare il codice da questa modifica, ti consigliamo di inizializzare le strutture di dati SLDataFormat_MIME e SLDataLocator_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 campo samplesPerSec 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.