需要代码好久前就已经用完了,但人懒没办法,现在才来总结,生怕以后要用的时候忘得一干二净,唉......
由于我是在对话框语音聊天工程使用的,所以还是以对话框语音聊天工程为例。
首先为工程连接winmm.lib库,然后在.h头文件中#include "mmsystem.h"。
然后在对话框头文件类定义之前定义一个参数:
#define BUFFER_SIZE 400 //录音buf大小,buf大小越小,实时性越好,连续性越差。
然后在类定义里面定义以下几个变量:
public:
WAVEHDR m_WAVEHDR1,m_WAVEHDR2;
char m_cbBuffer1[BUFFER_SIZE],m_cbBuffer2[BUFFER_SIZE];
HWAVEIN m_hWaveIn;
WAVEFORMATEX m_waveformin;
BOOL m_nRecordEnd; //录音停止状态,用这个变量来控制录音是否要结束。
然后在头文件中声明一个录音函数 void SoundIn();在cpp文件中定义录音函数:
void CChatDlg::SoundIn() //录音函数
{
if(!waveInGetNumDevs()) //先侦查有米可以录音的设备
{MessageBox("device In erroe") ;
return;}
m_waveformin.wFormatTag=WAVE_FORMAT_PCM; //设置录音格式,关于这个格式具体解释自己Google一下吧
m_waveformin.nChannels=1;
m_waveformin.nSamplesPerSec=11052;
m_waveformin.wBitsPerSample=8;
m_waveformin.nBlockAlign=m_waveformin.nChannels * m_waveformin.wBitsPerSample / 8;
m_waveformin.nAvgBytesPerSec=m_waveformin.nSamplesPerSec * m_waveformin.nBlockAlign;
m_waveformin.cbSize=0;
MMRESULT error;
error=waveInOpen(&m_hWaveIn,WAVE_MAPPER, &m_waveformin, (DWORD)m_hWnd,NULL,CALLBACK_WINDOW); //打开录音设备,成功的话函数会把录音设备的句柄赋给m_hWaveIn
if(MMSYSERR_NOERROR !=error) //打开设备失败的错误判断
{
if(MMSYSERR_ALLOCATED==error)
MessageBox("wave In open erroe:MMSYSERR_ALLOCATED") ;
if(MMSYSERR_BADDEVICEID==error)
MessageBox("wave In open erroe:MMSYSERR_BADDEVICEID") ;
if(MMSYSERR_NODRIVER==error)
MessageBox("wave In open erroe:MMSYSERR_NODRIVER") ;
if(MMSYSERR_NOMEM==error)
MessageBox("wave In open erroe:MMSYSERR_NOMEM") ;
if(WAVERR_BADFORMAT==error)
MessageBox("wave In open erroe:WAVERR_BADFORMAT") ;
return;
}
//开始为录音准备缓存,下面定义双缓冲,可以避免录音的不连续。
m_WAVEHDR1.lpData = (LPTSTR)m_cbBuffer1;
//把char m_cbBuffer1[BUFFER_SIZE]挂载到声音缓存结构体m_WAVEHDR1里面。
m_WAVEHDR1.dwBufferLength = BUFFER_SIZE;
m_WAVEHDR1.dwBytesRecorded = 0;
m_WAVEHDR1.dwUser=0;
m_WAVEHDR1.dwFlags=0;
m_WAVEHDR1.dwLoops=1;
m_WAVEHDR1.lpNext=NULL;
m_WAVEHDR1.reserved=0;
m_WAVEHDR2.lpData = (LPTSTR)m_cbBuffer2;
m_WAVEHDR2.dwBufferLength = BUFFER_SIZE;
m_WAVEHDR2.dwBytesRecorded = 0;
m_WAVEHDR2.dwUser=0;
m_WAVEHDR2.dwFlags=0;
m_WAVEHDR2.dwLoops=1;
m_WAVEHDR2.lpNext=NULL;
m_WAVEHDR2.reserved=0;
waveInPrepareHeader(m_hWaveIn,&m_WAVEHDR1,sizeof(WAVEHDR)); //按照字面理解就是准备内存块录音
waveInPrepareHeader(m_hWaveIn,&m_WAVEHDR2,sizeof(WAVEHDR));
waveInAddBuffer(m_hWaveIn,&m_WAVEHDR1,sizeof(WAVEHDR)); //按照字面理解就是把内存块加载上去
waveInAddBuffer(m_hWaveIn,&m_WAVEHDR2,sizeof(WAVEHDR));
m_nRecordEnd = FALSE; //设置录音状态
if(MMSYSERR_NOERROR !=waveInStart(m_hWaveIn)) //开始录音
{MessageBox("Wave In start erroe") ;
return;}
}
随着录音的不断进行,声音数据就不断的填充录音缓存,当一个录音缓存被填充满了之后就会促发MM_WIM_DATA消息,我们可以对这个消息做出处理,把缓存里面的声音数据按自己的要求处理。
首先在头文件定义消息处理函数,在两个AFX_MSG之间添加 afx_msg void OnMM_WIM_DATA(UINT wParam,LONG lParam);
在源文件添加消息映射,在两个AFX_MSG_MAP之间添加 ON_MESSAGE(MM_WIM_DATA,OnMM_WIM_DATA)
OnMM_WIM_DATA函数的具体定义如下:
void CChatDlg::OnMM_WIM_DATA(UINT wParam, LONG lParam)
{ PWAVEHDR pWaveHdr = (PWAVEHDR)lParam;
int length=sendto(soundsend, pWaveHdr->lpData,BUFFER_SIZE,0,(SOCKADDR*)&SoundaddrFrom,sizeof(SOCKADDR));
//由于这个例子是做语音聊天的,我们就把缓存里面的声音数据发送到指定的IP地址去。
if(SOCKET_ERROR==length)
{MessageBox("sound send failure!");
return;
}
if(m_nRecordEnd == TRUE)
/*判断录音状态,如果要停止录音就执行waveInClose(m_hWaveIn)关闭录音设备。我们可以建立一个停止录音按钮,按下按钮m_nRecordEnd 就变为TRUE。下面会给出停止录音按钮函数的实现。*/
{ waveInClose(m_hWaveIn);
return ;
}
waveInAddBuffer(m_hWaveIn, pWaveHdr, sizeof (WAVEHDR));
//把缓存加载到录音上去循环使用,不然的话,两个录音缓存装满了后就没有缓存用来继续录音了。
}
添加一个停止录音的按钮,对按钮按下做出消息响应,消息响应函数void OnSoundExit() 。
void CChatDlg::OnSoundExit()
{
// TODO: Add your control notification handler code here
m_nRecordEnd = TRUE;
waveInReset(m_hWaveIn);
}
在上面的函数中,除了把停止录音状态改为TRUE,还执行waveInReset(m_hWaveIn),这个函数会发出MM_WIM_DATA消息,从而接着执行OnMM_WIM_DATA(UINT wParam, LONG lParam) 函数,在OnMM_WIM_DATA函数里判断到m_nRecordEnd 为TRUE的话,就会执行waveInClose(m_hWaveIn),这个函数会发出MM_WIM_CLOSE消息,我们对这个消息作出响应,在响应函数中做一些收尾的工作。
首先在头文件声明消息响应函数
afx_msg void OnMM_WIM_CLOSE(UINT wParam,LONG lParam);
然后在cpp文件进行消息映射
ON_MESSAGE(MM_WIM_CLOSE,OnMM_WIM_CLOSE)
响应函数的定义如下:
void CChatDlg::OnMM_WIM_CLOSE(UINT wParam, LONG lParam)
{ m_nRecordEnd=FALSE; //把录音停止状态改为FALSE
waveInUnprepareHeader (m_hWaveIn, &m_WAVEHDR1, sizeof (WAVEHDR)) ; //解除录音缓存
waveInUnprepareHeader (m_hWaveIn, &m_WAVEHDR2, sizeof (WAVEHDR)) ;
}
OK 完毕了 下一篇总结如何放音吧 (*^__^*) 嘻嘻……