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
  • Penyajian otomatis semua input/streaming dalam satu callback.

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 stream data audio digital yang berkelanjutan. Jangan salah membedakan antara perangkat audio (mikrofon internal atau headset bluetooth) dengan perangkat Android (ponsel atau jam tangan) 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 stream 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 sebuah stream menentukan apakah stream 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. Stream eksklusif cenderung memiliki latensi lebih rendah, tetapi juga lebih cenderung terputus. Sebaiknya tutup stream eksklusif begitu Anda tidak memerlukannya lagi, 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 menetapkan 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 meliputi:

  • Format contoh
  • Sampel per frame
  • Frekuensi sampel

AAudio mengizinkan format contoh 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 sampai +1.0

AAudio mungkin melakukan konversi sampel sendiri. Misalnya, jika sebuah aplikasi menulis data FLOAT, tetapi HAL menggunakan PCM_I16, AAudio mungkin akan mengonversi sampel secara otomatis. Konversi dapat terjadi dalam salah satu arah. Jika aplikasi Anda memproses input audio, sebaiknya verifikasi format input dan bersiaplah mengonversi data jika diperlukan, seperti dalam contoh ini:

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

Membuat stream 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 arah stream tidak ditentukan, stream output akan digunakan sebagai default. Untuk semua parameter lainnya, Anda dapat secara eksplisit menetapkan nilai, atau membiarkan sistem menentukan nilai optimal dengan tidak menentukan parameter sama sekali atau menyetelnya ke AAUDIO_UNSPECIFIED.

    Untuk lebih amannya, periksa status stream 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 stream dibuat, 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 stream dan perangkat Android yang menjalankan stream tersebut. Sebagai upaya pemrograman defensif yang baik, sebaiknya periksa konfigurasi stream 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 lagi 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 stream 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 stream 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, stream harus segera memasuki status sementara Menjeda, dan nanti sampai dalam status Dijeda - meski tidak ada jaminan akan demikian. 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 stream 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 stream 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 stream akan dihapus segera setelah ditutup. Dan jangan memanggil AAudioStream_close() selagi waitForStateChange() berjalan di thread lain.

Membaca dan menulis ke streaming audio

Setelah streaming dimulai, Anda dapat membaca atau menulis padanya menggunakan fungsi AAudioStream_read(stream, buffer, numFrames, timeoutNanos) dan AAudioStream_write(stream, buffer, numFrames, timeoutNanos).

Untuk operasi baca/tulis yang bersifat memblokir, yang mentransfer sejumlah frame yang ditentukan, setel timeoutNanos ke 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 bisa 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 stream sebelum memulai stream 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 tersambung (misalnya saat headphone dicabut).
  • Terjadi error secara internal.
  • Perangkat audio tidak lagi menjadi perangkat audio utama.

Jika streaming terputus, statusnya akan menjadi "Terputus" dan upaya apa pun untuk mengeksekusi write() atau fungsi lainnya akan menampilkan AAUDIO_ERROR_DISCONNECTED. Jika stream terputus, Anda hanya dapat menutupnya.

Jika Anda ingin diberi tahu saat sambungan perangkat audio terputus, tulis fungsi AAudioStream_errorCallback dan daftarkan menggunakan AAudioStreamBuilder_setErrorCallback().

Callback harus memeriksa status stream seperti yang ditunjukkan dalam contoh berikut. Sebaiknya Anda tidak menutup atau membuka kembali stream dari callback; sebagai gantinya, gunakan thread lain. Perlu diperhatikan bahwa jika Anda membuka stream baru, stream tersebut mungkin memiliki karakteristik yang berbeda dengan stream asal (misalnya framesPerBurst):

void errorCallback(AAudioStream *stream,
                       void *userData,
                       aaudio_result_t error){

      aaudio_stream_state_t streamState = AAudioStream_getState(stream);
      if (streamState == AAUDIO_STREAM_STATE_DISCONNECTED){
        // Handle stream disconnect on a separate thread
        ...
      }
    }
    

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 menetapkan kapasitas ini. Metode ini membatasi kapasitas yang dapat Anda alokasikan ke jumlah maksimum yang diizinkan oleh perangkat. Gunakan AAudioStream_getBufferCapacityInFrames() untuk memastikan 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 sebuah stream.

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 stream input. Stream 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, stream 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 stream untuk mendaftarkan callback:

AAudioStreamBuilder_setDataCallback(builder, myCallback, myUserData);
    

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

Fungsi callback tidak boleh menjalankan operasi baca/tulis pada stream yang mengaktifkannya. Jika callback termasuk dalam stream input, kode Anda harus memproses data yang diberikan dalam buffer audioData (yang ditentukan sebagai argumen ketiga). Jika callback tersebut termasuk dalam stream output, kode harus Anda 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;
    }
    

Pemrosesan lebih dari satu stream dimungkinkan menggunakan AAudio. Anda dapat menggunakan satu stream sebagai master, dan meneruskan pointer ke stream lain dalam data pengguna. Daftarkan callback untuk stream 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. Ini karena AAudio menghindari penggunaan mutex, yang dapat menyebabkan penghentian thread untuk sementara dan gangguan.

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