AAudio

AAudio adalah Android C API yang diperkenalkan dalam rilis Android O. API ini didesain untuk aplikasi audio berperforma tinggi yang memerlukan latensi rendah. Aplikasi berkomunikasi dengan AAudio dengan membaca dan menulis data ke streaming.

Secara desain, API AAudio memiliki fungsi minimal dan tidak dapat melakukan:

  • Enumerasi perangkat audio
  • Perutean otomatis antar-endpoint audio
  • I/O file
  • Decoding audio terkompresi
  • Presentasi otomatis semua input/streaming dalam satu callback.

Memulai

Anda dapat memanggil AAudio dari kode C++. Untuk menambahkan set fitur AAudio ke aplikasi Anda, sertakan file header AAudio.h:

#include <aaudio/AAudio.h>

Streaming audio

AAudio memindahkan data audio antara input dan output aplikasi dan audio Anda di perangkat Android. Aplikasi Anda meneruskan data keluar masuk dengan membaca dari dan menulis ke stream audio, yang direpresentasikan oleh AAudioStream struktur. Panggilan baca/tulis ini dapat bersifat memblokir atau tidak memblokir.

Streaming ditentukan oleh hal-hal berikut:

  • Perangkat audio yang merupakan sumber atau sink untuk data dalam streaming tersebut.
  • Mode berbagi yang menentukan apakah stream memiliki akses eksklusif ke perangkat audio yang dalam keadaan lain mungkin digunakan bersama oleh beberapa stream.
  • Format data audio dalam streaming.

Perangkat audio

Setiap stream dikaitkan ke satu perangkat audio.

Perangkat audio adalah antarmuka hardware atau endpoint virtual yang bertindak sebagai sumber atau sink untuk streaming data audio digital yang berkelanjutan. Jangan salah membedakan antara perangkat audio (mikrofon internal atau headset bluetooth) dengan perangkat Android (ponsel atau smartwatch) yang menjalankan aplikasi Anda.

Anda dapat menggunakan metode getDevices() di AudioManager untuk menemukan perangkat audio yang tersedia di perangkat Android. Metode tersebut menampilkan informasi tentang type setiap perangkat.

Setiap perangkat audio memiliki ID unik di perangkat Android. Anda dapat menggunakan ID ini untuk mengaitkan streaming audio ke perangkat audio tertentu. Akan tetapi, biasanya Anda dapat mengizinkan AAudio memilih perangkat utama default, alih-alih menentukannya sendiri.

Perangkat audio yang dikaitkan ke streaming menentukan apakah streaming tersebut ditujukan untuk input atau output. Sebuah stream hanya dapat memindahkan data dalam satu arah. Saat menentukan stream, Anda juga menetapkan arahnya. Saat Anda membuka stream, Android memeriksa untuk memastikan kecocokan antara perangkat audio dan arah stream.

Mode berbagi

Streaming memiliki mode berbagi:

  • AAUDIO_SHARING_MODE_EXCLUSIVE berarti streaming memiliki akses eksklusif ke perangkat audionya; perangkat tidak dapat digunakan oleh streaming audio lain. Jika perangkat audio sudah digunakan, tidak mungkin bagi stream untuk memiliki akses eksklusif. Streaming eksklusif cenderung memiliki latensi lebih rendah, tetapi juga lebih berpotensi terputus. Sebaiknya tutup streaming eksklusif begitu Anda tidak memerlukannya, agar aplikasi lain dapat mengakses perangkat. Stream eksklusif menyediakan latensi terendah yang dimungkinkan.
  • AAUDIO_SHARING_MODE_SHARED memungkinkan AAudio mencampur audio. AAudio menggabungkan semua streaming bersama yang ditetapkan ke perangkat yang sama.

Anda dapat menyetel mode berbagi secara eksplisit saat membuat streaming. Secara default, mode berbagi adalah SHARED.

Format audio

Data yang diteruskan melalui stream memiliki atribut audio digital biasa. Atribut ini mencakup:

  • Format data sampel
  • Jumlah saluran (sampel per frame)
  • Frekuensi sampel

AAudio mengizinkan format sampel berikut:

aaudio_format_t Jenis data C Catatan
AAUDIO_FORMAT_PCM_I16 int16_t sampel 16-bit umum, format Q0.15
AAUDIO_FORMAT_PCM_FLOAT float -1.0 hingga +1.0
AAUDIO_FORMAT_PCM_I24_PACKED uint8_t dalam grup yang terdiri dari 3 sampel paket 24-bit, format Q0.23
AAUDIO_FORMAT_PCM_I32 int32_t sampel 32-bit umum, format Q0.31
AAUDIO_FORMAT_IEC61937 uint8_t audio terkompresi yang digabungkan dalam IEC61937 untuk passthrough HDMI atau S/PDIF

