Android için OpenSL ES

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

Aksi belirtilmedikçe, tüm özellikler Android 2.3 (API düzeyi 9) ve sonraki sürümlerde kullanılabilir. Bazı özellikler yalnızca Android 4.0 (API düzeyi 14) sürümünde mevcuttur. Bunlar,

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

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

Tüm Android Yerel Geliştirme Kiti'nde (NDK) olduğu gibi, Android için OpenSL ES'nin asıl amacı, Java Yerel Arayüzü (JNI ) kullanılarak çağrılacak paylaşılan kitaplıkların uygulanmasını kolaylaştırmaktır. NDK, yalnızca C/C++ uygulamaları yazmak için tasarlanmamıştır. Bununla birlikte, OpenSL ES tam özellikli bir API'dir ve Android çalışma zamanında kod çalıştırmaya gerek kalmadan, ses ihtiyaçlarınızın çoğunu yalnızca bu API'yi kullanarak karşılayabilmenizi umuyoruz.

Not: OpenSL ES'yi temel alan Android yerel ses (yüksek performanslı ses) API'si, herhangi bir OpenSL ES 1.0.1 profilinin (oyun, müzik veya telefon) uygun bir uygulaması değildir. Bunun nedeni, Android'in profillerin 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ı, belirli sınırlamalarla referans spesifikasyonundaki özelliklerin büyük bir kısmını devralır.

Global giriş noktaları

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

  • slCreateEngine
  • slQueryNumSupportedEngineInterfaces
  • slQuerySupportedEngineInterfaces

Nesneler ve arayüzler

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

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

Öne Çıkarın Ses çalar Ses kaydedici Motor Çıkış karışımı
Güçlü bas Evet Hayır Hayır Evet
Arabellek kuyruğu Evet Hayır Hayır Hayır
Arabellek kuyruğu veri bulucu 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
Çevre 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: Kodu PCM'ye çöz Hayır Hayır Hayır
Tek başına sessize al Evet Hayır Hayır Hayır
Nesne Evet Evet Evet Evet
Çıkış karması 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
Önceden 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 bulucu 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

Sonraki bölümde, bu özelliklerden bazılarıyla ilgili sınırlamalar açıklanmaktadır.

Sınırlamalar

Tablo 1'deki özellikler için belirli sınırlamalar vardır. Bu sınırlamalar, referans spesifikasyonundan farklılıkları gösterir. Bu bölümün geri kalanında bu farklılıklar hakkında bilgi verilmiştir.

Dinamik arayüz yönetimi

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

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

Aynı çıkış karışımında hem ortam yankısı hem de önceden ayarlanmış yankı kullanamazsınız.

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

Efekt gönderme

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

Çevre yankısı

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

MIME veri biçimi

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

OpenSL ES'nin Android uygulaması için mimeType öğesini NULL veya geçerli bir UTF-8 dizesine dönüştürmeniz gerekir. Ayrıca containerType öğesini geçerli bir değere başlatmanız gerekir. Bir uygulamanın başlıkla tanımlayamadığı diğer uygulamalara taşınabilirlik veya içerik biçimleri gibi başka hususlar yoksa mimeType öğesini NULL ve containerType değerini SL_CONTAINERTYPE_UNSPECIFIED olarak ayarlamanızı öneririz.

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

  • WAV PCM.
  • 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ünü inceleyin.

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

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

Android için OpenSL ES, nesneleri değiştirmek için kullanılan aşağıdaki yöntemleri desteklemez:

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

PCM veri biçimi

PCM, arabellek sıralarıyla kullanabileceğiniz tek veri biçimidir. Desteklenen PCM oynatma yapılandırmaları aşağıdaki özelliklere sahiptir:

  • 8 bit imzasız veya 16 bit imzalı.
  • Mono veya stereo.
  • Little-endian bayt sıralaması.
  • Ö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ı her cihazdan bağımsız olarak kullanılabilir.

samplesPerSec alanının değeri, yanıltıcı ada rağmen mili Hz cinsindendir. Yanlışlıkla yanlış değerin kullanılmasını önlemek için bu alanı, bu amaçla 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 nokta verilerini destekler.

Oynatma hızı

OpenSL ES oynatma hızı, bir nesnenin veri sunma hızını belirtir. Bu hız, binde bir normal hızın cinsinden veya binde bir olarak ifade edilir. Örneğin, bin gösterim başına 1.000'lik oynatma hızı, 1.000/1.000 veya normal hızdır. Ücret 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 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 çalışma zamanında bu özellikleri belirleyebilir.

Bir cihaz, genellikle PCM biçimindeki veri kaynağı için aynı hız aralığını ve diğer biçimler için bin başına 1.000 ile binde 1.000 birlik hız aralığını destekler. Diğer bir deyişle, birim ücret aralığı etkili bir şekilde tek bir değerdir.

Kaydet

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

Ara

SetLoop() yöntemi tam dosya döngüsünü etkinleştirir. Döngüyü etkinleştirmek için startPos parametresini 0, endPos parametresini SL_TIME_UNKNOWN olarak ayarlayın.

Arabellek kuyruğu veri bulucu

Arabellek sırası için veri bulucuya sahip bir ses çalar veya kaydedici, yalnızca PCM veri biçimini destekler.

G/Ç cihaz veri bulucu

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

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

URI veri bulucu

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

Android platformunda rtsp: için ses desteği doğrulanmadı.

Veri yapıları

Android şu 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ıştır ve iş parçacığına duyarlıdır. Uygulama başına tek bir motoru ve motor başına 32'ye kadar nesneyi destekler. Kullanılabilir cihaz belleği ve CPU, kullanılabilir nesne sayısını daha da kısıtlayabilir.

Şu 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 iki motoru da oluşturmalı, her iki motoru da kullanmalı ve son olarak her iki motoru da kaldırmalıdır. Uygulama, paylaşılan motorda bir referans sayısı tutar. Böylece, ikinci imha işlemi sırasında motor doğru şekilde yok edilir.

Programlama notları

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

Not: Size kolaylık sağlamak amacıyla NDK ile OpenSL ES 1.0.1 spesifikasyonunun bir kopyasını docs/opensles/OpenSL_ES_Specification_1.0.1.pdf dokümanına 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ı örnek kodunda gösterildiği gibi, Create() öğesine iletilen dizide arayüzü belirtin.

OpenSL ES'nin gelecekteki sürümlerini planlayın

Android yüksek performanslı ses API'leri Khronos Group OpenSL ES 1.0.1'i temel alır. Khronos, standardın düzeltilmiş bir 1.1 sürümünü yayınladı. Gözden geçirilmiş sürüm yeni özellikler, açıklamalar, yazım hatalarının düzeltilmesi ve bazı uyumsuzluklar içermektedir. Beklenen uyumsuzlukların çoğu nispeten küçüktür veya Android tarafından desteklenmeyen OpenSL ES alanlarındadır.

Bu sürümle geliştirilen bir uygulama, aşağıdaki İkili program uyumluluğu planı bölümünde belirtilen yönergelere uyduğunuz sürece Android platformunun gelecekteki sürümlerinde çalışacaktır.

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

İkili program uyumluluğu planı

Uygulamanızın gelecekteki ikili program uyumluluğunu iyileştirmek için aşağıdaki yönergeleri uygulamanızı öneririz:

  • Yalnızca OpenSL ES 1.0.1'deki Android destekli ö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ç kodu almaya hazırlıklı olun.
  • Uygulama geri çağırma işleyicileri genellikle kısıtlı bir bağlamda çalışır. Bunlar, işlerini hızlı bir şekilde yapmak ve mümkün olan en kısa sürede geri dönmek için yazılmış olmalıdır. Bir geri çağırma işleyici içinde karmaşık işlemler çalıştırmayın. Örneğin, arabellek sırası tamamlama geri çağırması sırasında başka bir arabelleği kuyruğa alabilir ancak ses çalar oluşturamazsınız.
  • Geri çağırma işleyicileri, ek etkinlik türleri almak için daha sık veya seyrek çağrılmaya hazır olmalı ve tanımadıkları etkinlik türlerini yoksaymalıdır. Etkin etkinlik türlerinden oluşan bir etkinlik maskesiyle yapılandırılan geri çağırmalar, aynı anda ayarlanmış birden fazla etkinlik türü biti ile çağrılmaya hazırlanmalıdır. Bir anahtar durumu yerine her bir etkinlik bitini test etmek için "&" karakterini kullanın.
  • Önceden getirme durumunu ve geri çağırmaları ilerlemenin genel göstergeleri olarak kullanın ancak sabit kodlanmış belirli doldurma seviyelerine veya geri çağırma sıralarına bağlı değildir. Önceden getirme durumu doldurma seviyesinin anlamı ve önceden getirme sırasında algılanan hataların davranışı değişebilir.

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

