OpenSL ES per Android

Questa pagina fornisce dettagli sulle differenze tra l'implementazione NDK di OpenSL ESTM e la specifica di riferimento per OpenSL ES 1.0.1. Quando utilizzi il codice campione della specifica, potresti doverlo modificare in modo che funzioni su Android.

Se non diversamente indicato, tutte le funzionalità sono disponibili su Android 2.3 (livello API 9) e versioni successive. Alcune funzioni sono disponibili solo per Android 4.0 (livello API 14) e sono indicate di seguito.

Nota: il CDD (Android Compatibility Definition Document) elenca i requisiti hardware e software di un dispositivo Android compatibile. Consulta la pagina relativa alla compatibilità con Android per ulteriori informazioni sul programma di compatibilità generale e il documento CDD per consultare il documento CDD effettivo.

OpenSL ES fornisce un'interfaccia in linguaggio C accessibile anche mediante C++. Offre funzionalità simili alle porzioni audio di queste API Java per Android:

Come con tutti gli altri SDK Native Development Kit (NDK), lo scopo principale di OpenSL ES per Android è facilitare l'implementazione di librerie condivise da chiamare utilizzando l'interfaccia nativa Java (JNI ). NDK non è concepito per la scrittura di applicazioni C/C++ puri. 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 Android.

Nota: benché sia basata su OpenSL ES, l'API Android native audio (audio ad alte prestazioni) non è un'implementazione conforme di nessun profilo OpenSL ES 1.0.1 (gioco, musica o telefono). Questo perché Android non implementa tutte le funzionalità richieste da nessuno dei profili. I 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 NDK per Android di OpenSL ES eredita gran parte del set di funzionalità dalla specifica di riferimento, con alcune limitazioni.

Punti di contatto globali

OpenSL ES per Android supporta tutti gli entry point globali nella specifica di Android. Questi punti di contatto includono:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Oggetti e interfacce

La seguente tabella mostra gli oggetti e le interfacce supportati dall'implementazione di Android NDK di OpenSL ES. Se nella cella viene visualizzato , significa che la funzionalità è disponibile in questa implementazione.

Supporto di Android NDK per oggetti e interfacce.

Feature Lettore audio Registratore audio Motore Mix di output
Amplificazione dei bassi No No
Coda di buffer No No No
Localizzatore dati 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
Localizzatore dati dispositivo I/O No Sì: origine No No
Estrazione dei metadati Sì: decodifica in PCM No No No
Disattiva audio singolo No No No
Oggetto
Localizzatore mix di output Sì: sink No No No
Gioca No No No
Velocità di riproduzione No No No
Stato di precaricamento No No No
Riverbero preimpostato No No No
Registra No No No
Cerca No No No
Localizzatore dati URI Sì: origine No No No
Virtualizzatore No No
Volume No No No

La prossima sezione illustra le limitazioni di alcune di queste funzionalità.

Limitazioni

Alcune limitazioni si applicano alle funzionalità nella Tabella 1. Queste limitazioni rappresentano differenze rispetto alla specifica di riferimento. Il resto di questa sezione fornisce informazioni su queste differenze.

Gestione dinamica dell'interfaccia

OpenSL ES per Android non supporta RemoveInterface o ResumeInterface.

Combinazioni di effetti: riverbero ambientale e riverbero preimpostato

Sullo stesso mix di uscita non possono essere presenti sia riverbero ambientale sia riverbero preimpostato.

La piattaforma potrebbe ignorare le richieste di effetti se ritiene che il carico della CPU sia troppo elevato.

Invio effetto

SetSendLevel() supporta un singolo 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 di dati URI e solo per un lettore audio. Non puoi utilizzare questo formato dati per un registratore audio.

L'implementazione di OpenSL ES su Android richiede l'inizializzazione di mimeType in NULL o in una stringa UTF-8 valida. Devi inoltre inizializzare containerType con un valore valido. In assenza di altre considerazioni, come la portabilità in altre implementazioni o formati di contenuti che un'app non può identificare in base all'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...
  • WAV ulaw.
  • MP3 Ogg Vorbis.
  • LC AAC
  • HE-AACv1 (AAC+).
  • HE-AACv2 (Migliorato AAC+).
  • 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 risiedere in un contenitore MP4 o ADTS.
  • OpenSL ES per Android non supporta MIDI.
  • WMA non fa parte di AOSP e non ne abbiamo verificato la compatibilità con OpenSL ES per Android.
  • L'implementazione NDK per Android di OpenSL ES non supporta la riproduzione diretta di DRM o contenuti criptati. Per riprodurre i contenuti audio protetti, devi decriptarli nell'applicazione prima di riprodurli e l'app applica eventuali restrizioni DRM.

OpenSL ES per Android non supporta i seguenti metodi per la manipolazione degli oggetti:

  • Resume()
  • RegisterCallback()
  • AbortAsyncOperation()
  • SetPriority()
  • GetPriority()
  • SetLossOfControlInterfaces()

Formato dei dati PCM

PCM è l'unico formato di dati che puoi utilizzare con le code di buffer. Le configurazioni di riproduzione PCM supportate hanno le seguenti caratteristiche:

  • 8 bit non firmato o 16 bit con firma.
  • 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. Di solito, indipendentemente dal dispositivo,sono disponibili le configurazioni mono a 16.000 Hz mono/16 bit.

Il valore del campo samplesPerSec è in milliHz, nonostante il nome sia fuorviante. Per evitare di utilizzare involontariamente 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 i dati in virgola mobile.

Velocità di riproduzione

Una frequenza di riproduzione OpenSL ES indica la velocità con cui un oggetto presenta i dati, espressa in millesimi rispetto alla velocità normale o per mille. Ad esempio, una velocità di riproduzione di 1000 per mille corrisponde a 1000/1000, ovvero la velocità normale. Un intervallo di frequenze è un intervallo chiuso che esprime una gamma di velocità di riproduzione possibili.

Il supporto per gli intervalli di velocità di riproduzione e altre funzionalità può variare a seconda della versione della piattaforma e dell'implementazione. La tua app può determinare queste funzionalità in fase di runtime utilizzando PlaybackRate::GetRateRange() o PlaybackRate::GetCapabilitiesOfRate() per eseguire query sul dispositivo.

In genere, un dispositivo supporta lo stesso intervallo di frequenze per un'origine dati in formato PCM e un intervallo di velocità di unità compreso tra 1000 per mille e 1000 per mille per altri formati; in altre parole, l'intervallo di frequenze unità è 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 abilitare il loop, imposta il parametro startPos su 0 e il parametro endPos su SL_TIME_UNKNOWN.

Localizzatore dati coda di buffer

Un lettore o un registratore audio con un localizzatore dati per una coda di buffer supporta solo il formato dei dati PCM.

Localizzatore dati dispositivo I/O

OpenSL ES per Android supporta l'utilizzo di un localizzatore di dati del dispositivo I/O solo se lo hai specificato come origine dati per Engine::CreateAudioRecorder(). Inizializza il localizzatore di 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};

Localizzatore dati URI

OpenSL ES per Android può utilizzare il localizzatore di dati URI solo con il formato dei dati MIME e solo per un lettore audio. Non puoi utilizzare un localizzatore 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 queste 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-threaded ed è a prova di thread. Supporta un solo motore per applicazione e fino a 32 oggetti per motore. La memoria e la CPU del dispositivo disponibili potrebbero limitare ulteriormente il numero di oggetti utilizzabili.

Le seguenti 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 unico oggetto del motore condiviso internamente e il limite di 32 oggetti è condiviso tra OpenMAX AL e OpenSL ES. L'applicazione deve creare entrambi i motori, utilizzare entrambi i motori e infine distruggerli. L'implementazione mantiene un conteggio di riferimento sul motore condiviso, in modo che venga eliminato correttamente durante la seconda operazione di eliminazione.

Note sulla programmazione

Le note di programmazione di OpenSL ES forniscono informazioni supplementari per garantire una corretta implementazione di OpenSL ES.

Nota: per praticità, 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 dinamica dell'interfaccia

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 sono basate 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 tipografici e alcune incompatibilità. La maggior parte delle incompatibilità previste è relativamente minore o si trova 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 vengano seguite le linee guida descritte nella sezione Pianificazione della compatibilità dei programmi binari di seguito.

Nota: la compatibilità delle fonti future non è un obiettivo. Ciò significa che se esegui l'upgrade a una versione più recente dell'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à; consulta i dettagli di seguito.

Pianifica la compatibilità del programma binario

Ti consigliamo di fare in modo che la tua applicazione segua queste linee guida per migliorare la compatibilità dei programmi binari in futuro:

  • Usare solo il sottoinsieme documentato delle funzionalità supportate da Android di OpenSL ES 1.0.1.
  • Non dipendere da un particolare codice risultato per un'operazione non riuscita; preparati ad affrontare un codice risultato diverso.
  • I gestori di callback dell'applicazione in genere vengono eseguiti in un contesto limitato. Devono essere scritti in modo da svolgere il loro lavoro rapidamente e poi tornare il prima possibile. Non eseguire operazioni complesse all'interno di un gestore di callback. Ad esempio, all'interno di un callback di completamento della coda del 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 quelli che non riconoscono. I callback configurati con una maschera di evento composta da tipi di eventi abilitati devono essere preparati per essere richiamati con più bit di tipo di evento impostati contemporaneamente. Utilizza "&" per testare ogni bit di evento anziché un caso di switch.
  • Utilizza lo stato di precaricamento e i callback come indicazioni generali dell'avanzamento, ma non dipendono da livelli di riempimento o sequenze di callback specifici. Il significato del livello di riempimento dello stato di precaricamento e il comportamento degli errori rilevati durante il precaricamento potrebbero cambiare.

Nota: per ulteriori dettagli, consulta la sezione Comportamento della coda del buffer di seguito.

Pianifica la compatibilità dell'origine

Come accennato, nella prossima versione di OpenSL ES di Khronos Group sono previste incompatibilità del codice sorgente. Le possibili aree di cambiamento includono:

  • Si prevede che l'interfaccia della coda del buffer presenterà modifiche significative, in particolare nelle aree di BufferQueue::Enqueue, dell'elenco dei parametri per slBufferQueueCallback e del nome del campo SLBufferQueueState.playIndex. Ti consigliamo di utilizzare per il codice dell'applicazione le code di buffer Android semplici. Nel codice di esempio fornito con l'NDK, per la riproduzione abbiamo utilizzato semplici code di buffer di Android per la riproduzione. Utilizziamo anche la coda di buffer semplice di Android per la registrazione e la decodifica su PCM, ma questo perché lo standard OpenSL ES 1.0.1 non supporta il record o la decodifica in un sink dati della coda del buffer.
  • Verrà aggiunto const ai parametri di input trasmessi per riferimento e ai campi struct SLchar * utilizzati come valori di input. Ciò non dovrebbe richiedere alcuna modifica al codice.
  • I tipi non firmati verranno sostituiti alcuni parametri attualmente firmati. Potresti dover modificare un tipo di parametro da SLint32 a SLuint32 o simile, oppure aggiungere una trasmissione.
  • Equalizer::GetPresetName copia la stringa nella memoria dell'applicazione anziché restituire un puntatore alla memoria di implementazione. Si tratta di un cambiamento significativo, quindi ti consigliamo di evitare di chiamare questo metodo o di isolarne l'utilizzo.
  • Nei tipi di struct sono presenti altri campi. Per i parametri di output, questi nuovi campi possono essere ignorati, ma per i parametri di input i nuovi campi dovranno essere inizializzati. Fortunatamente, tutti questi campi dovrebbero trovarsi in aree non supportate da Android.
  • I GUID dell'interfaccia verranno modificati. Per evitare una dipendenza, fai riferimento alle interfacce per nome simbolico anziché per GUID.
  • SLchar cambierà da unsigned char a char. Questo problema interessa principalmente il localizzatore di dati URI e il formato dei dati MIME.
  • SLDataFormat_MIME.mimeType verrà rinominato in pMimeType e SLDataLocator_URI.URI sarà rinominato in pURI. Ti consigliamo di inizializzare le strutture di dati SLDataFormat_MIME e SLDataLocator_URI utilizzando un elenco di valori racchiuso da parentesi graffe e separati da virgole, anziché il nome del campo, per isolare il codice da questa modifica. Questa tecnica viene utilizzata nel codice di esempio.
  • SL_DATAFORMAT_PCM non consente all'applicazione di specificare la rappresentazione dei dati come numero intero con segno, numero intero senza segno o in virgola mobile. L'implementazione di Android presuppone che i dati a 8 bit siano un numero intero senza segno e a 16 bit sia un numero intero firmato. Inoltre, il campo samplesPerSec è errato, poiché le unità effettive sono in 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 tratterà di un nuovo formato dei dati e l'attuale formato dei dati PCM continuerà a essere disponibile (anche se deprecato), non dovrebbe richiedere alcuna modifica immediata al codice.