Jika Anda meminta format sampel tertentu, maka streaming akan menggunakan format tersebut, meskipun formatnya tidak optimal untuk perangkat. Jika Anda tidak menentukan format sampel, AAudio akan memilih format yang optimal. Setelah streaming dibuka, Anda harus mengkueri format data sampel, lalu mengonversi data jika perlu, seperti dalam contoh ini:

aaudio_format_t dataFormat = AAudioStream_getDataFormat(stream);
//... later
if (dataFormat == AAUDIO_FORMAT_PCM_I16) {
     convertFloatToPcm16(...)
}

Membuat streaming audio

Library AAudio mengikuti pola desain builder dan menyediakan AAudioStreamBuilder.

  1. Membuat AAudioStreamBuilder:

    AAudioStreamBuilder *builder;
    aaudio_result_t result = AAudio_createStreamBuilder(&builder);
    

  2. Tetapkan konfigurasi stream audio di builder, menggunakan fungsi builder yang sesuai dengan parameter stream. Fungsi set opsional ini tersedia:

    AAudioStreamBuilder_setDeviceId(builder, deviceId);
    AAudioStreamBuilder_setDirection(builder, direction);
    AAudioStreamBuilder_setSharingMode(builder, mode);
    AAudioStreamBuilder_setSampleRate(builder, sampleRate);
    AAudioStreamBuilder_setChannelCount(builder, channelCount);
    AAudioStreamBuilder_setFormat(builder, format);
    AAudioStreamBuilder_setBufferCapacityInFrames(builder, frames);
    

    Perlu diperhatikan bahwa metode ini tidak melaporkan error, seperti konstanta yang tidak ditentukan atau nilai yang berada di luar rentang.

    Jika Anda tidak menentukan ID perangkat, perangkat output utama akan digunakan sebagai default. Jika Anda tidak menentukan arah streaming, streaming output akan digunakan sebagai default. Untuk semua parameter lainnya, Anda dapat secara eksplisit menetapkan nilai, atau membiarkan sistem menetapkan nilai optimal dengan tidak menentukan parameter sama sekali atau menetapkannya ke AAUDIO_UNSPECIFIED.

    Untuk lebih amannya, periksa status streaming audio setelah Anda membuatnya, seperti dijelaskan dalam langkah 4 di bawah.

  3. Jika AAudioStreamBuilder dikonfigurasi, gunakan untuk membuat stream:

    AAudioStream *stream;
    result = AAudioStreamBuilder_openStream(builder, &stream);
    

  4. Setelah membuat streaming, verifikasi konfigurasinya. Jika format sampel, frekuensi sampel, atau sampel per frame sudah ditentukan, konfigurasi tidak dapat diubah. Jika mode berbagi atau kapasitas buffer ditentukan, keduanya dapat berubah bergantung pada kapabilitas perangkat audio streaming dan perangkat Android yang menjalankan streaming tersebut. Sebagai upaya pemrograman defensif yang baik, sebaiknya periksa konfigurasi streaming sebelum menggunakannya. Tersedia fungsi untuk mengambil setelan streaming yang sesuai dengan setelan setiap builder:

    AAudioStreamBuilder_setDeviceId() AAudioStream_getDeviceId()
    AAudioStreamBuilder_setDirection() AAudioStream_getDirection()
    AAudioStreamBuilder_setSharingMode() AAudioStream_getSharingMode()
    AAudioStreamBuilder_setSampleRate() AAudioStream_getSampleRate()
    AAudioStreamBuilder_setChannelCount() AAudioStream_getChannelCount()
    AAudioStreamBuilder_setFormat() AAudioStream_getFormat()
    AAudioStreamBuilder_setBufferCapacityInFrames() AAudioStream_getBufferCapacityInFrames()

  5. Anda dapat menyimpan builder dan menggunakannya kembali di lain waktu untuk membuat streaming lainnya. Namun, jika tidak ingin menggunakannya lagi, sebaiknya hapus builder.

    AAudioStreamBuilder_delete(builder);
    

Menggunakan streaming audio

Transisi status

Streaming AAudio biasanya berada dalam salah satu dari lima status stabil (status error, Terputus, dijelaskan di akhir bagian ini):

  • Buka
  • Dimulai
  • Dijeda
  • Di-flush
  • Dihentikan

Data hanya mengalir melalui satu streaming jika streaming tersebut berstatus Dimulai. Untuk memindahkan streaming antar-status, gunakan salah satu fungsi yang meminta transisi status:

aaudio_result_t result;
result = AAudioStream_requestStart(stream);
result = AAudioStream_requestStop(stream);
result = AAudioStream_requestPause(stream);
result = AAudioStream_requestFlush(stream);

Perlu diperhatikan bahwa Anda hanya dapat meminta jeda atau flush pada streaming output:

Fungsi ini bersifat asinkron, dan perubahan status tidak terjadi dengan seketika. Saat Anda meminta perubahan status, streaming akan memindahkan salah satu status sementara yang terkait.

  • Memulai
  • Menjeda
  • Mem-flush
  • Menghentikan
  • Menutup

Diagram status di bawah menunjukkan status stabil sebagai persegi panjang bersudut bulat, dan status sementara sebagai persegi panjang bertitik-titik. Meski tidak ditampilkan, Anda dapat memanggil close() dari status mana saja.

Siklus Proses AAudio

AAudio tidak memberikan callback untuk memberitahukan perubahan status. Satu fungsi khusus, AAudioStream_waitForStateChange(stream, inputState, nextState, timeout), dapat digunakan untuk menunggu perubahan status.

Fungsi ini tidak mendeteksi perubahan status dengan sendirinya, dan tidak menunggu terjadinya status tertentu. Fungsi tersebut menunggu hingga status saat ini berbeda dengan inputState, yang Anda tentukan.

Misalnya, setelah meminta untuk menjeda, streaming harus segera memasuki status sementara Menjeda, dan nantinya akan berada dalam status Dijeda - meskipun tidak ada jaminan hal tersebut akan terjadi. Karena Anda tidak dapat menunggu hingga status berubah menjadi Dijeda, gunakan waitForStateChange() untuk menunggu status lain apa pun selain Menjeda. Berikut cara melakukannya:

aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_PAUSING;
aaudio_stream_state_t nextState = AAUDIO_STREAM_STATE_UNINITIALIZED;
int64_t timeoutNanos = 100 * AAUDIO_NANOS_PER_MILLISECOND;
result = AAudioStream_requestPause(stream);
result = AAudioStream_waitForStateChange(stream, inputState, &nextState, timeoutNanos);

Jika status streaming bukan Menjeda (inputState, yang kita asumsikan sebagai status saat ini pada saat melakukan panggilan), fungsi ini akan segera ditampilkan. Jika tidak, fungsi akan diblokir hingga status tidak lagi Menjeda atau waktu tunggu habis. Jika fungsi ditampilkan, parameter nextState akan menunjukkan status streaming saat ini.

Anda dapat menggunakan teknik yang sama ini setelah memanggil permintaan mulai, berhenti, atau flush, menggunakan status sementara yang terkait sebagai inputState. Jangan memanggil waitForStateChange() setelah memanggil AAudioStream_close(), karena streaming akan dihapus segera setelah ditutup. Kemudian, jangan memanggil AAudioStream_close() selagi waitForStateChange() berjalan di thread lain.

Membaca dan menulis ke streaming audio

Ada dua cara untuk memproses data dalam streaming setelah dimulai:

Untuk pembacaan atau penulisan blocking yang mentransfer sejumlah frame yang ditentukan, tetapkan timeoutNanos lebih besar daripada nol. Untuk panggilan yang bersifat tidak memblokir, setel timeoutNanos ke nol. Dalam hal ini, hasilnya adalah jumlah sebenarnya frame yang ditransfer.

Saat membaca input, sebaiknya verifikasi bahwa pembacaan dilakukan pada jumlah frame yang tepat. Jika tidak, buffer dapat berisi data tidak dikenal, yang dapat menyebabkan gangguan audio. Anda dapat menambahkan nol ke buffer untuk membuat dropout senyap:

aaudio_result_t result =
    AAudioStream_read(stream, audioData, numFrames, timeout);
if (result < 0) {
  // Error!
}
if (result != numFrames) {
  // pad the buffer with zeros
  memset(static_cast<sample_type*>(audioData) + result * samplesPerFrame, 0,
      sizeof(sample_type) * (numFrames - result) * samplesPerFrame);
}

