"); //-->
大型WAV文件的播放
在多媒体软件的设计中经常要处理声音文件,用Windows提供的API函数sndPlaySound可以实现小型WAV文件的播放。但是当WAV文件大于可用内存时,sndPlaySound函数就不能进行播放,那么如何利用MCI播放大型音频文件呢?本文将介绍一种方法。
Windows支持两种RIFF(resource interchange file format,“资源交互文件格式”)音频文件:MIDI的RMID文件和波形音频文件格式WAV文件,本文将介绍如何用MCI命令播放大型WAV文件。
用sndPlaySound播放音频文件只需要一行代码。比如实现异步播放的方法为
sndPlaySound("c:windowsding.wav",SND_ASYNC);
由此可以看到,sndPlaySound的使用是很简单的。但是用sndPlaySound播放音频文件有一个限制,即整个音频文件必须全部调入可用的物理内存。因此应用sndPlaySound播放的音频文件相对较小,最大约100K。要播放大一些的音频文件(在多媒体设计中是经常要遇到的情况)需要使用MCI的功能。
本文创建了一个Cwave类,可以处理播放音频的MCI命令,因为该类能够执行很多的MCI命令和建立了数据结构,所以只需要简单的成员函数(如OpenDevice, CloseDevice, Play和Stop)。在CWave类中抽象了特定的MCI命令和数据结构,只含几个简单的成员函数OpenDevice, CloseDevice, Play和Stop。波形音频设备是一个复合设备,如果打开波形设备,然后打开并关闭每个波形元素,最后关闭波形设备,这样可以使得播放性能更好。调用Cwave::OpenDevice就可以打开波形设备,OpenDevice将MCI_OPEN命令传递给mciSendCommand函数,如果调用成功,就用数据结构MCI_OPEN_PARMS的wDeviceID成员返回波形设备的标识符,该标识符保存在一个供以后使用的私有数据成员中。
一旦打开了Cwace对象,通过Cwace::Play播放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标志并跳过窗口句柄。这样做会使应用程序在mciSendCommand函数返回之前等待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消息会发送到指定的窗口,图1给出了一个WAV文件播放所发生的事件序列:(1)命令播放WAV文件并立即返回;(2)播放WAV文件;(3)完成后发送通知消息。
图1 播放WAV文件
完成播放后关闭WAV文件元素是程序员的责任,简单的调用Cwave类的Stop成员函数就可以了。Stop成员函数将WAV文件标识符和MCI_CLOSE命令传递给mciSendCommand函数,不必为该命令分配一个MCI结构,下述代码关闭了WAV文件
mciSendCommand(m)nElement,MCI_CLOSE,NULL,NULL);
播放完所有的WAV文件后必须关闭波形音频设备,Cwave类的析构函数调用Cwave::CloseDevice自动完成。
将本文中介绍的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
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
NEC Electronics SM+软件安装演示视频
如何提高fpga的工作频率,请大虾指点
谁告诉我VHDL里怎么实现多个边缘触发?
阿联酋大学研发非侵入式血流监测 采压电传感器实现高精准度
LinkSwitch-II
NEC Electronics 汇编器与PM+软件安装演示视频
NEC Electronics Applilet 软件安装演示视频
请教FPGA高速设计的问题
1,000V 125A MEMS 继电器概念验证
酒窖温度和湿度控制系统设计
1,700V反激式DC-DC转换器的五种汽车用途
LJA7225 (录像机和电视机)红外线遥控接收前置放大电路
黄仁勋:若被排除在中国AI市场之外将是“巨大的损失”
用AI协助儿童听力检测 以深度学习姿势识别技术提升准确性
FPGA设计时如何减少占用的资源
LM909 (电子玩具)无线电遥控接收译码电路
NEC Electronics C编译器软件安装演示视频
AI需求给力,AMD营收及指引超预期增长,盘后冲高回落
KA2184 (电视机和录像机)遥控接收前置放大电路
可关断晶闸管(GTO)
LBl475 (录像机)双线有线迢控电路
可编程键盘8279
LJC2200 (空调器、电风扇、收录机、电视机和玩具)红外线、超声波和无线电遥控接收电路
光程研创和采钰合作推出新世代硅基Metalens超颖透镜
晶振的选择
安森美公布 2025 年第一季度业绩
抢英伟达订单?三星提前量产12层堆叠HBM3E
FPGA节省资源设计的一个例子(vhdl)
烤烟房温湿度控制系统设计
台积电2nm需求超所有其它制程!苹果、NVIDIA、AMD都想要