Программирование звука в Windows (C++) | Win32 API

Функция PlaySound, пример для Visual C++


Проще всего озвучивать что-либо в вашем приложении — это использовать WinAPI функцию PlaySound. Она умеет озвучивать wav-файлы засчёт взаимодействия вашего приложения с ОС Windows.

Озвучивание wav-файлов с помощью функции PlaySound

Давайте будем считать, что вы уже знаете, как создавать каркас Win32 или MFC-приложения с помощью меню File -> New -> Project -> MFC Application (или Win32...).

Очень важно сделать следующие настройки в Visual C++. В меню найдите View -> Solution Explorer. Выделяете в дереве Solution Explorer название проекта. Затем в меню Project -> Properties выходите в окно свойств проекта. В левом дереве найдите C++ -> Code Generation. Справа появится таблица настроек. Выберите возле Runtime Library Multi-threaded DLL (/MD). После этого в левом дереве найдите Linker -> Input. Справа в таблице напротив Additional Dependencies напишите вручную winmm.lib. Для того чтобы любое созданное вами приложение запускалось вообще на всех компьютерах с ОС Windows (начиная с Windows 98), необходимо в левом дереве найти верхнюю ветку General и там выставить справа Use MFC in a Static Library. Это гарантирует, что ваше приложение будет тяжелее более чем на 100 кб, из-за того, что в exe-файл будет внедрена библиотека MFC71.dll, которой у пользователя скорее всего в системе не будет (если он не установил у себя Visual Studio.NET).

Далее, в исходном коде, либо в заголовках, либо в cpp-файлах, до использования функции PlaySound, но обязательно после #include <windows.h> (это уже включено в заголовочные файлы, которые в свою очередь включаются автоматически в исходники проекта) напишите #include <mmsystem.h> (проще всего это написать после всех остальных #include..., чтобы не сомневаться).

Если этого не сделать, то VC++ будет упорно утверждать что-то типа "unresolved external .... ___PlaySound_" и не захочет дать вам счастливую возможность поработать со звуком.

Как озвучить внешний wav-файл (не встроенный в exe-шник вашей программы):

Это проще и позволяет уберечь исполняемый файл программы от громадных размеров из-за ресурсов, таких как звуковые файлы. Это, например, актуально для случаев, когда заранее неизвестно, какой именно wav-файл захочет послушать пользователь вашего продукта.

PlaySound("name_of_file.wav", NULL, SND_FILENAME | SND_ASYNC);

Приведённый пример предполагает, что указанный wav-файл располагается там же, где и exe-файл программы. Третий аргумент расчитан для случая, когда программа не будет ждать окончания звучания файла. Более подробно об этих аргументах сказано в MSDN на англ. языке. Любой программист должен уметь читать документацию на английском.

Внедрение wav-файла в будущий exe-шник вашей программы:

Гораздо интереснее, когда ваша программа выглядит, как единый exe-шник, который даже можно не инсталлировать, а просто запускать из любого места. Это актуально именно в тех случаях, когда пользователю не предоставляется возможность воспроизводить любой выбранный wav-файл из любого места.

Для этого возьмите нужный вам wav-файл и скопируйте его в папку res (папка ресурсов по умолчанию) вашего Visual C++ проекта (впрочем это только для удобства). После этого в меню View выберите Resource View. Откроется дерево ресурсов. Там правой кнопкой мыши выберите действие Add resource. Появится почти квадратное окно. Справа в нём выберите Import. Найдите там папку res (если даже её нет, можно было её создать внутри папки проекта). Найдите в этой папке wav-файл, который вы заботливо туда скопировали. Кликните по нему дважды. И вот он появился в дереве ресурсов под видом IDR_WAVE1 (для него автоматически была создана логическая папка "WAVE" — этой папки на самом деле нет, но она отображается в дереве ресурсов как логическая папка). Если вы добавите таким же способом ещё один wav-файл, то он уже будет обозначен как IDR_WAVE2. И так далее.

Рассмотрим для двух видов создаваемых в VC++ приложений:

Win32-приложение (можно даже в консольных программах):

PlaySound(MAKEINTRESOURCE(IDR_WAVE1), NULL, SND_RESOURCE | SND_ASYNC | SND_LOOP);

К третьему аргументу добавили опцию бесконечного повтора звука, пока его не остановишь.

MFC-приложение (можно также и в консольных программах):

PlaySound( MAKEINTRESOURCE(IDR_WAVE1), AfxGetResourceHandle(), SND_RESOURCE | SND_ASYNC );

Я пробовал, в MFC-приложениях будет работать пример и для Win32!!! Почему? Любое Win32-приложение использует WinAPI функции и их аргументы, которые понимает любое МFC-приложение. Но далеко не всегда MFC-приложение использует то, что безоговорочно поймёт Win32-приложение. В данном случае под словом "приложение" я подразумеваю разрабатываемый проект программы, а не готовый exe-шник.

Как остановить звучание любого задействованного в программе wav-файла:

PlaySound(NULL, NULL, SND_ASYNC);

Возможно, что третий аргумент даже не имеет значения... Ведь звук всё равно прекращает звучать.

Программирование звука в Windows (C++) | Win32 API