PlaySound是Windows用于播放音乐的API函数。在vs2010以上版本需要加入#pragma comment(lib, “winmm.lib”)才能使用PlaySound(或者在构建选项的连接中添加winmm)。
PlaySound函数原型为 BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound)。
参数pszSound是指定了要播放声音的字符串,该参数可以是WAVE文件的名字,或是WAV资源的名字,或是内存中声音数据的指针,或是在系统注册表WIN.INI中定义的系统事件声音,如果该参数为NULL则停止正在播放的声音。
参数hmod是应用程序的实例句柄,除非pszSound的指向一个资源标识符(即fdwSound被定义为SND_RESOURCE),否则必须设置为NULL。
参数fdwSound是标志的组合,如下表所示:
标志 | 效果 |
---|---|
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)显示音量滑块控制系统通知的声音。设置该标志将下控制音量滑块。如果没有设置该标志,声音是分配到默认的音频会议的应用进程 |
由于PlaySound()本身就是采用多线程来播放声音的,所以即使采用多线程同时执行PlaySound()试图播放多个声音,后执行的PlaySound()的声音也会覆盖掉之前的声音。因此,只有考虑用多进程解决这个问题了。为了使得程序可以同时播放背景音乐和音效,可以再开一个进程负责播放背景音乐,主进程通过pipe联系子进程来切换背景音乐。代码如下:
#include <windows.h>
#include <fcntl.h>
#include <process.h>
#include <iostream>
int hpipe[2];
void setbgm(int b)//主程序调用,输入数字来设置BGM
{
int bgm=b;
write(hpipe[1],&bgm,sizeof(int));
}
int main(int argc,char* argv[])
{
char hstr[20];
int pid;
if(argc==1)//主进程
{
//管道初始化
setvbuf(stdout,NULL,_IONBF,0);
if(_pipe(hpipe,256,O_BINARY)==-1)exit(1);
itoa(hpipe[0],hstr,10);
if((pid=spawnl(P_NOWAIT,argv[0],argv[0],hstr,NULL))==-1)exit(1);
//以下为程序其他部分
PlaySound("3.wav",NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);//主进程播放的声音
setbgm(1);//通知子进程切换1号BGM
Sleep(5000);
setbgm(2);//通知子进程切换2号BGM
Sleep(10000);
setbgm(-1);//程序结束前调用来关闭子程序
}
else//子进程
{
system("title BGM");
int bgm;
hpipe[0]=atoi(argv[1]);
while(1)
{
if(read(hpipe[0],&bgm,sizeof(int)))//接收消息
{
switch(bgm)
{
//子程序退出
case -1:exit(0);
//1号BGM
case 1:PlaySound("1.wav",NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);break;
//2号BGM
case 2:PlaySound("2.wav",NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);break;
}
}
Sleep(100);//防止CPU占用过高
}
}
}