Carewho
大家都使用过有音效播放的软件或程序吧,这些程序可能是只播放一个提示音,也可能是播放整首音乐或曲子,又或许你自己开发一些程序或者游戏需要播放声音。Windows上播放音频的函数有很多,PlaySound 和 mciSendString 函数就是常用的两个播放声音的函数。
那么,怎么编程实现声音的播放?如果有多个声音同时播放,那应该如何实现?PlaySound 和 mciSendString 它们的使用场景有什么不同吗?带着这些疑问来阅读本文,本文会一一为你解答。现在,我就把实现原理和实现过程写成文档,分享给大家。
PlaySound功能播放由给定文件名,资源或系统事件指定的声音。
函数声明
BOOL PlaySound(
LPCTSTR pszSound,
HMODULE hmod,
DWORD fdwSound
);
参数
pszSound
指定要播放的声音的字符串。 包括空终止符的最大长度为256个字符。 如果此参数为NULL,则任何当前播放的波形声音都将停止。 要停止非波形声音,请在fdwSound参数中指定SND_PURGE。fdwSound(SND_ALIAS,SND_FILENAME和SND_RESOURCE)中的三个标志确定名称是否被解释为系统事件,文件名或资源标识符的别名。 如果没有指定这些标志,则PlaySound将在注册表或WIN.INI文件中搜索与指定声音名称的关联。 如果找到关联,则播放声音事件。 如果在注册表中没有找到关联,则名称将被解释为文件名。hmod
处理包含要加载的资源的可执行文件。 除非在fdwSound中指定了SND_RESOURCE,否则此参数必须为NULL。fdwSound
播放标志,定义了下面的值:
VALUE MEANING SND_APPLICATION 用应用程序指定的关联来播放声音 SND_ALIAS pszSound参数指定了注册表或WIN.INI中的系统事件的别名 SND_ALIAS_ID pszSound参数指定了预定义的声音标识符 SND_ASYNC 用异步方式播放声音,PlaySound函数在开始播放后立即返回 SND_FILENAME pszSound参数指定了WAVE文件名 SND_LOOP 重复播放声音,必须与SND_ASYNC标志一块使用 SND_MEMORY 播放载入到内存中的声音,此时pszSound是指向声音数据的指针 SND_NODEFAULT 不播放缺省声音,若无此标志,则PlaySound在没找到声音时会播放缺省声音 SND_NOSTOP PlaySound不打断原来的声音播出并立即返回FALSE SND_NOWAIT 如果驱动程序正忙则函数就不播放声音并立即返回 SND_PURGE 停止所有与调用任务有关的声音。若参数pszSound为NULL,就停止所有的声音,否则,停止pszSound指定的声音 SND_RESOURCE pszSound参数是WAVE资源的标识符,这时要用到hmod参数 SND_SYNC 同步播放声音,在播放完后PlaySound函数才返回 SND_SYSTEM 如果这个标志被设置,声音是分配到音频会议系统通知的声音。系统音量控制程序(sndvol)显示音量滑块控制系统通知的声音。设置该标志将下控制音量滑块。如果没有设置该标志,声音是分配到默认的音频会议的应用进程 返回值
- 如果成功返回TRUE,否则返回FALSE。
mciSendString函数向MCI设备发送命令字符串。 在命令字符串中指定发送命令的设备。
函数声明
MCIERROR mciSendString(
LPCTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback
);
参数
- lpszCommand
指向指定MCI命令字符串的以null结尾的字符串的指针。 有关列表,请参阅多媒体命令字符串。- lpszReturnString
指向接收返回信息的缓冲区的指针。 如果不需要返回信息,该参数可以为NULL。- cchReturn
由lpszReturnString参数指定的返回缓冲区的大小(以字符为单位)。- hwndCallback
如果在命令字符串中指定了“notify”标志,则处理回调窗口。返回值
- 如果成功返回零,否则返回错误。
由函数介绍可以知道,PlaySound 函数功能比较灵活,可以播放系统声音,也可以播放指定音频文件。音频可以是作为资源插在程序中、可以存放在内存中、还可以是本地的音频文件。但是,有一个缺点就是,使用 PlaySound 不能同时播放两个或者多个声音,因为 PlaySound 是独占播放音频文件的。如果使用 PlaySound 播放新的声音,那么之前使用它播放的声音会立即停止,从而播放新声音。要实现同时播放多个声音,需要使用 mciSendString 来实现了。
那么,使用 PlaySound 播放音频文件的代码就是:
::PlaySound(pszFileName, NULL, SND_ASYNC | SND_LOOP);
其中,pszFileName是音频文件路径;SND_ASYNC表示异步播放,SND_LOOP表示循环播放。
对于,mciSendString 函数,我在《使用mciSendString函数实现循环播放音频文件》文章中,讲过使用它来实现循环播放音乐。主要是要理解 mciSendString 的命令,其中, open 指令用于打开文件;play 指令用于播放声音;close 用于关闭声音的播放。使用方式如下所示:
// 打开音频文件
::mciSendString("open filename alias mymusic", NULL, 0, NULL);
// 播放音频文件
::mciSendString("play mymusic", NULL, 0, NULL);
// 关闭文件, 停止播放
::mciSendString("close mymusic", NULL, 0, NULL);
使用 mciSendString 函数可以实现同时播放多个声音,在一个游戏里面,通常使用 mciSendString 函数来播放背景音乐等比较久的声音,使用 PlaySound 函数来播放比较短促的音效声音。这样,就实现了同时播放多个声音了。
#include <MMSystem.h>
#pragma comment(lib, "winmm.lib")
BOOL PlayMySound1(char *pszFileName)
{
BOOL bRet = ::PlaySound(pszFileName, NULL, SND_ASYNC | SND_LOOP);
return bRet;
}
BOOL PlayMySound2(char *pszFileName)
{
char szCmd[MAX_PATH] = {0};
// 打开音频文件
::wsprintf(szCmd, "open \"%s\" alias mymusic", pszFileName);
::mciSendString(szCmd, NULL, 0, NULL);
// 播放音频文件
::mciSendString("play mymusic", NULL, 0, NULL);
return TRUE;
}
使用 PlaySound 不能同时播放两个或者多个声音,mciSendString 函数可以同时播放多个声音。
在一个游戏里面,通常使用 mciSendString 函数来播放背景音乐等比较久的声音,使用 PlaySound 函数来播放比较短促的音效声音。这样,就实现了同时播放多个声音了。
keyboard_arrow_left上一篇 : Bypass UAC 提权小结 使用VS2013静态编译ZLIB压缩库 : 下一篇keyboard_arrow_right