⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waveio.cpp

📁 这是G.723和G.729的音频编解码的源代码
💻 CPP
字号:

//filename: WaveIO.cpp

#include "stdafx.h"
#include "WaveIO.h"

UINT WaveThread(LPVOID pParam)
{
	((CWave*)pParam)->WaveThreadFunc();
	return 0L;
}

//implementation of class CWave
CWave::CWave(PWaveCallBack pWaveCallBack,int nBufferSize,int nBufferNum,int nSampleRate,int nSampleBitsLen)
{
	m_bIsComplete=TRUE;
	m_uDeviceID=WAVE_MAPPER;
	m_dwUserData=0;
	m_pWaveThread=0;	
	m_nBufferSize=nBufferSize;
	m_nBufferCount=nBufferNum;
	m_pWaveCallBack=pWaveCallBack;
	
	m_hWaveEvent=CreateEvent(NULL,// pointer to security attributes
						 FALSE,// flag for manual-reset event
						 FALSE,// flag for initial state
						 NULL);
	m_hRequestQuit=CreateEvent(NULL,FALSE,FALSE,NULL);
	m_hIndicateQuit=CreateEvent(NULL,FALSE,FALSE,NULL);

	if((!m_hWaveEvent)||
		(!m_hRequestQuit)||
		 (!m_hIndicateQuit))
		m_bIsComplete=FALSE;

	m_WaveHdr=new WAVEHDR[m_nBufferCount];
	m_bUsingBuffer=new BOOL[m_nBufferCount];
	m_pBuffer=new char * [m_nBufferCount];

	if((!m_WaveHdr)||(!m_bUsingBuffer)||(!m_pBuffer))
		m_bIsComplete=FALSE;

	m_WaveFormat.wFormatTag=WAVE_FORMAT_PCM;
    m_WaveFormat.nChannels=1;
    m_WaveFormat.nSamplesPerSec=(DWORD)nSampleRate;
    m_WaveFormat.nAvgBytesPerSec=(DWORD)nSampleRate*nSampleBitsLen/8;
    m_WaveFormat.nBlockAlign=nSampleBitsLen/8;
    m_WaveFormat.wBitsPerSample=nSampleBitsLen;
    m_WaveFormat.cbSize=0;

	if(!m_bIsComplete)return;

	int i=0;	
	for(i=0;i<m_nBufferCount;i++)
	{
		if(m_nBufferSize)
			m_pBuffer[i]=new char[m_nBufferSize];
		else
			m_pBuffer[i]=NULL;

		if(m_pBuffer[i]==NULL)
			m_bIsComplete=FALSE;

		m_bUsingBuffer[i]=FALSE;
		ZeroMemory(&(m_WaveHdr[i]),sizeof(WAVEHDR));
		m_WaveHdr[i].dwBufferLength=m_nBufferSize;
		m_WaveHdr[i].lpData=m_pBuffer[i];
	}
	
}

CWave::~CWave(void)
{
	if(m_hWaveEvent)CloseHandle(m_hWaveEvent);	
	if(m_hRequestQuit)CloseHandle(m_hRequestQuit);
	if(m_hIndicateQuit)CloseHandle(m_hIndicateQuit);

	m_hWaveEvent=m_hRequestQuit=m_hIndicateQuit=0;

	int i=0;
	for(i=0;i<m_nBufferCount;i++)
	{		
		if(m_pBuffer[i])
			delete [] m_pBuffer[i];
		m_pBuffer[i]=NULL;
		m_bUsingBuffer[i]=FALSE;
	}

	if(m_bUsingBuffer)delete[] m_bUsingBuffer;
	if(m_WaveHdr)delete[] m_WaveHdr;
	if(m_pBuffer)delete[] m_pBuffer;
	m_bUsingBuffer=NULL;
	m_WaveHdr=NULL;
	m_pBuffer=NULL;
}

void CWave::ExitThread()
{
	if(m_pWaveThread)
	{
		//request quit
		if(SetEvent(m_hRequestQuit))			
			WaitForSingleObject(m_hIndicateQuit,INFINITE);
		else
		{
			//force quit			
			DWORD dwExitCode;
			do
			{
				TerminateThread(m_pWaveThread->m_hThread,0);
				GetExitCodeThread(m_pWaveThread->m_hThread,&dwExitCode);
			}while(STILL_ACTIVE==dwExitCode);
		}
		m_pWaveThread=NULL;
	}
}

void CWave::WaveThreadFunc()
{
	HANDLE phHandles[]={m_hRequestQuit,m_hWaveEvent};
	DWORD dwWaitResult;
	while(1)
	{
		dwWaitResult=WaitForMultipleObjects(2,phHandles,FALSE,INFINITE); 
		if(dwWaitResult==WAIT_OBJECT_0)
		{
			while(!SetEvent(m_hIndicateQuit))
			{
				Sleep(0);
			}
			break;
		}
		else if(dwWaitResult==WAIT_OBJECT_0+1)		
			HandleWaveEvent();
		else
			continue;		
	}
}

