//////////////////////////////////////////////////////////////////////
// SoundIn.h: interface for the CSoundIn class.
//////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <mmsystem.h>
#define MAX_SAMPLES 8192 //
#define MAX_VOIE 2
#define MAX_SIZE_SAMPLES 1 // WORD
#define MAX_SIZE_INPUT_BUFFER MAX_SAMPLES*MAX_VOIE*MAX_SIZE_SAMPLES
#define DEFAULT_CAL_OFFSET 0 // >>>>> depends of you sound card
#define DEFAULT_CAL_GAIN 1.0
// buffers into which sound data is recorded
#define NUM_LEVEL_BUFFERS 2
class CSoundIn
{
public:
BOOL (*pParentProcessData)(LPVOID pUser, SHORT *pData, DWORD dwLen);
LPVOID pParentUser;
protected:
struct _HWWAVEDATA_STRUCT
{
WAVEHDR m_WaveHeader;
SHORT InputBuffer[MAX_SIZE_INPUT_BUFFER];
}m_HWWaveStruct[NUM_LEVEL_BUFFERS];
struct _WAVESAMPLED_STRUCT
{
ULONGLONG mTimesCount;
BOOL bSampleValid;
BOOL bIsReaded;
BOOL bIsCalculating;
DWORD m_SizeRecord;
SHORT InputBuffer[MAX_SIZE_INPUT_BUFFER];
}m_SampledData[2];
HWAVEIN m_WaveIn;
WAVEINCAPS m_WaveInDevCaps;
WAVEFORMATEX m_WaveFormat;
UINT m_WaveOutSampleRate;
ULONGLONG m_SampledTimesIndex;
short m_CalOffset;
double m_CalGain;
BOOL bTerminateFlage;
public :
void CloseMic();
MMRESULT OpenMic(LPVOID pUser, LPVOID pProcessSamp);
//////////////////////////////////////////////////////
// functions members
void WaveInitFormat(WORD nCh, // number of channels (mono, stereo)
DWORD nSampleRate, // sample rate
WORD BitsPerSample);
CSoundIn();
virtual ~CSoundIn();
public :
static void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
};
/////////////////////////////////////////////////////////////////////////////////////////
// SoundIn.cpp: implementation of the CSoundIn class.
//////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SoundIn.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#pragma comment(lib, "winmm.lib ")
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSoundIn::CSoundIn()
{
m_CalOffset = DEFAULT_CAL_OFFSET;
m_CalGain = DEFAULT_CAL_GAIN;
m_WaveIn = NULL;
m_SampledTimesIndex = 0;
m_WaveOutSampleRate = 44100;
// init format
WaveInitFormat(1/* mono*/, m_WaveOutSampleRate /* hz */,16 /* bits */);
memset(&m_HWWaveStruct, 0, sizeof(m_HWWaveStruct));
memset(&m_SampledData, 0, sizeof(m_SampledData));
bTerminateFlage = FALSE;
pParentUser = NULL;
pParentProcessData = NULL;
}
CSoundIn::~CSoundIn()
{
CloseMic();
}
///////////////////////////////////////////////////////////////////
MMRESULT CSoundIn::OpenMic(LPVOID pUser, LPVOID pProcessSamp)
{
pParentUser = pUser;
pParentProcessData = (BOOL (*)(LPVOID, SHORT *, DWORD))pProcessSamp;
memset(&m_SampledData, 0, sizeof(m_SampledData));
m_SampledTimesIndex = 0;
MMRESULT result;
result=waveInGetNumDevs();
if (result == 0)
{
AfxMessageBox( _T("No Sound Device") );
return result;
}
// test for Mic available
result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS));
if ( result!= MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot determine sound card capabilities !"));
}
// Open Input
//result = waveInOpen( &m_WaveIn,0, &m_WaveFormat,(DWORD)m_WaveInEvent , NULL, CALLBACK_EVENT);
result = waveInOpen( &m_WaveIn, 0, &m_WaveFormat, (DWORD)waveInProc, (DWORD)this, CALLBACK_FUNCTION);
if ( result!= MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot Open Sound Input Device!"));
return result;
}
for(int i=0; i<NUM_LEVEL_BUFFERS; i++)
{
_HWWAVEDATA_STRUCT *pWaveStruct = &m_HWWaveStruct[i];
pWaveStruct->m_WaveHeader.lpData = (CHAR *)&pWaveStruct->InputBuffer[0];
pWaveStruct->m_WaveHeader.dwBufferLength = MAX_SAMPLES *2;
pWaveStruct->m_WaveHeader.dwFlags = 0;
result = waveInPrepareHeader( m_WaveIn, &pWaveStruct->m_WaveHeader, sizeof(WAVEHDR) );
if ( (result!= MMSYSERR_NOERROR) || ( pWaveStruct->m_WaveHeader.dwFlags != WHDR_PREPARED) )
AfxMessageBox(_T("Cannot Prepare Header !"));
result = waveInAddBuffer( m_WaveIn, &pWaveStruct->m_WaveHeader, sizeof(WAVEHDR) );
if (result!= MMSYSERR_NOERROR)
AfxMessageBox(_T("Cannot Add Buffer !"));
}
bTerminateFlage = false;
result = waveInStart( m_WaveIn );
if (result!= MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot Start Wave In !"));
}
return result;
}
void CSoundIn:: WaveInitFormat(WORD nCh, // number of channels (mono, stereo)
DWORD nSampleRate, // sample rate
WORD BitsPerSample)
{
m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
m_WaveFormat.nChannels = nCh;
m_WaveFormat.nSamplesPerSec = nSampleRate;
m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
m_WaveFormat.wBitsPerSample = BitsPerSample;
m_WaveFormat.cbSize = 0;
}
void CSoundIn::CloseMic()
{
bTerminateFlage = TRUE;
if (m_WaveIn)
{
waveInStop(m_WaveIn);
waveInClose(m_WaveIn);
m_WaveIn = NULL;
}
}
void CSoundIn::waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
CSoundIn *pSoundIn = (CSoundIn*)dwInstance;
if(pSoundIn->bTerminateFlage)
return;
switch(uMsg)
{
case(WIM_OPEN):
{
break;
}
case(WIM_DATA):
{
MMRESULT result;
WAVEHDR *pWaveHeader = (WAVEHDR *)dwParam1;
/*
result = waveInUnprepareHeader( hwi, pWaveHeader, sizeof(WAVEHDR) );
if (result!= MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot UnPrepareHeader !"));
};
*/
SHORT *pSampleValidBuffer = 0;
DWORD dwSampledLength = 0;
//处理数据
{
_WAVESAMPLED_STRUCT *pWaveSampled = 0;
if(pSoundIn->m_SampledData[0].mTimesCount <= pSoundIn->m_SampledData[1].mTimesCount)
pWaveSampled = &pSoundIn->m_SampledData[0];
else
pWaveSampled = &pSoundIn->m_SampledData[1];
pWaveSampled->m_SizeRecord = pWaveHeader->dwBytesRecorded/2;
SHORT *pSrc = (SHORT*)pWaveHeader->lpData;
SHORT *pDst = pWaveSampled->InputBuffer;
pWaveSampled->bIsCalculating = TRUE; //计算中
if(pSoundIn->m_CalOffset != 0 || pSoundIn->m_CalGain != 1)
{
for (DWORD i = 0 ; i<pWaveSampled->m_SizeRecord ; i++) // scaling the input samples du to the sound card
{
pDst[i] = (SHORT)((double)(pSrc[i] + pSoundIn->m_CalOffset) * pSoundIn->m_CalGain);
}
}
else
{
for (DWORD i = 0 ; i<pWaveSampled->m_SizeRecord ; i++) // scaling the input samples du to the sound card
{
pDst[i] = pSrc[i];
}
}
pWaveSampled->bIsCalculating = false;
pWaveSampled->bSampleValid = TRUE;
pWaveSampled->mTimesCount = ++pSoundIn->m_SampledTimesIndex;//采样次数增加
pSampleValidBuffer = pDst;
dwSampledLength = pWaveSampled->m_SizeRecord;
}
// put the buffer back on the queue
result = waveInAddBuffer( hwi, pWaveHeader, sizeof(WAVEHDR) );
if (result!= MMSYSERR_NOERROR)
{
AfxMessageBox(_T("Cannot Add Buffer !"));//WAVERR_UNPREPARED
}
if(pSoundIn->pParentUser && pSoundIn->pParentProcessData)
{
pSoundIn->pParentProcessData(pSoundIn->pParentUser, pSampleValidBuffer, dwSampledLength);
}
}
case(WIM_CLOSE):
break;
default:
break;
}
}