Bu içerikte, yüksek kullanılabilirlik oluşturucuda (HAR) zil sesi çalma özelliği açıklanmaktadır.
Bir Audio sandığı, zil sesinin çalınmasını kontrol eden HAR uygulamasına AudioManager olarak sunar.
Gecikmeyi düşük tutmak için oynatma iş parçacıkları, uygulama kullanım süresi boyunca çalışır ve ses çalınmadığında boşta kalır ve işlemciyi serbest bırakır.
Terminoloji
- varlık
AudioAsset, oynatılabilir seslerle ilgilidir. Öğeler genellikle bilinir ve uygulamanın çalışma zamanında bulunur.- cihaz
AudioDevice, ses oynatma için ayrı bir veri yolu anlamına gelir. Cihaz, sistemin eriştiği donanımla ilgili en ayrıntılı birimdir. Standart SDVM uygulamasındaAudioDevice, tek bir Advanced Linux Sound Architecture (ALSA) PCM'yi ifade eder.- canlı oynatma
- Bir öğenin cihazda oynatılması. Yayınlar, planlandıkları andan tamamlanana, iptal edilene veya hata nedeniyle sona erene kadar devam eder.
Bileşenler
Şekil 1'de zil sesinin bileşen diyagramı gösterilmektedir:
Şekil 1. Bileşen şeması.
Ses sistemi ve PCM
Ses donanımı yapılandırması, standart HAR platformu soyutlama katmanı tasarımına uygundur ve har-platform-api bunu içerir.
HAR Audio sandığı, AudioDevice için yeni bir yapı tanımlar. Bu yapı, dahili HAR Audio sandığını ve oynatmayı etkileyen tüm veri yapıları için alanlar tanımlar. AudioDevice, platforma özel olabilecek ek parametreleri sarmalamak için de jeneriklerden yararlanır. tinyalsa durumunda, PlatformAudioDevice, ALSA PCM'nin tanımlayıcılarını ve özelliklerini içerir.
/// NOTE: The following code is a sample definition to help understanding, it is not a
/// representation of the final code/implementation.
AudioDevice<PlatformAudioDevice> {
/// Internal HAR Identifier for the device.
AudioDeviceID,
/// The size (in bytes) for chunks of audio data to stream to the device.
ChunkSize,
/// Properties necessary to control volume (details in "Mixer control" section).
VolumeControl,
/// Properties necessary to control spatialization (details in "Mixer control"
/// section).
SpatialControl,
/// Platform specific data for the AudioDevice.
/// E.g. ALSA properties and reference to opened PCM.
PlatformAudioDevice
}
/// Elaboration of the previously mentioned VolumeControl
VolumeControl {
/// Identifier for the control used to change volume.
ControlID,
/// Mapping between Decibel and control values. (see Mixer control section)
VolumeOutputIndex
}
Ses öğeleri
Bu bölümde, ses öğelerinin nasıl yapılandırıldığı ve uygulandığı açıklanmaktadır.
Yapılandırma
İlk HAR ses uygulaması, statik olarak yapılandırılmış ses öğelerini destekler. JSON yapılandırması, hangi öğelerin kullanılabileceğini ve hangi öğelerin WAV dosyaları olarak tanımlandığını belirler.
Uygulama, ses verileri oluşturmak için bir işlevi kabul eden daha genel bir öğe uygulaması aracılığıyla sentezlenmiş ve yayınlanmış ses öğelerini de destekler.
Uygulama
Öğeleri iki ayrı yapı kullanarak uygulayın: AudioAsset ve AudioStream.
AudioAsset, bir öğenin statik özelliklerini ve öğeyle ilgili olası dahili verilerin bulunduğu bir kapsayıcıyı tanımlar. AudioAsset AudioStream öğesinden, öğenin tek bir yayınlanabilir örneği olan AudioAsset AudioStream türetilebilir. AudioStream
Tek akış oynatmayla ilgili bir dahili durum içerir.
/// NOTE: The following code is a sample definition to help understanding, it is not a
/// representation of the final code/implementation.
/// Static properties and definition of an Asset.
AudioAsset {
/// Perform optional initialization steps, e.g. load bytes from file into memory.
/// Can also define lazy loading, to load data at first playback instead.
fn initialize(LazyLoad);
/// Create a new AudioStream from the asset.
fn create_stream() -> AudioStream;
/// More functions for metadata etc. of the asset.
...
}
/// Single streamable instance of an AudioAsset
AudioStream {
/// Gets the next bytes to play from the Asset together with if the current chunk of
/// bytes contains any control signals (e.g. fade-out).
fn get_playback(num_bytes: usize) -> ([u8], ControlSignals);
/// Gets playback Mode details used to handle special states of playback
/// e.g. when a chime gets is interrupted and put in "fade-out" mode.
fn playback_mode() -> PlaybackMode;
/// [0.0, 1.0] indication of how much of the stream was played.
fn progress() -> f32;
/// Reset the stream, e.g. if it should play again.
fn reset();
/// Time of which the stream was created.
fn created_at() -> Instant;
/// Additional metadata etc. for the stream.
...
}
Zil sesini oynatma
Bu bölümde, zil sesinin çalınmasıyla ilgili API ve prosedür açıklanmaktadır. Tek bir zil sesi çalmaya akış denir.
Yayınların yaşam döngüsü
Şekil 2'de bir akışın yaşam döngüsü gösterilmektedir:
Şekil 2. Akış oynatma ve etkinlikler
Şekil 2'de bu adımlar açıklanmaktadır:
Oynatma: Oynatılacak yayını planlayın.
Önceliklendirme: Oynatma önceliği, aşağıdakilerden hangisinin yapılacağına karar verir:
- Zili şimdi çal (ilk baytlar geldiğinde etkinliği başlatır)
- Çan sesini daha sonra çal (etkinlik duraklatıldı veya devam ettirildi)
- Çan sesine öncelik verme (iptal edilen etkinlik)
Mikser kontrolleri: Gerekirse mikser kontrollerini yapılandırılmış davranışlara göre güncelleyin.
Bayt yazma:
AudioDevicekonumuna bir bayt parçası yazın.Daha fazla veri: Akışta daha fazla veri varsa 2. adıma dönün.
Tekrarla: Yayın tekrarlanacaksa sıfırlayın ve 2. adıma (yeniden başlatılan etkinlik) dönün.
Tamamlandı: Yayın başarıyla tamamlandı (
FinishedSuccessfullyetkinliği).
Zil sesi, görüşmeleri duraklatma, devam ettirme veya durdurma çağrılarıyla istediğiniz zaman kesilebilir.
Zil öncelikleri
Bu mantık, zil sesi önceliklerini belirler:
Oynatma modu geçersiz kılmaları. Örneğin, sesin yavaşça kısıldığı modda, ses kısıma işlemi tamamlanana kadar zil sesine her zaman en yüksek öncelik verilir.
Belirtilen öncelik.
Eşit öncelikli olan daha yeni ise önce zil sesi çalınır.
Çanlar eşit önceliğe sahip olduğunda AudioManager, enum değeriyle oluşturulur.
API
Etkinlikler
Çan çalmaya başladığında bir etkinlik kanalı sağlanırsa HAR Audio oynatma sırasında bir dizi etkinlik yayınlar. Desteklenen etkinlikler şu örnekte gösterilmektedir:
/// NOTE: The following code is a sample definition to help understanding, it is not a
/// representation of the final code/implementation.
StreamBehaviors<PlatformStreamBehaviors> {
/// What should happen if the stream is interrupted for a higher priority stream.
/// e.g. pause-and-resume or cancel, will also define preference for fade-out.
OverrunBehavior,
/// Urgency, if interrupted streams are allowed to "fade-out", or if the stream should
/// urgently disrupt any other playback.
Optional<Urgency>,
/// Priority for the stream (or minimum if not specified).
Optional<StreamPriority>
/// Descriptor if a stream should be played on repeat.
Optional<RepeatBehavior>
/// Volume, if the stream should play at a specific volume.
Optional<Volume>
/// Spatialization, if the stream should play with specific spatialization.
Optional<Spatialization>
/// Optional generic for future expandability of the API, or pass-through of platform
/// specific Stream Behaviors
Optional<PlatformStreamBehaviors>
}
/// Plays a chime on specified device with given behaviors. StreamEvents are delivered
/// using the provided event transmitter. This method won't wait for any events.
fn play(AudioDeviceID, AssetID, StreamBehaviors, Option<EventTransmitter>) -> StreamController
/// Object used to control a Stream.
StreamController {
/// Gets the current state/metadata of a stream (e.g. ID, progress, playback_state).
fn metadata() -> StreamMetadata
/// Stops the stream.
fn stop()
/// Pauses a given stream, if the specified duration expires the stream is cancelled.
/// Timeout is required to make sure there are no paused streams left indefinitely
/// pending resumption.
fn pause(TimeoutDuration)
/// Resumes a paused stream.
fn resume()
/// Updates the spatialization of a playing stream.
fn set_spatialization(Spatialization)
/// Updates the volume of a playing stream.
fn set_volume(Volume)
}
Mikser kontrolü
Bu bölümde, ses seviyesinin ve uzamsallaştırmanın nasıl kontrol edildiği açıklanmaktadır.
Ses
HAR, hacmi tutarlı bir şekilde milibel cinsinden tanımlar. har-platform-api sandığı, milibelden kontrol sinyaline dönüştürme işlemini gerçekleştirir.
Milibel ile donanım gücü çıkışı arasındaki ilişki logaritmiktir ve farklı donanım ile hoparlör kurulumları arasında büyük ölçüde değişiklik gösterir. Sonuç olarak, AudioDevice (Ses Cihazı ve PCM) yapılandırmasının bir parçası olarak değerler arasında yapılandırma sağlayın ve dönüşüm, platform katmanı çağrılmadan önce gerçekleşmelidir.
Bu nedenle, PAL API'deki uygulama iki işlev tanımlar.
fn set_volume_millibel(AudioDeviceID, Millibel) {
/// Default implementation with conversion using DeviceConfig.
}
fn set_volume_control(AudioDeviceID, ControlValue);
set_volume_millibel için varsayılan uygulama, AudioDevice için sağlanan yapılandırmayı kullanır. Bu yapılandırma, referans milibel için bir dizi anahtar/değer çifti içerir. Bu çiftler, milibeli kontrol değerlerine dönüştürmek ve ardından dönüştürülen değerle set_volume_control işlevini çağırmak için kullanılır.
Bu tasarım, varsayılan bir eşleme sağlar ve sonraki uygulamaların varsayılan eşlemeyi geçersiz kılmasına olanak tanır.
Şekil 3. HAR ses akışı.
Uzamsallaştırma
Audio API, ses verilerinin hangi mekansal alanda oynatılacağını kontrol etme işlevini kullanıma sunar. Bu parametreler PAL katmanına iletilir ve donanım kontrolleri kullanılarak aşağı akışta uygulanır. Seçenekler, PAL API'nin bir parçası olarak şu şekilde tanımlanır:
/// NOTE: The following code is a sample definition to help understanding, it is not a
/// representation of the final code/implementation.
enum Spatialization {
Front,
FrontLeft,
FrontRight,
Center, // No spatialization
Rear,
RearLeft,
RearRight,
Right,
Left
}
Mikser kontrol katmanları
Bir öğede ve akışta ses seviyesini ve uzamsallaştırmayı tanımlayabilirsiniz. Akış önceliği tanımlarsanız akış, öğe tarafından tanımlanan kontrolleri geçersiz kılar.
İleti dizisi yönetimi
Ses yöneticisi, her AudioDevice örneği için bir ileti dizisi tutar. Her iş parçacığı bağımsız olarak çalışır. AudioManager ile oynatma iş parçacığı arasındaki etkileşimde, önceliğe göre sıralanmış paylaşılan bir akış sırası kullanılır.
ALSA çağrıları, verilerin ne zaman ayrıştırıldığını belirlemek için yoklama ile ASYNC yazma işlemlerini kullanır.
Şekil 4. İleti dizisi yönetim sırası.
Yoklama sırasında kontrol sinyalleri
Ses kartının baytları işlemesi beklenirken kontrol sinyalleri verilebilir. Örneğin, sesin geçişini veya uzamsallaştırılmasını değiştirmek için. Ses sisteminin durumunu almak için yoklama, AudioManager düzeyinde yapılandırılır veya varsayılan olarak 1 milisaniye olur. Oylama döngülerinin ardından oynatma iş parçacığı, zamanlanmış kontrol komutlarını özetleyip yayınlar.
Arabellek yönetimi
Kesinti gecikmesini en aza indirmek için cihaza yazılan arabellek boyutları küçük tutulur. Varsayılan olarak TinyALSA kullanılırken arabellek boyutu startup_threshold parametresiyle aynı olacak şekilde yapılandırılır.
TinyALSA, varsayılan değeri ayrılan cihaz arabelleğinin tamamının ikiye bölünmesi olarak tanımlar.
Yayın kesintisi
Akışlar kesintiye uğradığında, karta yazılan veriler boşaltılana kadar akışlar iş parçacığı önceliğini korur. Sonuç olarak, kesinti ile yeni yayın arasında bir geçiş dönemi yaşanır.
Örneğin,HAR'daki bir ses örneğinde:
- 3.072 boyutu
- 48.000 hızı
- İki örneklem boyutu
Bekleyen arabellek 3.072 ve 6.144 kare olarak hesaplanır. Bu da 64 ila 128 milisaniyelik bir kesinti gecikmesine neden olur. Üretim uygulaması daha küçük bir arabellek gerektirir.
Hata yönetimi ve riskler
Bu bölümde, hataların nasıl yönetildiği ve olası riskler açıklanmaktadır.
Eski akışlar ve kuyrukta açlık
AudioStream duraklatılabildiğinden ve oynatma yalnızca en yüksek öncelikli AudioStream örneğinden yapılabildiğinden, düşük öncelikli akışların aç kalmasına neden olan, büyüyen bir kuyruk riski ortaya çıkar.
Bunun olmasını önlemek için her kuyruk, yapılandırılabilir bir boyutta sınırlandırılır. Bu değer aşıldığında en düşük öncelikli yayın atılır.
İzleme ve uyarı
Üretimde, güvenlik monitörü oynatmanın beklendiği gibi gerçekleştiğini izlemek için ses özelliklerini takip eder.
AudioManager, gecikmelerle ilgili dahili istatistikleri ve günlük kaydı performansını tanımlayan bir işareti izler. Bu eşikler ayarlandıktan sonra, aşağıdaki durumlarda tüm hata ayıklama derlemeleri için uyarı günlükleri oluşturulur:
- Planlama ile oynatmanın başlatılması arasındaki süre
xmilisaniyeyi aşıyor. - (Kesintisiz bir akış için) öğe uzunluğu ve oynatma süresi
y'dan fazla farklılık gösteriyor.
Cihaz engellendi
Ses sisteminin yanıt vermemesi her zaman küçük bir risktir. Örneğin, sistemdeki başka bir işlem tarafından ayrılmış ve yazılmışsa bu durum yaşanabilir. Oynatma işlemi ayrı iş parçacıklarında eşzamansız olarak gerçekleştiğinden ve zil sesleri daha sonra çalınmak üzere sıraya alınabildiğinden bu durum, arayan uygulama için tamamen şeffaftır.
Bunu algılamak için, yeni bir zil sesi çalınmak üzere planlandığında iş parçacığı durum denetimi yapılır. Bir oynatma iş parçacığında dolu bir sıra varsa ve son bir saniyede yeni baytlar ayrıştırılmamışsa hata döndürülür.
Gelecekte cihazları yeniden başlatmayı / açmayı denemek gerekebilir ancak ilk uygulamada hatalar görünmez olmamalıdır.
Kod yapısı
Genel olarak, zil sesi çalmayla ilgili kod aşağıdaki paketlerde bulunur:
CRATE: display-safety/crates/(harry-app|harry)
Çan sesleri çalmak için çağrı gönderen mevcut HAR uygulaması.
NEW CRATE: display-safety/crates/audio
YENİ: Ses kontrolü ve oynatmayı yönetmek için kullanılan Crate (işlevlerin çoğu burada bulunur).
CRATE: display-safety/crates/har-platform-api/audio
Ses için gereken tüm sistem çağrıları dahil PAL.
CRATE: display-safety/crates/har-platform-(android|linux)/audio
TinyALSA kullanılarak oynatma için tinyalsa-rs numarasına yapılan aramalar. QNX desteği ilk çözümde uygulanmamıştır ve daha fazla platform desteklendikçe bu destek genişleyecektir.
TINYALSA PAL: display-safety/crates/tinyalsa-audio
Oynatma için TinyALSA'ya özgü kod. Bu, Android ve Linux platform uygulamaları tarafından kullanılır.
CRATE: display-safety/crates/tinyalsa-rs
TinyALSA C uygulaması için Rust bağlamaları
Rust uygulama ayrıntıları
Uygulamayla ilgili bazı ayrıntılar:
- Tüm API işlevleri,
Result<X, AudioError>değerini döndürür. BuradaX, () veya bir dönüş değeridir. - Hiçbir API işlevi
unsafeolarak işaretlenmemiş. - Mutex ve senkronizasyon mekanizmaları dahili olup
AudioManagerAPI'de kullanıma sunulmaz.
Sahiplik modeli ve AudioManager
Ses sistemiyle tüm uygulama etkileşimi
AudioManagerveyaAudioManager'dan döndürülen nesneler aracılığıyla gerçekleşir.AudioManageriş parçacığı açısından güvenlidir.AudioManager, HARry uygulamasında bir kez oluşturulur veMoved,Looper'nin sahipliği için kullanılır.AudioManager, başlatılan oynatma iş parçacıklarını yönetmek içintokio_util::CancellationTokenjetonu kullanır. Bu sayede,AudioManagerDroppedise iş parçacıklarının sonlandırılması ve kaynakların serbest bırakılması sağlanır.AudioManager, birden fazla örneğin oluşturulmasını açıkça engellemez. Birden fazla örnek varsawarnseviyesinde günlüğe kaydedilir.
Ortak sahiplik
Bir dizi nesne, özel erişimle birlikte sarılmış ve senkronize edilmiş ortak sahipliğe sahip. Bu mekanizmalar AudioManager API'sinde kullanıma sunulmaz ancak ses ve PAL uygulamaları için dahili olarak kullanılır.
AudioDevice- Açılan (işleyiciye sahip) her donanım referansı (ör. TinyALSA PCM) özel erişime sahiptir. SMP Tasarımı'na bakın.AudioStreamörnekleri, uygulama tarafından kontrol edilebildiği ve aynı anda oynatma iş parçacığı tarafından erişilebildiği için oynatma için planlandıktan sonra özel erişime sahiptir.Oynatma iş parçacığı, oynatma sırasında kilitleri tutmaz ancak oynatılacak bir sonraki arabelleğin değişmez bir anlık görüntüsünü oluşturur ve bir sonraki arabellek ayrıştırılana kadar değişiklikleri dikkate almaz.
Her oynatma iş parçacığında bir oynatma sırası bulunur. Bu sıra,
AudioManagerile oynatma iş parçacığı arasında paylaşılan bir referanstır. Bu nedenle, iş parçacığının değişiklikler için özel erişime ihtiyacı vardır.Akışı olmayan iş parçacıkları, yeni veriler algılandığında uyandırma etkinlikleri almak için
Condvardeğişkeniyle boşta kalır. Bu mekanizma, ortak mülkiyete sahiptir.
Bağımlılıklar
Crates ve audio crate, Android kaynak ağacında oluşturulması onaylanmayan crate'lere olan bağımlılıkları azaltmak için tasarlanmıştır. Dahil edilen crates listesine bakın.
Android ve Linux için aşağı akış platformu uygulamaları, TinyALSA ve mevcut ekran güvenliği tinyalsa-rs paketine bağlıdır.
Kalite özellikleri
Güvenilirlik
Ses oynatma güvenlik açısından kritik olsa da bu tasarım, güvenlik izlemenin uygulanmasını kapsamaz. Donanımda ve üretimde ses oynatma güvenilirliğini doğrulamak için bunu ayrı bir çalışmayla uygulayın.
Ölçeklenebilirlik
Cihaz başına bir iş parçacığı yaklaşımı, farklı donanım kurulumlarına ölçeklenecek şekilde tasarlanmıştır. Her ileti dizisi öncelikle boşta olduğundan, verileri beklediğinden veya cihazın yazılı verileri işlemesini beklediğinden işlemciyi zorlamamalı ya da sistemde performans açısından yoğun olmamalıdır.
Verilerin yalnızca tek bir cihazda oynatılmasına yönelik tasarım kararı, tüm çıkış denetimi için mikser denetim komutlarıyla birlikte, tam çıkışın ses donanımı tarafından işlenmesini sağlar ve gelecekteki sistemler için ölçeklenebilir olmalıdır.
Gecikme
Gecikme, ses sistemi için kritik öneme sahiptir. Bu nedenle, uygulamadan sonra sistemin gecikmesi için bir dizi hizmet düzeyi hedefi (SLO) tanımlanır. Gecikme durumunu sürekli olarak izlemek için sistem günlüklerinde tanımlanan tüm hata ayıklama derlemelerinde tanımlanan SLO'ları karşılamayan izleme.
Üretim sürümlerinde, izleme verileri günlükleri kullanmak yerine ses uygulaması dışındaki bazı sistemlere aktarılır.
Test ve test stratejisi
Kratlar ve ses kratı, test kapsamı ile tasarlanır. Tüm özelliklerin test edildiğini onaylamak için sahte bir platform uygulaması ekledik.
Donanım ve bağlamaların karmaşıklığı, platform uygulamaları için kapsamlı test kapsamını engeller. Çözümü donanımda ve Cuttlefish emülatöründe manuel olarak test etmek için örnek uygulamalar sunuyoruz.
Belgeler
Audio crates/audio içindeki README.md dosyası, AudioManager'nin nasıl kullanılacağını açıklar. crates/audio/examples aşağıdaki konularla ilgili örnekler içerir:
- Bir platform uygulayın.
AudioManagerörneği oluşturun.WavAssetvideo klibini oynatın.- Özel işlev öğesini tekrarlı olarak oynatma
- Oynatma etkinliklerini günlüğe kaydedin.