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.

AAudio API bersifat minimal sesuai desainnya, dan tidak melakukan fungsi ini:

  • Enumerasi perangkat audio
  • Perutean otomatis antara endpoint audio
  • File I/O
  • Dekode audio yang dikompresi
  • Penyajian otomatis semua masukan/streaming dalam satu callback.

Streaming audio

AAudio memindahkan data audio antara masukan dan keluaran aplikasi dan audio di perangkat Android. Aplikasi meneruskan data ke dalam dan ke luar dengan membaca dari dan menulis ke streaming audio, yang direpresentasikan oleh AAudioStream struktur. Pengaktifan read/write dapat memblokir atau tidak memblokir.

Streaming ditentukan oleh berikut ini:

  • Perangkat audio yang merupakan sumber atau sink untuk data dalam streaming.
  • Mode berbagi yang menentukan apakah streaming memiliki akses eksklusif ke perangkat audio yang mungkin dibagikan di antara berbagai streaming.
  • Format data audio dalam streaming.

Perangkat audio

Tiap streaming dilampirkan ke satu perangkat audio.

Perangkat audio adalah antarmuka hardware atau endpoint viertual yang bertindak sebagai sumber atau sink untuk streaming data audio digital yang berkelanjutan. Jangan merancukan perangkat audio (mic atau headset bluetooth built-in) dengan perangkat Android (ponsel atau jam tangan) yang menjalankan aplikasi.

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

Tiap perangkat audio memiliki ID unik di perangkat Android. Anda dapat menggunakan ID untuk mengaitkan streaming audio ke perangkat audio tertentu. Akan tetapi, biasanya Anda dapat mengizinkan AAudio memilih perangkat primer default daripada menentukannya sendiri.

Perangkat audio yang dilampirkan ke streaming menentukan apakah streaming untuk masukan atau keluaran. Streaming hanya dapat memindahkan data dalam satu arah. Saat menentukan streaming, Anda juga menyetel arahnya. Saat Anda membuka streaming, Android memeriksa untuk memastikan bahwa perangkat audio dan arah streaming sesuai.

Mode berbagi

Streaming memiliki mode berbagi:

  • AAUDIO_SHARING_MODE_EXCLUSIVE artinya streaming memiliki akses eksklusif ke perangkat audionya; perangkat tidak dapat digunakan oleh streaming audio lain. Jika perangkat audio sudah digunakan, streaming tidak mungkin memiliki akses eksklusif. Streaming eksklusif mungkin memiliki latensi yang lebih rendah, namun juga lebih mungkin terputus sambungannya. Sebaiknya tutup streaming eksklusif begitu Anda tidak memerlukannya, agar aplikasi lain dapat mengakses perangkat. Streaming eksklusif menyediakan latensi terendah yang memungkinkan.
  • AAUDIO_SHARING_MODE_SHARED memungkinkan AAudio mencampur audio. AAudio mencampur semua streaming bersama yang ditentukan untuk 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 streaming memiliki atribut audio digital biasa. Atribut tersebut sebagai berikut:

  • Format sampel
  • Sampel per frame
  • Frekuensi sampel

AAudio mengizinkan format sampel ini:

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 to +1.0

