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; 
}