Anda dapat melengkapi buffer streaming sebelum memulai streaming tersebut dengan menulis data atau kesenyapan ke dalamnya. Hal ini harus dilakukan dalam panggilan yang tidak memblokir dengan timeoutNanos disetel ke nol.

Data dalam buffer harus sama dengan format data yang ditampilkan oleh AAudioStream_getDataFormat().

Menutup stream audio

Tutup stream yang telah selesai digunakan:

AAudioStream_close(stream);

Stream yang telah ditutup tidak dapat digunakan lagi dengan fungsi berbasis stream AAudio mana pun.

Stream audio yang terputus

Streaming audio dapat terputus kapan saja jika salah satu peristiwa berikut terjadi:

  • Perangkat audio yang terkait tidak lagi terhubung (misalnya saat headphone dicabut).
  • Terjadi error secara internal.
  • Perangkat audio tidak lagi menjadi perangkat audio utama.

Jika streaming terputus, statusnya menjadi "Terputus" dan upaya apa pun untuk mengeksekusi AAudioStream_write() atau fungsi lain akan menampilkan error. Anda harus selalu menghentikan dan menutup streaming yang terputus, apa pun dari kode error-nya.

Jika Anda menggunakan callback data (bukan salah satu metode baca atau tulis langsung), Anda tidak akan menerima kode pengembalian bila aliran terputus. Agar diberi tahu saat hal ini terjadi, tulis fungsi AAudioStream_errorCallback lalu daftarkan fungsi tersebut menggunakan AAudioStreamBuilder_setErrorCallback().

Jika Anda diberi tahu tentang terjadinya pemutusan di thread callback error, maka penghentian dan penutupan streaming harus dilakukan dari thread lain. Jika tidak, Anda mungkin mengalami deadlock.

Perlu diketahui bahwa jika Anda membuka streaming baru, streaming tersebut mungkin memiliki setelan yang berbeda dari streaming asli (misalnya framesPerBurst):

void errorCallback(AAudioStream *stream,
                   void *userData,
                   aaudio_result_t error) {
    // Launch a new thread to handle the disconnect.
    std::thread myThread(my_error_thread_proc, stream, userData);
    myThread.detach(); // Don't wait for the thread to finish.
}

Mengoptimalkan performa

Anda dapat mengoptimalkan performa aplikasi audio dengan menyesuaikan buffer internalnya dan dengan menggunakan thread khusus prioritas tinggi.

Menyesuaikan buffer untuk meminimalkan latensi

AAudio meneruskan data ke dalam dan ke luar buffer internal yang dipeliharanya, satu buffer untuk tiap perangkat audio.

Kapasitas buffer adalah jumlah total data yang dapat ditampung oleh buffer. Anda dapat memanggil AAudioStreamBuilder_setBufferCapacityInFrames() untuk menyetel kapasitas ini. Metode ini membatasi kapasitas yang dapat Anda alokasikan ke jumlah maksimum yang diizinkan oleh perangkat. Gunakan AAudioStream_getBufferCapacityInFrames() untuk memverifikasi kapasitas buffer yang sebenarnya.

Aplikasi tidak harus menggunakan kapasitas buffer secara keseluruhan. AAudio mengisi buffer hingga ukuran yang dapat Anda tetapkan. Ukuran buffer tidak boleh lebih besar daripada kapasitasnya, dan biasanya lebih kecil. Dengan mengontrol ukuran buffer, Anda menentukan jumlah burst yang diperlukan untuk mengisinya, dan dengan demikian mengontrol latensi. Gunakan metode AAudioStreamBuilder_setBufferSizeInFrames() dan AAudioStreamBuilder_getBufferSizeInFrames() untuk mengelola ukuran buffer.

Saat memutar audio, aplikasi akan menulis ke buffer dan melakukan pemblokiran hingga operasi tulis tersebut selesai. AAudio membaca dari buffer dalam burst yang berlainan. Tiap burst berisi beberapa jumlah frame audio dan biasanya lebih kecil daripada ukuran buffer yang sedang dibaca. Sistem mengontrol ukuran dan frekuensi burst. Properti ini biasanya ditentukan oleh sirkuit perangkat audio. Meski tidak dapat mengubah ukuran atau frekuensi burst, Anda dapat menyetel ukuran buffer internal menurut jumlah burst yang terdapat di dalamnya. Umumnya, Anda mendapatkan latensi terendah jika ukuran buffer AaudioStream merupakan kelipatan dari ukuran burst yang dilaporkan.

      Buffering AAudio

