程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 大型WAV文件的播放

大型WAV文件的播放

編輯:vc教程

  在多媒體軟件的設計中經常要處理聲音文件,用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)完成後發送通知消息。

完成播放後關閉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);
   }
  }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved