OpenSL ES untuk Android

Halaman ini menyediakan detail tentang bagaimana implementasi OpenSL ES™ NDK berbeda dari spesifikasi referensi untuk OpenSL ES 1.0.1. Saat menggunakan kode contoh dari spesifikasi, Anda mungkin perlu memodifikasinya agar berfungsi di Android.

Kecuali jika dinyatakan berbeda, semua fitur tersedia di Android 2.3 (API level 9) dan lebih tinggi. Sebagian fitur hanya tersedia untuk Android 4.0 (API level 14); hal ini telah diketahui.

Catatan: Android Compatibility Definition Document (CDD) menyebutkan persyaratan hardware dan software untuk perangkat Android yang kompatibel. Lihat Kompatibilitas Android untuk informasi selengkapnya mengenai program kompatibilitas keseluruhan, dan CDD untuk dokumen CDD sebenarnya.

OpenSL ES menyediakan antarmuka bahasa C yang juga dapat diakses menggunakan C++. Fitur yang dieksposnya mirip dengan porsi audio Android Java API ini:

Seperti semua Android Native Development Kit (NDK), tujuan utama OpenSL ES untuk Android adalah memfasilitasi implementasi library bersama yang akan diaktifkan menggunakan Java Native Interface (JNI ). NDK tidak dimaksudkan untuk menulis aplikasi C/C++ murni. Akan tetapi, OpenSL ES adalah API berfitur lengkap, dan kami mengharapkan Anda dapat memenuhi sebagian besar kebutuhan audio hanya dengan menggunakan API ini, tanpa up-call ke kode yang berjalan di runtime Android.

Catatan: Meski berdasarkan OpenSL ES, API audio native Android (audio performa tinggi) bukanlah implementasi yang mengikuti profil OpenSL ES 1.0.1 (game, musik, atau ponsel). Hal ini karena Android tidak mengimplementasikan semua fitur yang diperlukan oleh salah satu profil tersebut. Semua kasus yang diketahui mengenai perilaku Android yang berbeda dari spesifikasi dijelaskan di halaman Ekstensi Android.

Fitur yang diwariskan dari spesifikasi referensi

Implementasi OpenSL ES Android NDK mewarisi banyak set fitur dari spesifikasi referensi, dengan keterbatasan tertentu.

Titik masuk global

OpenSL ES untuk Android mendukung semua titik masuk global dalam spesifikasi Android. Titik masuk ini antara lain:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Objek dan antarmuka

Tabel berikut menampilkan objek dan antarmuka yang didukung implementasi OpenSL ES Android NDK. Jika Ya muncul dalam sel, berarti fitur tersebut tersedia dalam implementasi ini.

Dukungan Android NDK untuk objek dan antarmuka.

Fitur Pemutar audio Perekam audio Mesin Campuran keluaran
Peningkatan bass Ya Tidak Tidak Ya
Antrean buffer Ya Tidak Tidak Tidak
Pencari data antrean buffer Ya: Sumber Tidak Tidak Tidak
Manajemen antarmuka dinamis Ya Ya Ya Ya
Pengiriman efek Ya Tidak Tidak Tidak
Engine Tidak Tidak Ya Tidak
Gema lingkungan Tidak Tidak Tidak Ya
Ekualiser Ya Tidak Tidak Ya
Pencari data perangkat I/O Tidak Ya: Sumber Tidak Tidak
Ekstraksi metadata Ya: Dekode ke PCM Tidak Tidak Tidak
Matikan suara solo Ya Tidak Tidak Tidak
Objek Ya Ya Ya Ya
Pencari campuran keluaran Ya: Sink Tidak Tidak Tidak
Pemutaran 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 data URI Ya: Sumber Tidak Tidak Tidak
Virtualizer Ya Tidak Tidak Ya
Volume Ya Tidak Tidak Tidak

Bagian berikutnya menjelaskan batasan beberapa fitur ini.

Batasan

Batasan tertentu berlaku pada fitur dalam Tabel 1. Batasan ini menyatakan perbedaan dari spesifikasi referensi. Selebihnya dari bagian ini menyediakan informasi tentang perbedaan tersebut.

Manajemen 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 keluaran 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 struct SLEnvironmentalReverbSettings.

Format data MIME

Anda dapat menggunakan format data MIME hanya dengan pencari data URI, dan hanya untuk pemutar audio. Anda tidak dapat menggunakan format data ini untuk perekam audio.

Implementasi OpenSL ES Android mengharuskan Anda melakukan inisialisasi mimeType ke NULL atau string UTF-8 yang valid. Anda juga harus melakukan inisialiasi containerType ke nilai yang valid. Jika tidak ada pertimbangan lain, misalnya portabilitas ke implementasi lainnya atau format konten tidak dapat diidentifikasi oleh aplikasi melalui header, kami merekomendasikan agar Anda menyetel mimeType ke NULL dan containerType ke SL_CONTAINERTYPE_UNSPECIFIED.

OpenSL ES untuk Android mendukung format audio berikut, asalkan platform Android juga mendukungnya:

  • PCM WAV.
  • WAV alaw.
  • WAV ulaw.
  • MP3 Ogg Vorbis.
  • AAC LC.
  • HE-AACv1 (AAC+).
  • HE-AACv2 (AAC+ yang disempurnakan).
  • AMR.
  • FLAC.

Catatan: Untuk daftar format audio yang didukung Android, lihat Format media yang didukung.

Batasan berikut berlaku pada penanganan format ini dan format lain dalam implementasi OpenSL ES:

  • 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 OpenSL ES Android NDK tidak mendukung pemutaran langsung DRM atau konten yang dienkripsi. Untuk memutar konten audio yang dilindungi, Anda harus mendekripsinya dalam aplikasi sebelum memutarnya, dengan aplikasi 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.
  • Laju contoh sebesar:
    • 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 bagi perekaman bergantung pada perangkat; biasanya tersedia 16.000 Hz mono/16-bit bertanda tangan, apa pun perangkatnya.

Nilai kolom samplesPerSec dalam satuan miliHz, meski namanya keliru. Untuk menghindari ketidaksengajaan menggunakan nilai yang salah, kami merekomendasikan agar Anda melakukan inisialisasi kolom ini menggunakan salah satu konstanta simbolik yang ditentukan untuk keperluan ini, misalnya SL_SAMPLINGRATE_44_1.

Android 5.0 (API level 21) ke atas mendukung data titik mengambang.

Laju pemutaran

Laju pemutaran OpenSL ES menunjukkan kecepatan objek menampilkan data, yang dinyatakan dalam seperseribu kecepatan normal, atau per mille. Misalnya, laju pemutaran 1.000 per mille adalah 1.000/1.000, atau kecepatan normal. Rentang laju adalah interval tertutup yang menyatakan rentang kemungkinan laju pemutaran.

Dukungan untuk rentang laju pemutaran dan kemampuan lainnya dapat bervariasi bergantung pada versi platform dan implementasi. Aplikasi dapat menentukan kemampuan ini pada runtime dengan menggunakan PlaybackRate::GetRateRange() atau PlaybackRate::GetCapabilitiesOfRate() untuk melakukan kueri ke perangkat.

Perangkat biasanya mendukung rentang laju yang sama untuk sumber data dalam format PCM, dan laju unitas berkisar dari 1000 per mille hingga 1000 per mille 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,setel parameter startPos ke 0, dan parameter endPos ke SL_TIME_UNKNOWN.

Pencari data antrean buffer

Sebuah pemutar audio atau perekam dengan pencari data untuk antrean buffer hanya mendukung format data PCM.

Pencari data perangkat I/O

OpenSL ES untuk Android hanya mendukung penggunaan pencari data perangkat I/O jika Anda telah menentukan pencari sebagai sumber data bagi Engine::CreateAudioRecorder(). Lakukan inisialisasi pencari 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 data URI

OpenSL ES untuk Android hanya dapat menggunakan pencari data URI dengan format data MIME, dan hanya untuk pemutar audio. Anda tidak dapat menggunakan pencari data URI untuk perekam audio. URI 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. Ini mendukung satu engine per aplikasi dan maksimal 32 objek per engine. Memori perangkat dan CPU yang tersedia mungkin membatasi lebih jauh jumlah objek yang dapat digunakan.

Opsi engine ini telah dikenali, namun diabaikan oleh slCreateEngine:

  • SL_ENGINEOPTION_THREADSAFE
  • SL_ENGINEOPTION_LOSSOFCONTROL

OpenMAX AL dan OpenSL ES dapat digunakan bersama dalam aplikasi yang sama. Dalam hal ini, secara internal ada 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 mempertahankan jumlah referensi atas engine bersama sehingga dapat dimusnahkan dengan benar selama operasi pemusnahan kedua.

Catatan pemrograman

Catatan pemrograman OpenSL ES menyediakan informasi tambahan untuk memastikan implementasi OpenSL ES yang 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.

Manajemen antarmuka dinamis

DynamicInterfaceManagement::AddInterface tidak berfungsi. Sebagai gantinya, tentukan antarmuka dalam array yang diteruskan ke Create(), seperti ditampilkan dalam kode contoh gema lingkungan.

Perencanaan versi mendatang OpenSL ES

API audio berkinerja tinggi Android didasarkan pada Khronos Group OpenSL ES1.0.1. 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 kecil atau ada dalam area OpenSL ES yang tidak didukung oleh Android.

Aplikasi yang dikembangkan dengan versi ini berfungsi pada versi mendatang platform Android, asalkan Anda mengikuti panduan yang diuraikan di bagian Perencanaan kompatibilitas biner di bawah.

Catatan: Kompatibilitas sumber di masa mendatang tidak menjadi tujuan. Dengan kata lain, jika Anda mengupgrade ke versi NDK yang lebih baru, Anda mungkin perlu memodifikasi kode sumber aplikasi agar mematuhi API baru. Kami memperkirakan bahwa hampir semua perubahan tersebut adalah perubahan kecil; lihat detail di bawah.

