UYARI: OpenSL ES desteği sonlandırılmıştır. Geliştiriciler, GitHub'da bulunan obua kitaplığını kullanabilirsiniz. Obua, Aaudio. Oboe, AAudio kullanılabilir olduğunda AAudio'yu çağırır ve AAudio kullanılamıyorsa OpenSL ES'ye geri döner.
Bu bölümdeki notlar, OpenSL ES 1.0.1 spesifikasyonlarına göz atın.
Nesneler ve arayüzü başlatma
OpenSL ES programlama modelinin yeni geliştiricilere aşina olmayabilecek iki yönü şunlardır: ve başlatma sırası arasındaki farkları ele alacağız.
Kısacası, OpenSL ES nesnesi şuradaki nesne kavramına benzerdir:
Java gibi programlama dilleri
ve C++ (OpenSL ES nesnesi yalnızca ilişkili arayüzleri aracılığıyla görünür olmalıdır).
Buna tüm nesneler için SLObjectItf
adlı ilk arayüz de dahildir.
Nesnenin tutma yeri yok
kendisi, yalnızca nesnenin SLObjectItf
arayüzüne ait bir tutma yeri.
İlk olarak bir OpenSL ES nesnesi oluşturulur. Bu işlem, SLObjectItf
, ardından
belirlemiştir. Bu, ilk önce bir proje başlatma belgesi oluşturmaya yönelik yaygın programlama kalıbına
nesne (bellek veya geçersiz parametreler dışında hiçbir zaman başarısız olması gerekmez) ve ardından
başlatma işlemi tamamlanır (kaynak yetersizliğinden dolayı başarısız olabilir). Gerçekleştirme adımı, gerekirse uygulamaya ek kaynaklar ayırmak için mantıklı bir yer sağlar.
Nesne oluşturma API'sinin parçası olarak uygulama, istenen arayüz dizisini belirtir. daha sonra satın almayı planlıyor. Bu dizinin otomatik olarak Arayüzleri edinme, bu yalnızca onları gelecekte edinme niyetini gösterir. Arayüzler aşağıdaki şekillerde ayırt edilir: dolaylı veya uygunsuz olabilir. Açık bir arayüz, dizide listelenmeli edinilir. Örtülü arayüzün nesne oluşturma dizisi, ancak onu burada listelemenin bir sakıncası yoktur. OpenSL ES, dinamik; nesnede belirtilmesi gerekmez dizi oluşturabilir ve eklenebilir. otomatik olarak eklenir. Android uygulaması, bu karmaşıklıktan kaçınmak için bir kolaylık özelliği sağlar. Bu özellik Nesne oluşturma sırasında dinamik arayüzler bölümünde açıklanmıştır.
Nesne oluşturulup gerçekleştirildikten sonra uygulama, ilk SLObjectItf
üzerinde GetInterface
kullanarak ihtiyaç duyduğu her özellik için arayüz edinmelidir.
Son olarak, nesne, arayüzleri aracılığıyla kullanılabilir ancak bazı nesneler yapmanız gerekir. Özellikle URI veri kaynağına sahip bir ses oynatıcının, bağlantı hatalarını algılayabilmesi için biraz daha hazırlık yapması gerekir. Bkz. Ayrıntılı bilgi için Ses çalar önceden getirme bölümüne bakın.
Uygulamanız nesneyle işlem bittikten sonra nesneyi açıkça yok etmeniz gerekir. Aşağıdaki Yok etme bölümüne bakın.
Ses çaların önceden getirilmesi
URI veri kaynağına sahip bir ses çalar için Object::Realize
, kaynakları ayırır ancak veri kaynağına bağlanmaz (hazırlanmaz) veya verileri önceden getirmeye başlamaz. Bunlar,
oynatıcı durumu SL_PLAYSTATE_PAUSED
veya SL_PLAYSTATE_PLAYING
olarak ayarlanır.
Bazı bilgiler bu sürecin nispeten sonuna kadar bilinmeyebilir. Özellikle, başlangıçta Player::GetDuration
SL_TIME_UNKNOWN
döndürür ve MuteSolo::GetChannelCount
, kanal sayısı sıfır olan başarılı bir sonuç veya SL_RESULT_PRECONDITIONS_VIOLATED
hata sonucunu döndürür. Bu API'ler uygun değerleri döndürür
yardımcı olur.
Başlangıçta bilinmeyen diğer özellikler arasında örnek hızı ve gerçek medya içeriği türü içeriğin başlığını incelemek veya uygulama tarafından belirtilen MIME türü ve kapsayıcı türü) olduğunu unutmayın. Bunlar daha sonra proje ekibinin ancak bunları önceden getirmesini geri yükleyebilirsiniz.
Önceden getirme durumu arayüzü, tüm bilgilerin ne zaman oluşturulacağını ve mevcutsa veya belirli aralıklarla yoklama yapabilir. MP3'lerin oynatma süresi gibi bazı bilgilerin hiçbir zaman bilinemeyeceğini unutmayın.
Önceden getirme durumu arayüzü, hataları tespit etmek için de yararlıdır. Geri arama kaydedin
ve
en az SL_PREFETCHEVENT_FILLLEVELCHANGE
ve SL_PREFETCHEVENT_STATUSCHANGE
etkinlikler. Bu etkinliklerin her ikisi de aynı anda yayınlanıyorsa ve PrefetchStatus::GetFillLevel
sıfır düzeyi bildiriyorsa, PrefetchStatus::GetPrefetchStatus
ise SL_PREFETCHSTATUS_UNDERFLOW
bildiriyorsa bu, veri kaynağında kurtarılamaz bir hata olduğunu gösterir. Ayrıca bu kişilerin
şuna bağlan:
veri kaynağına ilişkin ek açıklamaları görüntüleyin.
OpenSL ES'nin bir sonraki sürümünün, sırasındaki veri kaynağına da bakabilirsiniz. Bununla birlikte, gelecekteki ikili program uyumluluğu için, mevcut proje yönetimi metodolojilerini bir hata bildirme yöntemi kullanmanızı öneririz.
Özet olarak, önerilen kod sırası şu şekildedir:
Engine::CreateAudioPlayer
Object:Realize
SL_IID_PREFETCHSTATUS
içinObject::GetInterface
PrefetchStatus::SetCallbackEventsMask
PrefetchStatus::SetFillUpdatePeriod
PrefetchStatus::RegisterCallback
SL_IID_PLAY
içinObject::GetInterface
Play::SetPlayState
-SL_PLAYSTATE_PAUSED
veyaSL_PLAYSTATE_PLAYING
Not: Hazırlık ve önceden getirme burada gerçekleşir; bu süre zarfında geri arama düzenli durum güncellemeleri.
Yok Et
Uygulamanızdan çıkarken tüm nesneleri yok ettiğinizden emin olun. Nesneler şurada yok edilmeli: Herhangi bir bağımlı öğe içeren bir nesneyi yok etmek güvenli olmadığından, yaratılış sırasının tersi nesneler'i tıklayın. Örneğin, şu sırayla yok edin: ses çalarlar ve kaydediciler, çıkış mix'i ve sonra son olarak da motor.
OpenSL ES, otomatik atık toplamayı desteklemez veya
referans
arayüzlerin sayımı. Object::Destroy
adlı kişiyi aradıktan sonra, mevcut olanların hiçbiri
her bir ekip üyesinin
tanımsız hale gelir.
Android OpenSL ES uygulaması, bu tür arayüzlerin yanlış kullanımını algılamaz. Nesne yok edildikten sonra bu tür arayüzleri kullanmaya devam etmek, uygulamanızın tahmin edilemeyen şekillerde çökmesine veya davranmasına neden olabilir.
Hem birincil nesne arayüzünü hem de ilişkili tüm öğeleri açık bir şekilde ayarlamanızı öneririz.
nesne yok etme dizinizin bir parçası olarak NULL
ile arayüz oluşturur. Böylece,
eski arayüz tanıtıcılarının hatalı kullanımı.
Stereo kaydırma
Mono kaynağın stereo kaydırmayı etkinleştirmek için Volume::EnableStereoPosition
kullanıldığında
toplamda 3 dB küçülme var
ses gücü
düzeyi tıklayın. Bu, toplam ses gücü seviyesinin sabit kalmasını sağlamak için gereklidir.
kaynak
bir kanaldan diğerine
kaydırıldı. Bu nedenle, stereo konumlandırmayı yalnızca
somut olarak ortaya koyar. Daha fazla bilgi için
ses kaydırma.
Geri aramalar ve mesaj dizileri
Geri çağırma işleyiciler genellikle uygulama tarafından algılandığında unutmayın. Bu nokta, uygulamayla ilişkili olarak eşzamansız olduğundan, engellemeyen bir nokta kullanmanız gerekir. uygulama ve kullanıcı arasında paylaşılan değişkenlere erişimi kontrol etmek için geri çağırma işleyici. Örnek kodda (ör. arabellek sıraları için) bunu ya senkronizasyonun kullanılması veya engelleme senkronizasyonunun kullanılmasıdır. Ancak, herhangi bir üretim kodu için engellemeyen uygun senkronizasyon çok önemlidir.
Geri çağırma işleyiciler Android çalışma zamanı nedeniyle JNI kullanılamaz. Bu dahili ileti dizileri kritik önem taşır ve OpenSL ES uygulamasının bütünlüğünü bozuyorsa geri çağırma işleyici de veya gerçekleştir fazla iş yükü olabilir.
Geri çağırma işleyicinizin JNI kullanması veya geri çağırması için işleyicinin, bunun yerine başka bir iş parçacığının işlemesi için bir etkinlik yayınlaması gerekir. Örnekler Kabul edilebilir geri çağırma iş yükü arasında sonraki çıkış arabelleğinin oluşturulması ve sıraya alınması yer alır. (bir AudioPlayer için), az önce doldurulmuş giriş arabelleğini işleme ve sonraki boş arabellek (AudioRecorder için) veya Get ailesinin çoğu gibi basit API'leri kullanabilir. Bkz. İş yüküyle ilgili olarak aşağıdaki Performans bölümüne bakın.
Bunun tersinin de güvenli olduğunu unutmayın: JNI URL'sine giren bir Android uygulaması ileti dizisi şunları yapmasına izin verilir: OpenSL ES API'lerini doğrudan çağırır. Ancak, aramaları engellemek veya Uygulama Yanıt Vermiyor (ANR).
Geri arama işleyici çağıran iş parçacığının belirlenmesi, büyük ölçüde bazı ipuçları vereceğim. Bu esnekliğin nedeni, gelecekteki optimizasyonlara izin vermektir. bilhassa şuralarda: çok çekirdekli cihazlara sahip olması gerekir.
Geri çağırma işleyicinin çalıştırıldığı iş parçacığının, genelinde aynı kimliğe sahip olacağı garanti edilmez.
anlamına gelir. Bu nedenle, pthread_self()
tarafından döndürülen pthread_t
veya gettid()
tarafından döndürülen pid_t
değerinin çağrılar arasında tutarlı olmasını beklemeyin. Aynı nedenle, pthread_setspecific()
ve pthread_getspecific()
gibi iş parçacığı yerel depolama (TLS) API'lerini geri çağırma işlevinden kullanmayın.
Uygulama, Search Ads 360 için aynı türde eşzamanlı geri çağırmaların aynı nesne için meydana gelmez. Ancak farklı mesaj dizilerinde aynı nesne için farklı türde eşzamanlı geri çağırmalar mümkündür.
Performans
OpenSL ES yerel bir C API olduğundan, OpenSL ES çağrısı yapan çalışma zamanı olmayan uygulama iş parçacıkları atık toplama duraklatmaları gibi çalışma zamanıyla ilgili ek yük anlamına gelir. Aşağıda açıklanan bir istisna dışında, Bunun dışında OpenSL ES kullanımının ek performans faydası yoktur. Özellikle OpenSL ES'in kullanılması, platformun genel olarak sunduğundan daha düşük ses gecikmesi ve daha yüksek planlama önceliği gibi iyileştirmeler sunma garantisi vermez. Diğer yandan, Bir OpenSL ES uygulaması olan Android platformu ve belirli cihaz uygulamaları gelişmeye devam ediyor sistem performansı iyileştirmelerinden yararlanmayı bekleyebilirsiniz.
Bu gelişmelerden biri, ses çıkış gecikmesinin azaltılmasına yönelik destektir.
Daraltılmış kampanya için temel
çıkış gecikmesi ilk olarak Android 4.1 (API düzeyi 16) sürümüne dahil edildi ve ardından,
Android 4.2'de (API düzeyi 17) sürekli ilerleme kaydedildi. Bu iyileştirmelere
Cihaz uygulamaları için OpenSL ES,
hak talebinde bulunma özelliği android.hardware.audio.low_latency
.
Cihaz bu özelliği desteklemiyorsa ancak Android 2.3'ü (API düzeyi 9) destekliyorsa
ya da sonrasında OpenSL ES API'lerini kullanmaya devam edebilirsiniz ancak çıkış gecikmesi daha yüksek olabilir.
Alt
çıkış gecikmesi yolu yalnızca uygulama bir arabellek boyutu ve örnek hızı isterse kullanılır
Bunlar,
Cihazın yerel çıkış yapılandırmasıyla uyumlu. Bu parametreler
cihaza özgü
aşağıda açıklandığı şekilde elde edilmelidir.
Android 4.2 (API düzeyi 17) sürümünden itibaren, bir uygulama Cihazın birincil çıkışı için platformda yerel veya optimum çıkış örnek hızı ve arabellek boyutu akış şeklinde gösterilir. Uygulamalar, daha önce bahsedilen özellik testiyle birlikte artık destek olduğunu iddia eden cihazlarda daha düşük gecikme süresi çıkışı için kendisini uygun şekilde yapılandırabilir.
Android 4.2 (API düzeyi 17) ve önceki sürümler için iki veya daha fazla arabellek sayısı daha düşük gecikme için gereklidir. Android 4.3 (API düzeyi 18) sürümünden itibaren, bir arabellek daha düşük gecikme için bir değerin yeterli olması gerekir.
Çıkış efektleri için tüm OpenSL ES arayüzleri düşük gecikme yolunu engeller.
Önerilen adım sırası aşağıdaki gibidir:
- OpenSL ES kullanımını onaylamak için API düzeyi 9 veya üstünü kontrol edin.
- Aşağıdakine benzer bir kod kullanarak
android.hardware.audio.low_latency
özelliğini kontrol edin:Kotlin
import android.content.pm.PackageManager ... val pm: PackageManager = context.packageManager val claimsFeature: Boolean = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY)
Java
import android.content.pm.PackageManager; ... PackageManager pm = getContext().getPackageManager(); boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
-
android.media.AudioManager.getProperty()
- Bu cihazın şu sürümü için yerel veya optimum çıkış örnek hızını ve arabellek boyutunu alın:
birincil çıkış
akışı için aşağıdaki gibi bir kod kullanabilirsiniz:
Kotlin
import android.media.AudioManager ... val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager val sampleRate: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE) val framesPerBuffer: String = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)
Java
import android.media.AudioManager; ... AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
sampleRate
veframesPerBuffer
değerlerinin dize olduğunu unutmayın. İlk kontrol: null ve ardındanInteger.parseInt()
kullanarak int'e dönüştürün. - Şimdi OpenSL ES'yi kullanarak PCM arabellek sırası veri bulucusuyla bir AudioPlayer oluşturun.
Not: Ses cihazınızdaki OpenSL ES ses uygulamaları için yerel arabellek boyutunu ve örnekleme hızını belirlemek üzere Ses Arabellek Boyutu test uygulamasını kullanabilirsiniz. Ayrıca, adresini görüntülemek için GitHub'ı ziyaret edebilirsiniz ses-arabellek boyutu örnekleri.
Düşük gecikmeli ses oynatıcıların sayısı sınırlıdır. Uygulamanız için daha fazla daha az ses kaynaklarını uygulama düzeyinde miksleyin. Sesinizi yok etmeyi unutmayın diğer uygulamalarla paylaşılan küresel bir kaynak olduğundan, etkinliğiniz duraklatıldığında görüntüleyen oynatıcılar ekleyin.
Sesli arızaları önlemek için arabellek sırası geri çağırma işleyicisi, bir zaman aralığı belirleyin. Bu, genellikle kilitleme, koşul veya G/Ç işlemlerinde sınırsız engelleme olmadığı anlamına gelir. Bunun yerine kilitleri deneyin, kilitleri ve zaman aşımlarıyla beklemelerini kullanın kullanmaya devam edebilirsiniz.
Sonraki arabelleği oluşturmak (AudioPlayer için) veya önceki arabelleği kullanmak için gereken hesaplama arabellek (AudioRecord için), her geri arama için yaklaşık olarak aynı süre sürer. Belirgin olmayan bir süre içinde çalışan veya çalışma sırasında zorlu algoritmalardan kaçının daha iyi anlamanızı sağlayabilir. Belirli bir geri çağırmada harcanan CPU süresi varsa geri çağırma hesaplaması seri hâlindedir ortalamadan önemli ölçüde daha büyüktür. Özet olarak, işleyicinin CPU yürütme süresinin sıfıra yakın bir varyansa sahip olması ve işleyicinin sınırsız süre boyunca engellememesi idealdir.
Yalnızca şu çıkışlarda ses daha düşük gecikmeli olabilir:
- Cihazdaki hoparlörler.
- Kablolu kulaklıklar.
- Kablolu kulaklıklar.
- Çizgiyi çizin.
- USB dijital ses.
Bazı cihazlarda, cihazlar için dijital sinyal işleme nedeniyle hoparlör gecikmesi diğer yollardan daha yüksektir hoparlör düzeltme ve koruması.
Android 5.0 (API Düzeyi 21) sürümünden itibaren, daha düşük gecikme
ses girişi belirli cihazlarda desteklenir. Bu özellikten yararlanmak için önce yukarıda açıklandığı şekilde daha düşük gecikmeli çıkışın kullanılabildiğini onaylayın. Daha düşük gecikmeli çıkış elde etme özelliği
daha düşük gecikmeli giriş özelliğinin ön koşuludur. Ardından, aynı
çıkış için kullanılacak örnek hızı ve arabellek boyutu. Giriş efektleri için OpenSL ES arayüzleri
daha düşük gecikmeli yolu hariç tutar. Kayıt hazır ayarı
Daha düşük gecikme için SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
kullanılmalıdır; bu
hazır ayar, giriş yolunda gecikmeye neden olabilecek cihaza özel dijital sinyal işlemeyi devre dışı bırakır.
Kayıt hazır ayarlarıyla ilgili daha fazla bilgi için
Android yapılandırması
arayüz bölümünü inceleyin.
Eş zamanlı giriş ve çıkış için her biri için ayrı arabellek sırası tamamlama işleyicileri kullanılır yanı sıra. Bu geri aramaların göreli sırasına veya her iki taraf da aynı örnek hızını kullansa bile ses saatinde çalışır. Uygulamanız senkronize edildiğinden emin olun.
Bağımsız olabilecek ses saatlerinin sonuçlarından biri, eşzamansız örnek hızına duyulan ihtiyaçtır. gösterir. Zaman uyumsuz örnek hızı dönüşümü için basit (ses kalitesi açısından ideal olmasa da) bir teknik, sıfır geçiş noktasının yakınında gerektiği gibi örnekleri kopyalamak veya silmektir. Daha sofistike dönüşümlerinin nasıl mümkün olduğunu gösterir.
Performans modları
Android 7.1 (API Düzeyi 25) sürümünden itibaren OpenSL ES, performans modunu belirtmenin bir yolunu sundu seçin. Seçenekler şunlardır:
SL_ANDROID_PERFORMANCE_NONE
: Belirli bir performans şartı yoktur. Donanım ve yazılım efektlerine izin verir.SL_ANDROID_PERFORMANCE_LATENCY
: Gecikmeye öncelik verilir. Herhangi bir donanım veya oluşturmak için de kullanabilirsiniz. Bu, varsayılan moddur.SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS
: Gecikmeye öncelik verilir yine de donanım ve yazılım efektlerine izin verir.SL_ANDROID_PERFORMANCE_POWER_SAVING
: Güç tasarrufuna öncelik verilir. Donanım ve yazılım efektlerine izin verir.
Not: Düşük gecikmeli bir yola ihtiyacınız yoksa ve
cihazın yerleşik ses efektlerinden (örneğin, ses efektleri ve
kalitesi için) değer kullanıyorsanız performans modunu özel olarak
SL_ANDROID_PERFORMANCE_NONE
.
Performans modunu ayarlamak için Android üzerinden SetConfiguration
yöntemini çağırmanız gerekir.
aşağıdaki gibi yapılandırma arayüzü:
// Obtain the Android configuration interface using a previously configured SLObjectItf. SLAndroidConfigurationItf configItf = nullptr; (*objItf)->GetInterface(objItf, SL_IID_ANDROIDCONFIGURATION, &configItf); // Set the performance mode. SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE; result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(performanceMode));
Güvenlik ve izinler
Android'de güvenlik, kimlerin ne yapabileceğine göre işlem düzeyinde sağlanır. Java programlama dili kodu, yerel koddan daha fazlasını yapamaz ve yerel kod da Java programlama dili kodundan daha fazlasını yapamaz. Aralarındaki tek fark, kullanılabilir API'lerdir.
OpenSL ES kullanan uygulamalar, benzer
API'lerle başlayın. Örneğin, uygulamanız ses kaydediyorsa
android.permission.RECORD_AUDIO
izni. Ses efektleri kullanan uygulamalar
android.permission.MODIFY_AUDIO_SETTINGS
Ağ URI kaynaklarını oynatan uygulamalar
android.permission.NETWORK
gerekiyor. Daha fazla bilgi için bkz.
Sistemle Çalışma
İzinler.
Platform sürümüne ve uygulamaya bağlı olarak, medya içeriği ayrıştırıcılar ve yazılım codec'leri çalışması, OpenSL ES (donanım codec'leri) çağıran Android uygulaması bağlamında soyut ama cihaza bağlı) olabilir. Ayrıştırıcı ve codec'i kötüye kullanmak için tasarlanmış hatalı biçimlendirilmiş içerik bilinen bir saldırı vektörüdür. Yalnızca güvenilir kaynaklardan medya oynatmanızı öneririz veya uygulamanızı, bu sayfadaki medya içeriklerini işleyen kod güvenilir olmayan kaynaklar nispeten korumalı bir ortamda çalışır. Örneğin herkesin güvenilir olmayan kaynaklardan gelen medya içeriklerini ayrı bir işlemde işleyebilir. Her iki süreç de aynı UID altında çalıştırıldığında, bu ayırma, saldırıyı daha zor hale getirir.