يوضّح هذا المحتوى كيفية تشغيل الرنين في أداة العرض ذات مدى التوفّر العالي (HAR).
تعرض حزمة Audio AudioManager لتطبيق HAR، الذي يتحكّم في تشغيل
رنين الجهاز.
للحفاظ على سرعة الاستجابة، يتم تشغيل سلاسل التنفيذ الخاصة بالتشغيل طوال مدة استخدام التطبيق، وتتوقف مؤقتًا وتتوقف عن العمل عندما لا يتم تشغيل أي صوت.
المصطلحات
- مادة عرض يشير الرمز
AudioAssetإلى الصوت القابل للتشغيل. مواد العرض معروفة بشكل عام ومتاحة في وقت تشغيل التطبيق.- جهاز يشير
AudioDeviceإلى ناقل منفصل لتشغيل الصوت. والجهاز هو الوحدة الأكثر تفصيلاً المرتبطة بالأجهزة التي يمكن للنظام الوصول إليها. في عملية التنفيذ العادية لـ SDVM، يشيرAudioDeviceإلى تنسيق PCM واحد من Advanced Linux Sound Architecture (ALSA).- البث
- هي حالة تشغيل أحد الأصول على جهاز. تستمر عمليات البث المباشر من لحظة جدولتها إلى أن تكتمل أو يتم إلغاؤها أو تنتهي بخطأ.
المكونات
يعرض الشكل 1 مخطط المكوّنات الخاص بتطبيق Chime:
الشكل 1 مخطط المكوّنات
الجهاز الصوتي وPCM
يتبع إعداد أجهزة الصوت تصميم طبقة تجريد منصة HAR العادي، ويتضمّن har-platform-api هذا الإعداد.
يحدّد صندوق HAR Audio بنية جديدة لـ AudioDevice، والتي تحدّد حقولاً لجميع بنى البيانات التي تؤثر في صندوق HAR Audio الداخلي والتشغيل. تستخدِم AudioDevice أيضًا أنواعًا عامة لتضمين المَعلمات الإضافية المحتملة الخاصة بالنظام الأساسي. في حالة tinyalsa،
تحتوي PlatformAudioDevice على واصفات وخصائص ALSA PCM.
/// 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
}
مواد العرض الصوتية
يوضّح هذا القسم كيفية إعداد مواد عرض الصوت وتنفيذها.
الإعداد
يتيح التنفيذ الأوّلي لصوت HAR مواد عرض صوتية تم ضبطها بشكل ثابت. يحدّد إعداد JSON مواد العرض المتاحة ومواد العرض المحدّدة كملفات WAV.
يتيح التنفيذ أيضًا مواد عرض صوتية مركّبة ومباشرة من خلال تنفيذ أكثر عمومية لمواد العرض، ما يتيح استخدام دالة لإنشاء بيانات صوتية.
التنفيذ
نفِّذ مواد العرض باستخدام بنيتَين منفصلتَين، هما AudioAsset وAudioStream.
تحدّد AudioAsset الخصائص الثابتة لمادة العرض، وهي عبارة عن حاوية تتضمّن البيانات الداخلية المحتملة المرتبطة بمادة العرض. يمكن استخلاص AudioAsset AudioStream، وهو نسخة واحدة من مادة العرض يمكن بثها. تحتوي السمة AudioStream
على حالة داخلية مرتبطة بتشغيل البث الفردي.
/// 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.
...
}
تشغيل الجرس
يوضّح هذا القسم واجهة برمجة التطبيقات والإجراءات اللازمة لتشغيل جرس. يُشار إلى تشغيل رنين واحد باسم بث.
مراحل نشاط بث
يوضّح الشكل 2 دورة حياة البث:
الشكل 2 تشغيل البث والأحداث
يوضّح الشكل 2 هذه الخطوات:
تشغيل: تحديد موعد لبث المحتوى
تحديد الأولوية: يحدّد خيار تحديد أولوية التشغيل ما إذا كان يجب:
- تشغيل الرنين الآن (بدأ الحدث عند تلقّي البايتات الأولى)
- تشغيل الجرس لاحقًا (حدث متوقف مؤقتًا أو مستأنف)
- إلغاء أولوية الجرس (الحدث الملغى)
عناصر التحكّم في الخلاط: إذا لزم الأمر، عدِّل عناصر التحكّم في الخلاط استنادًا إلى السلوكيات التي تم ضبطها.
كتابة وحدات بايت: اكتب مجموعة من وحدات البايت إلى
AudioDevice.المزيد من البيانات: إذا كان مصدر البيانات يتضمّن المزيد من البيانات، ارجع إلى الخطوة 2.
التكرار: إذا كان من المفترض تكرار البث، أعِد الضبط وارجع إلى الخطوة 2 (حدث تمت إعادة تشغيله).
مكتملة: اكتملت عملية البث بنجاح (حدث
FinishedSuccessfully).
يمكن إيقاف الرنين مؤقتًا أو استئنافه أو إيقافه نهائيًا في أي وقت.
أولويات الرنين
تحدّد هذه المنطق أولويات الرنين:
عمليات إلغاء وضع التشغيل على سبيل المثال، يتم دائمًا منح صوت الرنين في وضع التلاشي الأولوية القصوى إلى أن يكتمل التلاشي.
الأولوية المحدّدة
إذا كان الرنين ذو الأولوية المتساوية أحدث، سيتم تشغيله أولاً.
عندما تكون الإشعارات الصوتية ذات أولوية متساوية، يتم إنشاء AudioManager بالقيمة enum.
واجهة برمجة التطبيقات
الأحداث
إذا تم توفير قناة أحداث عند بدء الرنين، سيُصدر HAR Audio عددًا من الأحداث أثناء التشغيل. يتم عرض الأحداث المتوافقة في المثال التالي:
/// 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)
}
التحكّم في الخلاط
يوضّح هذا القسم كيفية التحكّم في مستوى الصوت والتجسيم.
مستوى الصوت
تحدّد HAR مستوى الصوت بشكل ثابت بوحدة الملّيبل. تتعامل حزمة har-platform-api مع عملية التحويل من وحدات الميليبل إلى إشارة التحكّم.
العلاقة بين وحدات الميليبل ومستوى طاقة الأجهزة هي علاقة لوغاريتمية، وتختلف بشكل كبير بين إعدادات الأجهزة ومكبرات الصوت المختلفة. نتيجةً لذلك، يجب توفير إعدادات بين القيم كجزء من إعدادات AudioDevice
(جهاز الصوت وPCM)، ويجب إجراء التحويل قبل استدعاء طبقة النظام الأساسي.
نتيجةً لذلك، يحدّد التنفيذ في واجهة برمجة التطبيقات PAL دالتَين.
fn set_volume_millibel(AudioDeviceID, Millibel) {
/// Default implementation with conversion using DeviceConfig.
}
fn set_volume_control(AudioDeviceID, ControlValue);
يستخدم التنفيذ التلقائي لـ set_volume_millibel الإعدادات المتوفّرة لـ AudioDevice، بما في ذلك مجموعة من أزواج المفتاح/القيمة الخاصة بالملّيبل المرجعي - عنصر التحكّم، وتحويل الملّيبل إلى قيم عنصر التحكّم، ثم استدعاء الدالة set_volume_control بالقيمة المحوّلة.
يوفّر هذا التصميم إعدادًا تلقائيًا ويتيح عمليات التنفيذ اللاحقة إلغاء عملية الربط التلقائية.
الشكل 3 مسار الصوت في ملف HAR
التجسيم
تتيح واجهة برمجة التطبيقات Audio API وظائف للتحكّم في المنطقة المكانية التي يجب تشغيل البيانات الصوتية فيها. يتم تمرير هذه المَعلمات إلى طبقة PAL، ويمكن تطبيقها في المراحل اللاحقة باستخدام عناصر التحكّم في الأجهزة. يتم تحديد الخيارات كجزء من واجهة برمجة التطبيقات PAL على النحو التالي:
/// 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
}
مستويات التحكّم في "خلاط الأغاني"
يمكنك تحديد مستوى الصوت والتجسيم في أحد الأصول وفي بث. في حال تحديد أولوية بث، سيتم تجاهل عناصر التحكّم التي يحدّدها الأصل.
إدارة سلاسل المحادثات
تحتفظ أداة إدارة الصوت بسلسلة محادثات واحدة لكل مثيل AudioDevice. ويعمل كل مؤشر ترابط بشكل مستقل. يستخدم التفاعل بين AudioManager وسلسلة تشغيل الفيديو قائمة مشتركة لتدفق البيانات مرتبة حسب الأولوية.
تستخدم طلبات ALSA عمليات كتابة غير متزامنة مع الاقتراع لتحديد وقت استيعاب البيانات.
الشكل 4 تسلسل إدارة سلسلة المحادثات
إشارات التحكّم أثناء الاستطلاع
عند انتظار بطاقة الصوت لمعالجة وحدات البايت، يمكن إصدار إشارات التحكّم. على سبيل المثال، لتغيير التلاشي أو التجسيم الصوتي. يتم ضبط عملية الاستقصاء للحصول على حالة جهاز الصوت على مستوى AudioManager أو يتم ضبطها تلقائيًا على 1 مللي ثانية. بعد كل دورة استطلاع، تعالج سلسلة التشغيل أي أوامر تحكّم مؤقتة وتصدرها.
إدارة المخزن المؤقت
لتقليل وقت استجابة الانقطاع، يتم إبقاء أحجام المخزن المؤقت المكتوبة على الجهاز صغيرة. عند استخدام TinyALSA كإعداد تلقائي، يتم ضبط حجم ذاكرة التخزين المؤقت ليكون هو نفسه قيمة المَعلمة startup_threshold.
تحدِّد TinyALSA القيمة التلقائية على أنّها مخزن مؤقت الجهاز المخصّص بالكامل
مقسومًا على اثنين.
انقطاع البث
عندما يتم إيقاف عمليات البث مؤقتًا، تحتفظ عمليات البث بأولوية سلسلة المحادثات إلى أن يتم استنفاد البيانات التي تمت كتابتها على البطاقة. نتيجةً لذلك، تحدث فترة انتقالية بين الانقطاع والبث الجديد.
على سبيل المثال، إذا كانت عيّنة صوتية في ملف HAR تستخدم:
- حجم 3,072
- معدّل 48,000
- حجم العينة من شخصين
يتم احتساب المخزن المؤقت المعلق على أنّه 3,072 و6,144 إطارًا، ما يؤدي إلى تأخير في الانقطاع يتراوح بين 64 و128 مللي ثانية. سيتطلّب التنفيذ في مرحلة الإنتاج مخزنًا مؤقتًا أصغر.
إدارة الأخطاء والمخاطر
يوضّح هذا القسم كيفية إدارة الأخطاء والمخاطر المحتملة.
توقف البث المباشر ونقص المحتوى في قائمة الانتظار
بما أنّه يمكن إيقاف AudioStream مؤقتًا، وبما أنّه لا يمكن تشغيل المحتوى إلا من مثيل AudioStream ذي الأولوية القصوى، يزداد خطر عدم توفّر البث ذي الأولوية المنخفضة.
ولتجنُّب حدوث ذلك، يتم تحديد الحد الأقصى لحجم كل قائمة انتظار. وعند تجاوز هذه القيمة، يتم تجاهل البث ذي الأولوية الأدنى.
المراقبة والتنبيه
في مرحلة الإنتاج، يتتبّع نظام مراقبة الأمان ميزات الصوت للتأكّد من أنّ التشغيل يتم على النحو المتوقّع.
يراقب AudioManager الإحصاءات الداخلية الخاصة بمدد الاستجابة وعلامة تحدّد أداء التسجيل. بعد ضبط هذه الحدود، يتم إنشاء سجلات تحذير لجميع إصدارات تصحيح الأخطاء في الحالات التالية:
- تتجاوز المدة بين تحديد موعد التشغيل وبدء التشغيل
xمللي ثانية. - (بالنسبة إلى بث غير متقطّع) يختلف طول مادة العرض ووقت التشغيل بأكثر من
y%.
تم حظر الجهاز
هناك دائمًا احتمال بسيط بأن يصبح جهاز الصوت غير مستجيب، على سبيل المثال، إذا تم تخصيصه وكتابته بواسطة عملية أخرى في النظام. بما أنّ التشغيل يتم بشكل غير متزامن في سلاسل محادثات منفصلة، وبما أنّه يمكن وضع الإشعارات في قائمة الانتظار لتشغيلها لاحقًا، فإنّ ذلك لا يؤثر على التطبيق الذي يجري المكالمة.
لرصد ذلك، يتم إجراء التحقق من صحة سلسلة التعليمات كلما تم تحديد موعد لتشغيل جرس جديد، ويتم عرض خطأ إذا كانت سلسلة التعليمات الخاصة بالتشغيل تحتوي على صفّ ممتلئ ولم يتم استيعاب أي وحدات بايت جديدة خلال الثانية الأخيرة.
قد يكون من الضروري في المستقبل محاولة إعادة تشغيل الأجهزة أو فتحها، ولكن في عملية التنفيذ الأولية، يجب ألا تكون الأخطاء غير مرئية.
بنية الرمز
على مستوى عالٍ، يتوفّر الرمز البرمجي المرتبط بتشغيل الرنين في الحزم التالية:
CRATE: display-safety/crates/(harry-app|harry)
تطبيق HAR الحالي الذي يرسل طلبات لتشغيل الأجراس.
NEW CRATE: display-safety/crates/audio
جديد: حاوية لإدارة عناصر التحكّم في الصوت وتشغيله (تتوفّر معظم الوظائف هنا).
CRATE: display-safety/crates/har-platform-api/audio
PAL بما في ذلك جميع طلبات النظام المطلوبة لتشغيل الصوت
CRATE: display-safety/crates/har-platform-(android|linux)/audio
مكالمات إلى tinyalsa-rs لتشغيل الصوت باستخدام TinyALSA لا تتضمّن الحلول الأولية دعم نظام التشغيل QNX، وسيتم توفير هذا الدعم مع إتاحة المزيد من المنصات.
TINYALSA PAL: display-safety/crates/tinyalsa-audio
الرمز الخاص بتطبيق TinyALSA للتشغيل يتم استخدام هذا المعرّف في عمليات تنفيذ منصتَي Android وLinux.
CRATE: display-safety/crates/tinyalsa-rs
أدوات ربط Rust لتنفيذ TinyALSA C
تفاصيل التنفيذ في Rust
في ما يلي بعض تفاصيل التنفيذ المحدّدة:
- تعرض جميع دوال واجهة برمجة التطبيقات
Result<X, AudioError>حيث تكونXإما () أو قيمة معروضة. - لم يتم وضع علامة
unsafeعلى أي من دوال واجهة برمجة التطبيقات. - إنّ آليات Mutex والمزامنة داخلية ولا يتم عرضها في واجهة
AudioManagerAPI.
نموذج الملكية وAudioManager
يتم إجراء جميع تفاعلات التطبيق مع نظام الصوت من خلال
AudioManagerأو الكائنات التي يتم عرضها منAudioManager.AudioManagerآمن للاستخدام في سلاسل التعليمات البرمجية المتعددة.يتم إنشاء مثيل
AudioManagerمرة واحدة في تطبيق HARry، ويتم إنشاءMovedلكي يكونLooperهو المالك.يستخدم
AudioManagerرمزًا مميزًاtokio_util::CancellationTokenلإدارة سلاسل التشغيل التي بدأها، ما يضمن إنهاء السلاسل وإتاحة الموارد إذا كانAudioManagerDropped.لا يمنع
AudioManagerبشكل صريح إنشاء مثيلات متعددة. إذا كان هناك أكثر من مثيل واحد، يتم التسجيل بالمستوىwarn.
الملكية المشتركة
تمت مشاركة ملكية عدد من العناصر وتغليفها ومزامنتها مع إمكانية الوصول الحصري. لا يتم عرض هذه الآليات في واجهة برمجة التطبيقات AudioManager، ولكنها تكون مضمّنة في عمليات تنفيذ الصوت وPAL.
AudioDevice- يمكن لكل مرجع للأجهزة (مثل TinyALSA PCM) تم فتحه (لديه معرّف) الوصول بشكل حصري. اطّلِع على تصميم SMP.تتمتّع مثيلات
AudioStreamبإذن وصول حصري بعد تحديد موعد تشغيلها، لأنّه يمكن للتطبيق التحكّم فيها ويمكن لخيط التشغيل الوصول إليها في الوقت نفسه.لا يحتفظ مؤشر ترابط التشغيل بأقفال أثناء التشغيل، بل ينشئ لقطة غير قابلة للتغيير من المخزن المؤقت التالي المطلوب تشغيله، ولا يأخذ في الاعتبار أي تغييرات إلى أن يتم تحليل المخزن المؤقت التالي.
يحتوي كل مؤشر ترابط تشغيل على قائمة انتظار تشغيل، ومرجع مشترك بين
AudioManagerومؤشر ترابط التشغيل. نتيجةً لذلك، يجب أن يكون لدى سلسلة المحادثات إذن وصول حصري لإجراء التغييرات.تصبح سلاسل التعليمات التي لا تتضمّن عمليات بث غير مستخدمة من قِبل أي برنامج حاليًا مع المتغيّر
Condvarلتلقّي أحداث التنشيط عند رصد بيانات جديدة. تتضمّن هذه الآلية ملكية مشتركة.
الطلبات التابعة
تم تصميم الحزم وصناديق المحتوى الصوتي للحدّ من الاعتماد على الحزم التي لم تتم الموافقة على إنشائها في شجرة المصدر لنظام Android. اطّلِع على قائمة الحِزم المضمّنة.
تعتمد عمليات تنفيذ المنصات في الإصدارات الأقدم من Android وLinux على TinyALSA وحزمة tinyalsa-rs الحالية الخاصة بأمان العرض.
سمات الجودة
الموثوقية
مع أنّ تشغيل الصوت مهم جدًا من ناحية الأمان، لا يغطّي هذا التصميم تنفيذ عملية مراقبة الأمان. يجب تنفيذ ذلك في خطوة منفصلة للتحقّق من موثوقية تشغيل الصوت على الأجهزة وفي مرحلة الإنتاج.
قابلية التوسّع
يهدف أسلوب استخدام سلسلة محادثات واحدة لكل جهاز إلى التوسّع ليشمل إعدادات الأجهزة المختلفة. بما أنّ كل سلسلة تعليمات تكون في وضع الخمول في الغالب، أو تنتظر البيانات، أو تنتظر أن يستوعب الجهاز البيانات المكتوبة، من المفترض ألا تستهلك الكثير من موارد المعالج أو تتطلّب أداءً عاليًا من النظام.
إنّ قرار التصميم الذي يقضي بتشغيل البيانات على جهاز واحد فقط، بالإضافة إلى أوامر التحكّم في الخلاط لجميع عناصر التحكّم الأخرى في الإخراج، يضمن أن يتم التعامل مع الإخراج الدقيق بواسطة أجهزة الصوت، ومن المفترض أن يكون قابلاً للتوسيع في الأنظمة المستقبلية.
وقت الاستجابة
تُعدّ مدة الاستجابة عاملاً مهمًا لنظام الصوت، لذا بعد التنفيذ، يتم تحديد مجموعة من أهداف مستوى الخدمة (SLO) لمدّة استجابة النظام. لمراقبة سلامة وقت الاستجابة بشكل مستمر، يجب أن تتضمّن سجلّات النظام عمليات مراقبة لا تستوفي مؤشرات SLO المحدّدة في جميع إصدارات تصحيح الأخطاء.
بالنسبة إلى إصدارات الإنتاج، يتم تمرير بيانات المراقبة إلى بعض الأنظمة الخارجية لعملية تنفيذ الصوت، بدلاً من الاعتماد على السجلات.
الاختبار واستراتيجية الاختبار
تم تصميم الحزم وحزمة الصوت مع توفير تغطية الاختبار. أضفنا عملية تنفيذ وهمية للنظام الأساسي للتأكّد من اختبار جميع الإمكانات.
يؤدي تعقيد الأجهزة وعمليات الربط إلى عدم توفّر تغطية اختبارية شاملة لعمليات تنفيذ المنصة. نوفّر عمليات تنفيذ نموذجية لاختبار الحل يدويًا على الأجهزة وعلى محاكي Cuttlefish.
الوثائق
يوضّح ملف README.md في Audio crates/audio كيفية استخدام AudioManager. يحتوي crates/audio/examples على أمثلة لما يلي:
- استخدام منصة
- أنشئ مثيلاً من
AudioManager. - تشغيل
WavAsset. - تشغيل مادة عرض دالة مخصّصة بشكل متكرّر
- تسجيل أحداث التشغيل