AAudio mungkin melakukan konversi sampel sendiri. Misalnya, jika aplikasi menulis data FLOAT, namun HAL menggunakan PCM_I16, AAudio mungkin mengonversi sampel secara otomatis. Konversi dapat terjadi dalam salah satu arah. Jika aplikasi memproses masukan audio, sebaiknya verifikasi format masukan dan bersiap mengonversi data jika diperlukan, seperti di 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. Setel konfigurasi streaming audio di builder, menggunakan fungsi builder yang sesuai dengan parameter streaming. 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 konstan yang tidak ditentukan atau nilai di luar rentang.

    Jika Anda tidak menentukan ID perangkat, defaultnya adalah perangkat keluaran primer. Jika Anda tidak menentukan arah streaming, defaultnya adalah streaming keluaran. Untuk semua parameter lainnya, Anda dapat secara eksplisit menyetel nilai, atau membiarkan sistem menentukan nilai optimal dengan tidak menentukan parameter sama sekali atau menyetelnya ke AAUDIO_UNSPECIFIED.

    Agar aman, periksa status streaming audio setelah Anda membuatnya, seperti dijelaskan di langkah 4 di bawah.

  3. Jika AAudioStreamBuilder dikonfigurasi, gunakan untuk membuat streaming:

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

  4. Setelah membuat streaming, verifikasi konfigurasinya. Jika Anda menentukan format sampel, frekuensi sampel, atau sampel per frame, konfigurasinya tidak akan berubah. Jika Anda menentukan mode berbagi atau kapasitas buffer, mungkin berubah bergantung pada kemampuan perangkat audio streaming dan perangkat Android yang menjalankannya. Untuk pemrograman defensif yang baik, sebaiknya periksa konfigurasi streaming sebelum menggunakannya. Ada fungsi untuk mendapatkan setelan streaming yang sesuai dengan setelan tiap 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 masa mendatang untuk membuat streaming lainnya. Namun, jika Anda tidak berencana menggunakannya lagi, sebaiknya hapus.

    AAudioStreamBuilder_delete(builder);
    

Menggunakan streaming audio

Transisi keadaan

Streaming AAudio biasanya berada dalam lima keadaan stabil (keadaan error, Terputus, dijelaskan di akhir bagian ini):

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

Data hanya mengalir melalui streaming jika streaming dalam keadaan Dimulai. Untuk memindahkan streaming dari satu keadaan ke keadaan lainnya, gunakan salah satu fungsi yang meminta transisi keadaan:

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 keluaran:

Fungsi ini asinkron, dan perubahan keadaan tidak terjadi dengan segera. Jika Anda meminta perubahan keadaan, streaming memindahkan salah satu keadaan sementara yang sesuai.

  • Memulai
  • Menjeda
  • Flushing
  • Berhenti
  • Menutup

Diagram keadaan di bawah menampilkan keadaan stabil sebagai persegi panjang bulat, dan keadaan sementara sebagai persegi panjang bertitik. Meski tidak ditampilkan, Anda dapat mengaktifkan close() dari keadaan mana saja

Siklus Hidup AAudio

AAudio tidak memberikan callback untuk memperingatkan Anda tentang perubahan keadaan. Satu fungsi khusus, AAudioStream_waitForStateChange(stream, inputState, nextState, timeout) dapat digunakan untuk menunggu perubahan keadaan.

Fungsi tersebut tidak mendeteksi perubahan keadaan sendiri, dan tidak menunggu keadaan tertentu. Fungsi tersebut menunggu hingga keadaan saat ini berbeda dari inputState, yang Anda tentukan.

Misalnya, setelah meminta untuk dijeda, streaming harus segera masuk keadaan sementara Menjeda, dan nanti tiba dalam keadaan Dijeda - meski tidak ada jaminan demikian. Karena Anda tidak dapat menunggu keadaan Dijeda, gunakan waitForStateChange() untuk menunggu keadaan apa saja 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 keadaan streaming bukan Menjeda (inputState, yang kita anggap sebagai keadaan saat ini pada waktu pengaktifan), fungsi ditampilkan segera. Jika tidak, akan diblokir hingga keadaan tidak lagi Menjeda atau waktu tunggu habis. Jika fungsi ditampilkan, parameter nextState menunjukkan keadaan streaming saat ini.

Anda dapat menggunakan teknik yang sama ini setelah mengaktifkan permintaan mulai, berhenti, atau flush, menggunakan keadaan sementara yang sesuai sebagai keadaan masukan. Jangan aktifkan waitForStateChange() setelah mengaktifkan AAudioStream_close() karena streaming akan dihapus segera setelah ditutup. Dan jangan aktifkan AAudioStream_close() saat waitForStateChange() sedang berjalan di thread lain.

