标签:
class UIHELPER_EXPORT wWavePlayer
{
public:
bool wavePlayStart(UINT idDev, const chConstString& strFilePath);
void wavePlayStop();
int getCurrentSample();
public:
wWavePlayer();
~wWavePlayer();
private:
HWAVEOUT m_hWaveOut;
chByteArray m_dataWaveFile;
WAVEHDR m_hdrWaveData;
public:
UINT64 m_tickStart;
};
struct WAVEHEAD{
char riffTag[4];
char dataLen[4];
char waveTag[4];
char fmtTag[4];
char resvr[4];
char dataType[2];
char channelTag[2];
char SamplesPerSecTag[4];
char DataTransferRatePerSec[4];
char BitsPerSample[2];
char PCM[2];
char fact[4];
char filesize[4];
public:
bool operator == (const WAVEHEAD& head) const
{
return (memcmp(head.riffTag, riffTag, 4) == 0
&& memcmp(head.waveTag, waveTag, 4) == 0
&& memcmp(head.fmtTag, fmtTag, 4) == 0
&& memcmp(head.channelTag, channelTag, 2) == 0
&& memcmp(head.SamplesPerSecTag, SamplesPerSecTag, 4) == 0
&& memcmp(head.BitsPerSample, BitsPerSample, 2) == 0);
}
};
static bool is8k16bitWaveData(const chByteArray& data)
{
static WAVEHEAD wave8K16bit = {
{‘R‘, ‘I‘, ‘F‘, ‘F‘},
{},
{‘W‘, ‘A‘, ‘V‘, ‘E‘},
{‘f‘, ‘m‘, ‘t‘, ‘ ‘},
{},
{},
{0x1, 0x0},
{0x40, 0x1f, 0x0, 0x0},
{},
{0x2, 0x0}
};
WAVEHEAD* pFileFmt = (WAVEHEAD*)data.data();
return data.size() >= sizeof(WAVEHEAD) && wave8K16bit == *pFileFmt;
}
bool wWavePlayer::wavePlayStart(UINT idDev, const chConstString& strFilePath)
{
m_dataWaveFile = etlDumpBinFile(strFilePath);
if(m_dataWaveFile.empty())
{
INFO_TRACE("Unable to load file");
return false;
}
chASSERT(is8k16bitWaveData(m_dataWaveFile));
WAVEFORMATEX wfx; /* look this up in your documentation */
wfx.nSamplesPerSec = 8000; /* sample rate */
wfx.wBitsPerSample = 16; /* sample size */
wfx.nChannels = 1; /* channels*/
wfx.cbSize = 0; /* size of _extra_ info */
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
if(waveOutOpen(&m_hWaveOut,
idDev,
&wfx,
0,
0,
CALLBACK_NULL) != MMSYSERR_NOERROR)
{
INFO_TRACE("unable to open WAVE_MAPPER device");
return false;
}
INFO_TRACE("The Wave Mapper device was opened successfully!");
ZeroMemory(&m_hdrWaveData, sizeof(WAVEHDR));
m_hdrWaveData.lpData = (LPSTR)m_dataWaveFile.data() + sizeof(WAVEHEAD);
m_hdrWaveData.dwBufferLength = m_dataWaveFile.size() - sizeof(WAVEHEAD) ;
m_hdrWaveData.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
m_hdrWaveData.dwLoops = -1;
waveOutPrepareHeader(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
waveOutWrite(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
m_tickStart = etlGetTickCount();
return true;
}
void wWavePlayer::wavePlayStop()
{
if (m_hWaveOut != NULL)
{
waveOutReset(m_hWaveOut);
waveOutUnprepareHeader(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
waveOutClose(m_hWaveOut);
m_hWaveOut = NULL;
m_tickStart = 0;
}
}
int wWavePlayer::getCurrentSample()
{
//chASSERT(m_Playblock.size() != 0);
//1毫秒偏移16byte ===> 16*1*8000/1000/8 = 16byte
UINT64 nByteOffset = (etlGetTickCount() - m_tickStart) * 16;
int iDataOffset = nByteOffset % (m_dataWaveFile.size() - sizeof(WAVEHEAD));
LPBYTE pWaveData = m_dataWaveFile.data() + sizeof(WAVEHEAD);
return chMAKEWORD(pWaveData[iDataOffset], pWaveData[iDataOffset+1]);
}
wWavePlayer::wWavePlayer()
{
m_hWaveOut = NULL;
m_tickStart = 0;
}
wWavePlayer::~wWavePlayer()
{
wavePlayStop();
}
标签:
原文地址:http://www.cnblogs.com/hqu-ye/p/4315937.html