Kaynak uyumluluğu için planlama yapın

Daha önce de belirtildiği gibi, Khronos Group'un bir sonraki OpenSL ES sürümünde kaynak kodu uyumsuzlukları beklenmektedir. Olası değişim alanları şunlardır:

  • Arabellek sırası arayüzünün özellikle BufferQueue::Enqueue alanlarında, slBufferQueueCallback için parametre listesinde ve SLBufferQueueState.playIndex alanının adında önemli değişiklikler olması bekleniyor. Uygulama kodunuzun bunun yerine Android basit arabellek sıralarını kullanmasını öneririz. NDK ile sağlanan örnek kodda bu nedenle oynatma için Android basit arabellek sıralarını kullandık. (PCM'ye kayıt ve kod çözme işlemleri için de Android basit arabellek kuyruğunu kullanırız. Bunun nedeni, standart OpenSL ES 1.0.1'in arabellek sırası veri havuzuna kaydetmeyi veya kodunu çözmeyi desteklememesidir.)
  • Referans olarak iletilen giriş parametrelerine const, giriş değerleri olarak kullanılan SLchar * struct alanları ise eklenecek. Bunun için kodunuzda herhangi bir değişiklik yapmanız gerekmez.
  • Şu anda imzalı olan bazı parametreler için imzasız türlerin yerini alacaktır. SLint32 olan bir parametre türünü SLuint32 veya benzeri bir değer olarak değiştirmeniz ya da yayın eklemeniz gerekebilir.
  • Equalizer::GetPresetName, uygulama belleğine işaretçi döndürmek yerine dizeyi uygulama belleğine kopyalar. Bu önemli bir değişiklik olacağından, bu yöntemi çağırmamanızı veya kullanımınızı izole etmenizi öneririz.
  • struct türlerinde ek alanlar olacak. Çıkış parametreleri için bu yeni alanlar yoksayılabilir ancak giriş parametreleri için yeni alanların başlatılması gerekir. Neyse ki bu alanların hepsinin Android'in desteklemediği alanlarda bulunması bekleniyor.
  • Arayüz GUID'leri değişir. Bağımlılığı önlemek için arayüzlere GUID yerine sembolik adla başvuruda bulunun.
  • unsigned char olan SLchar değeri char olarak değişecek. Bu, öncelikli olarak URI veri bulucuyu ve MIME veri biçimini etkiler.
  • SLDataFormat_MIME.mimeType alanı pMimeType, SLDataLocator_URI.URI adı ise pURI olarak yeniden adlandırılacak. Kodunuzu bu değişiklikten izole etmek için SLDataFormat_MIME ve SLDataLocator_URI veri yapılarını alan adı yerine ayraç içine alınmış, virgülle 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 işaretli tam sayı, imzasız tam sayı veya kayan nokta olarak gösterilmesini belirtmesine izin vermez. Android uygulamasında, 8 bitlik verilerin imzasız tam sayı, 16 bitlik verilerin ise imzalı tam sayı olduğu varsayılır. Ayrıca, gerçek birimler miliHz olduğundan samplesPerSec alanı yanlış bir addır. Bu sorunların bir sonraki OpenSL ES sürümünde ele alınması beklenmektedir. Bu sürümde, uygulamanın temsili açıkça belirtmesine izin veren ve alan adını düzelten, genişletilmiş yeni bir PCM veri biçimi kullanıma sunulacaktır. Bu yeni bir veri biçimi olacağı ve mevcut PCM veri biçimi (kullanımdan kaldırılmış olsa da) kullanılmaya devam edeceğinden, kodunuzda hemen değişiklik yapmanız gerekmez.