WPF, Відтворення WAV-аудіо

Платформа .NET Framework має багату історію підтримки звуку. Версії 1.0 і 1.1 не пропонували ніякого керованого способу відтворення аудіо, а коли довгоочікувана підтримка, нарешті, з'явилася в .NET 2.0, вона була представлена ​​у формі класуSoundPlayer (який можна знайти в "малонаселеному"). простір імен System.Media). Клас SoundPlayer досить обмежений: він може відтворювати лише файли у форматі WAV, не підтримує відтворення одночасно більше одного звуку і зовсім не надає можливостей керування жодними аспектами відтворення аудіо (наприклад, гучністю та балансом).

Щоб отримати ці можливості, розробники, які використовують Windows Forms, змушені були працювати з бібліотекою некерованого коду quartz.dll.Бібліотека quartz.dll - ключова частина DirectX, і вона присутня в медіапрогравачі Windows і операційній системі Windows. (Той самий компонент відомий під назвою DirectShow, а попередні версії називалися ActiveMovie.)

Клас SoundPlayer підтримується у програмах WPF. Якщо змиритися з його суттєвими обмеженнями, то можна сказати, що він пропонує найпростіший і найлегший спосіб додавання роботи з аудіо в додатки. Клас SoundPlayer також упаковується у клас SoundPlayerAction. який дозволяє відтворювати звук через декларативний тригер (замість написання кількох рядків коду C# в обробнику подій). У наступних розділах буде представлений короткий огляд обох класів, а потім описи більш потужних WPF-класів MediaPlayer і MediaElement.

Клас SoundPlayer

Щоб відтворити звук за допомогою класу SoundPlayer, потрібно виконати наведені нижче кроки:

Створити екземплярSoundPlayer.

Вказати звуковий вміст, встановивши або якістьStream, або якістьSoundLocation. Якщо є об'єкт Stream, що містить звук у форматі WAV, використовуйте властивість Stream. Якщо є шлях до файлу або URL, що вказує на файл WAV, застосовуйте властивість SoundLocation.

Якщо аудіо-вміст зберігається у вигляді двійкового ресурсу і вбудований у додаток, то буде потрібний доступ до нього у вигляді потоку та використання властивості SoundPlayer.Stream. Причина в тому, що SoundPlayer не підтримує синтаксис упакованих URL у WPF.

Встановивши властивість Stream або SoundLocation, можна змусити SoundPlayer завантажити аудіодані, викликавши метод Load() або LoadAsync(). Метод Load() найпростіший — він зупиняє виконання коду до того часу, поки весь звуковий фрагмент буде завантажено на згадку. LoadAsync() виконує свою роботу в іншому потоці та по завершенні ініціює подію LoadCompleted.

Формально використовувати Load() чи LoadAsync() не обов'язково. Примірник SoundPlayer завантажує аудіодані за необхідності, коли викликається метод Play() або PlaySync(). Однак явно завантажити аудіо-фрагмент – гарна ідея; це не тільки дозволить знизити накладні витрати при багаторазовому відтворенні, але також спростить обробку винятків, пов'язаних з файловими проблемами, окремо від винятків, викликаних причинами процесу відтворення.

Після цього можна викликати PlaySync(), який призупинить код на час відтворення аудіо-фрагмента, або застосувати Play() для відтворення в іншому потоці, забезпечуючи інтерфейсу програми здатність реагувати на дії користувача. Єдиний інший доступний варіант - це метод PlayLooping(), що відтворює аудіо-фрагмент асинхроннонескінченному циклі (що ідеально для саундтреків). Щоб зупинити поточне відтворення будь-якої миті, необхідно викликати метод Stop().

У наступному фрагменті коду демонструється найпростіший підхід до завантаження та асинхронного відтворення аудіофайлу:

До цього часу в коді передбачалося, що аудіофайл присутній у тому ж каталозі, що й скомпільований додаток. Однак завантажувати SoundPlayer аудіо з файлу не обов'язково. Для коротких звуків, які відтворюються в кількох місцях програми, можливо, розумніше вбудувати звукові файли безпосередньо в скомпільовану збірку у вигляді двійкових ресурсів (не плутайте їх із декларативними ресурсами, що визначаються в коді XAML). Ця техніка працює зі звуковими файлами так само добре, як і із графічними зображеннями.

Наприклад, якщо додати файл ding.wav як ресурс на ім'я Ding (просто перейдіть до вузла Properties --> Resources (Властивості --> ресурси) у вікні Solution Explorer і скористайтеся підтримкою візуального конструктора), то можна буде застосувати наступний код для його відтворення:

Клас SoundPlayer не надто добре працює з великими аудіофайлами, оскільки він повинен завантажити весь файл повністю. Може здатися, що цю проблему можна вирішити, розбивши великий аудіофайл на шматки, але клас SoundPlayer не призначений для цього. Не існує простого способу такої синхронізації SoundPlayer, щоб він міг відтворити багато аудіофрагментів один за одним, оскільки він не забезпечує жодних засобів для організації черг. Щоразу, коли викликається метод PlaySound() або Play(), поточне відтворення зупиняється. Обхідні шляхи можливі, але набагато краще натомість скористатися класом MediaElement.

КласSoundPlayerAction

Клас SoundPlayerAction дозволяє зручніше використовувати клас SoundPlayer. Клас SoundPlayerAction успадкований від TriggerAction, який дозволяє використовувати його у відповідь на будь-яку подію.

Нижче наведено розмітку кнопки, яка застосовує SoundPlayerAction для підключення події Click до звуку. Тригер організований так, що його можна застосувати до багатьох кнопок (якщо перенести його в колекцію Resources):

Під час використання SoundPlayerAction звук завжди відтворюється асинхронно.

Системні звуки

Однією з особливостей операційної системи Windows є здатність відображати аудіофайли на певні системні події. Поряд із SoundPlayer у WPF також наданоклас SystemSounds, що дозволяє отримати доступ до найчастіше використовуваних з цих звуків і задіяти їх у власних додатках. Ця техніка працює краще, якщо все, що потрібно, це прості короткі звуки, призначені для того, щоб повідомити про завершення якоїсь тривалої операції або подати сигнал попередження.

На жаль, клас SystemSounds заснований на функції MessageBeep з API-інтерфейсу Win32, внаслідок чого він забезпечує доступ тільки до наступних загальних системних звуків:

Asterisk (Питальний знак)

Вієр (Сповістка про отримання пошти)

Hand (Критична помилка)

Клас SystemSounds надає властивість кожному з цих звуків, повертає об'єкт SystemSound, який можна використовуватиме відтворення звуку з допомогою методу Play(). Наприклад, для відтворення звуку Віяло в коді служить наступний рядок:

Щоб вказати системі, які файли WAV слід використовувати для кожного системного звуку, увійдіть у панель керування та виберіть піктограму Звуки тааудіопристрою (в Windows ХР) або Звук (у Windows Vista або Windows 7).