Salah satu cara untuk mengoptimalkan ukuran buffer adalah memulai dengan buffer besar, lalu menurunkannya secara bertahap hingga terjadi underrun, baru kemudian menaikkannya kembali. Atau, Anda dapat memulai dengan ukuran buffer kecil dan, jika underrun terjadi, meningkatkan ukuran buffer hingga output-nya mengalir dengan bersih lagi.

Proses ini dapat terjadi sangat cepat, mungkin sebelum pengguna memutar bunyi pertama. Sebaiknya Anda melakukan pengubahan ukuran buffer awal terlebih dahulu, menggunakan kesenyapan, agar pengguna tidak mendengar gangguan audio. Performa sistem dapat berubah dari waktu ke waktu (misalnya, pengguna mungkin menonaktifkan mode pesawat). Karena penyesuaian buffer menambahkan overhead yang sangat kecil, aplikasi Anda dapat melakukannya secara berkelanjutan selagi aplikasi membaca atau menulis data ke streaming.

Berikut contoh loop pengoptimalan buffer:

int32_t previousUnderrunCount = 0;
int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
int32_t bufferSize = AAudioStream_getBufferSizeInFrames(stream);

int32_t bufferCapacity = AAudioStream_getBufferCapacityInFrames(stream);

while (go) {
    result = writeSomeData();
    if (result < 0) break;

    // Are we getting underruns?
    if (bufferSize < bufferCapacity) {
        int32_t underrunCount = AAudioStream_getXRunCount(stream);
        if (underrunCount > previousUnderrunCount) {
            previousUnderrunCount = underrunCount;
            // Try increasing the buffer size by one burst
            bufferSize += framesPerBurst;
            bufferSize = AAudioStream_setBufferSize(stream, bufferSize);
        }
    }
}

Teknik ini tidak memberikan keuntungan dalam pengoptimalan ukuran buffer untuk streaming input. Streaming input berjalan secepat mungkin, dengan mencoba meminimalkan jumlah data yang di-buffer, lalu memenuhinya jika aplikasi sudah dihentikan sementara.

Menggunakan callback prioritas tinggi

Jika aplikasi Anda membaca atau menulis data audio dari thread biasa, aplikasi tersebut mungkin terhenti sementara atau mengalami timing jitter. Hal ini dapat menyebabkan gangguan audio. Penggunaan buffer besar dapat melindungi dari gangguan semacam ini, tetapi buffer besar juga menghasilkan latensi audio yang lebih panjang. Untuk aplikasi yang memerlukan latensi rendah, streaming audio dapat menggunakan fungsi callback asinkron untuk mentransfer data ke dan dari aplikasi. AAudio mengeksekusi callback ini dalam thread prioritas lebih tinggi yang memiliki performa lebih baik.

Fungsi callback memiliki prototipe ini:

typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames);

Gunakan build streaming untuk mendaftarkan callback:

AAudioStreamBuilder_setDataCallback(builder, myCallback, myUserData);

Dalam kasus yang paling sederhana, streaming mengeksekusi fungsi callback secara berkala untuk mendapatkan data bagi burst berikutnya.

Fungsi callback tidak boleh menjalankan operasi baca/tulis pada streaming yang mengaktifkannya. Jika callback termasuk dalam streaming input, kode Anda harus memproses data yang diberikan dalam buffer audioData (yang ditentukan sebagai argumen ketiga). Jika callback tersebut termasuk dalam streaming output, kode Anda harus menempatkan data ke dalam buffer.

Misalnya, Anda dapat menggunakan callback untuk menghasilkan output gelombang sinus secara berkelanjutan seperti ini:

aaudio_data_callback_result_t myCallback(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames) {
    int64_t timeout = 0;

    // Write samples directly into the audioData array.
    generateSineWave(static_cast<float *>(audioData), numFrames);
    return AAUDIO_CALLABCK_RESULT_CONTINUE;
}

Anda dapat memproses lebih dari satu streaming menggunakan AAudio. Anda dapat menggunakan satu streaming sebagai master, dan meneruskan pointer ke streaming lain dalam data pengguna. Daftarkan callback untuk streaming master. Lalu, gunakan I/O yang tidak memblokir pada stream lainnya. Di bawah ini adalah contoh callback bolak-balik yang meneruskan stream input ke stream output. Stream pemanggilan master adalah stream output. Stream input disertakan dalam data pengguna.

Callback ini melakukan pembacaan yang tidak memblokir dari stream input yang menempatkan data ke dalam buffer stream output:

