#include "CHI_AI_DSound.h"
#include <process.h>
#define RECORD_FRAME 1
UINT CHI_AI_DSound::ThreadRecord(LPVOID lpPara)
{
CHI_AI_DSound* pDSound = (CHI_AI_DSound*)lpPara;
DWORD dwResult =0;
pDSound->m_bRecording = TRUE;
while(pDSound->m_bRecording)
{
//dwResult = WaitForMultipleObjects(1, &pDSound->m_hNotificationEvent,FALSE,100 );
dwResult = WaitForSingleObject( pDSound->m_hNotificationEvent,100 );
switch( dwResult )
{
case WAIT_OBJECT_0:
pDSound->RecordCapturedData();
break;
case WAIT_TIMEOUT:
break;
}
}
return 0;
}
HI_VOID PASCAL CHI_AI_DSound::PlaySoundCaptrueThread(UINT wTimerID, UINT msg,DWORD_PTR dwUser,DWORD_PTR dwl,DWORD_PTR dw2)
{
__try
{
if (dwUser != 0)
{
HRESULT hResult = ((CHI_AI_DSound*)dwUser)->RecordCapturedData();
if ( hResult != S_OK)
{
//((CHI_AI_DSound*)dwUser)->HI_AI_Stop();
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
HRESULT CHI_AI_DSound::RecordCapturedData()
{
HRESULT hr;
VOID *pbCaptureData = NULL;
DWORD dwCaptureLength;
VOID *pbCaptureData2 = NULL;
DWORD dwCaptureLength2;
DWORD dwReadPos;
DWORD dwCapturePos;
if(m_pDSCaptrueB8 == NULL )
{
return S_FALSE;
}
if(FAILED( hr = m_pDSCaptrueB8->GetCurrentPosition(&dwCapturePos,&dwReadPos)))
{
return hr;
}
if( FAILED( hr = m_pDSCaptrueB8->Lock( 0 ,320 * RECORD_FRAME,&pbCaptureData, &dwCaptureLength, &pbCaptureData2, &dwCaptureLength2, 0L ) ) )
{
return hr;
}
if (pbCaptureData)
{
for (HI_S32 s32Num = 0; s32Num < RECORD_FRAME; s32Num++)
{
m_AISample.m_AVFrame.u32Size = dwCaptureLength / RECORD_FRAME;
m_AISample.m_AVFrame.pu8Data = (HI_U8*)pbCaptureData + RECORD_FRAME * s32Num;
m_AISample.m_AVFrame.u64Pts = m_u64SampleTimeStamp;
m_u64SampleTimeStamp += 20;
m_pCallBack->HI_AI_OnSample(&m_AISample);
#ifdef _DEBUG
mmioWrite(m_mmiorRecordTemp, (const char *)pbCaptureData, dwCaptureLength);
m_waveFormat.dwDataLen += dwCaptureLength;
#endif
}
}
if (pbCaptureData2)
{
for (HI_S32 s32Num = 0; s32Num < RECORD_FRAME; s32Num++)
{
m_AISample.m_AVFrame.u32Size = dwCaptureLength2 / RECORD_FRAME;
m_AISample.m_AVFrame.pu8Data = (HI_U8*)pbCaptureData2 + RECORD_FRAME * s32Num;
m_AISample.m_AVFrame.u64Pts = m_u64SampleTimeStamp;
m_u64SampleTimeStamp += 20;
m_pCallBack->HI_AI_OnSample(&m_AISample);
#ifdef _DEBUG
mmioWrite(m_mmiorRecordTemp, (const char *)pbCaptureData2, dwCaptureLength2);
m_waveFormat.dwDataLen += dwCaptureLength;
#endif
}
}
return m_pDSCaptrueB8->Unlock( pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2 );
}
CHI_AI_DSound::CHI_AI_DSound()
{
m_bRecording = FALSE;
m_AISample.CHI_COMMON_CleanUp();
m_Format.cbSize = 0; //sizeof(WAVEFORMATEX);
m_Format.nChannels = 1;
m_Format.nSamplesPerSec = 8000;
m_Format.wBitsPerSample = 16;
m_Format.wFormatTag = WAVE_FORMAT_PCM;
m_Format.nBlockAlign = 2;
m_Format.nAvgBytesPerSec = 16000;
m_hdlThreadCapture = NULL;
m_u64SampleTimeStamp = 0;
TIMECAPS tcaps;
const int TIMER_ACCURACY = 1;
if(timeGetDevCaps(&tcaps, sizeof(TIMECAPS)) == TIMERR_NOERROR)
{
m_wAccuracy = min(max(tcaps.wPeriodMin, TIMER_ACCURACY), tcaps.wPeriodMax);
timeBeginPeriod(m_wAccuracy);
}
m_unTimeEscape = 20 * RECORD_FRAME;
m_TilerID_Record = 0;
m_pDSNotify = NULL;
m_pDSCaptrueB8 = NULL;
m_pDCaptrue8 = NULL;
#ifdef _DEBUG
m_mmiorRecordTemp = mmioOpen("D:\\WaveData.wav", NULL, MMIO_READWRITE | MMIO_CREATE);
#endif
}
CHI_AI_DSound::~CHI_AI_DSound()
{
}
HRESULT CHI_AI_DSound::HI_AI_Stop()
{
if (!m_pDSCaptrueB8)
{
return -1;
}
m_bRecording = FALSE;
if (m_hdlThreadCapture != NULL)
{
WaitForSingleObject(m_hdlThreadCapture, INFINITE);
CloseHandle(m_hdlThreadCapture);
m_hdlThreadCapture = NULL;
}
if (0 != m_TilerID_Record)
{
if(TIMERR_NOERROR == timeKillEvent(m_TilerID_Record))
{
m_TilerID_Record = 0;
}
}
(HI_VOID)timeEndPeriod(m_wAccuracy);
if (m_pDSCaptrueB8)
{
m_pDSCaptrueB8->Stop();
}
if (m_pDSCaptrueB8)
{
m_pDSCaptrueB8->Release();
m_pDSCaptrueB8 = NULL;
}
if (m_pDSNotify)
{
m_pDSNotify->Release();
m_pDSNotify = NULL;
}
if (m_pDCaptrue8)
{
m_pDCaptrue8->Release();
m_pDCaptrue8 = NULL;
}
m_u64SampleTimeStamp = 0;
m_AISample.CHI_COMMON_CleanUp();
#ifdef _DEBUG
m_mmiorRecord = mmioOpen("D:\\test.wav", NULL, MMIO_CREATE | MMIO_WRITE);
m_waveFormat.dwWaveLen += m_waveFormat.dwDataLen;
mmioWrite(m_mmiorRecord, (const char*)&m_waveFormat, sizeof(m_waveFormat));
char szBuf[1024];
mmioSeek(m_mmiorRecordTemp, 0, SEEK_SET);
LONG lDataLen;
for (int n = 0; n < m_waveFormat.dwDataLen;)
{
lDataLen = mmioRead(m_mmiorRecordTemp, szBuf, 1024);
mmioWrite(m_mmiorRecord, szBuf, lDataLen);
n += lDataLen;
}
mmioClose(m_mmiorRecord, MMIO_FHOPEN);
mmioClose(m_mmiorRecordTemp, MMIO_FHOPEN);
WAVE_FORMAT wave_format;
memcpy(&m_waveFormat, &wave_format, sizeof(wave_format));
#endif
return HI_SUCCESS;
}
HRESULT CHI_AI_DSound::HI_AI_Start(IHI_AI_CallBack* pCallBack)
{
m_pCallBack = pCallBack;
HRESULT hResult = InitSound();
if (FAILED (hResult))
{
return S_FALSE;
}
hResult = InitNotifications();
if (FAILED (hResult))
{
return S_FALSE;
}
StartRecord();
return S_OK;
}
HRESULT CHI_AI_DSound::InitSound()
{
m_dwNotifySize = 320 * RECORD_FRAME;
return CreateCaptureBuffer();
}
HRESULT CHI_AI_DSound::StartRecord()
{
if (!m_pDSCaptrueB8)
{
return S_FALSE;
}
HRESULT hResult = m_pDSCaptrueB8->Start(DSCBSTART_LOOPING);
if (!m_hdlThreadCapture)
{
m_hdlThreadCapture = (HANDLE)_beginthreadex(NULL, 0, ThreadRecord, this, 0, NULL);
}
// if (0 == m_TilerID_Record)
// {
// m_TilerID_Record = timeSetEvent(m_unTimeEscape, m_wAccuracy, (LPTIMECALLBACK)PlaySoundCaptrueThread,
// (DWORD_PTR)this, TIME_PERIODIC);
// }
return hResult;
}
HRESULT CHI_AI_DSound::InitNotifications()
{
HRESULT hr;
m_hNotificationEvent = CreateEvent(NULL,FALSE,FALSE,NULL); //创建事件
if(!m_pDSCaptrueB8 )
{
return E_FAIL;
}
if(FAILED(hr = m_pDSCaptrueB8 ->QueryInterface(IID_IDirectSoundNotify,(VOID**)&m_pDSNotify)))
{
return hr;
}
m_aPosNotify.dwOffset = m_dwNotifySize - 1;
m_aPosNotify.hEventNotify = m_hNotificationEvent;
if(FAILED( hr =m_pDSNotify->SetNotificationPositions( 1, &m_aPosNotify)))
return hr;
return S_OK;
}
HRESULT CHI_AI_DSound::CreateCaptureBuffer()
{
HRESULT hResult = DirectSoundCaptureCreate8(NULL, &m_pDCaptrue8, NULL);
if (FAILED( hResult))
{
return hResult;
}
DSCBUFFERDESC dscbd;
LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
if ((NULL == m_pDCaptrue8) )
return E_INVALIDARG;
dscbd.dwSize = sizeof(DSCBUFFERDESC);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes = 320 * RECORD_FRAME;
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = &m_Format; //设置录音用的wave格式
dscbd.dwFXCount = 0;
dscbd.lpDSCFXDesc = NULL;
if (SUCCEEDED(hResult = m_pDCaptrue8->CreateCaptureBuffer(&dscbd, &pDSCB, NULL)))
{
hResult = pDSCB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)&m_pDSCaptrueB8);
pDSCB->Release();
pDSCB = NULL;
}
return hResult;
}
HRESULT CHI_AI_DSound::HI_AI_SetInFormat(const PLAYER_ATTR_AUDIO_S& struAStreamParam)
{
m_Format.cbSize = 0; //sizeof(WAVEFORMATEX);
m_Format.nChannels = (WORD)struAStreamParam.lChannels;
m_Format.nSamplesPerSec = (DWORD)struAStreamParam.lSamplesPerSec;
m_Format.wBitsPerSample = (WORD)struAStreamParam.lBitsPerSample;
m_Format.wFormatTag = WAVE_FORMAT_PCM;
m_Format.nBlockAlign = (WORD)struAStreamParam.lBlockAlign;
m_Format.nAvgBytesPerSec = struAStreamParam.lBitRate/8 ;
return HI_SUCCESS;
}
HRESULT CHI_AI_DSound::HI_AI_GetInFormat(PLAYER_ATTR_AUDIO_S *pAStreamParam)
{
if (NULL == pAStreamParam)
{
return HI_ERR_NULL_POINTER;
}
pAStreamParam->lChannels = m_Format.nChannels;
pAStreamParam->lSamplesPerSec = m_Format.nSamplesPerSec;
pAStreamParam->lBitsPerSample = m_Format.wBitsPerSample;
pAStreamParam->lBlockAlign = m_Format.nBlockAlign;
return HI_SUCCESS;
}