用VC++5.0实现波形文件的录制

发表于:2007-07-04来源:作者:点击数: 标签:
王惠民、李京川 WAV文件在多媒体软件的 开发 中得到了广泛应用。我们在制作多媒体软件时,常常需要在某一时刻播放一段波形文件,但有时也需要该软件具有录制波形文件的功能。对于如何在多媒体软件中播放波形文件,许多文章已有论述,故本文将着重说明怎样进行
王惠民、李京川


  WAV文件在多媒体软件的开发中得到了广泛应用。我们在制作多媒体软件时,常常需要在某一时刻播放一段波形文件,但有时也需要该软件具有录制波形文件的功能。对于如何在多媒体软件中播放波形文件,许多文章已有论述,故本文将着重说明怎样进行波形文件的录制。


  一、波形文件的结构


  波形文件是具有特定结构的文件,只有弄清了它的结构,我们才能录制波形文件。波形文件的结构被称为“资源交换文件格式”(Resources Interchange File Format),简称RIFF。RIFF可以看做一种树状结构,其基本构成单位为chunk,每个chunk由“辨别码”、“数据大小”、“数据”组成。当辨别码是RIFF时,数据部分被切分成两个部分,“格式辨别码”和“数据”,其中“格式辨别码”占4个字节,此时,允许chunk内部再包含chunk。波形文件的结构如下图所示,整个结构由一个RIFF chunk 组成,该chunk的辨别码为“RIFF”,

  它的格式辨别码为“WAVE”,RIFF chunk 的数据部分由两个chunk组成:辨别码“fmt ”,“data”。上图中,结构PCMWAVEFORMAT的定义如下:



  typedef struct pcmwaveformat—tag{

  WAVEFORMAT wf;

  WORD wBitsPerSample; //取样大小,表示音量大小,可为8位或16位

  } PCMWAVEFORMAT;

  typedef struct waveformat—tag{

  WORD wFormatTag; //声音的格式代号, 一般是WAVE—FORMAT—PCM

  WORD nChannels; //声道,对于双声道,取值为2

  DWORD nSamplesPerSec; //取样频率,一般有11.025kHz,22.05kHz及44.1kH(CD音质)

  DWORD nAvgBytesPerSec; //每秒的数据量

  WORD nBlockAlign; //区块的对齐单位

  }WAVEFORMAT;



  以上几个结构分量有以下关系:



  nBlockAlign=nChannels*wBitsPerSamples/8

  nAvgBytesPerSec=nSamplesPerSec*nBlockAlign


  二、MCI多媒体控件


  上面介绍了WAV文件的结构,我们在进行一个新的波形文件的录制时,可以按此结构用程序产生一个新文件,然后将声音录制到该文件中去。在传统的Windows 程序编制中,我们可以采用MCI提供的函数及指令编制音效程序,也可以利用低阶函数控制音效,这两种方法都是有效的,但相对来说它们复杂一些,因为我们可以利用VC++5.0中的ActiveX控件——MCI多媒体控件来更简便地实现多媒体程序的编制。

  VC++5.0中提供了代码重用的重要工具——组件及控制平台(Components and Controls Gallery),在这个平台中,有常用的Windows 95组件和许多ActiveX控件,我们可以将ActiveX控件自由地插入具有ActiveX控件功能的应用程序中,从而直接引用控件的强大功能而无须太多的编程。MCI多媒体控件就是这个平台的一个ActiveX控件,它封装了多媒体控制接口,并以类CMciCtrl的形式提供给编程者,例如:



  CString CMciCtrl::GetCommand() //获取Command属性

  {

   CString result;

   GetProperty(0x17,VT—BSTR, (void*)&result);

  return result;

  }

  void CMciCtrl:: SetCommand(LPCTSTR propVal) //设置Command属性

  {

   SetProperty(0x17,VT—BSTR,propVal);

  }

  CString CMciCtrl::GetDeviceType()  //获取DeviceType属性

  {

   CString result;

   GetProperty(0x15,VT—BSTR,(void*)&result);

   return result;

  }

  void CMciCtrl::SetDeviceType(LPCTSTR propVal)  //设置DeviceType属性

  {

   SetProperty(0x15,VT—BSTR,propVal);

  }

  

  利用CMciCtrl类的个成员函数可以设置或获取多媒体控制的个属性,例如,SetDeviceType(“WaveAudio”)将设备类型设置为WAVE,从而能够对波形文件进行操作,SetCommand(“Open”)发送命令打开MCI设备,SetCommand(“Close”)发送命令关闭MCI设备,SetCommand(“Save”)将缓冲区里的内容存入已经打开的文件中。


  三、实现的方法与步骤


  下面详细介绍如何在VC++5.0中利用MCI控制实现波形文件的录制。

  1.利用AppWizard创建基于对话框的应用mci,注意在MFC AppWizard Step 2 of 4中设置ActiveX Control。

  2.在主菜单Project中,选择Add to Project,在其弹出的菜单中,选择Compoents and Controls,出现组件控制平台,在Registered ActiveX Controls中,选择Microsoft MCI Version 5.0,将其插入到项目mci中。

  3.对mci对话框进行可视化设计,加入多媒体控件IDC—MMCONTROL1, “新建”按钮IDC—NEW,“打开”按钮IDC—OPEN,“保存"按钮IDC—SAVE,“退出”按钮IDC—EXIT。

  4.利用ClassWizard给多媒体控件IDC—MMCONTROL1添加变量m—Mci,在mciDlg.cpp中,添加#include “mmsystem.h”,#include “stdio.h”,添加static char BASED—CODE szFilter[]=“WAVE FILES (*.wav)|*.wav|”;在mciDlg.cpp中添加函数void PreparePlay()并分别为“新建”,“打开”,“保存”,“退出”等四个按钮添加处理函数及代码如下:

  

  void CMciDlg::OnExit()

  { m—Mci.SetCommand(″Close″);

   DestroyWindow();

  }

  void CMciDlg::OnNew()

  { CString filename;

   CFileDialog

  fileopenbox(TRUE,″WAV″,NULL,OFN—HIDEREADONLY|OFN—OVERWRITEPROMPT,szFilter);

   fileopenbox.m—ofn.lpstrTitle=″新建声音文件″;

   if(fileopenbox.DoModal()==IDOK)

   filename=fileopenbox.GetPathName();

   CFile myfile;

   CFileException fileException;

  if ( !myfile.Open( filename, CFile::modeCreate |

   CFile::modeReadWrite ), &fileException )

   TRACE( ″Can′t open file %s, error = %u\n″,

   filename, fileException.m—cause );

  PCMWAVEFORMAT L1;

  (L1.wf).wFormatTag=WAVE—FORMAT—PCM;

  (L1.wf).nChannels=2;

  (L1.wf).nSamplesPerSec=44100;

  (L1.wf).nAvgBytesPerSec=176400;

  (L1.wf).nBlockAlign=4;

  L1.wBitsPerSample=16;

  char head[]={′R′,′I′,′F′,′F′};

  myfile.Write(head,4);

  int i;

  i=20+sizeof(L1);

  myfile.Write(&i,sizeof(i));

  char biao[]={′W′,′A′,′V′,′E′,};

  myfile.Write(biao,4);

  char zhong[]={′f′,′m′,′t′,′ ′};

  myfile.Write(zhong,4);

  DWORD t=sizeof(L1);

  myfile.Write(&t,sizeof(t));

  myfile.Write(&L1,sizeof(L1));

  char last[]={′d′,′a′,′t′,′a′};

  myfile.Write(last,4);

  int p=0;

  myfile.Write(&p,sizeof(p));

  myfile.Close();

  PreparePlay(filename);

  IsModified=TRUE;

  }

  void CMciDlg::OnOpen()

   { CString filename;

   CFileDialog

  fileopenbox(TRUE,″WAV″,NULL,OFN—HIDEREADONLY|OFN—OVERWRITEPROMPT,szFilter);

   fileopenbox.m—ofn.lpstrTitle=″打开声音文件″;

  if(fileopenbox.DoModal()==IDOK)

   filename=fileopenbox.GetPathName();

   PreparePlay(filename);

   IsModified=FALSE;

   }

  void CMciDlg::OnSave()

  { m—Mci.SetNotify(FALSE);

   m—Mci.SetWait(TRUE);

   m—Mci.SetCommand(″Save″);

  }

  void CMciDlg::PreparePlay(CString filename)

  { m—Mci.SetDeviceType(″WaveAudio″);

   m—Mci.SetBackVisible(FALSE);

   m—Mci.SetStepVisible(FALSE);

   if(m—Mci.GetMode()!=524)  //当值为524时,设备关闭

   m—Mci.SetCommand(″Close″);

   m—Mci.SetFileName(filename);

   m—Mci.SetCommand(″Open″);

  }



  本文说明了在VC++5.0中实现波形文件的录制,实际上,同时也实现了波形文件的播放,由于本文着重介绍方法,故程序仅作为演示用途。在实际的多媒体软件开发中,可以借助本文讲述的原理和方法制作更加完美的程序。

back.gif (1185 字节)

原文转自:http://www.ltesting.net