📄 waveio.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 + -