Android için OpenSL ES

UYARI: OpenSL ES desteği sonlandırıldı. Geliştiriciler, GitHub'da bulunan açık kaynak Oboe kitaplığını kullanmalıdır. Oboe, AAudio'ya çok benzeyen bir API sağlayan bir C++ sarmalayıcıdır. Oboe, AAudio kullanılabilir olduğunda AAudio'yu çağırır ve AAudio kullanılamıyorsa OpenSL ES'ye geri döner.

Bu sayfada, OpenSL ESTM'nin NDK uygulamasının OpenSL ES 1.0.1'in referans spesifikasyonundan nasıl farklı olduğu hakkında ayrıntılı bilgi verilmektedir. Spesifikasyondaki örnek kodu kullanırken Android'de çalışacak şekilde değiştirmeniz gerekebilir.

Aksi belirtilmedikçe tüm özellikler Android 2.3 (API seviyesi 9) ve sonraki sürümlerde kullanılabilir. Bazı özellikler yalnızca Android 4.0 (API düzeyi 14) için kullanılabilir. Bu özellikler belirtilmiştir.

Not: Android Uyumluluk Tanımlama Belgesi (CDD), uyumlu bir Android cihazın donanım ve yazılım şartlarını belirtir. Genel uyumluluk programı hakkında daha fazla bilgi için Android Uyumluluğu'na, gerçek CDD belgesi için de CDD'ye bakın.

OpenSL ES, C++ kullanılarak da erişilebilen bir C dil arayüzü sağlar. Aşağıdaki Android Java API'lerinin ses bölümlerine benzer özellikler sunar:

Tüm Android Native Development Kit'te (NDK) olduğu gibi, Android için OpenSL ES'nin asıl amacı, Java Native Interface (JNI ) kullanılarak çağrılacak paylaşılan kitaplıkların uygulanmasını kolaylaştırmaktır. NDK, tam C/C++ uygulamaları yazmak için tasarlanmamıştır. Ancak OpenSL ES tam özellikli bir API'dir ve ses ihtiyaçlarınızın çoğunu Android çalışma zamanında çalışan koda çağrı göndermeden yalnızca bu API'yi kullanarak karşılayabilmenizi bekleriz.

Not: OpenSL ES'ye dayalı olsa da, Android yerel ses (yüksek performanslı ses) API'si hiçbir OpenSL ES 1.0.1 profiline uygun bir uygulama değildir (oyun, müzik veya telefon). Bunun nedeni, Android'in profillerden herhangi birinin gerektirdiği tüm özellikleri uygulamamasıdır. Android'in spesifikasyondan farklı davrandığı bilinen tüm durumlar Android uzantıları sayfasında açıklanmaktadır.

Referans spesifikasyonundan devralınan özellikler

OpenSL ES'nin Android NDK uygulaması, referans spesifikasyonundaki özelliklerin büyük bir kısmını belirli sınırlamalarla devralır.

Genel giriş noktaları

Android için OpenSL ES, Android spesifikasyonundaki tüm genel giriş noktalarını destekler. Bu giriş noktaları şunlardır:

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Nesneler ve arayüzler

Aşağıdaki tabloda, OpenSL ES'in Android NDK uygulamasının desteklediği nesneler ve arayüzler gösterilmektedir. Hücrede Evet görünüyorsa özellik bu uygulamada kullanılabilir.

Nesneler ve arayüzler için Android NDK desteği.

Özellik Ses çalar Ses kaydedici Motor Çıkış karması
Güçlü bas Evet Hayır Hayır Evet
Arabellek sırası Evet Hayır Hayır Hayır
Arabellek sırası veri bulma aracı Evet: Kaynak Hayır Hayır Hayır
Dinamik arayüz yönetimi Evet Evet Evet Evet
Efekt gönderme Evet Hayır Hayır Hayır
Motor Hayır Hayır Evet Hayır
Ortam yankısı Hayır Hayır Hayır Evet
Ekolayzer Evet Hayır Hayır Evet
G/Ç cihazı veri bulucu Hayır Evet: Kaynak Hayır Hayır
Meta veri ayıklama Evet: PCM olarak kod çözme Hayır Hayır Hayır
Tek kişinin sesini kapat Evet Hayır Hayır Hayır
Nesne Evet Evet Evet Evet
Çıkış karışımı bulucu Evet: Lavabo Hayır Hayır Hayır
Oynat Evet Hayır Hayır Hayır
Oynatma hızı Evet Hayır Hayır Hayır
Ön getirme durumu Evet Hayır Hayır Hayır
Hazır yankı Hayır Hayır Hayır Evet
Kaydet Hayır Evet Hayır Hayır
Ara Evet Hayır Hayır Hayır
URI veri bulma aracı Evet: Kaynak Hayır Hayır Hayır
Sanallaştırıcı Evet Hayır Hayır Evet
Ses Evet Hayır Hayır Hayır

Bu özelliklerin bazılarıyla ilgili sınırlamalar sonraki bölümde açıklanmıştır.

Sınırlamalar

Tablo 1'de yer alan özellikler için belirli sınırlamalar vardır. Bu sınırlamalar, referans spesifikasyondan kaynaklanan farklılıkları gösterir. Bu bölümün geri kalanında bu farklılıklar hakkında bilgi verilmektedir.

Dinamik arayüz yönetimi

Android için OpenSL ES, RemoveInterface veya ResumeInterface'ü desteklemez.

Efekt kombinasyonları: ortam yankısı ve hazır yankı

Aynı çıkış karışımında hem ortam yankısı hem de hazır ayar yankısı kullanamazsınız.

Platform, CPU yükünün çok yüksek olacağını tahmin ederse efekt isteklerini yoksayabilir.

Efekt gönderme

SetSendLevel(), ses oynatıcı başına tek bir gönderme düzeyini destekler.

Ortam yankısı

Ortam yankısı, SLEnvironmentalReverbSettings yapısını reflectionsDelay, reflectionsLevel veya reverbDelay alanlarını desteklemez.

MIME veri biçimi

MIME veri biçimini yalnızca URI veri bulucuyla ve yalnızca ses çalar için kullanabilirsiniz. Bu veri biçimini ses kaydedici için kullanamazsınız.

OpenSL ES'in Android uygulamasında, mimeType değerini NULL veya geçerli bir UTF-8 dizesi olarak başlatmanız gerekir. Ayrıca containerType değerini geçerli bir değerle başlatmanız gerekir. Uygulamanın başlıktan tanımlayamadığı diğer uygulamalara veya içerik biçimlerine taşınabilirlik gibi başka bir durum söz konusu değilse mimeType değerini NULL, containerType değerini ise SL_CONTAINERTYPE_UNSPECIFIED olarak ayarlamanızı öneririz.

Android için OpenSL ES, Android platformu da desteklediği sürece aşağıdaki ses biçimlerini destekler:

  • WAV PCM'dir.
  • WAV alaw.
  • WAV ulaw.
  • MP3 Ogg Vorbis.
  • AAC LC.
  • HE-AACv1 (AAC+).
  • HE-AACv2 (geliştirilmiş AAC+).
  • AMR.
  • FLAC.

Not: Android'in desteklediği ses biçimlerinin listesi için Desteklenen medya biçimleri bölümüne bakın.

OpenSL ES'nin bu uygulamasında bu ve diğer biçimlerin işlenmesinde aşağıdaki sınırlamalar geçerlidir:

  • AAC biçimleri bir MP4 veya ADTS kapsayıcısında olmalıdır.
  • Android için OpenSL ES, MIDI'yi desteklemez.
  • WMA, AOSP'nin bir parçası değildir ve Android için OpenSL ES ile uyumluluğunu doğrulamadık.
  • OpenSL ES'in Android NDK uygulaması, DRM veya şifrelenmiş içeriğin doğrudan oynatılmasını desteklemez. Korunan ses içeriğini oynatmak için oynatmadan önce uygulamanızda şifresini çözmeniz gerekir. Bu sırada uygulamanız DRM kısıtlamalarını uygular.

Android için OpenSL ES, nesneleri değiştirmeyle ilgili aşağıdaki yöntemleri desteklemez:

  • Resume()
  • RegisterCallback()
  • AbortAsyncOperation()
  • SetPriority()
  • GetPriority()
  • SetLossOfControlInterfaces()

PCM veri biçimi

Arabellek sıralarıyla kullanabileceğiniz tek veri biçimi PCM'dir. Desteklenen PCM oynatma yapılandırmaları aşağıdaki özelliklere sahiptir:

  • 8 bit imzasız veya 16 bit imzalı.
  • Mono veya stereo.
  • Küçük uç bayt sırası.
  • Aşağıdaki örnek hızları:
    • 8.000 Hz.
    • 11.025 Hz.
    • 12.000 Hz.
    • 16.000 Hz.
    • 22.050 Hz.
    • 24.000 Hz.
    • 32.000 Hz.
    • 44.100 Hz.
    • 48.000 Hz.

Android için OpenSL ES'nin kayıt için desteklediği yapılandırmalar cihaza bağlıdır. Genellikle 16.000 Hz mono/16 bit imzalı imzalı yapılandırmalar cihazdan bağımsız olarak kullanılabilir.

Yanıltıcı ada rağmen samplesPerSec alanının değeri miliHz birimi cinsindendir. Yanlış değeri yanlışlıkla kullanmaktan kaçınmak için bu alanı, bu amaç için tanımlanan sembolik sabitlerden birini (ör. SL_SAMPLINGRATE_44_1) kullanarak başlatmanızı öneririz.

Android 5.0 (API düzeyi 21) ve sonraki sürümler kayan noktalı verileri destekler.

Oynatma hızı

OpenSL ES oynatma hızı, bir nesnenin veri sunma hızını, normal hızın binde biri olarak veya binde bir ifadeyle belirtir. Örneğin, binde 1.000 oynatma hızı 1.000/1.000 veya normal hızdır. Hız aralığı, olası oynatma hızları aralığını ifade eden kapalı bir aralıktır.

Oynatma hızı aralıkları ve diğer özellikler için sağlanan destek, platform sürümüne ve uygulamaya bağlı olarak değişiklik gösterebilir. Uygulamanız, cihazı sorgulamak için PlaybackRate::GetRateRange() veya PlaybackRate::GetCapabilitiesOfRate() kullanarak bu özellikleri çalışma zamanında belirleyebilir.

Cihazlar genellikle PCM biçimindeki bir veri kaynağı için aynı hız aralığını ve diğer biçimler için 1.000 ila 1.000 mille arasında bir birlik hızı aralığını destekler. Yani birlik hızı aralığı aslında tek bir değerdir.

Kaydet

Android için OpenSL ES, SL_RECORDEVENT_HEADATLIMIT veya SL_RECORDEVENT_HEADMOVING etkinliklerini desteklemez.

Ara

SetLoop() yöntemi, dosyanın tamamını döngü şeklinde oynatmayı sağlar. Döngüyü etkinleştirmek için startPos parametresini 0, endPos parametresini ise SL_TIME_UNKNOWN olarak ayarlayın.

Arabellek sırası veri bulma aracı

Arabellek kuyruğu için veri bulucu içeren bir ses çalar veya kaydedici yalnızca PCM veri biçimini destekler.

G/Ç cihazı veri bulma aracı

Android için OpenSL ES, yalnızca Engine::CreateAudioRecorder() için veri kaynağı olarak bulucuyu belirttiğinizde G/Ç cihaz veri bulucusunun kullanımını destekler. Aşağıdaki kod snippet'inde yer alan değerleri kullanarak cihaz veri bulucusunu başlatın:

SLDataLocator_IODevice loc_dev =
  {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};

URI veri bulma aracı

Android için OpenSL ES, URI veri bulucusunu yalnızca MIME veri biçimiyle ve yalnızca ses çalar için kullanabilir. Ses kaydedici için URI veri bulucu kullanamazsınız. URI'de yalnızca http: ve file: şemaları kullanılabilir. https:, ftp: veya content: gibi diğer şemalara izin verilmez.

Android platformunda sesli rtsp: desteğini doğrulamadık.

Veri yapıları

Android, aşağıdaki OpenSL ES 1.0.1 veri yapılarını destekler:

  • SLDataFormat_MIME
  • SLDataFormat_PCM
  • SLDataLocator_BufferQueue
  • SLDataLocator_IODevice
  • SLDataLocator_OutputMix
  • SLDataLocator_URI
  • SLDataSink
  • SLDataSource
  • SLEngineOption
  • SLEnvironmentalReverbSettings
  • SLInterfaceID

Platform yapılandırması

Android için OpenSL ES, çok iş parçacıklı uygulamalar için tasarlanmış ve iş parçacığı açısından güvenlidir. Uygulama başına tek bir motoru ve motor başına en fazla 32 nesneyi destekler. Kullanılabilir cihaz belleği ve CPU, kullanılabilir nesne sayısını daha da kısıtlayabilir.

Aşağıdaki motor seçenekleri tanınır ancak slCreateEngine tarafından yoksayılır:

  • SL_ENGINEOPTION_THREADSAFE
  • SL_ENGINEOPTION_LOSSOFCONTROL

OpenMAX AL ve OpenSL ES aynı uygulamada birlikte kullanılabilir. Bu durumda, dahili olarak tek bir paylaşılan motor nesnesi vardır ve 32 nesne sınırı OpenMAX AL ile OpenSL ES arasında paylaşılır. Uygulama, her iki motoru da oluşturmalı, her iki motoru da kullanmalı ve sonunda her iki motoru da imha etmelidir. Uygulama, paylaşılan motorda bir referans sayısını tutarak ikinci kaldırma işlemi sırasında doğru şekilde yok edilmesini sağlar.

Programlama notları

OpenSL ES programlama notları, OpenSL ES'in doğru şekilde uygulanmasını sağlamak için ek bilgiler sağlar.

Not: Size kolaylık sağlamak amacıyla, docs/opensles/OpenSL_ES_Specification_1.0.1.pdf içinde NDK'nın yer aldığı OpenSL ES 1.0.1 spesifikasyonunun bir kopyasını ekledik.

Platform sorunları

Bu bölümde, bu API'leri destekleyen ilk platform sürümündeki bilinen sorunlar açıklanmaktadır.

Dinamik arayüz yönetimi

DynamicInterfaceManagement::AddInterface çalışmıyor. Bunun yerine, çevresel yankı için örnek kodda gösterildiği gibi Create() parametresine iletilen dizi içinde arayüzü belirtin.

OpenSL ES'in gelecekteki sürümleri için planlama yapma

Android yüksek performanslı ses API'leri Khronos Group OpenSL ES 1.0.1 çözümünü temel alır. Khronos, standardın düzeltilmiş 1.1 sürümünü yayınladı. Düzeltilmiş sürümde yeni özellikler, açıklamalar, yazım hatalarının düzeltmeleri ve bazı uyumsuzluklar yer alır. Beklenen uyumsuzlukların çoğu nispeten küçüktür veya Android'in desteklemediği OpenSL ES alanlarındadır.

Bu sürümle geliştirilen bir uygulama, aşağıdaki İkili uyumluluk için planlama bölümünde belirtilen yönergelere uymanız koşuluyla Android platformunun gelecekteki sürümlerinde çalışmalıdır.

Not: Gelecekte kaynak uyumluluğu hedefimiz değildir. Yani NDK'nın daha yeni bir sürümüne yükseltirseniz uygulama kaynak kodunuzu yeni API'ye uygun olacak şekilde değiştirmeniz gerekebilir. Bu tür değişikliklerin çoğunun küçük olmasını bekliyoruz. Ayrıntıları aşağıda bulabilirsiniz.

İkili program uyumluluğunu planlama

Gelecekteki ikili program uyumluluğunu iyileştirmek için uygulamanızın şu yönergelere uymasını öneririz:

  • Yalnızca OpenSL ES 1.0.1 sürümünde Android tarafından desteklenen özelliklerin belgelenen alt kümesini kullanın.
  • Başarısız bir işlem için belirli bir sonuç koduna güvenmeyin; farklı bir sonuç koduyla karşılaşmaya hazır olun.
  • Uygulama geri çağırma işleyicileri genellikle kısıtlı bir bağlamda çalışır. Bu kişiler, işlerini hızlı bir şekilde tamamlayıp en kısa sürede geri dönecek şekilde yazılmalıdır. Geri çağırma işleyici içinde karmaşık işlemler çalıştırmayın. Örneğin, arabellek sırası tamamlama geri çağırması içinde başka bir arabelleği sıraya alabilir ancak ses çalar oluşturamazsınız.
  • Geri çağırma işleyicileri, ek etkinlik türleri almak için daha az veya daha sık çağrılmaya hazır olmalı ve tanımadıkları etkinlik türlerini yoksaymalıdır. Etkin etkinlik türlerinden oluşan bir etkinlik maskesi ile yapılandırılmış geri çağırma işlevleri, aynı anda birden fazla etkinlik türü biti ayarlanmış şekilde çağrılmaya hazırlanmalıdır. Her etkinlik bitini test etmek için switch case yerine "&" kullanın.
  • Önceden getirme durumunu ve geri çağırmaları ilerlemenin genel göstergesi olarak kullanın ancak sabit kodlu belirli dolgu düzeylerine veya geri çağırma sıralarına bağımlı kalmayın. Ön prefetch durum dolgu düzeyinin anlamı ve ön prefetch sırasında algılanan hataların davranışı değişebilir.

Not: Daha fazla bilgi için aşağıdaki Arabellek sırası davranışı bölümüne bakın.

Kaynak uyumluluğunu planlama

Belirtildiği gibi, Khronos Group'tan OpenSL ES'nin bir sonraki sürümünde kaynak kodu uyumsuzluklarının oluşması beklenmektedir. Değişiklik olasılığı olan alanlar şunlardır:

  • Özellikle BufferQueue::Enqueue alanında, slBufferQueueCallback parametre listesinde ve SLBufferQueueState.playIndex alanının adında olmak üzere arabellek aralığı arayüzünde önemli değişiklikler yapılması beklenmektedir. Uygulama kodunuzda bunun yerine Android basit arabellek kuyruklarını kullanmanızı öneririz. NDK ile birlikte sağlanan örnek kodda, bu nedenle oynatma için Android basit arabelleğe alma sıralarını kullandık. (PCM'ye kayıt ve kod çözme için Android basit arabellek sırasını da kullanırız. Bunun nedeni, standart OpenSL ES 1.0.1'in arabellek sırası veri alıcısına kayıt veya kod çözme işlemini desteklememesidir.)
  • Referans yoluyla iletilen giriş parametrelerine const ve giriş değeri olarak kullanılan SLchar * struct alanlarına eklenecek. Bu işlem için kodunuzda herhangi bir değişiklik yapmanız gerekmez.
  • Şu anda imzalanmış olan bazı parametreler için imzasız türler kullanılacak. Bir parametre türünü SLint32 yerine SLuint32 veya benzeri bir türe değiştirmeniz ya da bir yayın eklemeniz gerekebilir.
  • Equalizer::GetPresetName, uygulama belleğine bir işaretçi döndürmek yerine dizeyi uygulama belleğine kopyalar. Bu önemli bir değişiklik olacağından bu yöntemi çağırmaktan kaçınmanızı veya kullanımını izole etmenizi öneririz.
  • Yapı türlerinde ek alanlar olacaktır. Çıkış parametrelerinde bu yeni alanlar yoksayılabilir ancak giriş parametreleri için yeni alanların başlatılması gerekir. Neyse ki bu alanların tümünün Android tarafından desteklenmeyen bölgelerde olması beklenir.
  • Arayüz GUID'leri değişecek. Bağımlılık oluşturmamak için arayüzlere GUID yerine sembolik adla referans verin.
  • unsigned char olan SLchar fiyatı char olarak değiştirilecek. Bu, öncelikli olarak URI veri bulucuyu ve MIME veri biçimini etkiler.
  • SLDataFormat_MIME.mimeType, pMimeType olarak, SLDataLocator_URI.URI ise pURI olarak yeniden adlandırılacak. Kodunuzu bu değişiklikten korumak için SLDataFormat_MIME ve SLDataLocator_URI veri yapılarını, alan adına göre değil, parantez içine alınmış, virgül ile ayrılmış bir değer listesi kullanarak başlatmanızı öneririz. Bu teknik, örnek kodda kullanılmıştır.
  • SL_DATAFORMAT_PCM, uygulamanın verilerin gösterimini signed integer, unsigned integer veya floating-point olarak belirtmesine izin vermiyor. Android uygulamasında, 8 bit verilerin imzasız tam sayı, 16 bit verilerin ise imzalı tam sayı olduğu varsayılır. Ayrıca, gerçek birimler milili Hz olduğundan samplesPerSec alanı yanlış bir addır. Bu sorunların, uygulamanın temsili açıkça belirtmesine izin veren ve alan adını düzelten yeni bir genişletilmiş PCM veri biçimi sunacak olan bir sonraki OpenSL ES sürümünde ele alınması bekleniyor. Bu yeni bir veri biçimi olacağından ve mevcut PCM veri biçimi yine kullanılabileceğinden (desteği sonlandırılmış olsa da) kodunuzda acil bir değişiklik yapmanız gerekmeyecektir.