aaudio_data_callback_result_t myCallback(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames) {
    AAudioStream *inputStream = (AAudioStream *) userData;
    int64_t timeout = 0;
    aaudio_result_t result =
        AAudioStream_read(inputStream, audioData, numFrames, timeout);

  if (result == numFrames)
      return AAUDIO_CALLABCK_RESULT_CONTINUE;
  if (result >= 0) {
      memset(static_cast<sample_type*>(audioData) + result * samplesPerFrame, 0,
          sizeof(sample_type) * (numFrames - result) * samplesPerFrame);
      return AAUDIO_CALLBACK_RESULT_CONTINUE;
  }
  return AAUDIO_CALLBACK_RESULT_STOP;
}

Perlu diperhatikan bahwa dalam contoh ini diasumsikan bahwa stream input dan output memiliki jumlah channel, format, dan frekuensi sampel yang sama. Format stream boleh tidak sama - asalkan kode menangani penerjemahannya dengan tepat.

Menyetel mode performa

Setiap AAudioStream memiliki mode performa yang berpengaruh besar pada perilaku aplikasi. Terdapat tiga mode performa:

  • AAUDIO_PERFORMANCE_MODE_NONE adalah mode default. Mode ini menggunakan stream dasar yang menyeimbangkan latensi dan penghematan daya.
  • AAUDIO_PERFORMANCE_MODE_LOW_LATENCY menggunakan buffer yang lebih kecil dan jalur data yang dioptimalkan untuk menghasilkan latensi yang lebih rendah.
  • AAUDIO_PERFORMANCE_MODE_POWER_SAVING menggunakan buffer internal yang lebih besar dan jalur data yang mengorbankan latensi demi menghemat daya.

Anda dapat memilih mode performa dengan memanggil setPerformanceMode(), dan mengetahui mode saat ini dengan memanggil getPerformanceMode().

Jika latensi rendah lebih penting daripada penghematan daya dalam aplikasi Anda, gunakan AAUDIO_PERFORMANCE_MODE_LOW_LATENCY. Ini berguna untuk aplikasi yang sangat interaktif, seperti game atau keyboard synthesizer.

Jika penghematan daya lebih penting daripada latensi rendah dalam aplikasi Anda, gunakan AAUDIO_PERFORMANCE_MODE_POWER_SAVING. Hal ini umum ditemukan pada aplikasi yang memutar musik yang dibuat sebelumnya, seperti pemutar audio streaming atau file MIDI.

Dalam versi AAudio saat ini, untuk mencapai latensi serendah mungkin, Anda harus menggunakan mode performa AAUDIO_PERFORMANCE_MODE_LOW_LATENCY beserta callback prioritas tinggi. Ikuti contoh ini:

// Create a stream builder
AAudioStreamBuilder *streamBuilder;
AAudio_createStreamBuilder(&streamBuilder);
AAudioStreamBuilder_setDataCallback(streamBuilder, dataCallback, nullptr);
AAudioStreamBuilder_setPerformanceMode(streamBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

// Use it to create the stream
AAudioStream *stream;
AAudioStreamBuilder_openStream(streamBuilder, &stream);

Keamanan thread

AAudio API tidak sepenuhnya aman untuk thread. Anda tidak dapat memanggil beberapa fungsi AAudio secara serentak dari lebih dari satu thread pada satu waktu. Hal ini karena AAudio menghindari penggunaan mutex, yang dapat menyebabkan preemption thread dan glitch.

Untuk amannya, jangan memanggil AAudioStream_waitForStateChange() atau melakukan baca/ tulis ke stream yang sama dari dua thread berbeda. Selain itu, jangan menutup stream di satu thread saat operasi baca atau tulis berlangsung di thread yang lain.

Panggilan yang menampilkan setelan stream, seperti AAudioStream_getSampleRate() dan AAudioStream_getChannelCount(), aman untuk thread.

Panggilan berikut juga aman untuk thread:

  • AAudio_convert*ToText()
  • AAudio_createStreamBuilder()
  • AAudioStream_get*() kecuali untuk AAudioStream_getTimestamp()

Masalah umum

  • Latensi audio untuk fungsi write() yang memblokir cukup tinggi karena rilis Android O DP2 tidak menggunakan track FAST. Gunakan callback untuk mendapatkan latensi yang lebih rendah.

Referensi lainnya

Untuk mempelajari lebih lanjut, manfaatkan referensi berikut:

Referensi API

Codelab

Video