www.pudn.com > IP_phone.rar > WaveIn.cpp
/**********************************************************/
/*类名:CWaveIn */
/*简述:封装的音频采集类 */
/**********************************************************/
// WaveIn.cpp: implementation of the CWaveIn class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "stdafx.h"
#include "../NC_Client.h"
#include "WaveIn.h"
#include "math.h"
#pragma comment(lib,"Winmm")
DWORD CWaveIn::s_dwInstance = 0;
extern CCompress g_comp;
extern CWaveOut *g_wave_out;
DWORD WINAPI CWaveIn::AudioInThreadProc(LPVOID lpParameter);
CWaveIn::CWaveIn(CSendSocket *temp_socket,CNC_ClientDlg *temp)
{
m_dlg=temp;
m_wChannel=1;
m_dwSample=WISA_POOR;
m_wBit=16;
m_buf_number=10;
m_hIn=0;
m_bThreadStart=false;
m_bDevOpen=false;
m_bAllocBuffer=false;
m_bRecord=false;
m_pHdr=NULL;
m_dwAudioInId=0;
s_dwInstance++;
send_socket=temp_socket;
m_bSend=false;
}
CWaveIn::~CWaveIn()
{
}
///////////////////////////////////////////////////////////////////////////
//音频设备初始化
BOOL CWaveIn::Ini()
{
//启动监听线程
if (!StartThread())
{
return false;
};
//打开输入设备
if (!OpenDev())
{
StopThread ();
};
//初始化数据缓冲队列
if (!PerPareBuffer())
{
CloseDev ();
}
//开始采集音频
if (!OpenRecord())
{
FreeBuffer();
}
return true;
}
///////////////////////////////////////////////////////////////////////////
//收尾
BOOL CWaveIn::Release()
{
CloseRecord ();
Sleep(1500);
FreeBuffer();
if (CloseDev())
{
StopThread ();
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////
BOOL CWaveIn::StartThread()
{
if (m_bThreadStart)
return false;
m_hAudioIn=CreateThread(0,0,AudioInThreadProc,this,0,&m_dwAudioInId);
if(!m_hAudioIn)
{
AfxMessageBox("监听线程启动失败!");
return false;
}
m_bThreadStart=true;
return true;
}
////////////////////////////////////////////////////////////////////////////
BOOL CWaveIn::StopThread()
{
if (!m_bThreadStart)
return false;
if(m_hAudioIn)
{
int t=50;
DWORD ExitCode;
BOOL bEnd=false;
PostThreadMessage(m_dwAudioInId,WM_QUIT,0,0);
while(t)
{
GetExitCodeThread(m_hAudioIn,&ExitCode);
if(ExitCode!= STILL_ACTIVE)
{
bEnd=true;
break;
}
else
Sleep(10);
t--;
}
if(!bEnd)
{
//TerminateThread wave in thread
TerminateThread(m_hAudioIn,0);
}
m_hAudioIn=0;
}
m_bThreadStart = false;
return true;
}
/////////////////////////////////////////////////////////////////////////
BOOL CWaveIn::OpenDev()
{
if (m_bDevOpen)
return false;
//检查音频设备
MMRESULT result;
result=waveInGetNumDevs(); //获得设备对象数目
if (result==0)
{
AfxMessageBox("No Sound Device");
return false;
}
result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS));//检测输入设备能力
if (result!=MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot determine sound card capabilities !"));
return false;
}
//定义音频格式
WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = m_wChannel;
wfx.nSamplesPerSec = m_dwSample;
wfx.nAvgBytesPerSec = m_wChannel * m_dwSample * m_wBit / 8;
wfx.nBlockAlign = m_wBit * m_wChannel / 8;
wfx.wBitsPerSample = m_wBit;
wfx.cbSize = 0;
m_mmr=waveInOpen(0,WAVE_MAPPER,&wfx,0,0,WAVE_FORMAT_QUERY);
if(m_mmr)
{
AfxMessageBox("waveInOpen_query error!");
return false;
}
m_mmr=waveInOpen(&m_hIn,WAVE_MAPPER,&wfx,m_dwAudioInId,s_dwInstance,CALLBACK_THREAD);
if(m_mmr)
{
AfxMessageBox("waveInOpen error!");
return false;
}
m_bDevOpen = true;
return true;
}
/////////////////////////////////////////////////////////////////////////
BOOL CWaveIn::CloseDev()
{
if (!m_bDevOpen)
return false;
if(!m_hIn)
{
AfxMessageBox("Device hasn't opened!");
return false;
}
m_mmr=waveInClose(m_hIn);
if(m_mmr)
{
AfxMessageBox(GetLastErrorString());
m_hIn=0;
m_bDevOpen=false;
return false;
}
m_hIn=0;
m_bDevOpen=false;
return true;
}
/////////////////////////////////////////////////////////////////////////
BOOL CWaveIn::PerPareBuffer()
{
if (m_bAllocBuffer)
return false;
//复位音频设备
m_mmr=waveInReset(m_hIn);
if(m_mmr)
{
AfxMessageBox("waveInReset error!");
return false;
}
UINT i;
m_pHdr=new WAVEHDR[m_buf_number];//缓冲区队列数组
//初始化数据缓冲队列
for(i=0;iwavebuffer,InputBuffer,iLen);
if(m_dlg->btest)
{
//本机测试
/*char buffertemp[1024];
memcpy(buffertemp,InputBuffer,iLen);
g_wave_out->Play(buffertemp,iLen);*/
g_wave_out->Play(pBuffer,iLen);
memcpy(m_dlg->wavebuffer,pBuffer,iLen);
}
else
{
m_soLock.Lock();
if(m_bSend)
{
int iOut=sizeof(m_cBufOut);
//压缩and发送
g_comp.CompressAudioData(pBuffer,iLen,m_cBufOut,&iOut);
send_socket->Send(m_cBufOut,iOut/*60*/);
}
m_soLock.Unlock();
}
}
/////////////////////////////////////////////////////////////////////////
void CWaveIn::EnableSend(BOOL bSend)
{
m_soLock.Lock ();
m_bSend = bSend;
m_soLock.Unlock ();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Glogal Thread procedure for the CWaveIn class
// It cannot be included inside the Class
//
// The LPARAM is the Class pointer (this) it can be the base class CWaveIn ptr or a derived new class
// The value of this parametre can change according the Topmost class of the process
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI CWaveIn::AudioInThreadProc(LPVOID lpParameter)
{
char buffer[1024];//用于转发的临时缓冲区变量
CWaveIn *pWaveIn = (CWaveIn *)lpParameter;
//接受消息
MSG msg;
while(GetMessage(&msg,0,0,0))
{
switch(msg.message )
{
case MM_WIM_OPEN:
break;
case MM_WIM_CLOSE:
break;
case MM_WIM_DATA:
//从缓冲块中取出数据
WAVEHDR* pWH=(WAVEHDR*)msg.lParam;
waveInUnprepareHeader((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
if(pWH->dwBytesRecorded!=SIZE_AUDIO_FRAME)
break;
//将数据传给压缩线程
memcpy(buffer,pWH->lpData,pWH->dwBytesRecorded);
pWaveIn->GetData (buffer ,pWH->dwBytesRecorded );
//重新准备该缓冲块,并加入缓冲队列
waveInPrepareHeader((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
waveInAddBuffer((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
break;
}
}
return msg.wParam;
}