www.pudn.com > hmmPlatform.rar > LargeFileWaveOut.cpp
#include "StdAfx.h"
#include ".\largefilewaveout.h"
CLargeFileWaveOut::CLargeFileWaveOut(void)
{
// 设置默认属性
this->m_nBufferNums = LARGEWAVEOUT_BUFFER_NUMS;
this->m_pNextBuffer = NULL;
this->m_pAllocBuffer = NULL;
this->m_nBufferNums = 0;
this->m_nSamplesPerBlock = LARGEWAVEOUT_SAMPLES_PER_BLOCK;
this->m_dwBufferSize = 0;
}
CLargeFileWaveOut::~CLargeFileWaveOut(void)
{
this->Stop();
}
//////////////////////////////////////////////////////////////////////////
// 打开输出设备,设置回调方式,并分配播放缓冲和读入部分数据
BOOL CLargeFileWaveOut::Init(WAVEFORMATEX fmt, DWORD hWnd)
{
// 打开输出设备,设置回调方式
BOOL bRet = CFileWaveOut::Init(fmt, hWnd);
// 读取字节数
UINT nRead = 0;
// 分配缓存区结构
if (bRet)
{
this->m_pAllocBuffer = new WAVEHDR[this->m_nBufferNums];
this->m_pNextBuffer = this->m_pAllocBuffer;
// 分配缓冲块
if (this->m_pAllocBuffer != NULL)
{
for (unsigned int i = 0; i < this->m_nBufferNums; i++)
{
this->m_pAllocBuffer[i].lpData = new char[this->m_dwBufferSize];
this->m_pAllocBuffer[i].lpNext = NULL;
this->m_pAllocBuffer[i].dwBufferLength = 0;
if (this->m_pAllocBuffer[i].lpData != NULL &&
! this->m_wavFile.IsEOF())
{
// 获取实际读取得byte数
nRead = this->m_wavFile.ReadBytes(
this->m_pAllocBuffer[i].lpData, this->m_dwBufferSize);
// 填写缓冲块格式信息
this->m_pAllocBuffer[i].dwBufferLength = nRead;
this->m_pAllocBuffer[i].dwBytesRecorded = 0;
this->m_pAllocBuffer[i].dwFlags = 0;
this->m_pAllocBuffer[i].dwLoops = 0;
this->m_pAllocBuffer[i].dwUser = 0;
// 预制缓冲块
waveOutPrepareHeader(this->m_hWaveOut,
&this->m_pAllocBuffer[i], sizeof(WAVEHDR));
}
}
}
}
return bRet;
}
//////////////////////////////////////////////////////////////////////////
// 设置缓冲块数量
void CLargeFileWaveOut::SetBufferNums(UINT nCount)
{
this->m_nBufferNums = nCount;
}
//////////////////////////////////////////////////////////////////////////
// 处理WOM_DONE消息,继续播放下一个缓冲块
LRESULT CLargeFileWaveOut::OnDone(DWORD dwParam)
{
WAVEHDR* pTempHdr = (WAVEHDR*) dwParam; // 播放完的缓冲块
UINT nRead = 0;
// 已播放的缓冲块标记长度为0,用于标记已经播放
pTempHdr->dwBufferLength = 0;
// 确定待播放的缓冲块,类似使用循环队列
if (this->m_pNextBuffer - this->m_pAllocBuffer >= this->m_nBufferNums)
{
this->m_pNextBuffer = this->m_pAllocBuffer;
}
// 若要播放的缓冲块未播放过,则播放此缓冲块
if (this->m_pNextBuffer->dwBufferLength > 0)
{
waveOutWrite(this->m_hWaveOut, this->m_pNextBuffer, sizeof(WAVEHDR));
this->m_pNextBuffer ++;
// 若文件未读取完毕,从文件载入下一个缓冲块,装入已播放缓冲块中
if (! this->m_wavFile.IsEOF())
{
nRead = this->m_wavFile.ReadBytes(pTempHdr->lpData, this->m_dwBufferSize);
// 填写缓冲块信息
pTempHdr->dwBufferLength = nRead;
pTempHdr->dwBytesRecorded = 0;
pTempHdr->dwFlags = 0;
pTempHdr->dwLoops = 0;
pTempHdr->dwUser = 0;
}
}
// 所有缓冲块都已经播放完毕,停止播放
else
{
this->Stop();
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
// 设定缓冲块大小
void CLargeFileWaveOut::SetSamplesPerBlock(UINT nSamplesCount)
{
this->m_nSamplesPerBlock = nSamplesCount;
}
//////////////////////////////////////////////////////////////////////////
// 清除缓冲区,初始化数据
void CLargeFileWaveOut::Dispose()
{
// 释放播放文件分配的缓存
if (this->m_pAllocBuffer != NULL)
{
// 释放所有缓冲块
for (unsigned int i = 0; i < this->m_nBufferNums; i++)
{
this->m_pNextBuffer = &this->m_pAllocBuffer[i];
if (this->m_pNextBuffer->lpData != NULL)
{
delete[] this->m_pNextBuffer->lpData;
}
}
// 删除缓冲结构
delete[] this->m_pAllocBuffer;
}
this->m_pAllocBuffer = NULL;
this->m_pNextBuffer = NULL;
// 重置CWaveOut数据
CWaveOut::Dispose();
}
//////////////////////////////////////////////////////////////////////////
// 开始播放音频逻数据,发送第一个缓冲块
void CLargeFileWaveOut::Start()
{
if (this->m_pAllocBuffer != NULL)
{
CWaveOut::Start();
// 发送第一个缓冲块
this->m_pNextBuffer = this->m_pAllocBuffer + 1;
waveOutWrite(this->m_hWaveOut, this->m_pAllocBuffer, sizeof(WAVEHDR));
}
}
//////////////////////////////////////////////////////////////////////////
// 停止播放,关闭输出设备, UnPrepare所用到的缓冲块
void CLargeFileWaveOut::Stop()
{
// 停止播放
CWaveOut::Stop();
// UnPrepare所有缓冲块
for (unsigned int i = 0; i < this->m_nBufferNums; i++)
{
this->m_pNextBuffer = &this->m_pAllocBuffer[i];
waveOutUnprepareHeader(
this->m_hWaveOut, this->m_pNextBuffer, sizeof(WAVEHDR));
}
// 关闭输出设备
CWaveOut::CloseDev();
// 清除缓冲区,初始化数据
this->Dispose();
}