www.pudn.com > audioTest.rar > WaveIn.cpp
// WaveIn.cpp: implementation of the CWaveIn class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "WaveIn.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
double avg;//
/////////////////////////////////////////////////////////////////////
//当系统返回一个音频数据块时,系统调用回调函数,此时,hwi设置为录音设备句柄,
//第二个参数是消息,一般为WIM_DATA;第三个参数则是在waveInOpen第五个参数中给出的
//实例数据;其他参数是与消息有关的参数
void CALLBACK waveInProc(HWAVEIN hwi,UINT uMsg,DWORD dwInstance,DWORD dwParam1,
DWORD dwParam2)//系统反馈回来的消息通过这个指定函数来处理
{
switch(uMsg)
{
case MM_WIM_DATA:
WAVEHDR *pWaveHdr = ((WAVEHDR*)dwParam1);//WAVEHDR为缓存格式
CWaveIn *pWaveIn=(CWaveIn*)(pWaveHdr->dwUser);//dwUser为用户的数据
if(pWaveHdr && hwi && pWaveIn)
{
if(pWaveHdr->dwFlags & (WHDR_DONE == WHDR_DONE))//缓存使用结束时,将缓存中的数据返回给应用程序
{
pWaveHdr->dwFlags =0;
//在保存系统返回的音频数据之前,需要调用waveInUnprepareHeader发送一个通知
//告诉设备驱动程序该数据块已经不能用于录音
if(pWaveIn->IsError(waveInUnprepareHeader(hwi,pWaveHdr,sizeof(WAVEHDR))))
{
break;
}
if(pWaveHdr->dwBytesRecorded > 0)
{
//pWaveIn->AddNewBuffer(pWaveHdr);//分析波形
//调用这个的时间差为:缓存大小/采样频率*最小数据格式大小
pWaveIn->BufferDill(pWaveHdr,dwInstance);
}
delete []pWaveHdr->lpData;
pWaveHdr->lpData=NULL;
}
if(!pWaveIn->ResetRequired(pWaveIn))
{//给录音设备添加数据块以继续录音,否则会因为数据块耗尽而停止录音
if(!pWaveIn->AddNewHeader(hwi))
{
break;
}
}
}
break;
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CWaveIn::CWaveIn(WAVEFORMATEX tagFormat,const CWaveDevice &aDevice):m_waveDevice(aDevice),\
m_hWaveIn(0),m_nIndexWaveHdr(/*NUMWAVEINHDR-1*/-1),m_bResetRequired(true)
{
SetWaveFormat(tagFormat);
InitListOfHeader();
}
CWaveIn::CWaveIn():m_hWaveIn(0),m_bResetRequired(true)
{
InitListOfHeader();
}
CWaveIn::~CWaveIn()
{
Close();
FreeListOfBuffer();
FreeListOfHeader();
}
//////////////////////////////////////////////////////////
//Initialisation
//////////////////////////////////////////////////////////
void CWaveIn::SetDevice(const CWaveDevice &aDevice)
{
m_waveDevice = aDevice;
}
////////////////////////////////////////////
void CWaveIn::SetWaveFormat(WAVEFORMATEX tagFormat)
{
m_wave.BuildFormat(tagFormat.nChannels,tagFormat.nSamplesPerSec,tagFormat.wBitsPerSample);
}
void CWaveIn::regist(LPVOID wnd)
{
//m_wnd = (CWnd* )wnd;
m_wnd=(CWinThread*)wnd;
}
/////////////////////////////////////////////
void CWaveIn::InitListOfHeader()
{
for(int i = 0; i < NUMWAVEINHDR;i++)
{
m_tagWaveHdr[i].lpData=NULL;
}
}
///////////////////////////////////////////////////////
//son
///////////////////////////////////////////////////////
bool CWaveIn::Close()
{
if(m_hWaveIn != NULL)
{
if(!Stop())
{
return false;
}
if(IsError(waveInClose(m_hWaveIn)))
{
return false;
}
m_hWaveIn =0;
}
return true;
}
//////////////////////////////////////////////////////////
bool CWaveIn::Continue()
{
if(m_hWaveIn)
{
return !IsError(waveInStart(m_hWaveIn));
}
return true;
}
//////////////////////////////////////
bool CWaveIn::Open()
{
return !IsError(waveInOpen(&m_hWaveIn,m_waveDevice.GetDevice(),&m_wave.GetFormat(),\
(DWORD)waveInProc,m_waveDevice.GetDevice(),CALLBACK_FUNCTION));
}
////////////////////////////////
bool CWaveIn::Pause()
{
if(m_hWaveIn)
{
return !IsError(waveInStop(m_hWaveIn));
}
return true;
}
/////////////////////////////////////////
bool CWaveIn::Record(UINT nTaille/*=4096*/)
{
ASSERT(nTaille > 0);
ASSERT(m_hWaveIn);
if(!Stop())
{
return false;
}
m_bResetRequired = false;
FreeListOfBuffer();
FreeListOfHeader();
SetWaveFormat(m_wave.GetFormat());
//m_nIndexWaveHdr = NUMWAVEINHDR-1;
m_nIndexWaveHdr=-1;
m_nBufferSize = nTaille;
for(int i =0 ; iCopyBuffer(pWaveHdr->lpData,\
pWaveHdr->dwBytesRecorded/m_wave.GetFormat().nBlockAlign,\
m_wave.GetFormat().nBlockAlign);
return true;
}
void CWaveIn::BufferDill(WAVEHDR *pWaveHdr,DWORD deviceNo)
{
wimm_data *wd=new wimm_data;
wd->len=pWaveHdr->dwBufferLength;
wd->data_buffer=new int[wd->len];
wd->deviceNo=deviceNo;
for(unsigned int dw=0;dw < wd->len; dw++)
{
wd->data_buffer[dw]=(int)(pWaveHdr->lpData[dw]);
}
//CWnd *cwnd = AfxGetApp()->GetMainWnd();
bool postresul = m_wnd->PostThreadMessage(WM_MSG_1,(WPARAM)wd,0);
}
///////////////////////////
bool CWaveIn::AddNewHeader(HWAVEIN hwi)
{
ASSERT(m_nBufferSize > 0);
m_nIndexWaveHdr++;
if(m_nIndexWaveHdr==NUMWAVEINHDR)
m_nIndexWaveHdr=0;
if(m_tagWaveHdr[m_nIndexWaveHdr].lpData==NULL)
{
m_tagWaveHdr[m_nIndexWaveHdr].lpData=new char[m_nBufferSize];
}
ZeroMemory(m_tagWaveHdr[m_nIndexWaveHdr].lpData,m_nBufferSize);
m_tagWaveHdr[m_nIndexWaveHdr].dwBufferLength=m_nBufferSize;
m_tagWaveHdr[m_nIndexWaveHdr].dwFlags=0;
m_tagWaveHdr[m_nIndexWaveHdr].dwUser=(DWORD)(void *)this;
//为录音设备配置数据块,而在此之前要调用waveInPrepareHeader准备数据块
if(IsError(waveInPrepareHeader(hwi,&m_tagWaveHdr[m_nIndexWaveHdr],sizeof(WAVEHDR))))
return false;//第二个参数为描述数据块的结构WAVEHDR,第三个参数为该结构的大小
if(IsError(waveInAddBuffer(hwi,&m_tagWaveHdr[m_nIndexWaveHdr],sizeof(WAVEHDR))))
return false;
return true;
}
///////////////////////////
void CWaveIn::FreeListOfHeader()
{
for(int i = 0 ; i GetNumSamples();
}
return dwTotal;
}
CString CWaveIn::GetError() const
{
if(m_nError!=MMSYSERR_NOERROR)
{
TCHAR szText[MAXERRORLENGTH+1];
if(waveInGetErrorText(m_nError,szText,MAXERRORLENGTH)==MMSYSERR_NOERROR)
return szText;
}
return "";
}
////////////////////////////////////////////////
DWORD CWaveIn::GetPosition()
{
if(m_hWaveIn)
{
MMTIME mmt;
mmt.wType = TIME_SAMPLES;
if(IsError(waveInGetPosition(m_hWaveIn,&mmt,sizeof(MMTIME))))
return -1;
else
return mmt.u.sample;
}
return -1;
}
bool CWaveIn::IsError(MMRESULT nResult)
{
m_nError= nResult;
return (m_nError !=MMSYSERR_NOERROR);
}
//////////////////////////////////////////
bool CWaveIn::ResetRequired(CWaveIn *pWaveIn)
{
return m_bResetRequired;
}
bool CWaveIn::IsRecording()
{
bool bResult = false;
if(m_nIndexWaveHdr > -1&& m_tagWaveHdr[m_nIndexWaveHdr].dwFlags!=0)
{
bResult|=!(m_tagWaveHdr[m_nIndexWaveHdr].dwFlags & (WHDR_DONE == WHDR_DONE));
}
return bResult;
}
/////////////////////////////////////////
CWave CWaveIn::MakeWave()
{
void *pBuffer = new char[GetNumSamples()*m_wave.GetFormat().nBlockAlign];
DWORD dwPosInBuffer = 0L;
POSITION pos= m_listOfBuffer.GetHeadPosition();
while(pos)
{
CWaveBuffer *p_waveBuffer = (CWaveBuffer *)m_listOfBuffer.GetNext(pos);
CopyMemory((char*)pBuffer+dwPosInBuffer,p_waveBuffer->GetBuffer(),\
p_waveBuffer->GetNumSamples()*p_waveBuffer->GetSampleSize());
dwPosInBuffer+=p_waveBuffer->GetNumSamples()*p_waveBuffer->GetSampleSize();
}
m_wave.SetBuffer(pBuffer,GetNumSamples());
return m_wave;
}