📄 hsound.cpp
字号:
/*****************************************************************
* HSound.cpp: implementation of the CHSound class.
*
* WARNINGS:
* - Just 1 and only 1 instance of this class must be
* created.
*
*
* Auther: Hamed.M.
* eMail : HamedMosavi @ hotmail.com
* HamedMosavi @ gmail.com
*****************************************************************/
#include "stdafx.h"
#include "HSound.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define SET 0
#define KILL 1
DWORD CHSound::m_dwStatus = STT_ASLEEP;
BOOL CHSound::m_bContinue = TRUE;
BOOL CHSound::m_bThreadContinue = TRUE;
HANDLE CHSound::m_hStatEvent = NULL;
LPWAVEHDR CHSound::m_lpWHdr = NULL;
/*****************************************************************
* Constructor
*****************************************************************/
//HANDLE CHSound::s_hEvent = NULL;
CHSound::CHSound()
{
InitializeCriticalSection(&m_statusCrtcSec);
InitializeCriticalSection(&m_externalResetCrtcSec);
m_hStatEvent = CreateEvent(NULL, TRUE/*ManualReset*/, FALSE, NULL);
m_bThreadContinue = TRUE; /* Don't exit the thread */
/* Run a thread to cleanup wave buffer */
m_pCallBackThread = AfxBeginThread (
CallBackThread,
(LPVOID) this,
THREAD_PRIORITY_NORMAL);
m_dwMinBufSize = 10240;//61440;//10240;//5120; // = 5 KBytes
m_bExitAfter = FALSE;
m_bForceClose = FALSE;
m_sndIndex = 0;
m_wndTimer = NULL;
m_dwDevId = 0;
m_playList.Reset();
}
/*****************************************************************
* Destructor
*****************************************************************/
CHSound::~CHSound()
{
m_bThreadContinue = FALSE;
DeleteCriticalSection(&m_statusCrtcSec);
DeleteCriticalSection(&m_externalResetCrtcSec);
}
/*****************************************************************
* Plays a given file, to the given device
*****************************************************************/
BOOL CHSound::Play(DWORD dwDevId, LPCTSTR szWaveFile)
{
if (GetStatus() != STT_ASLEEP)
return FALSE;
SetStatus(STT_PREPARE);
m_dwDevId = dwDevId;
HPSTR lpData = NULL; /* Pointer to Wave data */
LPWAVEFORMATEX lpWaveFormatEx = NULL;
MMRESULT mmRes;
LPWAVEHDR lpWaveHdr = NULL;
m_dwBufCnt = 0;
m_dwCurrtBufIndex=0;
m_dwDataSize = 0;
SetStatus(STT_FILEOPN);
lpData = Open( szWaveFile, /* Open & read WaveFile */
lpWaveFormatEx,
m_dwDataSize);
SetStatus(STT_PREPARE);
if ( NULL == lpData ) { /* File opening error */
goto CLEAN_EXIT;
}
if (!m_bContinue) {
goto CLEAN_EXIT;
}
/* Allocate a buffer for header */
lpWaveHdr = (LPWAVEHDR) calloc (1,(DWORD)sizeof(WAVEHDR));
if (! lpWaveHdr) { /* Can't allocate memory */
goto CLEAN_EXIT;
}
if (!m_bContinue) {
goto CLEAN_EXIT;
}
if (m_dwDataSize>m_dwMinBufSize) {
m_dwBufCnt = m_dwDataSize / m_dwMinBufSize;
// a 13 KB file for example
if ( (m_dwBufCnt*m_dwMinBufSize) < m_dwDataSize)
m_dwBufCnt++;
lpWaveHdr->dwBufferLength = m_dwMinBufSize;
m_dwBLength = ( (m_dwDataSize-m_dwMinBufSize)>m_dwMinBufSize)?m_dwMinBufSize:(m_dwDataSize-m_dwMinBufSize);
m_lpBuf2 = lpData;
m_lpBuf2 += m_dwMinBufSize;
} else {
lpWaveHdr->dwBufferLength = m_dwDataSize;
}
m_lpWHdr = lpWaveHdr;
lpWaveHdr->lpData = lpData;
m_lpData = lpData;
SetStatus(STT_OPENING);
/* Open the device, and set callback function */
mmRes = waveOutOpen (
&m_hWaveOut,
dwDevId,
lpWaveFormatEx,
(DWORD)m_pCallBackThread->m_nThreadID,
0L,
CALLBACK_THREAD | WAVE_MAPPED);
/* Can't Open specified device */
if ( MMSYSERR_NOERROR != mmRes ) {
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
return FALSE;
}
free(lpWaveFormatEx);
lpWaveFormatEx = NULL;
if (!m_bContinue) {
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
goto CLEAN_EXIT;
}
/* Prepare header */
mmRes = waveOutPrepareHeader(
m_hWaveOut,
lpWaveHdr,
sizeof (WAVEHDR) );
/* Can't Prepare header */
if ( MMSYSERR_NOERROR != mmRes ) {
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
goto CLEAN_EXIT;
}
if (!m_bContinue) {
SetStatus(STT_RSTTING);
waveOutUnprepareHeader(m_hWaveOut,lpWaveHdr,sizeof(WAVEHDR));
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
goto CLEAN_EXIT;
}
/* Modem's are weak! Loud as much as possible */
waveOutSetVolume(m_hWaveOut,0xFF00FF00);
SetStatus(STT_PLAYING);
/* Write a block of data to the device */
mmRes = waveOutWrite(
m_hWaveOut,
lpWaveHdr,
sizeof(WAVEHDR) );
/* Can't Do the last job :(( */
if ( MMSYSERR_NOERROR != mmRes ) {
SetStatus(STT_RSTTING);
waveOutUnprepareHeader(m_hWaveOut,lpWaveHdr,sizeof(WAVEHDR));
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
goto CLEAN_EXIT;
}
if (m_dwDataSize>m_dwMinBufSize) {
m_lpWHdr->lpData = m_lpBuf2;
m_lpWHdr->dwBufferLength = m_dwBLength;
m_dwCurrtBufIndex++;
}
/* Playback started, events will be received by callback
function, then it will notify thread to cleanup. */
return TRUE;
CLEAN_EXIT:;
SetStatus(STT_RSTTING);
if (lpData)
free(lpData);
if (lpWaveFormatEx)
free(lpWaveFormatEx);
if (lpWaveHdr)
free(lpWaveHdr);
SetStatus(STT_ASLEEP);
return FALSE;
}
/*****************************************************************
* Opens a wave file, buffers wave data
* Returns a pointer to buffer
*****************************************************************/
HPSTR CHSound::Open(LPCTSTR szWaveFile, LPWAVEFORMATEX& lpWaveFmt, DWORD& dwDataSize)
{
HMMIO hmmio;
MMCKINFO mmckinfoParent;
MMCKINFO mmckinfoSubchunk;
DWORD dwFmtSize = 0;
hmmio = mmioOpen((unsigned short*) /* Open Wave file */
szWaveFile, NULL, MMIO_READ | MMIO_ALLOCBUF);
if(!hmmio) /* Can't open */
{
return NULL;
}
if (!m_bContinue)
{
mmioClose(hmmio, 0);
return NULL;
}
/* Make sure file format is Wave */
mmckinfoParent.fccType = MAKEFOURCC('W', 'A', 'V', 'E');
if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent,
NULL, MMIO_FINDRIFF))
{ /* File format is NOT 'Wave' */
mmioClose(hmmio, 0);
return NULL;
}
if (!m_bContinue)
{
mmioClose(hmmio, 0);
return NULL;
}
/* Make sure there is a 'fmt ' chunk */
mmckinfoSubchunk.ckid = MAKEFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hmmio, (LPMMCKINFO)&mmckinfoSubchunk,
(LPMMCKINFO)&mmckinfoParent, MMIO_FINDCHUNK))
{ /* No 'fmt ' chunk */
mmioClose(hmmio, 0);
return NULL;
}
if (!m_bContinue)
{
mmioClose(hmmio, 0);
return NULL;
}
/* Find size of the 'fmt ' chunk */
dwFmtSize = mmckinfoSubchunk.cksize;
/* Allocate memory for format chunk */
lpWaveFmt = (LPWAVEFORMATEX) calloc (1, dwFmtSize);
// HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, dwFmtSize);
if (!lpWaveFmt) /* Can't alocate memory */
{
mmioClose(hmmio, 0);
return NULL;
}
if (!m_bContinue)
{
free(lpWaveFmt);
mmioClose(hmmio, 0);
return NULL;
}
/* Read 'fmt ' chunk */
if (mmioRead(hmmio, (HPSTR) lpWaveFmt, dwFmtSize) !=
(LONG) dwFmtSize)
{ /* Corrupt 'fmt ' chunk */
free(lpWaveFmt);
mmioClose(hmmio, 0);
return NULL;
}
if (!m_bContinue)
{
free(lpWaveFmt);
mmioClose(hmmio, 0);
return NULL;
}
/* Ascend out of the 'fmt ' subchunk */
mmioAscend(hmmio, &mmckinfoSubchunk, 0);
/* Find the data subchunk */
mmckinfoSubchunk.ckid = MAKEFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
MMIO_FINDCHUNK))
{ /* No data subchunk! */
free(lpWaveFmt);
mmioClose(hmmio, 0);
return NULL;
}
/* Get the size of the data subchunk */
dwDataSize = mmckinfoSubchunk.cksize;
if ( 0L == dwDataSize ) /* No data in the data subchunk */
{
free(lpWaveFmt);
mmioClose(hmmio, 0);
return NULL;
}
if (!m_bContinue)
{
free(lpWaveFmt);
mmioClose(hmmio, 0);
dwDataSize = 0;
return NULL;
}
/* Allocate memory for data, no need to lock */
HPSTR lpData = (HPSTR) calloc (1, dwDataSize );
// HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, dwDataSize);
/* Read the waveform data subchunk */
if(mmioRead(hmmio, (HPSTR) lpData, dwDataSize)
!= (LONG) dwDataSize)
{
free(lpWaveFmt);
free(lpData);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -