如何播放 WAV 文件?
from http://www.vckbase.com/index.php/wv/434
平时,你在多媒体软件的设计中是怎样处理声音文件的呢?使用Windows 提供的API函数 sndPlaySound来实现WAV文件的播放?但是,你有没有遇到过这种情况呢:当WAV文件大于可用内存时,sndPlaySound 函数就不能进行播放!!!那么,如何利用MCI播放大型音频文件呢?
本文将介绍一种方法。
Windows支持两种RIFF(resource interchange file format,“资源交互文件格式”)音 频文件:MIDI的RMID文件和波形音频文件格式WAV文件,本文将介绍如何用MCI命令播放大型W AV文件。用sndPlaySound播放音频文件只需要一行代码。比如实现异步播放的方法为 sndPlaySound("c:\windows\ding.wav",SND_ASYNC);
由此可以看到,sndPlaySound 的使用是很简单的。但是用sndPlaySound播放音频文件有 一个限制,即整个音频文件必须全部调入可用的物理内存。因此应用sndPlaySound播放的音频 文件相对较小,最大约100K。要播放大一些的音频文件(在多媒体设计中是经常要遇到的情况 )需要使用MCI的功能。这里创建了一个Cwave类,可以处理播放音频的MCI命令,因为该类能够 执行很多的MCI命令和建立了数据结构,所以只需要简单的成员函数(如OpenDevice, CloseDe vice, Play和Stop)。在CWave类中抽象了特定的MCI命令和数据结构,只含几个简单的成员函
数OpenDevice, CloseDevice, Play和Stop。波形音频设备是一个复合设备,如果打开波形设 备,然后打开并关闭每个波形元素,最后关闭波形设备,这样可以使得播放性能更好。调用C wave::OpenDevice就可以打开波形设备,OpenDevice将MCI_OPEN命令传递给mciSendCommand函 数,如果调用成功,就用数据结构MCI_OPEN_PARMS的wDeviceID成员返回波形设备的标识符, 该标识符保存在一个供以后使用的私有数据成员中。一旦打开了Cwace对象,通过Cwace::Pla
y播放WAV文件就就绪了,WAV文件名和一个窗口指针被传递给Play方法以便将MCI通知消息发送 到制定的窗口。
WAV文件的播放首先要通过分配一个MCI_OPEN_PARMS结构并给所要播放的WAV文件设置
lpstrElementName成员打开WAV文件。将该结构和MCI_OPEN传递给mciSendCommand,打开WAV文件 并用MCI_OPEN_PARMS结构的wDeviceID成员返回元素标识符。第二步是命令波形音频设备播放 WAV文件。分配了MCI_PLAY_PARMS结构并将dwCallback成员设置为窗口句柄。如果要同步播放 音频波形文件,就增加MCI_WAIT标志并跳过窗口句柄。这样做会使应用程序在mciSendComman d函数返回之前等待WAV文件播放完毕。最可能的情况是异步播放大型WAV文件,可以象下面那
样指定MCI_NOTIFY标志并设置dwCallback成员做到这一点。
MCI_PLAY_PARMS mciPlayParms;
MciPlayParms.dwCallback=(DWORD)pWnd->m_hWnd;
DwResult=mciSendCommand(m_nDevice,
MCI_PLAY,
MCI_NOTIFY,
(DWORD)(LPVOID)&mciPlayParms);
这样就开始了WAV文件的播放,并且在播放完毕后,MM_MCINOTIFY消息会发送到指定的窗口。一个WAV文件播放所发生的事件序列为:(1)命令播放WAV文件并立即返回;(2)播放WAV文 件;(3)完成后发送通知消息。
完成播放后关闭WAV文件元素是程序员的责任,简单的调用Cwave类的Stop成员函数就可以了。Stop成员函数将WAV文件标识符和MCI_CLOSE命令传递给mciSendCommand函数,不必为该命令分配一个MCI结构,下述代码关闭了WAV文件:
mciSendCommand(m_nElement,MCI_CLOSE,NULL,NULL);
播放完所有的WAV文件后必须关闭波形音频设备,Cwave类的析构函数调用Cwave::Close Device自动完成。 将本文中介绍的CWave类加入到自己的程序中,就可以方便的应用它播放音频文件了。
//建立Cwave类,放在Wave.h文件中:
class CWave:public CObject
{
//Construction
public:
CWave();
virtual ~CWave(); //Operations
public:
DWORD OpenDevice();
DWORD CloseDevice();
DWORD Play(CWnd *pParentWnd,LPCSTR pFileName);
DWORD Stop(); //Implementation
protected:
void DisplayErrorMsg(DWORD dwError); //Members
protected:
MCIDEVICEID m_nDeviceID;
MCIDEVICEID m_nElementID;
}; //Cwave类的实现代码,Cwave.cpp
#include <stdafx.h>
#include "cwave.h" CWave::CWave()
{
m_nDeviceID=0;
m_nElementID=0;
} CWave::~CWave()
{
if(m_nElementID)
Stop();
if(m_nDeviceID)
CloseDevice();
} DWORD CWave::OpenDevice()
{
DWORD dwResult=0; if (m_nDeviceID)
{
MCI_OPEN_PARMS mciOpenParms; mciOpenParms.lpstrDeviceType=(LPSTR)MCI_DEVTYPE_WAVEFORM_AUDIO; //open the wave device
dwResult = mciSendCommand(NULL,
MCI_OPEN,
MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_WAIT,
(DWORD)(LPVOID)&mciOpenParms); //save device identifier,will use eith other MCI commands
m_nDeviceID = mciOpenParms.wDeviceID; //display error message if failed
if(dwResult)
DisplayErrorMsg(dwResult);
}
//return result of MCI operation
return dwResult;
} DWORD CWave::CloseDevice()
{
DWORD dwResult=0; //close if currently open
if(m_nDeviceID)
{
//close the MCI device
dwResult=mciSendCommand(m_nDeviceID,MCI_CLOSE,NULL,NULL); //display error message if failed
if(dwResult)
DisplayErrorMsg(dwResult); //set identifier to close state
else
m_nDeviceID=0;
} //return result of MCI operation
return dwResult;
} DWORD CWave::Play(CWnd* pWnd,LPCSTR pFileName)
{
MCI_OPEN_PARMS mciOpenParms;
//initialize structure
memset(&mciOpenParms,0,sizeof(MCI_OPEN_PARMS)); //set the WAV file name to be played
mciOpenParms.lpstrElementName=pFileName; //first open the device
DWORD dwResult=mciSendCommand(m_nDeviceID,MCI_OPEN,
MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpenParms); //display error message if failed
if(dwResult)
DisplayErrorMsg(dwResult); //if successful,instruct the device to play the WAV file
else
{
//save element indentifier
m_nElementID=mciOpenParms.wDeviceID; MCI_PLAY_PARMS mciPlayParms; //set the window that will receive notification message
mciPlayParms.dwCallback=(DWORD)pWnd->m_hWnd; //instruct device to play file
dwResult=mciSendCommand(m_nElementID,MCI_PLAY,
MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms); //display error and close element if failed
if(dwResult)
{
DisplayErrorMsg(dwResult);
Stop();
}
} //return result of MCI operation
return dwResult;
} DWORD CWave::Stop()
{
DWORD dwResult=0; //close if element is currently open
if(m_nElementID)
{
dwResult=mciSendCommand(m_nElementID,MCI_CLOSE,NULL,NULL); //display error message if failed
if(dwResult)
DisplayErrorMsg(dwResult);
//set identifier to closed state
else
m_nElementID=0;
}
return dwResult;
} void CWave::DisplayErrorMsg(DWORD dwError)
{
//check if there was an error
if(dwError)
{
//character string that contains error message
char szErrorMsg[MAXERRORLENGTH]; //retrieve string associated error message
if(!mciGetErrorString(dwError,szErrorMsg,sizeof(szErrorMsg)))
strcpy(szErrorMsg,"Unknown Error");
//display error string in message box
AfxMessageBox(szErrorMsg);
}
}
如何播放 WAV 文件?的更多相关文章
- C#播放wav文件
C#使用HWQPlayer类播放wav文件 类的代码: using System.IO; using System.Runtime.InteropServices; namespace HoverTr ...
- python 播放 wav 文件
未使用其他库, 只是使用 pywin32 调用系统底层 API 播放 wav 文件. # Our raison d'etre - playing sounds import pywintypes im ...
- WinAPI: sndPlaySound - 播放 wav 文件
WinAPI: sndPlaySound - 播放 wav 文件 //声明: sndPlaySound( lpszSoundName: PChar; {声音文件} uFlags: UINT{播 ...
- 8086汇编语言 调用声卡播放wav文件(sound blaster)
开更 大概最后做了一个能播放无损音乐(无压缩.不需解码)的播放器 原理是基于dosbox的模拟声卡,通过硬件之间的相互通讯做到的 关于详细内容接下来再讲. 一.从dosbox入手 我们知道cpu可以直 ...
- Linux音频编程--使用ALSA库播放wav文件
在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...
- c++(qt)播放wav文件的四种方式
//方法一(要符合RIFF规范) 1 QSound::play("E:/Projects/报警声1-1.wav"); //方法二(要符合RIFF规范) 1 QSoundEffect ...
- windows下使用waveout函数族播放wav文件
要使用waveout函数组,族,首先要知道几个数据结构,首先是这个 typedef struct tWAVEFORMATEX { WORD wFormatTag; /* 格式的类型 */ WORD n ...
- 【C#学习笔记】播放wav文件
using System; using System.Media; namespace ConsoleApplication { class Program { static void Main(st ...
- java播放wav文件
import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import java ...
随机推荐
- 再也不怕和老外交流了!我用python实现一个微信聊天翻译助手!
前言 在前面的一篇文章如何用python“优雅的”调用有道翻译中咱们清楚的写过如何一层一层的解开有道翻译的面纱,并且笔者说过那只是脑洞的开始.现在笔者又回来了.当你遇到一些外国小哥哥小姐姐很心动.想结 ...
- spring boot集成spring-boot-starter-mail邮件功能
前情提要 以目前IT系统功能来看,邮件功能是非常重要的一个功能.例如:找回密码.邮箱验证,邮件动态码.忘记密码,邮件营销等,都需要用到邮件功能.结合当下最流行的spring boot微服务,推出了sp ...
- linux下安装OpenCV-2.4
OpenCV(Open Source Computer Vision Library),是一个跨平台计算机视觉库,实现了图像处理和计算机视觉方面的很多通用算法. OpenCV由一系列 C 函数和少量 ...
- python命名空间(namespace)
命名空间: 每一个作用域变量存储的位置,或者解释为 存储作用域中变量的字典. 作用: 获取想查看某个作用域中的变量名.变量值. 使用方法: locals() #当前命名空间 1. 效果图: 2. 代 ...
- JPQ整合Querydsl入门篇
# JPQ整合Querydsl入门篇 不知道你们喜不喜欢用JPA ,我本人是很喜欢 不要和我说JPA不适合复杂查询等等的,你要知道现在都是微服务,只要你服务器拆分够细表设计够合理,都是服务之间调能用 ...
- Linux删除文件 清除缓存
相信很多测试 经常会经历开发叫你清除缓存这种事. 那我们要怎么清呢? 一.首先,确认你要清除的缓存在哪个目录下,然后切换到该目录下,比如 我现在知道我的的缓存目录是在newerp这个目录下,则如图 二 ...
- Spring学习记录5——数据库事务基础知识
何为数据库事务 “一荣共荣,一损共损”这句话很能体现事务的思想,很多复杂的事务要分步进行,但它们组成了一个整体,要么整体生效,要么整体失效.这种思想反映到数据库上,就是多条SQL语句,要么全部成功,要 ...
- 神秘常量0x077CB531,德布莱英序列的恩赐
本文发布于游戏程序员刘宇的个人博客, 转载请注明来源https://www.cnblogs.com/xiaohutu/p/10950011.html 某天我在优化游戏的算法,在将一个个关键数据结构优化 ...
- 如梦令编程语言发布 (RML)
如梦令编程语言是在Rebol语言核心语法的基础上,做了一些自以为是的修改而来.谨以此为Rebol语法的传承,略尽绵薄之力. 基本概念 如梦令语言分属Lisp语系,代码本身是一个层层嵌套的Token列表 ...
- 异想家Ubuntu安装的软件
[替换国内源] https://developer.aliyun.com/mirror/ubuntu 我提供一个下载,方便第一次安装懒得敲命令: https://jfz.me/16.04/source ...