Управление громкостью звукового устройства в Windows на C#


Громкость звукового устройства определяет, насколько громко воспроизводятся звуки, как для текущего приложения, так и для всей операционной системы. Эту громкость можно регулировать для левого и правого каналов независимо с помощью функций Windows API.

Многие компьютеры оснащены звуковой картой или встроенным чипсетом, который позволяет воспроизводить цифровое аудио, например, в формате аудиофайла wav (WAV). Некоторые аппаратные средства обеспечивают одноканальный или моноканальный выход. Другое оборудование обеспечивает стереозвук с отдельными аудиоканалами для левого и правого динамиков. Для некоторых программных приложений вы можете захотеть управлять громкостью этих каналов независимо или вместе.

Более старые версии Microsoft Windows позволяют изменять громкость для всех приложений с помощью функций Windows API, которые вы можете вызывать с помощью служб вызова платформы (P/Invoke). Более современные версии операционной системы позволяют независимо изменять громкость звукового устройства для приложений, позволяя пользователю уменьшать громкость для некоторых программ и увеличивать ее для других программ.

В этой статье мы создадим проект Windows Forms, который позволит изменять звук. Мы включим возможность синхронизации левого и правого каналов или их изменения независимо. Мы также добавим кнопку отключения звука и кнопку, которая воспроизводит звук.

Функции Windows API

Мы будем использовать две функции Windows API для работы. Первый - это waveOutGetVolume. Он дает вам 32-разрядное целое значение, представляющее объемы двух каналов. Нижние шестнадцать битов содержат значение от нуля до 65 535. Ноль указывает на тишину, а 65 535 - максимально возможная громкость. Более высокие шестнадцать битов содержат аналогичное значение для правого канала. Для моно девайсов эти два значения совпадают.

Функция waveOutSetVolume позволяет изменять громкость. Опять же, вы используете 32-разрядное целое число с громкостью левого канала в битах нижнего порядка и громкостью правого канала в битах верхнего порядка.

Чтобы использовать функции Windows API, нам необходимо получить доступ к типам из System.Runtime.InteropServices пространства имен. Мы также будем использовать System.Media пространство имен, поэтому включите в свой код следующие директивы using. Если вы хотите воссоздать пример программы, добавьте его в код для формы по умолчанию в проекте Windows Form.

using System.Media;
using System.Runtime.InteropServices;
Теперь вы можете добавить два объявления функций Windows API. Каждый из них использует целочисленный параметр без знака для громкости. Для прлучения громкости это выходной параметр.

[DllImport("winmm.dll")]
public static extern int waveOutGetVolume(IntPtr hwo, out uint pdwVolume);
 
[DllImport("winmm.dll")]
public static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
Хотя это не имеет прямого отношения к функциям громкости устройства wave, мы также добавим кнопку отключения звука в пример программы. Я описал использование этой функции в предыдущей заметке Базовый регулятор громкости, поэтому не буду повторять информацию здесь. Чтобы добавить функцию отключения звука, добавьте следующее:

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
 
const int WM_APPCOMMAND = 0x319; 
const int APPCOMMAND_VOLUME_MUTE = 0x80000;
Дизайн формы Windows

Теперь мы можем добавить некоторые элементы управления в форму Windows, которые позволят пользователю изменять громкость и прослушивать эффект. Нам нужно пять элементов управления. Две панели треков позволят изменять громкость левого и правого каналов. Мы установим флажок, чтобы указать, хотим ли мы, чтобы два канала были синхронизированы автоматически. Наконец, нам нужны две кнопки. Одна включает и выключает звук. Другая воспроизводит тестовый звук, чтобы вы могли услышать изменение громкости.



На рисунке ниже показана возможная компоновка элементов управления.



Получение текущего уровня громкости

При первой загрузке формы мы хотим, чтобы на панелях треков отображалась текущая громкость для левого и правого каналов. Мы будем использовать функцию wavOutGetVolume для извлечения этой объединенной информации. Чтобы получить громкость левого канала, мы можем использовать логический побитовый оператор AND для удаления битов более высокого порядка. Для правильного канала нам нужно сдвинуть биты вправо перед использованием оператора AND. Это дает нам два шестнадцатибитных значения, которые мы можем применить к свойствам значения трекбара.

