Ekstensi Android

OpenSL ES untuk Android memperluas spesifikasi OpenSL ES referensi untuk membuatnya kompatibel dengan Android, dan untuk memanfaatkan kemampuan dan fleksibilitas platform Android.

Definisi API untuk ekstensi Android ini berada di OpenSLES_Android.h dan file header yang disertakannya. Lihat OpenSLES_Android.h untuk mengetahui detail tentang ekstensi ini. File ini berada pada root penginstalan Anda, dalam direktori sysroot/usr/include/SLES. Kecuali jika dinyatakan lain, semua antarmuka bersifat eksplisit.

Ekstensi ini membatasi portabilitas aplikasi Anda ke implementasi OpenSL ES lainnya, karena ekstensi ini khusus Android. Anda dapat memitigasi masalah ini dengan menghindari penggunaan ekstensi tersebut atau menggunakan #ifdef untuk mengecualikannya pada waktu kompilasi.

Tabel berikut menampilkan antarmuka khusus Android dan pencari lokasi data yang didukung Android OpenSL ES untuk setiap jenis objek. Nilai Ya dalam sel menunjukkan antarmuka dan pencari lokasi data yang tersedia untuk setiap jenis objek.

Fitur Pemutar audio Perekam audio Engine Campuran output
Antrean buffer Android Ya: Sumber (dekode) Tidak Tidak Tidak
Konfigurasi Android Ya Ya Tidak Tidak
Efek Android Ya Tidak Tidak Ya
Kemampuan efek Android Tidak Tidak Ya Tidak
Pengiriman efek Android Ya Tidak Tidak Tidak
Antrean buffer sederhana Android Ya: Sumber (pemutaran) atau sink (dekode) Ya Tidak Tidak
Pencari lokasi data antrean buffer Android Ya: Sumber (dekode) Tidak Tidak Tidak
Pencari lokasi data deskriptor file Android Ya: Sumber Tidak Tidak Tidak
Pencari lokasi data antrean buffer sederhana Android Ya: Sumber (pemutaran) atau sink (dekode) Ya: Sink Tidak Tidak

Antarmuka konfigurasi Android

Antarmuka konfigurasi Android menyediakan cara menyetel parameter khusus platform untuk objek. Antarmuka ini berbeda dengan antarmuka OpenSL ES 1.0.1 lainnya, yaitu aplikasi Anda dapat menggunakannya sebelum membuat instance objek yang terkait. Karena itu, Anda dapat mengonfigurasi objek ini sebelum membuat instance-nya. File header OpenSLES_AndroidConfiguration.h, yang berada di /sysroot/usr/include/SLES, mendokumentasikan kunci dan nilai konfigurasi berikut yang tersedia:

  • Jenis stream untuk pemutar audio (default SL_ANDROID_STREAM_MEDIA).
  • Profil perekaman untuk perekam audio (default SL_ANDROID_RECORDING_PRESET_GENERIC).

Cuplikan kode berikut menunjukkan cara menentukan jenis streaming audio Android pada pemutar audio:

// CreateAudioPlayer and specify SL_IID_ANDROIDCONFIGURATION
// in the required interface ID array. Do not realize player yet.
// ...
SLAndroidConfigurationItf playerConfig;
result = (*playerObject)->GetInterface(playerObject,
    SL_IID_ANDROIDCONFIGURATION, &playerConfig);
