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