#include "IOVoices.h"
#include "stdio.h"
#include <process.h>
#define BUFFER_SIZE (8)//缓冲区大小
#define ACQ_TIMES_PER_ONE_SECOND (25)//每秒采集的次数
extern void LOG(const char* fmt, ...);
static void CALLBACK WaveInCallback(HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
XWaveIn* pXWaveIn = (XWaveIn*)dwInstance;
switch (uMsg)
{
case WIM_OPEN:
break;
case WIM_CLOSE:
break;
case WIM_DATA:
pXWaveIn->OnCollectSoundData(dwParam1, dwParam2);
break;
default:
break;
}
}
XWaveIn::XWaveIn()
: m_hWaveIn(NULL)
, m_bWorking(false)
, m_pAudioCallback(NULL)
, m_pUser(NULL)
, m_Buffer(NULL)
, m_BufferLen(NULL)
{
m_lpHdrIn = new WAVEHDR[BUFFER_SIZE];
memset(m_lpHdrIn, 0, sizeof(WAVEHDR)*BUFFER_SIZE);
for (int i = 0; i < BUFFER_SIZE; i++)
{
m_lpHdrIn[i].dwFlags = WHDR_DONE;
}
memset(&m_WaveFormatEx, 0, sizeof(m_WaveFormatEx));
}
XWaveIn::~XWaveIn()
{
CloseInDevice();
if (m_lpHdrIn)
{
delete[] m_lpHdrIn;
m_lpHdrIn = NULL;
}
if (m_Buffer)
{
delete[] m_Buffer;
m_Buffer = NULL;
}
}
int XWaveIn::OpenInDevice(const WAVEFORMATEX &WaveFormatEx, AudioCallback pCallback, long pUser)
{
m_pAudioCallback = pCallback;
MMRESULT mmResult = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &WaveFormatEx, (DWORD)WaveInCallback, (DWORD_PTR)this, CALLBACK_FUNCTION);
if (mmResult)
{
return mmResult;
}
//准备缓冲区
for (int i = 0; i < BUFFER_SIZE; i++)
{
m_lpHdrIn[i].dwBufferLength = WaveFormatEx.nAvgBytesPerSec / ACQ_TIMES_PER_ONE_SECOND;
m_lpHdrIn[i].lpData = new char[m_lpHdrIn[i].dwBufferLength];
memset(m_lpHdrIn[i].lpData, 0, m_lpHdrIn[i].dwBufferLength);
//为声音输入设备准备一个声音缓冲
mmResult = waveInPrepareHeader(m_hWaveIn, &m_lpHdrIn[i], sizeof(WAVEHDR));
if (mmResult == MMSYSERR_NOERROR)
{
// 发送声音缓冲区给数据输入设备
mmResult = waveInAddBuffer(m_hWaveIn, &m_lpHdrIn[i], sizeof(WAVEHDR));
}
}
mmResult = waveInStart(m_hWaveIn);
m_pUser = pUser;
return mmResult;
}
int XWaveIn::OnCollectSoundData(int wParam, int lParam)
{
if (m_pAudioCallback == NULL)
{
return -1;
}
PWAVEHDR hHdr= (PWAVEHDR)wParam;
if (m_BufferLen != hHdr->dwBytesRecorded)
{
if (m_Buffer) delete[] m_Buffer;
m_Buffer = new char[hHdr->dwBytesRecorded];
m_BufferLen = hHdr->dwBytesRecorded;
}
memset(m_Buffer, 0, m_BufferLen);
memcpy(m_Buffer, hHdr->lpData, hHdr->dwBytesRecorded);
m_pAudioCallback(m_Buffer, hHdr->dwBytesRecorded, m_pUser);
// MMRESULT mmReturn = waveInUnprepareHeader(m_hWaveIn, (PWAVEHDR)wParam, sizeof(WAVEHDR));
// if (mmReturn != MMSYSERR_NOERROR)
// {
// return mmReturn;
// }
MMRESULT mmReturn = waveInPrepareHeader(m_hWaveIn, hHdr, sizeof(WAVEHDR));
if (mmReturn)
{
return mmReturn;
}
mmReturn = waveInAddBuffer(m_hWaveIn, hHdr, sizeof (WAVEHDR));
if (mmReturn)
{
return mmReturn;
}
return mmReturn;
}
int XWaveIn::CloseInDevice(void)
{
if (m_hWaveIn == NULL)
{
return -1;
}
m_pUser = NULL;
m_pAudioCallback = NULL;
MMRESULT mmReturn = waveInReset(m_hWaveIn);
for (int i = 0; i < BUFFER_SIZE; i++)
{
if (m_lpHdrIn[i].dwFlags & WHDR_PREPARED)
{
waveInUnprepareHeader(m_hWaveIn, &m_lpHdrIn[i], sizeof(WAVEHDR));
delete[] m_lpHdrIn[i].lpData;
m_lpHdrIn[i].lpData = NULL;
m_lpHdrIn[i].dwBufferLength = 0;
}
}
mmReturn = waveInClose(m_hWaveIn);
m_hWaveIn = NULL;
return mmReturn;
}
//
/*
CWaveBuffer
*/
XWaveBuffer::XWaveBuffer()
{
}
BOOL XWaveBuffer::Init(HWAVEOUT hWave, int Size)
{
m_hWave = hWave;
m_nBytes = 0;
/* Allocate a buffer and initialize the header */
m_Hdr.lpData = (LPSTR)LocalAlloc(LMEM_FIXED, Size);
if (m_Hdr.lpData == NULL) {
return FALSE;
}
m_Hdr.dwBufferLength = Size;
m_Hdr.dwBytesRecorded = 0;
m_Hdr.dwUser = 0;
m_Hdr.dwFlags = 0;
m_Hdr.dwLoops = 0;
m_Hdr.lpNext = 0;
m_Hdr.reserved = 0;
/* Prepare it */
waveOutPrepareHeader(hWave, &m_Hdr, sizeof(WAVEHDR));
return TRUE;
}
XWaveBuffer::~XWaveBuffer() {
if (m_Hdr.lpData) {
waveOutUnprepareHeader(m_hWave, &m_Hdr, sizeof(WAVEHDR));
LocalFree(m_Hdr.lpData);
}
}
void XWaveBuffer::Flush()
{
//ASSERT(m_nBytes != 0);
m_nBytes = 0;
waveOutWrite(m_hWave, &m_Hdr, sizeof(WAVEHDR));
}
BOOL XWaveBuffer::Write(PBYTE pData, int nBytes, int& BytesWritten)
{
//ASSERT((DWORD)m_nBytes != m_Hdr.dwBufferLength);
BytesWritten = min((int)m_Hdr.dwBufferLength - m_nBytes, nBytes);
CopyMemory((PVOID)(m_Hdr.lpData + m_nBytes), (PVOID)pData, BytesWritten);
m_nBytes += BytesWritten;
if (m_nBytes == (int)m_Hdr.dwBufferLength) {
/* Write it! */
m_nBytes = 0;
waveOutWrite(m_hWave, &m_Hdr, sizeof(WAVEHDR));
return TRUE;
}
return FALSE;
}
void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
if (uMsg == WOM_DONE) {
ReleaseSemaphore((HANDLE)dwUser, 1, NULL);
}
}
/*
CWaveOut
*/
XWaveOut::XWaveOut(LPCWAVEFORMATEX Format, int nBuffers, int BufferSize) :
m_nBuffers(nBuffers),
m_CurrentBuffer(0),
m_NoBuffer(TRUE),
m_hSem(CreateSemaphore(NULL, nBuffers, nBuffers, NULL)),
m_Hdrs(new XWaveBuffer[nBuffers]),
m_hWave(NULL)
{
/* Create wave device */
waveOutOpen(&m_hWave,
WAVE_MAPPER, Format,
(DWORD)WaveCallback,
(DWORD)m_hSem,
CALLBACK_FUNCTION);
/* Initialize the wave buffers */
for (int i = 0; i < nBuffers; i++) {
m_Hdrs[i].Init(m_hWave, BufferSize);
}
}
XWaveOut::~XWaveOut()
{
/* First get our buffers back */
waveOutReset(m_hWave);
/* Free the buffers */
delete[] m_Hdrs;
/* Close the wave device */
waveOutClose(m_hWave);
/* Free our semaphore */
CloseHandle(m_hSem);
}
void XWaveOut::Flush()
{
if (!m_NoBuffer) {
m_Hdrs[m_CurrentBuffer].Flush();
m_NoBuffer = TRUE;
m_CurrentBuffer = (m_CurrentBuffer + 1) % m_nBuffers;
}
}
void XWaveOut::Reset()
{
waveOutReset(m_hWave);
}
void XWaveOut::Write(PBYTE pData, int nBytes)
{
while (nBytes != 0) {
/* Get a buffer if necessary */
if (m_NoBuffer) {
WaitForSingleObject(m_hSem, INFINITE);
m_NoBuffer = FALSE;
}
/* Write into a buffer */
int nWritten;
if (m_Hdrs[m_CurrentBuffer].Write(pData, nBytes, nWritten)) {
m_NoBuffer = TRUE;
m_CurrentBuffer = (m_CurrentBuffer + 1) % m_nBuffers;
nBytes -= nWritten;
pData += nWritten;
}
else {
//ASSERT(nWritten == nBytes);
break;
}
}
}
void XWaveOut::Wait()
{
/* Send any remaining buffers */
Flush();
/* Wait for our buffers back */
for (int i = 0; i < m_nBuffers; i++) {
WaitForSingleObject(m_hSem, INFINITE);
}
LONG lPrevCount;
ReleaseSemaphore(m_hSem, m_nBuffers, &lPrevCount);
}