assert(SL_RESULT_SUCCESS == result);
SLint32 streamType = SL_ANDROID_STREAM_ALARM;
result = (*playerConfig)->SetConfiguration(playerConfig,
    SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
assert(SL_RESULT_SUCCESS == result);
// ...
// Now realize the player here.

Anda dapat menggunakan kode serupa guna mengonfigurasi preset untuk perekam audio:

// ... obtain the configuration interface as the first four lines above, then:
SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
result = (*playerConfig)->SetConfiguration(playerConfig,
    RECORDING_PRESET, &presetValue, sizeof(SLuint32));

Antarmuka efek Android

Antarmuka efek, pengiriman efek, dan kapabilitas efek Android menyediakan mekanisme generik bagi aplikasi untuk mengkueri dan menggunakan efek audio khusus perangkat. Produsen perangkat harus mendokumentasikan efek audio khusus perangkat apa pun yang mereka sediakan.

Aplikasi portabel harus menggunakan API OpenSL ES 1.0.1 untuk efek audio, bukan ekstensi efek Android.

Pencari lokasi data deskriptor file Android

Pencari lokasi data deskriptor file Android memungkinkan Anda menentukan sumber untuk pemutar audio sebagai deskriptor file terbuka dengan akses baca. Format data harus berupa MIME.

Ekstensi ini sangat berguna jika digunakan bersama pengelola aset native, karena aplikasi membaca aset dari APK melalui deskriptor file.

Antarmuka dan pencari lokasi data antrean buffer sederhana Android

Dalam spesifikasi referensi OpenSL ES 1.0.1, antrean buffer dapat digunakan untuk pemutar audio saja dan kompatibel dengan PCM dan format data lainnya. Spesifikasi antarmuka dan pencari lokasi data antrean buffer sederhana Android sama persis dengan spesifikasi standar, dengan dua pengecualian:

  • Anda dapat menggunakan antrean buffer sederhana Android dengan perekam audio dan pemutar audio.
  • Anda hanya dapat menggunakan format data PCM dengan antrean ini.

Untuk merekam, aplikasi harus mengantrekan buffer kosong. Jika callback yang terdaftar mengirim notifikasi bahwa sistem telah selesai menulis data ke buffer, aplikasi dapat membaca dari buffer tersebut.

Pemutaran berfungsi dengan cara yang sama. Akan tetapi, untuk kompatibilitas kode sumber di masa mendatang, kami menyarankan agar aplikasi menggunakan antrean buffer sederhana Android sebagai ganti antrean buffer OpenSL ES 1.0.1.

Perilaku antrean buffer

Implementasi Android tidak menyertakan persyaratan spesifikasi referensi yang dikembalikan oleh kursor pemutaran ke awal buffer pemutaran saat ini jika pemutaran memasuki status SL_PLAYSTATE_STOPPED. Implementasi ini dapat mengikuti perilaku tersebut, atau dapat membiarkan lokasi kursor pemutaran tidak berubah. Akibatnya, aplikasi Anda tidak dapat berasumsi bahwa salah satu perilaku terjadi. Oleh karena itu, Anda harus memanggil metode BufferQueue::Clear() secara eksplisit setelah transisi ke SL_PLAYSTATE_STOPPED. Tindakan ini menyetel antrean buffer ke status yang diketahui.

Demikian pula, tidak ada spesifikasi yang mengatur apakah pemicu callback antrean buffer harus berupa transisi ke SL_PLAYSTATE_STOPPED atau eksekusi BufferQueue::Clear(). Oleh karena itu, sebaiknya Anda tidak membuat dependensi pada satu atau yang lainnya; sebagai gantinya, aplikasi Anda harus dapat menangani keduanya.

Antarmuka dinamis saat pembuatan objek

Agar praktis, implementasi Android OpenSL ES 1.0.1 mengizinkan aplikasi Anda menentukan antarmuka dinamis saat membuat instance objek. Ini merupakan alternatif dari penggunaan DynamicInterfaceManagement::AddInterface() untuk menambahkan antarmuka ini setelah pembuatan instance.

Pelaporan ekstensi

Ada tiga metode untuk mengkueri apakah platform mendukung ekstensi Android. Metode tersebut adalah:

  • Engine::QueryNumSupportedExtensions()
  • Engine::QuerySupportedExtension()
  • Engine::IsExtensionSupported()

Setiap metode ini menampilkan ANDROID_SDK_LEVEL_<API-level>, dengan API-level yang merupakan API level platform; misalnya, ANDROID_SDK_LEVEL_23. Platform API level 9 atau lebih tinggi artinya platform mendukung ekstensi.

Mendekode audio ke PCM

Bagian ini menjelaskan ekstensi khusus Android yang tidak digunakan lagi pada OpenSL ES 1.0.1 untuk mendekode stream berenkode ke PCM tanpa pemutaran langsung. Tabel di bawah memberikan rekomendasi penggunaan ekstensi ini dan alternatifnya.

API level Alternatif
15 dan lebih rendah Codec open source dengan lisensi yang sesuai
16 sampai 20 Class MediaCodec atau codec open source dengan lisensi yang sesuai
21 dan lebih tinggi MediaCodec NDK dalam file header <media/NdkMedia*.h>, class MediaCodec, atau codec open source dengan lisensi yang sesuai

Catatan: Saat ini tidak ada dokumentasi untuk versi NDK dari MediaCodec API. Akan tetapi, Anda dapat merujuk kode contoh codec native untuk melihat contoh.

Pemutar audio standar memutar ke perangkat audio, dengan menentukan campuran output sebagai sink data. Ekstensi Android berbeda karena pemutar audio berfungsi sebagai decoder jika aplikasi telah menentukan sumber datanya sebagai URI atau pencari lokasi data deskriptor file Android yang dijelaskan menggunakan format data MIME. Dalam kasus semacam itu, sink data adalah pencari lokasi data antrean buffer sederhana Android yang menggunakan format data PCM.

Fitur ini ditujukan terutama bagi game untuk melakukan pra-muat aset audionya saat mengubah ke level game baru, yang serupa dengan fungsionalitas yang disediakan oleh class SoundPool.

Pertama-tama, aplikasi perlu mengantrekan satu kumpulan buffer kosong dalam antrean buffer sederhana Android. Setelah itu, aplikasi mengisi buffer dengan data PCM. Callback antrean buffer sederhana Android akan diaktifkan setelah setiap buffer terisi. Handler callback memproses data PCM, mengantrekan kembali buffer yang sekarang kosong, lalu menampilkannya. Aplikasi bertanggung jawab memantau buffer hasil dekode; daftar parameter callback tidak menyertakan informasi yang cukup untuk menunjukkan buffer yang berisi data atau buffer yang harus diantrekan berikutnya.

Sumber data secara implisit melaporkan akhir streaming (EOS) dengan mengirim peristiwa SL_PLAYEVENT_HEADATEND pada akhir streaming. Setelah mendekode semua data yang diterimanya, aplikasi tidak akan melakukan panggilan lebih lanjut ke callback antrean buffer sederhana Android.

Format data PCM sink biasanya cocok dengan format data untuk sumber data berenkode dalam hal frekuensi sampel, jumlah channel, dan kedalaman bit. Akan tetapi, Anda dapat mendekode ke frekuensi sampel, jumlah channel, atau kedalaman bit yang berbeda. Untuk informasi tentang penyediaan untuk mendeteksi format PCM yang sebenarnya, lihat Menentukan format data PCM hasil dekode melalui metadata.

Fitur decoding PCM di OpenSL ES untuk Android mendukung jeda dan pencarian awal, tetapi tidak mendukung kontrol volume, efek, pengulangan, atau laju pemutaran.

Bergantung pada implementasi platform, decoding mungkin memerlukan resource yang tidak dapat dibiarkan menganggur. Oleh karena itu, sebaiknya Anda memastikan untuk menyediakan buffer PCM kosong dalam jumlah yang cukup; jika tidak, decoder akan kekurangan buffer. Ini mungkin saja terjadi, misalnya, jika aplikasi Anda kembali dari callback antrean buffer sederhana Android tanpa mengantrekan buffer kosong lainnya. Akibat dari decoder yang kekurangan buffer tersebut tidak ditentukan, tetapi meliputi: penurunan data PCM hasil dekode, jeda dalam proses decoding, atau penghentian decoder langsung.

Catatan: Guna mendekode streaming berenkode ke PCM tetapi tidak segera memutarnya, untuk aplikasi yang berjalan di Android 4.x (API level 16–20), sebaiknya gunakan class MediaCodec. Untuk aplikasi baru yang berjalan di Android 5.0 (API level 21) atau yang lebih tinggi, sebaiknya gunakan padanan NDK, <NdkMedia*.h>. File header ini berada dalam direktori media/ pada root penginstalan Anda.

Mendekode streaming ADTS AAC ke PCM

Pemutar audio berfungsi sebagai decoder streaming jika sumber data berupa pencari lokasi data antrean buffer Android yang menggunakan format data MIME, dan sink data berupa pencari lokasi data antrean buffer sederhana Android yang menggunakan format data PCM. Konfigurasi format data MIME sebagai berikut:

  • Penampung: SL_CONTAINERTYPE_RAW
  • String jenis MIME: SL_ANDROID_MIME_AACADTS

Fitur ini ditujukan terutama untuk aplikasi media streaming yang menangani audio AAC, tetapi perlu melakukan pemrosesan audio kustom sebelum pemutaran. Sebagian besar aplikasi yang perlu mendekode audio ke PCM harus menggunakan metode yang dijelaskan dalam Mendekode audio ke PCM, karena metode tersebut lebih sederhana dan menangani lebih banyak format audio. Teknik yang dijelaskan di sini adalah pendekatan yang lebih khusus, yang hanya akan digunakan jika kedua kondisi ini terpenuhi:

  • Sumber audio terkompresi adalah streaming frame AAC yang dimuat dalam header ADTS.
  • Aplikasi mengelola streaming ini. Data tidak berada dalam resource jaringan yang ID-nya adalah URI atau dalam file lokal yang ID-nya adalah deskriptor file.

Pertama-tama, aplikasi harus mengantrekan satu kumpulan buffer yang terisi dalam antrean buffer Android. Setiap buffer berisi satu atau beberapa frame ADTS AAC lengkap. Callback antrean buffer Android akan diaktifkan setelah setiap buffer dikosongkan. Handler callback harus mengisi ulang dan mengantrekan kembali buffer, lalu kembali. Aplikasi tidak perlu memantau buffer yang dienkode; daftar parameter callback mencakup informasi yang memadai untuk menunjukkan buffer yang harus diantrekan berikutnya. Akhir streaming ditandai secara eksplisit dengan mengantrekan item EOS. Setelah EOS, tidak ada lagi antrean yang diizinkan.

Sebaiknya pastikan Anda menyediakan buffer ADTS AAC lengkap, agar decoder tidak sampai kekurangan buffer. Hal ini mungkin saja terjadi, misalnya, jika aplikasi Anda kembali dari callback antrean buffer Android tanpa mengantrekan buffer penuh lainnya. Akibat dari decoder yang kekurangan buffer tidak jelas.

Kecuali dalam aspek sumber datanya, metode dekode streaming itu sama seperti yang dijelaskan dalam Mendekode audio ke PCM

Meskipun namanya mirip, antrean buffer Android tidak sama dengan antrean buffer sederhana Android. Decoder streaming menggunakan kedua jenis antrean buffer: antrean buffer Android untuk sumber data ADTS AAC, dan antrean buffer sederhana Android untuk sink data PCM. Untuk informasi selengkapnya tentang API antrean buffer sederhana Android, lihat Antarmuka dan pencari lokasi data antrean buffer sederhana Android. Untuk informasi selengkapnya tentang API antrean buffer Android, lihat file index.html dalam direktori docs/Additional_library_docs/openmaxal/ di root penginstalan.

Menentukan format data PCM hasil dekode melalui metadata

Antarmuka SLMetadataExtractionItf adalah bagian dari spesifikasi referensi. Namun, kunci metadata yang mengindikasikan format sebenarnya dari data PCM hasil dekode berlaku khusus untuk Android. File header OpenSLES_AndroidMetadata.h menentukan kunci metadata tersebut. File header ini berada pada root penginstalan Anda, dalam direktori /sysroot/usr/include/SLES.

Indeks kunci metadata langsung tersedia setelah metode Object::Realize() selesai dieksekusi. Namun, nilai-nilai yang terkait tidak tersedia sampai aplikasi selesai mendekode data yang pertama dienkode. Praktik yang baik adalah mengkueri indeks kunci dalam thread utama setelah memanggil metode Object::Realize, dan membaca nilai metadata format PCM dalam handler callback antrean buffer sederhana Android saat memanggilnya untuk pertama kalinya. Lihat kode contoh dalam paket NDK untuk contoh menangani antarmuka ini.

Nama kunci metadata bersifat stabil, tetapi indeks kunci tersebut tidak didokumentasikan dan sewaktu-waktu dapat berubah. Aplikasi tidak boleh berasumsi bahwa indeks tersebut tetap ada di seluruh eksekusi lain yang berjalan, dan tidak boleh berasumsi bahwa beberapa instance objek menggunakan indeks yang sama saat sama-sama dijalankan.

Data floating point

Aplikasi yang berjalan pada Android 5.0 (API level 21) dan yang lebih tinggi dapat menyuplai data ke AudioPlayer dalam format floating point presisi tunggal.

Dalam kode contoh berikut, metode Engine::CreateAudioPlayer() membuat pemutar audio yang menggunakan data floating point:

#include <SLES/OpenSLES_Android.h>
...
SLAndroidDataFormat_PCM_EX pcm;
pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
pcm.numChannels = 2;
pcm.sampleRate = SL_SAMPLINGRATE_44_1;
pcm.bitsPerSample = 32;
pcm.containerSize = 32;
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
...
SLDataSource audiosrc;
audiosrc.pLocator = ...
audiosrc.pFormat = &pcm;
Baca selengkapnya tentang audio floating point di halaman Pengambilan Sampel Audio.