Membaca dan menulis ke streaming audio

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

Untuk membaca atau menulis yang bersifat memblokir, yang mentransfer jumlah frame yang ditentukan, setel timeoutNanos lebih besar dari nol. Untuk pengaktifkan yang tidak memblokir, setel timeoutNanos ke nol. Dalam hal ini, hasilnya adalah jumlah sebenarnya frame yang ditransfer.

Jika Anda membaca masukan, sebaiknya verifikasi bahwa jumlah frame yang tepat dibaca. Jika tidak, buffer mungkin berisi data yang tidak diketahui, 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 dengan menulis data atau kesenyapan ke dalamnya. Ini harus dilakukan dalam pengaktifkan yang tidak memblokir dengan timeoutNanos disetel ke nol.

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

Menutup streaming audio

Jika Anda sudah selesai menggunakan streaming, silakan tutup:

AAudioStream_close(stream);

Setelah menutup streaming, Anda tidak dapat menggunakannya dengan fungsi berbasis streaming AAudio.

Streaming audio yang terputus

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

  • Perangkat audio terkait tidak tersambung lagi (misalnya, saat headphone tidak dicolokkan).
  • Error terjadi secara internal.
  • Perangkat audio tidak lagi menjadi perangkat audio primer.

Jika streaming terputus, keadaannya menjadi "Terputus" dan upaya untuk mengeksekusi write() atau fungsi lain menampilkan AAUDIO_ERROR_DISCONNECTED. Jika streaming terputus, Anda hanya dapat menutupnya.

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

Callback harus memeriksa keadaan streaming seperti ditampilkan di contoh berikut. Anda sebaiknya tidak menutup atau membuka kembali streaming dari callback, gunakan thread lain. Perlu diperhatikan bahwa jika Anda membuka streaming baru, streaming tersebut mungkin memiliki karakteristik berbeda dari streaming 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.

Catatan: Jangan merancukan buffer internal AAudio dengan parameter buffer fungsi menulis dan membaca dari streaming AAudio.

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

Aplikasi tidak harus menggunakan seluruh kapasitas buffer. AAudio mengisi buffer hingga ukuran yang dapat Anda setel. Ukuran buffer tidak dapat 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 mengubah ukuran buffer.

Saat aplikasi memutarkan audio, aplikasi menulis ke buffer dan blok hingga menulis 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 burst 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 beberapa kali dari ukuran burst yang dilaporkan.

      Buffering AAudio

Salah satu cara untuk mengoptimalkan ukuran buffer adalah memulai dengan buffer besar dan secara bertahap menurunkannya hingga memulai dengan proses yang sangat kecil, lalu menaikkannya kembali. Selain itu, Anda dapat memulai dengan ukuran buffer kecil dan jika buffer tersebut menghasilkan proses yang sangat kecil, tingkatkan ukuran buffer hingga keluarannya mengalir dengan bersih lagi.

Proses ini dapat terjadi sangat cepat, mungkin sebelum pengguna memutar bunyi pertama. Anda dapat 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 dapat melakukannya secara berkelanjutan saat 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);
        }
    }
}

Tidak ada manfaat menggunakan teknik ini untuk mengoptimalkan ukuran buffer bagi streaming masukan. Streaming masukan berjalan secepat mungkin, mencoba meminimalkan jumlah data buffer, lalu mengisinya jika aplikasi sudah di-preempt.

Menggunakan callback prioritas tinggi

Jika aplikasi membaca atau menulis data audio dari thread biasa, aplikasi tersebut mungkin di-preemp atau mengalami jitter penentuan waktu. Ini dapat menyebabkan gangguan audio. Penggunaan buffer besar mungkin melindungi dari gangguan tersebut, namun 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 pada 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 secara berkala mengeksekusi fungsi callback untuk mendapatkan data bagi burst berikutnya.