Perencanaan kompatibilitas biner

Kami menyarankan agar aplikasi Anda mengikuti panduan ini untuk meningkatkan kompatibilitas biner 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.
  • Pengendali callback aplikasi umumnya dijalankan dalam konteks yang dibatasi. Pengendali tersebut harus ditulis untuk melakukan pekerjaannya dengan cepat, lalu kembali secepatnya. Jangan menjalankan operasi yang kompleks dalam pengendali callback. Misalnya, dalam callback penyelesaian antrean buffer, Anda dapat mengantrekan buffer lain, namun jangan membuat pemutar audio.
  • Pengendali callback harus disiapkan untuk lebih sering atau kurang sering diaktifkan, untuk menerima jenis peristiwa tambahan, dan harus mengabaikan jenis peristiwa yang tidak dikenalinya. Callback yang dikonfigurasi dengan mask peristiwa dari jenis peristiwa yang diaktifkan harus siap untuk diaktifkan dengan beberapa bit jenis peristiwa yang disetel secara serentak. Gunakan "&" untuk menguji tiap bit peristiwa, bukan switch case.
  • Gunakan status pra-pengambilan dan callback sebagai penanda umum progres, namun jangan bergantung pada tingkat isian hard-code atau urutan callback tertentu. Arti dari tingkat isian status pra-pemuatan, dan perilaku error yang terdeteksi selama pra-pemuatan, dapat berubah.

Catatan: Lihat bagian Perilaku antrean buffer di bawah untuk detail selengkapnya.

Perencanaan kompatibilitas sumber

Seperti disebutkan, inkompatibilitas kode sumber telah diperkirakan dalam OpenSL ES versi berikutnya dari Khronos Group. Area yang kemungkinan akan berubah antara lain:

  • Antarmuka antrean buffer diperkirakan banyak berubah, khususnya dalam area BufferQueue::Enqueue, daftar parameter untuk slBufferQueueCallback, dan nama kolom SLBufferQueueState.playIndex. Kami merekomendasikan agar aplikasi Anda menggunakan antrean buffer sederhana Android. Dalam kode contoh yang diberikan dengan NDK, kami telah menggunakan antrean buffer sederhana Android untuk pemutaran karena alasan ini. (Kami juga menggunakan antrean buffer sederhana Android untuk perekaman dan decoding ke PCM, namun itu karena OpenSL ES 1.0.1 tidak mendukung perekaman atau dekode ke sink data antrean buffer.)
  • Akan ada penambahan const ke parameter masukan yang diteruskan melalui referensi, dan ke kolom struct SLchar * yang digunakan sebagai nilai masukan. Penambahan ini tidak memerlukan perubahan 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 ke SLuint32 atau yang serupa, atau menambahkan cast.
  • Equalizer::GetPresetName menyalin string ke memori aplikasi, bukan menampilkan pointer ke memori implementasi. Ini akan menjadi perubahan yang signifikan, jadi kami merekomendasikan agar Anda menghindari pengaktifkan metode ini, atau mengisolasi penggunaannya.
  • Akan ada kolom tambahan dalam jenis struct. Untuk parameter keluaran, kolom baru ini dapat diabaikan, namun untuk parameter masukan, kolom baru ini perlu dilakukan inisialisasi. Untungnya, semua kolom ini diperkirakan akan berada dalam area yang tidak didukung oleh Android.
  • GUID antarmuka akan berubah. Cari antarmuka melalui nama simbolik daripada melalui GUID untuk menghindari dependensi.
  • SLchar akan berubah dari unsigned char menjadi char. Perubahan ini terutama memengaruhi pencari data URI dan format data MIME.
  • SLDataFormat_MIME.mimeType akan diganti namanya menjadi pMimeType, dan SLDataLocator_URI.URI akan diganti namanya menjadi pURI. Kami merekomendasikan agar Anda melakukan inisialisasi struktur data SLDataFormat_MIME dan SLDataLocator_URI dengan menggunakan daftar nilai yang dipisah koma dalam kurung kurawal, bukan dengan 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 titik-mengambang. Implementasi Android berasumsi bahwa data 8-bit adalah bilangan bulat tidak bertanda tangan dan 16-bit adalah bilangan bulat bertanda tangan. Selain itu, kolom samplesPerSec adalah istilah yang salah, karena satuan sebenarnya adalah milliHz. Masalah ini diharapkan teratasi dalam OpenSL ES versi berikutnya, yang akan memperkenalkan format data PCM perluasan baru yang mengizinkan aplikasi untuk secara eksplisit menentukan representasi dan mengoreksi nama kolom. Karena akan menjadi format data baru, dan format data PCM saat ini tetap akan tersedia (meski tidak digunakan lagi), maka tidak perlu perubahan segera pada kode Anda.