Код для этого показан ниже. Добавьте вызов ShowCurrentVolume в конструктор и создайте новый метод следующим образом:

public VolumeForm()
{
    InitializeComponent();
    ShowCurrentVolume();
}
 
private void ShowCurrentVolume()
{
    uint volume;
    waveOutGetVolume(IntPtr.Zero, out volume);
    int left = (int)(volume & 0xFFFF);
    int right = (int)((volume >> 16) & 0xFFFF);
    LeftVolumeSlider.Value = left;
    RightVolumeSlider.Value = right;
}
Автобалансировка

Для флажка Автобалансировки требуется небольшой код для события CheckChanged. Если флажок снят, никаких действий не требуется, так как громкость не изменяется. Когда флажок установлен, нам нужно убедиться, что оба канала имеют одинаковую громкость. Мы могли бы сделать это, изменив нижний из двух каналов, чтобы он соответствовал верхнему, изменив больший объем, чтобы он соответствовал нижнему, или переместив оба в среднее из двух. В примере приложения я решил усреднить две громкости.

Добавьте событие CheckChanged в флажок Автобалансировки и включите код, показанный ниже.

private void Autobalance_CheckedChanged(object sender, EventArgs e)
{
    if (Autobalance.Checked)
    {
        int volume = (LeftVolumeSlider.Value + RightVolumeSlider.Value) / 2;
        LeftVolumeSlider.Value = volume;
        RightVolumeSlider.Value = volume;
        SetVolume();
    }
}
Метод setVolume использует waveOutSetVolume для установки громкости для каждого канала в соответствии со значениями на дорожках. 32-разрядное целое число вычисляется путем сдвига значения правого канала на шестнадцать мест влево, чтобы занять биты более высокого порядка, и добавления значения левого канала в биты более низкого порядка.

private void SetVolume()
{
    uint volume = (uint)(LeftVolumeSlider.Value + (RightVolumeSlider.Value << 16));
    waveOutSetVolume(IntPtr.Zero, volume);
}
Управление левым и правым каналами

Когда значение в любой из трекбаров изменится, мы немедленно обновим громкость. Если флажок Автобалансировка установлен, мы изменим другую панель треков так, чтобы эти два значения совпадали. Чтобы включить эту функцию, добавьте события прокрутки на обе панели треков и включите приведенный ниже код:

private void LeftVolumeSlider_Scroll(object sender, EventArgs e)
{
    if (Autobalance.Checked) RightVolumeSlider.Value = LeftVolumeSlider.Value;
    SetVolume();
}
 
private void RightVolumeSlider_Scroll(object sender, EventArgs e)
{
    if (Autobalance.Checked) LeftVolumeSlider.Value = RightVolumeSlider.Value;
    SetVolume();
}
Кнопка отключения звука

Давайте быстро добавим код для кнопки отключения звука. Добавьте обработчик события нажатия, как показано ниже.

private void MuteButton_Click(object sender, EventArgs e)
{
    SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_MUTE);
}
Кнопка воспроизведения

Наконец, нам нужно добавить код события щелчка для кнопки воспроизведения. Эта кнопка воспроизводит WAV-файл, чтобы можно было протестировать. Перед добавлением кода вам необходимо добавить WAV-файл в проект с помощью обозревателя решений. Достаточно любого файла, предоставленного Windows. После добавления используйте Обозреватель решений, чтобы переименовать файл в "Test.wav" и изменить свойство файла "Копировать в выходную папку" на "Копировать всегда".

Если файл теста доступен, добавьте следующий код в событие щелчка для кнопки.

private void PlayButton_Click(object sender, EventArgs e)
{
    SoundPlayer player = new SoundPlayer();
    player.SoundLocation = "Test.wav";
    player.Play();
}
Теперь вы можете выполнить программу и опробовать элементы управления. Если вы откроете утилиту микшера громкости Windows, вы увидите, что она отражает изменения громкости. В зависимости от используемой версии Windows изменения затронут либо основной уровень громкости для операционной системы, либо конкретный уровень для текущей программы. Обратите внимание, что микшер громкости показывает громкость более громкого из двух каналов для стереоустройств.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, си шарп, громкость, устройства




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Несколько полезных сочетаний клавиш для IntelliJ IDEA
Возможные проблемы при подключении к Firebird из Visual Studio
Заливка и извлечение изображений из базы sqlite на C#