Fungsi callback seharusnya tidak melakukan membaca atau menulis pada streaming yang mengaktifkannya. Jika callback termasuk ke dalam streaming masukan, kode harus memproses data yang diberikan dalam buffer audioData (ditentukan sebagai argumen ketiga). Jika callback termasuk ke dalam streaming keluaran, kode harus menempatkan data ke buffer.

Misalnya, Anda dapat menggunakan callback untuk membuat keluaran sine wave 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;
}

Dimungkinkan untuk 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 streaming lain. Berikut contoh callback dua arah yang meneruskan streaming masukan ke streaming keluaran. Streaming yang mengaktifkan master adalah streaming keluaran. Streaming masukan disertakan di data pengguna.

Callback melakukan pembacaan yang tidak memblokir dari streaming masukan yang menempatkan data ke buffer streaming keluaran:

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 di contoh ini diasumsikan bahwa streaming keluaran dan masukan memiliki jumlah channel, format, dan frekuensi sampel yang sama. Format streaming dapat tidak sesuai - selama kode menangani terjemahan dengan tepat.

Menyetel mode performa

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

  • AAUDIO_PERFORMANCE_MODE_NONE adalah mode default. Mode ini menggunakan streaming dasar yang menyeimbangkan latensi dan penghematan daya.
  • AAUDIO_PERFORMANCE_MODE_LOW_LATENCY menggunakan buffer yang lebih kecil dan lokasi data yang dioptimalkan untuk penurunan latensi.
  • AAUDIO_PERFORMANCE_MODE_POWER_SAVING menggunakan buffer internal yang lebih besar dan lokasi data yang menyeimbangkan latensi untuk daya yang lebih rendah.

Anda dapat memilih mode performa dengan mengaktifkan setPerformanceMode(), dan menemukan mode saat ini dengan mengaktifkan getPerformanceMode().

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

Jika menghemat daya lebih penting daripada latensi rendah di aplikasi, gunakan AAUDIO_PERFORMANCE_MODE_POWER_SAVING. Ini hal umum untuk aplikasi yang memutar musik yang dibuat sebelumnya, seperti pemutar audio streaming atau file MIDI.

Di versi AAudio saat ini, untuk mencapai latensi terendah yang memungkinkan, 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 mengaktifkan beberapa fungsi AAudio secara serentak dari lebih dari satu thread pada satu waktu. Ini karena AAudio menghindari penggunaan mutex, yang dapat menyebabkan preemption thread dan gangguan.

Agar aman, jangan aktifkan AAudioStream_waitForStateChange() atau baca atau tulis ke streaming yang sama dari dua thread berbeda. Selain itu, jangan tutup streaming dalam satu thread saat membaca atau menulis ke streaming dalam thread lain.

Pengaktifkan yang menampilkan setelan streaming, seperti AAudioStream_getSampleRate() dan AAudioStream_getChannelCount(), aman untuk thread.

Pengaktifan ini juga aman untuk thread:

  • AAudio_convert*ToText()
  • AAudio_createStreamBuilder()
  • AAudioStream_get*() except for AAudioStream_getTimestamp()

Catatan: Jika streaming menggunakan fungsi callback, makan aman untuk membaca/menulis dari thread callback sambil juga menutup streaming dari thread yang menjalankannya.

Sampel kode

Dua apikasi demo AAudio kecil tersedia di halaman GitHub kami:

  • Hello-Audio menghasilkan sine wave dan memutar audio.
  • Echo menunjukkan cara mengimplementasikan loop audio dua arah ke dalam/luar. Ini menggunakan fungsi callback yang menyinkronkan dua streaming, dan melakukan penyesuaian buffer yang berkelanjutan.

Untuk informasi selengkapnya tentang mencapai latensi keluaran optimal dan menghindari gangguan audio menggunakan OpenSL ES, lihat Simple Synth.

Masalah umum

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