Carewho的文章

  • PlaySound 和 sciSendString 实现音频播放的两种方式

    背景大家都使用过有音效播放的软件或程序吧,这些程序可能是只播放一个提示音,也可能是播放整首音乐或曲子,又或许你自己开发一些程序或者游戏需要播放声音。Windows上播放音频的函数有很多,PlaySound 和 mciSendString 函数就是常用的两个播放声音的函数。
    那么,怎么编程实现声音的播放?如果有多个声音同时播放,那应该如何实现?PlaySound 和 mciSendString 它们的使用场景有什么不同吗?带着这些疑问来阅读本文,本文会一一为你解答。现在,我就把实现原理和实现过程写成文档,分享给大家。
    函数介绍PlaySound 函数
    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 函数
    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")
    PlaySound方法播放BOOL PlayMySound1(char *pszFileName){ BOOL bRet = ::PlaySound(pszFileName, NULL, SND_ASYNC | SND_LOOP); return bRet;}
    mciSendString方法播放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 函数来播放比较短促的音效声音。这样,就实现了同时播放多个声音了。
    1  留言 2019-01-07 18:10:43
  • 实现音频播放的两种方式之PlaySound和sciSendString

    背景大家都使用过有音效播放的软件或程序吧,这些程序可能是只播放一个提示音,也可能是播放整首音乐或曲子,又或许你自己开发一些程序或者游戏需要播放声音。Windows上播放音频的函数有很多,PlaySound 和 mciSendString 函数就是常用的两个播放声音的函数。
    那么,怎么编程实现声音的播放?如果有多个声音同时播放,那应该如何实现?PlaySound 和 mciSendString 它们的使用场景有什么不同吗?带着这些疑问来阅读本文,本文会一一为你解答。现在,我就把实现原理和实现过程写成文档,分享给大家。
    函数介绍PlaySound 函数
    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 函数
    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")
    PlaySound方法播放BOOL PlayMySound1(char *pszFileName){ BOOL bRet = ::PlaySound(pszFileName, NULL, SND_ASYNC | SND_LOOP); return bRet;}
    mciSendString方法播放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 函数来播放比较短促的音效声音。这样,就实现了同时播放多个声音了。
    1  留言 2018-11-07 10:51:02

发送私信

人生没有彩排,每天都是现场直播

10
文章数
21
评论数
eject