AAudio, Android O sürümünde kullanıma sunulan yeni bir Android C API'sidir. Düşük gecikme gerektiren yüksek performanslı ses uygulamaları için tasarlanmıştır. Uygulamalar, akışlara veri okuyup yazarak AAudio ile iletişim kurar.
AAudio API, tasarım gereği minimum düzeydedir ve aşağıdaki işlevleri gerçekleştirmez:
- Ses cihazı numaralandırması
- Ses uç noktaları arasında otomatik yönlendirme
- Dosya G/Ç
- Sıkıştırılmış sesin kodunu çözme
- Tek bir geri çağırma işlevinde tüm girişlerin/akışların otomatik olarak sunulması.
Başlarken
AAudio'yu C++ kodundan çağırabilirsiniz. AAudio özellik grubunu uygulamanıza eklemek için AAudio.h başlık dosyasını ekleyin:
#include <aaudio/AAudio.h>
Ses yayınları
AAudio, ses verilerini uygulamanız ile Android cihazınızdaki ses girişleri ve çıkışları arasında taşır. Uygulamanız, AAudioStream yapısıyla temsil edilen ses akışlarından veri okuyup yazarak veri aktarır. Okuma/yazma çağrıları engelleyici veya engellemeyen olabilir.
Akış şu şekilde tanımlanır:
- Akıştaki verilerin kaynağı veya hedefi olan ses cihazı.
- Bir yayının, birden fazla yayın arasında paylaşılabilen bir ses cihazına özel erişimi olup olmadığını belirleyen paylaşım modu.
- Akıştaki ses verilerinin biçimi.
Ses cihazı
Her yayın tek bir ses cihazına bağlıdır.
Ses cihazı, sürekli bir dijital ses verisi akışı için kaynak veya alıcı görevi gören bir donanım arayüzü veya sanal uç noktadır. Ses cihazını (yerleşik mikrofon veya Bluetooth mikrofonlu kulaklık) uygulamanızı çalıştıran Android cihazla (telefon veya kol saati) karıştırmayın.
Android cihazınızda kullanılabilen ses cihazlarını keşfetmek için AudioManager
yöntemini getDevices()
kullanabilirsiniz. Yöntem, her cihazın type
hakkında bilgi döndürür.
Her ses cihazının Android cihazda benzersiz bir kimliği vardır. Bir ses akışını belirli bir ses cihazına bağlamak için kimliği kullanabilirsiniz. Ancak çoğu durumda, kendiniz belirtmek yerine varsayılan birincil cihazı AAudio'nun seçmesine izin verebilirsiniz.
Bir akışa bağlı ses cihazı, akışın giriş mi yoksa çıkış için mi olduğunu belirler. Akışlar yalnızca bir yönde veri taşıyabilir. Bir akışı tanımlarken yönünü de ayarlarsınız. Bir yayını açtığınızda Android, ses cihazının ve yayın yönünün eşleşip eşleşmediğini kontrol eder.
Paylaşım modu
Akışların bir paylaşım modu vardır:
AAUDIO_SHARING_MODE_EXCLUSIVE
, yayının ses cihazına özel erişimi olduğu anlamına gelir. Cihaz başka bir ses akışı tarafından kullanılamaz. Ses cihazı zaten kullanılıyorsa yayının özel erişimi olmayabilir. Özel yayınların gecikmesi daha düşüktür ancak bağlantının kesilmesi olasılığı da daha yüksektir. Diğer uygulamaların cihaza erişebilmesi için artık ihtiyaç duymadığınız özel yayınları hemen kapatmanız gerekir. Özel yayınlar mümkün olan en düşük gecikmeyi sağlar.AAUDIO_SHARING_MODE_SHARED
, AAudio'nun sesleri karıştırmasına izin verir. AAudio, aynı cihaza atanan tüm paylaşılan akışları karıştırır.
Akış oluştururken paylaşım modunu açıkça ayarlayabilirsiniz. Varsayılan paylaşım modu SHARED
'tür.
Ses biçimi
Bir akış üzerinden iletilen veriler, normal dijital ses özelliklerine sahiptir. Bunlar aşağıdaki gibidir:
- Örnek veri biçimi
- Kanal sayısı (kare başına örneklem)
- Örnek hızı
AAudio şu örnek biçimlerine izin verir:
aaudio_format_t | C veri türü | Notlar |
---|---|---|
AAUDIO_FORMAT_PCM_I16 | int16_t | yaygın 16 bit örnekler, Q0,15 biçimi |
AAUDIO_FORMAT_PCM_FLOAT | float | -1,0 ile +1,0 arası |
AAUDIO_FORMAT_PCM_I24_PACKED | 3'lü gruplar halinde uint8_t | paketlenmiş 24 bit örnekler, Q0.23 biçimi |
AAUDIO_FORMAT_PCM_I32 | int32_t | yaygın 32 bit örnekler, Q0.31 biçimi |
AAUDIO_FORMAT_IEC61937 | uint8_t | HDMI veya S/PDIF geçişi için IEC61937'ye sarmalanmış sıkıştırılmış ses |
Belirli bir örnek biçim isterseniz cihaz için en uygun biçim olmasa bile yayın bu biçimi kullanır. Örnek biçimi belirtmezseniz AAudio en uygun olanı seçer. Akış açıldıktan sonra örnek veri biçimini sorgulamanız ve ardından gerekirse verileri dönüştürmeniz gerekir. Bu örnekte gösterildiği gibi:
aaudio_format_t dataFormat = AAudioStream_getDataFormat(stream);
//... later
if (dataFormat == AAUDIO_FORMAT_PCM_I16) {
convertFloatToPcm16(...)
}
Ses akışı oluşturma
AAudio kitaplığı, yapıcı tasarım kalıbını izler ve AAudioStreamBuilder sağlar.
- AAudioStreamBuilder oluşturun:
AAudioStreamBuilder *builder; aaudio_result_t result = AAudio_createStreamBuilder(&builder);
- Akış parametrelerine karşılık gelen oluşturucu işlevlerini kullanarak oluşturucuda ses akışı yapılandırmasını ayarlayın. Aşağıdaki isteğe bağlı ayar işlevleri kullanılabilir:
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);
Bu yöntemlerin, tanımlanmamış sabit veya aralık dışında değer gibi hataları bildirmediğini unutmayın.
deviceId belirtilmezse varsayılan olarak birincil çıkış cihazı kullanılır. Akış yönünü belirtmezseniz varsayılan olarak çıkış akışı kullanılır. Diğer tüm parametreler için açıkça bir değer ayarlayabilir veya parametreyi hiç belirtmeden ya da
AAUDIO_UNSPECIFIED
olarak ayarlayarak sistemin optimum değeri atamasına izin verebilirsiniz.Güvende olmak için, oluşturduğunuz ses akışının durumunu aşağıdaki 4. adımda açıklandığı şekilde kontrol edin.
- AAudioStreamBuilder yapılandırıldığında, akış oluşturmak için kullanın:
AAudioStream *stream; result = AAudioStreamBuilder_openStream(builder, &stream);
- Akış oluşturulduktan sonra yapılandırmasını doğrulayın. Örnek biçimi, örnek hızı veya kare başına örnek sayısı gibi ayarlar değişmez. Paylaşım modunu veya arabelleğe alma kapasitesini belirttiyseniz bu ayarlar, yayının ses cihazının ve çalıştırıldığı Android cihazın özelliklerine bağlı olarak değişebilir. İyi bir savunma programlama gereği olarak, kullanmadan önce yayının yapılandırmasını kontrol etmeniz gerekir. Her oluşturucu ayarına karşılık gelen yayın ayarını almak için işlevler vardır:
- Oluşturucuyu kaydedip daha fazla yayın oluşturmak için gelecekte yeniden kullanabilirsiniz. Ancak artık kullanmayı planlamıyorsanız hesabınızı silmeniz gerekir.
AAudioStreamBuilder_delete(builder);
Ses akışı kullanma
Durum geçişleri
AAudio aktarımı genellikle beş kararlı durumdan birinde olur (Bağlantı Kesildi hata durumu bu bölümün sonunda açıklanmıştır):
- Aç
- Başladı
- Duraklatıldı
- Kızarmış yüz
- Durduruldu
Veriler yalnızca yayın Başladı durumundayken akış üzerinden aktarılır. Bir akışı eyaletler arasında taşımak için durum geçişi isteyen işlevlerden birini kullanın:
aaudio_result_t result;
result = AAudioStream_requestStart(stream);
result = AAudioStream_requestStop(stream);
result = AAudioStream_requestPause(stream);
result = AAudioStream_requestFlush(stream);
Yalnızca bir çıkış akışında duraklatma veya temizleme isteğinde bulunabileceğinizi unutmayın:
Bu işlevler asenkrondur ve durum değişikliği hemen gerçekleşmez. Durum değişikliği isteğinde bulunduğunuzda akış, aşağıdaki geçici durumlardan birine taşınır:
- Başlatılıyor
- Duraklatma
- Flushing
- Durduruluyor
- Kapanma
Aşağıdaki durum diyagramında kararlı durumlar yuvarlak dikdörtgenler, geçici durumlar ise noktalı dikdörtgenler olarak gösterilmiştir.
Gösterilmese de close()
'ü herhangi bir eyaletten arayabilirsiniz
AAudio, durum değişiklikleri konusunda sizi uyarmak için geri çağırma işlevi sağlamaz. Durum değişikliğini beklemek için AAudioStream_waitForStateChange(stream, inputState, nextState, timeout)
adlı özel işlev kullanılabilir.
İşlev, durum değişikliğini kendi başına algılamaz ve belirli bir durumu beklemez. Mevcut durum, belirttiğiniz inputState
değerinden farklı olana kadar bekler.
Örneğin, duraklatma isteğinde bulunulan bir akış hemen Duraklatılıyor geçici durumuna girer ve bir süre sonra Duraklatıldı durumuna gelir. Ancak bu durumun gerçekleşeceği garanti edilmez.
Duraklatıldı durumunu bekleyemezsiniz. Duraklatılıyor dışındaki bir durumu beklemek için waitForStateChange()
simgesini kullanın. Bunu nasıl yapacağınız aşağıda açıklanmıştır:
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);
Akış duraklatılmış durumda değilse (inputState
, çağrı sırasındaki mevcut durum olarak varsaydığımız durum) işlev hemen döndürülür. Aksi takdirde, durum Duraklatılıyor olmadığı veya zaman aşımı sona erene kadar engellenir. İşlev döndürüldüğünde nextState
parametresi, aktarımın mevcut durumunu gösterir.
inputState olarak ilgili geçici durumu kullanarak request start, stop veya flush işlevini çağırdıktan sonra aynı tekniği kullanabilirsiniz. Akış kapatıldıktan hemen sonra silineceği için AAudioStream_close()
'u aradıktan sonra waitForStateChange()
'ü aramayın. Ayrıca, waitForStateChange()
başka bir iş parçacığında çalışırken AAudioStream_close()
işlevini çağırmayın.
Ses akışına okuma ve yazma
Başlatılan bir akıştaki verileri işlemenin iki yolu vardır:
- Yüksek öncelikli geri arama kullanın.
AAudioStream_read(stream, buffer, numFrames, timeoutNanos)
veAAudioStream_write(stream, buffer, numFrames, timeoutNanos)
işlevlerini kullanın. akışları okumak veya yazmak için.
Belirtilen sayıda kareyi aktaran engelleyen bir okuma veya yazma için timeoutNanos değerini sıfırdan büyük ayarlayın. Engellemeyen bir çağrı için timeoutNanos değerini sıfıra ayarlayın. Bu durumda sonuç, aktarılan gerçek kare sayısıdır.
Giriş bilgisini okurken doğru sayıda karenin okunduğunu doğrulamanız gerekir. Aksi takdirde, arabelleğe alınan veriler ses kesintilerine neden olabilecek bilinmeyen veriler içerebilir. Sessiz bir kesinti oluşturmak için arabelleği sıfırlarla doldurabilirsiniz:
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);
}
Akışa başlamadan önce veri veya sessizlik yazarak akış arabelleğinin önünü doldurabilirsiniz. Bu işlem, timeoutNanos sıfır olarak ayarlanmış, engellenmeyen bir çağrıda yapılmalıdır.
Arabellekteki veriler, AAudioStream_getDataFormat()
tarafından döndürülen veri biçimiyle eşleşmelidir.
Ses akışını kapatma
Bir yayını kullanmayı tamamladığınızda yayını kapatın:
AAudioStream_close(stream);
Bir akışı kapattıktan sonra akış işaretçisini AAudio akış tabanlı işlevlerle kullanamazsınız.
Bir akışı kapatmak, mesaj dizisinde güvenli değildir. Bir ileti dizisindeki yayını kullanırken başka bir ileti dizisindeki yayını KAPATMAYA ÇALIŞMAYIN. Birden fazla mesaj dizisi kullanıyorsanız bunlar dikkatlice senkronize edilmelidir. Tüm veri akışı işleme kodunuzu tek bir iş parçacığına yerleştirip ardından atomik bir sıra kullanarak komut gönderebilirsiniz.
Ses akışının bağlantısı kesildi
Aşağıdaki etkinliklerden biri gerçekleşirse ses akışının bağlantısı herhangi bir zamanda kesilebilir:
- İlişkili ses cihazı artık bağlı değilse (ör. kulaklığın fişi çekildiğinde).
- Dahili olarak bir hata meydana gelir.
- Ses cihazı artık birincil ses cihazı değil.
Bir akış bağlantısı kesildiğinde "Bağlı değil" durumuna geçer ve AAudioStream_write() veya diğer işlevleri yürütme girişimleri hata döndürür. Hata koduna bakılmaksızın, bağlantısı kesilen bir yayını her zaman durdurup kapatmanız gerekir.
Doğrudan okuma/yazma yöntemlerinden birinin yerine veri geri çağırma kullanıyorsanız akış bağlantısı kesildiğinde herhangi bir dönüş kodu almazsınız. Bu durum gerçekleştiğinde bilgilendirilmek için bir AAudioStream_errorCallback işlevi yazın ve AAudioStreamBuilder_setErrorCallback() kullanarak kaydedin.
Bağlantının kesildiğine dair bildirim bir hata geri çağırma mesaj dizisinde gönderilirse akışın durdurulması ve kapatılması başka bir mesaj dizisinden yapılmalıdır. Aksi takdirde kilitlenmeyle karşılaşabilirsiniz.
Yeni bir yayın açtığınızda orijinal yayından farklı ayarlara (ör. framesPerBurst) sahip olabileceğini unutmayın:
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.
}
Performansı optimize etme
Dahili arabelleklerini ayarlayarak ve özel yüksek öncelikli iş parçacıkları kullanarak bir ses uygulamasının performansını optimize edebilirsiniz.
Gecikmeyi en aza indirmek için arabellekleri ayarlama
AAudio, her ses cihazı için bir tane olmak üzere, yönettiği dahili arabellekleri kullanarak verileri aktarır.
Arabelleğin kapasitesi, bir arabelleğin tutabileceği toplam veri miktarıdır. Kapasiteyi ayarlamak için AAudioStreamBuilder_setBufferCapacityInFrames()
numaralı telefonu arayabilirsiniz. Bu yöntem, ayırabileceğiniz kapasiteyi cihazın izin verdiği maksimum değerle sınırlandırır. Arabelleğin gerçek kapasitesini doğrulamak için AAudioStream_getBufferCapacityInFrames()
simgesini kullanın.
Uygulamaların, arabelleğin tüm kapasitesini kullanması gerekmez. AAudio, bir arabelleği ayarlayabileceğiniz bir boyuta kadar doldurur. Arabelleğin boyutu, kapasitesinden büyük olamaz ve genellikle daha küçüktür. Arabellek boyutunu kontrol ederek, arabelleği doldurmak için gereken paket sayısına karar verir ve böylece gecikmeyi kontrol edersiniz. Arabellek boyutuyla çalışmak için AAudioStreamBuilder_setBufferSizeInFrames()
ve AAudioStreamBuilder_getBufferSizeInFrames()
yöntemlerini kullanın.
Bir uygulama ses oynatırken bir arabelleğe yazar ve yazma işlemi tamamlanana kadar engeller. AAudio, arabellekten ayrı paketler halinde veri okur. Her paket birden fazla ses çerçevesi içerir ve genellikle okunmakta olan arabelleğin boyutundan daha küçüktür. Sistem, paket boyutunu ve hızını kontrol eder. Bu özellikler genellikle ses cihazının devresi tarafından belirlenir. Bir paketin boyutunu veya paket hızını değiştiremeseniz de dahili arabelleğin boyutunu, içerdiği paket sayısına göre ayarlayabilirsiniz. Genellikle, AAudioStream'inizin arabellek boyutu, bildirilen artımlı boyutun bir katıysa en düşük gecikmeyi elde edersiniz.
Arabellek boyutunu optimize etmenin bir yolu, büyük bir arabellekle başlayıp eksik okumalar başlayana kadar arabelleği kademeli olarak azaltmak ve ardından tekrar yükseltmektir. Alternatif olarak, küçük bir arabelleğe alma boyutuyla başlayabilir ve bu durumda eksik veri aktarımı oluşursa çıkış tekrar düzgün bir şekilde akmaya başlayana kadar arabelleğe alma boyutunu artırabilirsiniz.
Bu işlem çok hızlı bir şekilde, hatta kullanıcı ilk sesi çalmadan önce gerçekleşebilir. Kullanıcının ses kesintisi duymaması için ilk arabellek boyutlandırmasını sessiz kullanarak gerçekleştirmek isteyebilirsiniz. Sistem performansı zaman içinde değişebilir (ör. kullanıcı uçak modunu kapatabilir). Arabellek ayarı çok az ek yük oluşturduğundan uygulamanız, bir akışa veri okurken veya yazarken bunu sürekli olarak yapabilir.
Aşağıda, arabellek optimizasyon döngüsü örneği verilmiştir:
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);
}
}
}
Giriş akışının arabellek boyutunu optimize etmek için bu tekniğin kullanılmasının bir avantajı yoktur. Giriş akışları, arabelleğe alınan veri miktarını en aza indirmeye çalışarak mümkün olduğunca hızlı çalışır ve uygulama öncelik verildiğinde doldurulur.
Yüksek öncelikli geri arama kullanma
Uygulamanız normal bir iş parçacığından ses verileri okuyor veya yazıyorsa öncelikli hale getirilebilir ya da zamanlama sıçraması yaşayabilir. Bu durum, ses sorunlarına neden olabilir. Daha büyük arabellekler kullanmak bu tür hatalara karşı koruma sağlayabilir ancak büyük bir arabellek, ses gecikmesini de artırır. Düşük gecikmeye ihtiyaç duyan uygulamalarda ses akışı, uygulamanızla veri aktarmak için ayarsız geri çağırma işlevi kullanabilir. AAudio, geri çağırma işlevini daha iyi performansa sahip daha yüksek öncelikli bir iş parçacığında yürütür.
Geri çağırma işlevinin prototipi şu şekildedir:
typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(
AAudioStream *stream,
void *userData,
void *audioData,
int32_t numFrames);
Geri çağırma işlevini kaydetmek için akış oluşturma aracını kullanın:
AAudioStreamBuilder_setDataCallback(builder, myCallback, myUserData);
En basit durumda akış, bir sonraki patlamasının verilerini almak için geri çağırma işlevini düzenli olarak yürütür.
Geri çağırma işlevi, kendisini çağıran akışta okuma veya yazma işlemi gerçekleştirmemelidir. Geri çağırma bir giriş akışına aitse kodunuz, audioData arabelleğinde sağlanan verileri (üçüncü bağımsız değişken olarak belirtilir) işlemelidir. Geri çağırma bir çıkış akışına aitse kodunuz verileri arabelleğe yerleştirmelidir.
Örneğin, aşağıdaki gibi bir sinüs dalgası çıkışını sürekli olarak oluşturmak için geri çağırma işlevi kullanabilirsiniz:
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;
}
AAudio kullanılarak birden fazla akış işlenebiliyor. Ana veri akışı olarak bir veri akışı kullanabilir ve kullanıcı verilerindeki diğer veri akışlarına işaretçiler iletebilirsiniz. Ana akış için geri çağırma işlevi kaydedin. Ardından, diğer akışlarda engellenmeyen G/Ç kullanın. Aşağıda, bir giriş akışını çıkış akışına aktaran gidiş dönüş geri çağırma örneği verilmiştir. Ana arama akışı, çıkış akışıdır. Giriş akışı, kullanıcı verilerine dahil edilir.
Geri çağırma işlevi, verileri çıkış akışının arabelleğine yerleştirerek giriş akışından engellenmeyen bir okuma yapar:
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;
}
Bu örnekte, giriş ve çıkış akışlarının aynı sayıda kanala, biçime ve örnekleme hızına sahip olduğu varsayılmıştır. Kod, çevirileri düzgün şekilde ele aldığı sürece akışların biçimi uyuşmayabilir.
Performans modunu ayarlama
Her AAudioStream'in, uygulamanızın davranışı üzerinde büyük etkisi olan bir performans modu vardır. Üç mod vardır:
AAUDIO_PERFORMANCE_MODE_NONE
varsayılan moddur. Gecikme ve güç tasarrufunu dengeleyen temel bir akış kullanır.AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
, daha az gecikme için daha küçük arabellekler ve optimize edilmiş bir veri yolu kullanır.AAUDIO_PERFORMANCE_MODE_POWER_SAVING
, daha büyük dahili tamponlar ve daha düşük güç için gecikme süresini feda eden bir veri yolu kullanır.
setPerformanceMode()'yi çağırarak performans modunu seçebilir ve getPerformanceMode()'yi çağırarak mevcut modu öğrenebilirsiniz.
Uygulamanızda düşük gecikme süresi, güç tasarrufundan daha önemliyse AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
değerini kullanın.
Bu özellik, oyunlar veya klavye sentezleyiciler gibi çok etkileşimli uygulamalar için kullanışlıdır.
Uygulamanızda güç tasarrufu, düşük gecikmeden daha önemliyse AAUDIO_PERFORMANCE_MODE_POWER_SAVING
değerini kullanın.
Bu durum, önceden oluşturulmuş müzikleri çalan uygulamalarda (ör. akışlı ses veya MIDI dosyası oynatıcıları) yaygındır.
AAudio'nun mevcut sürümünde, mümkün olan en düşük gecikmeyi elde etmek için yüksek öncelikli bir geri çağırma işleviyle birlikte AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
performans modunu kullanmanız gerekir. Aşağıdaki örneğe uyun:
// 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);
Mesaj dizisi güvenliği
AAudio API tamamen iş parçacığı güvenli değildir. AAudio işlevlerinin bazılarını aynı anda birden fazla iş parçacığında eşzamanlı olarak çağıramazsınız. Bunun nedeni, AAudio'nun iş parçacığı önceliğine ve aksamalara neden olabilecek mutex'leri kullanmaktan kaçınmasıdır.
Güvende olmak için AAudioStream_waitForStateChange()
işlevini çağırmayın veya aynı akışı iki farklı iş parçacığından okuyup yazmayın. Benzer şekilde, bir mesaj dizisindeki bir akışı okurken veya başka bir mesaj dizisinde bu akışa yazarken kapatmayın.
AAudioStream_getSampleRate()
ve AAudioStream_getChannelCount()
gibi yayın ayarlarını döndüren çağrılar, iş parçacığı açısından güvenlidir.
Bu çağrılar ayrıca iş parçacığı açısından güvenlidir:
AAudio_convert*ToText()
AAudio_createStreamBuilder()
AAudioStream_getTimestamp()
hariçAAudioStream_get*()
Bilinen sorunlar
- Android O DP2 sürümü FAST kanalı kullanmadığı için write() işlevinin engellenmesi durumunda ses gecikmesi yüksektir. Daha düşük gecikme süresi elde etmek için geri çağırma işlevini kullanın.
Ek kaynaklar
Daha fazla bilgi edinmek için aşağıdaki kaynaklardan yararlanabilirsiniz: