VC:大型WAV文件的播放

原创 2001年07月24日 08:22:00
VC:大型WAV文件的播放

(10/25/1999)

    在多媒体软件的设计中经常要处理声音文件,用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)完成后发送通知消息。

完成播放后关闭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
  #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);
   }
  }

VC实现wav录音文件的播放

因为只需在Windows上执行,先想到用MCI接口。试了一下,用mciSendCommand可以实现基本的播放wav文件的功能。但循环播放wav就麻烦了,必须向窗口传送MM_MCINOTIFY消息。 ...
  • lujianfeiccie2009
  • lujianfeiccie2009
  • 2012年05月09日 09:38
  • 1687

VC++中播放声音wav

因为只需在Windows上执行,先想到用MCI接口。试了一下,用mciSendCommand可以实现基本的播放wav文件的功能。但循环播放wav就麻烦了,必须向窗口传送MM_MCINOTIFY消息。 ...
  • laguoqing
  • laguoqing
  • 2016年09月16日 17:12
  • 923

ALSA的WAV播放和录音程序

这段时间在探索ALSA架构,从ALSA Core到ALSA Lib,再到Android Audio System。在看ALSA Lib时,写了一个比较典型的基于ALSA的播放录音程序。程序包包含四个部...
  • jack_a8
  • jack_a8
  • 2015年01月25日 12:13
  • 1359

android wav录音,停止和播放

这几天一直在做录音方面的应用,下面一个wav的录音,停止和播放。 public class AudioFileFunc {     //音频输入-麦克风     public final...
  • flamejack
  • flamejack
  • 2016年01月22日 22:38
  • 2596

MFC播放wav音频文件

首先你的资源要是wav格式的而且要包括头文件和必须的库文件如下 #include #pragma comment( lib, "Winmm.lib" ) PlaySound...
  • rankun1
  • rankun1
  • 2016年08月03日 17:53
  • 758

声音的录制(VC)(保存为WAV文件) (转)

|举报|字号 订阅 这里只录制了最原始的声音,格式PCM,未作任何处理,未压缩,(要压缩可能需要用到其它库) 本文用的是回调函数方式 waveInOpen...
  • kgzhw
  • kgzhw
  • 2014年09月30日 10:59
  • 732

VC中如何播放WAV文件

VC中播放WAV文件的API为PlaySound函数。 1.函数详细说明: PlaySound函数的声明为:   BOOL PlaySound(LPCSTR pszSound, HMODULE...
  • ccx_john
  • ccx_john
  • 2013年08月23日 15:00
  • 584

[译]Android音频: 如何使用AudioTrack播放一个WAV格式文件?

原文链接:Android Audio: Play a WAV file on an AudioTrack 译者注: 1. 由于这是技术文章,所以有些词句使用原文,表达更准确。 2. 由于水平有效...
  • langwang2
  • langwang2
  • 2015年12月05日 22:34
  • 648

Qt之实现录音播放及raw(pcm)转wav格式

简述在上一篇 Qt 之 WAV文件解析 中详细地分析了wav格式文件的文件头信息。通过QAudioInput实现录音功能,但是录音生成的文件并不能用播放器打开,就算更改后缀名也无法识别(有时候下载的一...
  • GoForwardToStep
  • GoForwardToStep
  • 2016年10月10日 20:24
  • 3131

linux 播放wav文件

from : http://blog.chinaunix.net/uid-9672747-id-3309602.html #include #include #include #incl...
  • yan420523
  • yan420523
  • 2013年05月10日 17:09
  • 1626
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC:大型WAV文件的播放
举报原因:
原因补充:

(最多只允许输入30个字)