//implementation of class CWaveIn
CWaveIn::CWaveIn(PWaveCallBack pWaveCallBack,
				 int nBufferSize,				 
				 int nSampleRate,
				 int nSampleBitsLen)
				 :CWave(pWaveCallBack,
						nBufferSize,
						WAVE_IN_BUFFER_NUM,
						nSampleRate,
						nSampleBitsLen)
{
	m_hWaveIn=0;
}

CWaveIn::~CWaveIn(void){End();}

BOOL CWaveIn::Begin(DWORD dwUserData)
{
	m_dwUserData=dwUserData;
	//test parameter ?
	if(!m_bIsComplete)return FALSE;
	if(!m_pWaveCallBack)return FALSE;

	if(m_hWaveIn)
		End();

	//open wave in device
	if(MMSYSERR_NOERROR!=waveInOpen(&m_hWaveIn,
									m_uDeviceID,
									&m_WaveFormat,
									(DWORD)m_hWaveEvent,
									0,
									CALLBACK_EVENT))
	{
		m_hWaveIn=0;
		return FALSE;
	}
	//prepare header
	int i=0;
	int nPreparedBuffer=0;
	for(i=0;i<m_nBufferCount;i++)
	{
		if(m_bUsingBuffer[i])
		{
			nPreparedBuffer++;
			continue;
		}

		m_WaveHdr[i].lpData=m_pBuffer[i];
		m_WaveHdr[i].dwBufferLength=m_nBufferSize;
		m_WaveHdr[i].dwFlags=0;

		if(MMSYSERR_NOERROR!=waveInPrepareHeader(m_hWaveIn,
											     &(m_WaveHdr[i]),
											     sizeof(WAVEHDR)))
			continue;
		
		if(MMSYSERR_NOERROR!=waveInAddBuffer(m_hWaveIn,
											 &(m_WaveHdr[i]),
											 sizeof(WAVEHDR)))
			continue;
		
		m_bUsingBuffer[i]=TRUE;
		nPreparedBuffer++;							
	}
	//less than two valid buffer
	if(nPreparedBuffer<2)
	{
		CloseWaveIn();
		return FALSE;			
	}
	//start wave in
	if(MMSYSERR_NOERROR!=waveInStart(m_hWaveIn))
	{
		CloseWaveIn();		
		return FALSE;
	}
	//begin thread
	if(m_pWaveThread)return TRUE;	
	m_pWaveThread=AfxBeginThread(WaveThread,this);//,THREAD_PRIORITY_TIME_CRITICAL);
	if(!m_pWaveThread)
	{
		CloseWaveIn();
		return FALSE;		
	}
	return TRUE;
}

void CWaveIn::CloseWaveIn()
{
	if(!m_hWaveIn)return;	
	int i=0;
	int nFirstValidHeader=0;
	
Loop:
	//find first valid header
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])continue;
		nFirstValidHeader=i;
		break;
	}
	//reset wave out device
	while(1)	
	{
		Sleep(0);
		if(MMSYSERR_NOERROR!=waveInReset(m_hWaveIn))		
			continue;
		if((m_WaveHdr[nFirstValidHeader].dwFlags&
			WHDR_DONE)==WHDR_DONE)break;			
	}
	//clear header
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])continue;	
		while(MMSYSERR_NOERROR!=waveInUnprepareHeader(m_hWaveIn,
													  &(m_WaveHdr[i]),
													  sizeof(WAVEHDR)))
		{
			Sleep(0);
		}
		m_bUsingBuffer[i]=FALSE;
	}
	//close wave in device
	if(WAVERR_STILLPLAYING==waveInClose(m_hWaveIn))
		goto Loop;
	m_hWaveIn=NULL;
}

void CWaveIn::End(void)
{	
	ExitThread();
	CloseWaveIn();	
}

void CWaveIn::HandleWaveEvent(void)
{
	int i=0;
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])
			continue;		
		if(((m_WaveHdr[i].dwFlags)&WHDR_DONE)!=WHDR_DONE)
			continue;		
		(*m_pWaveCallBack)((BYTE*)(m_pBuffer[i]),
							m_nBufferSize,
							m_dwUserData);		
		waveInUnprepareHeader(m_hWaveIn,
							  &(m_WaveHdr[i]),
							  sizeof(WAVEHDR));							  
		m_WaveHdr[i].dwFlags=0;
		m_WaveHdr[i].lpData=m_pBuffer[i];
		m_WaveHdr[i].dwBufferLength=m_nBufferSize;
		waveInPrepareHeader(m_hWaveIn,
							&(m_WaveHdr[i]),
							sizeof(WAVEHDR));							
		waveInAddBuffer(m_hWaveIn,
						&(m_WaveHdr[i]),
						sizeof(WAVEHDR));	
	}
}

//implementation of class CWaveOut
CWaveOut::CWaveOut(PWaveCallBack pWaveCallBack,
				   int nBufferSize,
				   int nSampleRate,
				   int nSampleBitsLen)
				   :CWave(pWaveCallBack,
						  nBufferSize,
						  WAVE_OUT_BUFFER_NUM,
						  nSampleRate,
						  nSampleBitsLen)
{
	m_hWaveOut=0;
}

CWaveOut::~CWaveOut(void)
{
	End();
}

BOOL CWaveOut::Begin(DWORD dwUserData)
{	
	//parameter check	
	if(!m_bIsComplete)return FALSE;
	if(!m_pWaveCallBack)return FALSE;

	if(m_hWaveOut)
		End();
	m_dwUserData=dwUserData;

	//open wave out device
	if(MMSYSERR_NOERROR!=waveOutOpen(&m_hWaveOut,
									 m_uDeviceID,
									 &m_WaveFormat,
									 (DWORD)m_hWaveEvent,
									 0,
									 CALLBACK_EVENT))
	{
		m_hWaveOut=0;
		return FALSE;
	}

	//prepare Header
	int i=0;
	int nPreparedCount=0;
	for(i=0;i<m_nBufferCount;i++)
	{
		ZeroMemory(m_pBuffer[i],m_nBufferSize);
		if(m_bUsingBuffer[i])
		{
			nPreparedCount++;
			continue;
		}		
		m_WaveHdr[i].dwFlags=0;
		m_WaveHdr[i].dwBufferLength=2;
		m_WaveHdr[i].lpData=m_pBuffer[i];
		if(MMSYSERR_NOERROR==waveOutPrepareHeader(m_hWaveOut,
												  &(m_WaveHdr[i]),
												  sizeof(WAVEHDR)))
			if(MMSYSERR_NOERROR==waveOutWrite(m_hWaveOut,
											  &(m_WaveHdr[i]),
											  sizeof(WAVEHDR)))
		{
			nPreparedCount++;
			m_bUsingBuffer[i]=TRUE;
		}
	}

	//less than two valid header buffer
	if(nPreparedCount<2)
	{
		CloseWaveOut();
		return FALSE;
	}

	//startup thread
	if(m_pWaveThread)return TRUE;	
	m_pWaveThread=AfxBeginThread(WaveThread,this,THREAD_PRIORITY_ABOVE_NORMAL);
	if(m_pWaveThread==NULL)
	{
		CloseWaveOut();
		return FALSE;
	}
	return TRUE;
}

void CWaveOut::CloseWaveOut()
{
	if(!m_hWaveOut)return;	
	int i=0;
	int nFirstValidHeader=0;
	
Loop:
	//find first valid header
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])continue;
		nFirstValidHeader=i;
		break;
	}
	//reset wave out header
	while(1)	
	{
		Sleep(0);
		if(MMSYSERR_NOERROR!=waveOutReset(m_hWaveOut))
			continue;
		if((m_WaveHdr[nFirstValidHeader].dwFlags&
			WHDR_DONE)==WHDR_DONE)break;
	}
	//clear header
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])continue;	
		while(MMSYSERR_NOERROR!=waveOutUnprepareHeader(m_hWaveOut,
													  &(m_WaveHdr[i]),
													  sizeof(WAVEHDR)))
		{
			Sleep(0);
		}
		m_bUsingBuffer[i]=FALSE;
	}
	//close wave out device
	if(WAVERR_STILLPLAYING==waveOutClose(m_hWaveOut))
		goto Loop;

	m_hWaveOut=NULL;
}

void CWaveOut::End(void)
{	
	ExitThread();
	CloseWaveOut();
}

void CWaveOut::HandleWaveEvent(void)
{	
	int i=0;
	int nActualLength=0;
	for(i=0;i<m_nBufferCount;i++)
	{
		if(!m_bUsingBuffer[i])continue;
		if((m_WaveHdr[i].dwFlags&WHDR_DONE)!=WHDR_DONE)
			continue;
		waveOutUnprepareHeader(m_hWaveOut,
							   &(m_WaveHdr[i]),
							   sizeof(WAVEHDR));

		
		nActualLength=m_pWaveCallBack((BYTE*)(m_pBuffer[i]),
									  m_nBufferSize,
									  m_dwUserData);
		if(nActualLength)
		{
			m_WaveHdr[i].dwBufferLength=nActualLength;
		}
		else
		{
			m_WaveHdr[i].dwBufferLength=2;
			ZeroMemory(m_pBuffer[i],m_nBufferSize);
		}
		m_WaveHdr[i].dwFlags=0;
		m_WaveHdr[i].lpData=m_pBuffer[i];

		waveOutPrepareHeader(m_hWaveOut,
							 &(m_WaveHdr[i]),
							 sizeof(WAVEHDR));
		waveOutWrite(m_hWaveOut,
					 &(m_WaveHdr[i]),
					 sizeof(WAVEHDR));
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -