PERINGATAN: OpenSL ES tidak digunakan lagi. Developer harus menggunakan library Oboe open source yang tersedia di GitHub. Oboe adalah wrapper C++ yang menyediakan API yang sangat mirip dengan AAudio. Oboe memanggil AAudio saat tersedia, dan melakukan fallback ke OpenSL ES jika AAudio tidak tersedia.
Halaman ini memberikan detail tentang perbedaan implementasi NDK untuk OpenSL ES™ dengan spesifikasi referensi untuk OpenSL ES 1.0.1. Saat menggunakan kode contoh dari spesifikasi ini, Anda mungkin perlu memodifikasinya agar berfungsi di Android.
Kecuali jika dinyatakan berbeda, semua fitur tersedia di Android 2.3 (API level 9) dan lebih baru. Sebagian fitur hanya tersedia untuk Android 4.0 (API level 14); hal ini telah diketahui.
Catatan: CDD (Dokumen Definisi Kompatibilitas) Android menyebutkan persyaratan hardware dan software perangkat Android yang kompatibel. Lihat Kompatibilitas Android untuk informasi selengkapnya tentang program kompatibilitas keseluruhan, dan CDD untuk dokumen CDD sebenarnya.
OpenSL ES menyediakan antarmuka bahasa C yang juga dapat diakses menggunakan C++. OpenSL ES menampilkan fitur yang mirip dengan bagian audio API Java Android berikut:
Seperti pada semua Android NDK (Native Development Kit), kegunaan utama OpenSL ES untuk Android adalah untuk mempermudah implementasi library bersama yang akan dipanggil menggunakan Java Native Interface (JNI ). NDK tidak dimaksudkan untuk menulis aplikasi C/C++ murni. Namun, OpenSL ES adalah API berfitur lengkap, dan kami berharap Anda dapat memenuhi sebagian besar kebutuhan audio dengan hanya menggunakan API ini, tanpa perlu melakukan up-call ke kode yang berjalan di runtime Android.
Catatan: Meskipun didasarkan pada OpenSL ES, API audio native Android (audio performa tinggi) bukan implementasi yang mengikuti profil OpenSL ES 1.0.1 apa pun (game, musik, atau ponsel). Hal ini karena Android tidak mengimplementasikan semua fitur yang diperlukan oleh salah satu profil tersebut. Semua kasus yang diketahui terkait Android berperilaku berbeda dari spesifikasinya dijelaskan di halaman ekstensi Android.
Fitur yang diwariskan dari spesifikasi referensi
Implementasi Android NDK untuk OpenSL ES mewarisi banyak set fitur dari spesifikasi referensi, dengan pembatasan tertentu.
Titik masuk global
OpenSL ES untuk Android mendukung semua titik masuk global dalam spesifikasi Android. Titik masuk ini mencakup:
slCreateEngine
slQueryNumSupportedEngineInterfaces
slQuerySupportedEngineInterfaces
Objek dan antarmuka
Tabel berikut menampilkan objek dan antarmuka yang didukung oleh implementasi Android NDK untuk OpenSL ES. Jika Ya muncul dalam sel, berarti fitur tersebut tersedia dalam implementasi ini.
Fitur | Pemutar audio | Perekam audio | Engine | Campuran output |
---|---|---|---|---|
Peningkatan bass | Ya | Tidak | Tidak | Ya |
Antrean buffer | Ya | Tidak | Tidak | Tidak |
Pencari lokasi data antrean buffer | Ya: Sumber | Tidak | Tidak | Tidak |
Pengelolaan antarmuka dinamis | Ya | Ya | Ya | Ya |
Pengiriman efek | Ya | Tidak | Tidak | Tidak |
Engine | Tidak | Tidak | Ya | Tidak |
Gema lingkungan | Tidak | Tidak | Tidak | Ya |
Equalizer | Ya | Tidak | Tidak | Ya |
Pencari lokasi data perangkat I/O | Tidak | Ya: Sumber | Tidak | Tidak |
Ekstraksi metadata | Ya: Decode ke PCM | Tidak | Tidak | Tidak |
Bisukan audio solo | Ya | Tidak | Tidak | Tidak |
Objek | Ya | Ya | Ya | Ya |
Pencari lokasi campuran output | Ya: Sink | Tidak | Tidak | Tidak |
Putar | Ya | Tidak | Tidak | Tidak |
Laju pemutaran | Ya | Tidak | Tidak | Tidak |
Status pra-pengambilan | Ya | Tidak | Tidak | Tidak |
Gema preset | Tidak | Tidak | Tidak | Ya |
Rekam | Tidak | Ya | Tidak | Tidak |
Cari | Ya | Tidak | Tidak | Tidak |
Pencari lokasi data URI | Ya: Sumber | Tidak | Tidak | Tidak |
Virtualizer | Ya | Tidak | Tidak | Ya |
Volume | Ya | Tidak | Tidak | Tidak |
Bagian selanjutnya menjelaskan batasan untuk beberapa fitur ini.
Batasan
Batasan tertentu berlaku untuk fitur dalam Tabel 1. Batasan ini menunjukkan perbedaan dengan spesifikasi referensi. Selebihnya dari bagian ini menyajikan informasi tentang perbedaan tersebut.
Pengelolaan antarmuka dinamis
OpenSL ES untuk Android tidak mendukung RemoveInterface
atau ResumeInterface
.
Kombinasi efek: gema lingkungan dan gema preset
Anda tidak dapat memiliki gema lingkungan dan gema preset pada campuran output yang sama.
Platform mungkin mengabaikan permintaan efek jika memperkirakan bahwa beban CPU akan menjadi terlalu tinggi.
Pengiriman efek
SetSendLevel()
mendukung tingkat pengiriman tunggal per pemutar audio.
Gema lingkungan
Gema lingkungan tidak mendukung kolom reflectionsDelay
, reflectionsLevel
, atau reverbDelay
dari struct SLEnvironmentalReverbSettings
.
Format data MIME
Anda dapat menggunakan format data MIME hanya dengan pencari lokasi data URI, dan hanya untuk pemutar audio. Anda tidak dapat menggunakan format data ini untuk perekam audio.
Implementasi Android untuk OpenSL ES mengharuskan Anda melakukan inisialisasi mimeType
ke NULL
atau string UTF-8 yang valid. Anda juga harus melakukan inisialisasi
containerType
ke nilai yang valid.
Jika tidak ada pertimbangan lain, misalnya portabilitas ke implementasi lainnya atau format konten yang tidak dapat diidentifikasi oleh aplikasi berdasarkan header, kami merekomendasikan Anda menetapkan mimeType
ke NULL
dan containerType
ke SL_CONTAINERTYPE_UNSPECIFIED
.
OpenSL ES untuk Android mendukung format audio berikut, selama platform Android juga mendukungnya:
- WAV PCM.
- WAV alaw.
- WAV ulaw.
- MP3 Ogg Vorbis.
- AAC LC.
- HE-AACv1 (AAC+).
- HE-AACv2 (enhanced AAC+).
- AMR.
- FLAC.
Catatan: Untuk daftar format audio yang didukung Android, lihat Format media yang didukung.
Batasan berikut berlaku untuk penanganan format ini dan format lainnya dalam implementasi OpenSL ES ini:
- Format AAC harus berada dalam container MP4 atau ADTS.
- OpenSL ES untuk Android tidak mendukung MIDI.
- WMA bukan bagian dari AOSP, dan kami belum memverifikasi kompatibilitasnya dengan OpenSL ES untuk Android.
- Implementasi Android NDK untuk OpenSL ES tidak mendukung pemutaran langsung DRM atau konten yang dienkripsi. Untuk memutar konten audio yang dilindungi, Anda harus mendekripsinya dalam aplikasi sebelum memutarnya, dengan aplikasi Anda yang memberlakukan pembatasan DRM.
Metode yang terkait objek
OpenSL ES untuk Android tidak mendukung metode berikut untuk memanipulasi objek:
Resume()
RegisterCallback()
AbortAsyncOperation()
SetPriority()
GetPriority()
SetLossOfControlInterfaces()
Format data PCM
PCM adalah satu-satunya format data yang dapat Anda gunakan bersama antrean buffer. Konfigurasi pemutaran PCM yang didukung memiliki karakteristik berikut:
- 8 bit tidak bertanda tangan atau 16 bit bertanda tangan.
- Mono atau stereo.
- Penyusunan byte little-endian.
- Frekuensi sampel:
- 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.
Konfigurasi yang didukung OpenSL ES untuk Android untuk perekaman bergantung pada perangkatnya; biasanya 16.000 Hz mono/16 bit bertanda tangan akan tersedia apa pun perangkatnya.
Nilai kolom samplesPerSec
adalah dalam satuan miliHz, meskipun namanya mungkin tidak mengindikasikan demikian. Untuk menghindari penggunaan nilai yang salah secara tidak sengaja, sebaiknya lakukan inisialisasi pada kolom ini menggunakan
salah satu konstanta simbolik yang ditentukan untuk keperluan ini, misalnya SL_SAMPLINGRATE_44_1
.
Android 5.0 (API level 21) dan yang lebih baru mendukung data floating point.
Laju pemutaran
Laju pemutaran OpenSL ES menunjukkan kecepatan objek dalam menyajikan data, yang dinyatakan dalam seperseribu kecepatan normal, atau permil. Misalnya, laju pemutaran 1.000 permil adalah 1.000/1.000, atau kecepatan normal. Rentang laju adalah interval tertutup yang menyatakan rentang laju pemutaran yang dimungkinkan.
Dukungan untuk rentang laju pemutaran dan kapabilitas lainnya dapat bervariasi bergantung pada versi platform dan implementasi. Aplikasi Anda dapat menentukan kapabilitas ini saat waktu proses menggunakan PlaybackRate::GetRateRange()
atau PlaybackRate::GetCapabilitiesOfRate()
untuk mengkueri perangkat.
Sebuah perangkat biasanya mendukung rentang laju yang sama untuk sumber data yang berformat PCM, dan rentang laju unitas sebesar 1.000 permil hingga 1.000 permil untuk format lain; dengan kata lain, rentang laju unitas secara efektif adalah nilai tunggal.
Rekam
OpenSL ES untuk Android tidak mendukung peristiwa SL_RECORDEVENT_HEADATLIMIT
atau SL_RECORDEVENT_HEADMOVING
.
Cari
Metode SetLoop()
memungkinkan pengulangan keseluruhan file. Untuk mengaktifkan pengulangan, tetapkan parameter startPos
ke 0, dan parameter endPos
ke SL_TIME_UNKNOWN
.
Pencari lokasi data antrean buffer
Pemutar atau perekam audio dengan pencari lokasi data untuk antrean buffer hanya mendukung format data PCM.
Pencari lokasi data perangkat I/O
OpenSL ES untuk Android hanya mendukung penggunaan pencari lokasi data perangkat I/O jika Anda telah menentukan pencari tersebut sebagai sumber data untuk Engine::CreateAudioRecorder()
.
Lakukan inisialisasi pencari lokasi data perangkat dengan menggunakan nilai yang dimuat dalam cuplikan kode berikut:
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
Pencari lokasi data URI
OpenSL ES untuk Android hanya dapat menggunakan pencari lokasi data URI dengan format data MIME, dan hanya untuk pemutar audio. Anda tidak dapat menggunakan pencari lokasi data URI untuk perekam audio. URI ini hanya dapat menggunakan skema http:
dan file:
. Skema lainnya, seperti https:
, ftp:
, atau content:
tidak diizinkan.
Kami belum memverifikasi dukungan untuk rtsp:
dengan audio di platform Android.
Struktur data
Android mendukung struktur data OpenSL ES 1.0.1 ini:
SLDataFormat_MIME
SLDataFormat_PCM
SLDataLocator_BufferQueue
SLDataLocator_IODevice
SLDataLocator_OutputMix
SLDataLocator_URI
SLDataSink
SLDataSource
SLEngineOption
SLEnvironmentalReverbSettings
SLInterfaceID
Konfigurasi platform
OpenSL ES untuk Android didesain untuk aplikasi multi-thread dan aman untuk thread. OpenSL ES mendukung satu engine per aplikasi dan hingga 32 objek per engine. Memori perangkat dan CPU yang tersedia mungkin membatasi lebih jauh jumlah objek yang dapat digunakan.
Opsi engine ini telah dikenali, tetapi diabaikan oleh slCreateEngine
:
SL_ENGINEOPTION_THREADSAFE
SL_ENGINEOPTION_LOSSOFCONTROL
OpenMAX AL dan OpenSL ES dapat digunakan bersama-sama dalam aplikasi yang sama. Dalam hal ini, secara internal terdapat satu objek engine bersama, dan batas 32 objek digunakan bersama antara OpenMAX AL dan OpenSL ES. Aplikasi harus membuat kedua engine, menggunakan kedua engine, dan akhirnya memusnahkan kedua engine tersebut. Implementasi ini mempertahankan jumlah referensi atas engine bersama sehingga dapat dimusnahkan dengan benar selama operasi pemusnahan kedua.
Catatan pemrograman
Catatan pemrograman OpenSL ES memberikan informasi tambahan untuk memastikan implementasi OpenSL ES dilakukan dengan tepat.
Catatan: Untuk memudahkan Anda, kami telah menyertakan salinan spesifikasi OpenSL ES 1.0.1 dengan NDK di docs/opensles/OpenSL_ES_Specification_1.0.1.pdf
.
Masalah platform
Bagian ini menjelaskan masalah umum dalam rilis platform awal yang mendukung API ini.
Pengelolaan antarmuka dinamis
DynamicInterfaceManagement::AddInterface
tidak berfungsi. Sebagai gantinya, tentukan antarmuka dalam
array yang diteruskan ke Create()
, sebagaimana ditunjukkan dalam kode contoh gema lingkungan.
Rencana untuk versi OpenSL ES mendatang
API audio berperforma tinggi Android didasarkan pada OpenSL ES 1.0.1 Khronos Group. Khronos telah merilis versi revisi 1.1 dari standar. Versi revisi ini menyertakan berbagai fitur baru, klarifikasi, koreksi kesalahan ketik, dan beberapa inkompatibilitas. Sebagian besar inkompatibilitas yang diperkirakan relatif bersifat minor atau berada dalam area OpenSL ES yang tidak didukung oleh Android.
Aplikasi yang dikembangkan dengan versi ini akan berfungsi pada platform Android versi mendatang, asalkan Anda mengikuti pedoman yang diuraikan di bagian Rencana untuk kompatibilitas biner di bawah.
Catatan: Kompatibilitas sumber di masa mendatang bukan sasaran. Dengan kata lain, jika melakukan upgrade ke NDK versi baru, Anda mungkin perlu memodifikasi kode sumber aplikasi agar mematuhi API baru tersebut. Kami memperkirakan bahwa sebagian besar perubahan tersebut adalah perubahan kecil; lihat detailnya di bawah.
Rencana untuk kompatibilitas biner
Sebaiknya aplikasi Anda mengikuti pedoman ini untuk meningkatkan kompatibilitas biner di masa mendatang:
- Gunakan hanya subset fitur yang didukung Android dari OpenSL ES 1.0.1, yang telah didokumentasikan.
- Jangan bergantung pada kode hasil tertentu untuk operasi yang tidak berhasil; bersiaplah menangani berbagai macam kode hasil.
- Handler callback aplikasi umumnya dijalankan dalam konteks yang dibatasi. Handler tersebut harus ditulis untuk menjalankan tugasnya dengan cepat, lalu menampilkan hasilnya secepat mungkin. Jangan menjalankan operasi yang kompleks dalam handler callback. Misalnya, dalam callback penyelesaian antrean buffer, Anda dapat mengantrekan buffer lain, tetapi jangan membuat pemutar audio.
- Handler callback harus disiapkan untuk lebih sering atau lebih jarang dipanggil, untuk menerima jenis peristiwa tambahan, dan harus mengabaikan jenis peristiwa yang tidak dikenalnya. Callback yang dikonfigurasi dengan mask peristiwa yang tersusun atas jenis-jenis peristiwa yang diaktifkan harus siap untuk dipanggil dengan berbagai bit jenis peristiwa yang disetel secara serentak. Gunakan "&" untuk menguji setiap bit peristiwa, bukan switch case.
- Gunakan status pengambilan data dan callback sebagai indikasi progres secara umum, tetapi jangan bergantung pada level isian hard-code atau urutan callback tertentu. Arti dari level isian status pengambilan data, dan perilaku error yang terdeteksi selama pengambilan data, dapat berubah.
Catatan: Lihat bagian Perilaku antrean buffer di bawah untuk detail selengkapnya.
Rencana untuk kompatibilitas sumber
Seperti disebutkan di atas, inkompatibilitas kode sumber telah diperkirakan dalam OpenSL ES versi berikutnya dari Khronos Group. Area yang kemungkinan akan berubah antara lain:
- Antarmuka antrean buffer diperkirakan mengalami perubahan signifikan, khususnya di area
BufferQueue::Enqueue
, daftar parameter untukslBufferQueueCallback
, dan nama kolomSLBufferQueueState.playIndex
. Sebaiknya aplikasi Anda menggunakan antrean buffer sederhana Android. Dalam kode contoh yang disertakan dengan NDK, kami telah menggunakan antrean buffer sederhana Android untuk pemutaran karena alasan ini. (Kami juga menggunakan antrean buffer sederhana Android untuk perekaman dan dekode ke PCM, tetapi itu karena OpenSL ES 1.0.1 tidak mendukung perekaman atau dekode ke sink data antrean buffer.) - Akan ada penambahan
const
ke parameter input yang diteruskan melalui referensi, dan ke kolom structSLchar *
yang digunakan sebagai nilai input. Penambahan ini tidak memerlukan perubahan apa pun pada kode Anda. - Akan ada pengganti dengan jenis yang tidak bertandatangan untuk beberapa parameter yang saat ini bertanda tangan.
Anda mungkin perlu mengubah jenis parameter dari
SLint32
menjadiSLuint32
atau yang serupa, atau menambahkan cast. Equalizer::GetPresetName
menyalin string ke memori aplikasi, bukan menampilkan pointer ke memori implementasi. Ini akan menjadi perubahan signifikan, jadi sebaiknya Anda menghindari memanggil metode ini, atau mengisolasi penggunaannya.- Akan ada kolom tambahan dalam jenis struct. Untuk parameter output, kolom baru ini dapat diabaikan, tetapi untuk parameter input, kolom baru ini perlu diinisialisasi. Untungnya, semua kolom ini diperkirakan akan berada di area yang tidak didukung oleh Android.
- GUID antarmuka akan berubah. Rujuklah antarmuka melalui nama simbolik, bukan GUID, untuk menghindari dependensi.
SLchar
akan berubah dariunsigned char
menjadichar
. Perubahan ini terutama memengaruhi pencari lokasi data URI dan format data MIME.SLDataFormat_MIME.mimeType
akan diganti namanya menjadipMimeType
, danSLDataLocator_URI.URI
akan diganti namanya menjadipURI
. Kami merekomendasikan Anda melakukan inisialisasi struktur dataSLDataFormat_MIME
danSLDataLocator_URI
menggunakan daftar nilai yang dipisahkan koma dalam kurung kurawal, bukan berdasarkan nama kolom, untuk mengisolasi kode Anda dari perubahan ini. Teknik ini digunakan dalam kode contoh.SL_DATAFORMAT_PCM
tidak mengizinkan aplikasi menentukan representasi data sebagai bilangan bulat bertanda tangan, bilangan bulat tidak bertanda tangan, atau bilangan titik mengambang. Implementasi Android mengasumsikan bahwa data 8 bit adalah bilangan bulat tidak bertanda tangan sedangkan 16 bit adalah bilangan bulat bertanda tangan. Selain itu, kolomsamplesPerSec
adalah istilah yang salah, karena satuan sebenarnya adalah miliHz. Masalah ini diharapkan akan teratasi dalam OpenSL ES versi berikutnya, yang akan memperkenalkan format data PCM baru yang diperluas, yang mengizinkan aplikasi untuk menentukan representasi secara eksplisit dan mengoreksi nama kolom. Karena ini akan menjadi format data baru, dan format data PCM saat ini tetap akan tersedia (meski tidak digunakan lagi), maka tidak perlu ada perubahan segera pada kode Anda.