分享
 
 
 

大型WAV文件的播放

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

大型WAV文件的播放

在多媒体软件的设计中经常要处理声音文件,用Windows提供的API函数sndPlaySound可以实现小型WAV文件的播放。但是当WAV文件大于可用内存时,sndPlaySound函数就不能进行播放,那么如何利用MCI播放大型音频文件呢?本文将介绍一种方法。

Windows支持两种RIFF(resource interchange file format,“资源交互文件格式”)音频文件:MIDI的RMID文件和波形音频文件格式WAV文件,本文将介绍如何用MCI命令播放大型WAV文件。

用sndPlaySound播放音频文件只需要一行代码。比如实现异步播放的方法为

sndPlaySound("c:\windows\ding.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

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);

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有