📄 sy1104.htm
字号:
<html>
<HEAD>
<TITLE>Visual C++与计算机接口</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=gb2312" >
</HEAD>
<body>
<font color="#0000FF">使用多媒体API</font>
<p>
(一)实验目的:<BR>
学习使用多媒体API<BR><BR>
(二)实验内容<BR><BR>
使用MCI可以很好的进行多媒体的播放和录制,但当你要做一些实际工作的时候,你会发现MCI的功能远远不够,因为它不能对多媒体设备和多媒体文件进行精细的控制。要做到这些,需要使用多媒体API。<BR><BR>
多媒体API分为许多类,例如:<BR>
waveOutxxxx 类函数用于wave声音播放设备的控制<BR>
waveInxxxx 类函数用于wave声音录制设备的控制<BR>
midiStreamxxxx 类函数用于midi声音的播放控制<BR>
midiOutxxxx 类函数用于midi声音播放设备的控制<BR>
midiInxxxx 类函数用于midi声音录制设备的控制<BR>
AVIFilerxxxx 类函数用于AVI文件的操作<BR>
AVIStreamxxxx 类函数用于AVI流的播放控制<BR>
capxxxx 类函数用于AVI图象的录制控制<BR>
mmioxxxx 类函数用于RIFF类多媒体文件的操作<BR>
.wav文件、.avi文件、.mid文件都属于RIFF(resource information file format)类多媒体文件。<BR><BR>
下面将以声音播放设备和录制设备的控制为例,学习多媒体API的使用。其他类多媒体API的使用,请参阅MSDN文档。<BR><BR>
(三)音频多媒体API的使用:<BR><BR>
使用多媒体API,源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Winmm.lib。<BR><BR>
1、音频设备句柄<BR>
在Windows中可以发现,许多时候都会用到句柄,例如最常用的窗口句柄HWND,绘图句柄HDC等。<BR>
句柄不是指针,可以认为句柄就是一个号码,一个代表。代表一块内存,一个硬件设备或一个软件结构体。<BR><BR>
在多媒体应用中,每一个多媒体设备都可以申请一个句柄并通过这个句柄来操作这个设备。<BR>
注意:声卡并不是多媒体设备,一块声卡上至少有一个waveOut、一个waveIn和一个midiOut设备。每一个多媒体并不是只能有一个句柄,有的多媒体设备可以同时申请多个句柄。<BR><BR>
打开waveOut设备:<BR>
MMRESULT waveOutOpen( <BR>
LPHWAVEOUT phwo, //句柄指针,用于存放返回的设备句柄<BR>
UINT uDeviceID, //设备ID,通常使用WAVE_MAPPER由系统来选择<BR>
LPWAVEFORMATEX pwfx, //设备属性设置<BR>
DWORD dwCallback, //回调句柄,通常是一个窗口句柄HWND<BR>
DWORD dwCallbackInstance, //回调Instance,通常设为NULL<BR>
DWORD fdwOpen //回调方式,通常设为CALLBACK_WINDOW<BR>
);<BR>
下面是WAVEFORMATEX结构的定义:<BR>
typedef struct {<BR>
WORD wFormatTag; //设备类型,通常为WAVE_FORMAT_PCM<BR>
WORD nChannels; //设备通道数,1或2<BR>
DWORD nSamplesPerSec; //声音频率,通常为8000、11025、22050、44100<BR>
DWORD nAvgBytesPerSec; //通常为 nSamplesPerSec * nBlockAlign<BR>
WORD nBlockAlign; //通常为 nChannels * wBitsPerSample/8<BR>
WORD wBitsPerSample; //声音采样位数,8或16<BR>
WORD cbSize; //附加字节数,通常为0<BR>
} WAVEFORMATEX;<BR>
可以理解,应首先设置WAVEFORMATEX结构值,然后再用此结构来打开一个waveOut设备或waveIn设备,获得设备句柄。<BR><BR>
2、声音数据信息WAVEHDR<BR><BR>
typedef struct { <BR>
LPSTR lpData; //声音数据指针<BR>
DWORD dwBufferLength; //声音数据长度<BR>
DWORD dwBytesRecorded; //已经录制的声音数据长度<BR>
DWORD dwUser; //可不用关心<BR>
DWORD dwFlags; //可不用关心<BR>
DWORD dwLoops; //播放循环次数<BR>
struct wavehdr_tag * lpNext; //可不用关心<BR>
DWORD reserved;<BR>
} WAVEHDR; <BR>
声音数据信息WAVEHDR用于存放声音数据的信息,主要信息为数据指针和数据长度。<BR><BR>
获得音频设备句柄以后,即可在waveOutPrepareHeader函数或waveInPrepareHeader、waveInAddBuffer函数中准备WAVEHDR,之后可以调用waveOutWrite或waveInStart进行声音的播放或录制,使用完毕后,调用waveOutUnprepareHeader或waveInUnprepareHeader函数释放WAVEHDR。<BR><BR>
3、实例<BR><BR>
(1)建一个多文档的MFC应用程序。<BR>
(2)在View类的头文件中加入变量:<BR>
HWAVEIN hWaveIn;<BR>
HWAVEOUT hWaveOut;<BR>
WAVEFORMATEX hWaveFmt;<BR>
WAVEHDR hWaveHdr;<BR>
char buf[102400l];<BR>
(3)建立菜单项ID_RECORD和ID_PLAY。<BR>
(4)在View类中加入ID_PLAY的响应函数:<BR><BR>
hWaveFmt.wFormatTag = WAVE_FORMAT_PCM;<BR>
hWaveFmt.nChannels = 2;<BR>
hWaveFmt.nSamplesPerSec = 22050;<BR>
hWaveFmt.nAvgBytesPerSec = 44100;<BR>
hWaveFmt.nBlockAlign = 4; <BR>
hWaveFmt.wBitsPerSample = 16;<BR>
hWaveFmt.cbSize = 0;<BR>
<BR>
hWaveHdr.lpData = buf;<BR>
hWaveHdr.dwBufferLength = 102400;<BR>
hWaveHdr.dwFlags = 0L;<BR>
hWaveHdr.dwLoops = 0L; <BR>
hWaveHdr.dwUser = 0;<BR>
<BR>
waveOutOpen(&hWaveOut, WAVE_MAPPER, &hWaveFmt, (WORD)m_hWnd, 0L, CALLBACK_WINDOW); <BR>
waveOutPrepareHeader(hWaveOut, &hWaveHdr, sizeof(WAVEHDR)); <BR>
waveOutWrite(hWaveOut, &hWaveHdr, sizeof(WAVEHDR));<BR><BR>
(5)在View类中加入ID_RECORD的响应函数:<BR><BR>
hWaveFmt.wFormatTag = WAVE_FORMAT_PCM;<BR>
hWaveFmt.nChannels = 2;<BR>
hWaveFmt.nSamplesPerSec = 22050;<BR>
hWaveFmt.nAvgBytesPerSec = 44100;<BR>
hWaveFmt.nBlockAlign = 4; <BR>
hWaveFmt.wBitsPerSample = 16;<BR>
hWaveFmt.cbSize = 0;<BR>
<BR>
hWaveHdr.lpData = buf;<BR>
hWaveHdr.dwBufferLength = 102400;<BR>
hWaveHdr.dwFlags = 0L;<BR>
<BR>
waveInOpen(&hWaveIn, WAVE_MAPPER, &hWaveFmt, (WORD)m_hWnd, 0L, CALLBACK_WINDOW); <BR>
waveInPrepareHeader(hWaveIn, &hWaveHdr, sizeof(WAVEHDR)); <BR>
waveInAddBuffer(hWaveIn, &hWaveHdr, sizeof(WAVEHDR)); <BR>
waveInStart(hWaveIn); <BR><BR>
(6)在View类中用ClassWizard重载WindowProc函数。<BR>
(7)在此函数中加入代码:<BR>
if (message == MM_WIM_DATA)<BR>
{<BR>
waveInUnprepareHeader(hWaveIn,&(hWaveHdr),sizeof(WAVEHDR));<BR>
waveInClose(hWaveIn);<BR>
}<BR>
(8)编译运行。<BR><BR>
现在此例子可以录制声音并播放刚录制的声音。<BR><BR>
<p></p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -