|
为了解决playSound函数装载大文件速度慢和不支持MP3的播放,我自己写一个模拟PlaySound的函数来播放音频文件。
我使用了常规的双缓冲,用一个callback函数不停的装载数据,播放很流畅,但是如果在播放过程中停止播放在waveOutClose的时候出现33的错误(任然有buffer没有清空),尝试了几次都不行,请大家帮我看看是什么问题,谢谢!!
void CALLBACK waveOutProcCallback( HWAVEOUT hwo2, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
HRESULT mr;
LPWAVEHDR pWaveHeader = NULL;
//系统自动识别是哪一个WAVEHDR播放完毕
pWaveHeader = (LPWAVEHDR)dwParam1;
switch(uMsg)
{
case WOM_CLOSE:
break;
case WOM_OPEN:
break;
case WOM_DONE:
//播放完后须调用此函数
waveOutUnprepareHeader( hwo2, pWaveHeader, sizeof(WAVEHDR) );
EnterCriticalSection(&g_csReadyQueue);
if(g_qReadyQueue.empty())
{
LeaveCriticalSection(&g_csReadyQueue);
}
else
{
g_pPlayBuf = g_qReadyQueue.front();
g_qReadyQueue.pop();
LeaveCriticalSection(&g_csReadyQueue);
//装填新的buffer
pWaveHeader->lpData = (char *)g_pPlayBuf;
//把使用过的buffer放回Unready Queue
EnterCriticalSection(&g_csUnreadyQueue);
g_qUnreadyQueue.push(g_pPlayBuf);
LeaveCriticalSection(&g_csUnreadyQueue);
mr = waveOutPrepareHeader(hwo2, pWaveHeader, sizeof(WAVEHDR));
mr = waveOutWrite(hwo2, pWaveHeader, sizeof(WAVEHDR));
}
break;
default:
break;
}
}
DWORD WINAPI PlayThread(LPVOID lpParam)
{
DWORD dwWait;
HRESULT mr;
//分配两个结构体双缓冲
WAVEHDR hdr1;
WAVEHDR hdr2;
int count = 0;
RETAILMSG(1, (TEXT("PlayThread Begin!\r\n")));
//打开设备,使用回调函数处理双缓冲播放
mr = waveOutOpen(&hwo, WAVE_MAPPER, g_pwfx, (DWORD)waveOutProcCallback, NULL, CALLBACK_FUNCTION );
MRCHECK1(mr, waveOutOpen, ERROR_OPEN);
while(!g_bStopThread)
{
//只执行一次,初始化开始两个buffer
if(0 == count)
{
//从一个Unready队列中提取buffer赋值给WAVEHDR hdr1,WAVEHDR hdr2
EnterCriticalSection(&g_csReadyQueue);
if(g_qReadyQueue.empty())
{
LeaveCriticalSection(&g_csReadyQueue);
continue;
}
g_pPlayBuf = g_qReadyQueue.front();
g_qReadyQueue.pop();
LeaveCriticalSection(&g_csReadyQueue);
memset(&hdr1, 0, sizeof(hdr1));
hdr1.dwBufferLength = BUF_SIZE; //BUF_SIZE = 0x8000
1.lpData = (char *) g_pPlayBuf;
hdr1.dwFlags = 0;
hdr1.dwLoops = 0;
EnterCriticalSection(&g_csUnreadyQueue);
g_qUnreadyQueue.push(g_pPlayBuf);
LeaveCriticalSection(&g_csUnreadyQueue);
EnterCriticalSection(&g_csReadyQueue);
if(g_qReadyQueue.empty())
{
LeaveCriticalSection(&g_csReadyQueue);
continue;
}
g_pPlayBuf = g_qReadyQueue.front();
g_qReadyQueue.pop();
LeaveCriticalSection(&g_csReadyQueue);
memset(&hdr2, 0, sizeof(hdr2));
hdr2.dwBufferLength = BUF_SIZE;
hdr2.lpData = (char *) g_pPlayBuf;
hdr2.dwFlags = 0;
hdr2.dwLoops = 0;
EnterCriticalSection(&g_csUnreadyQueue);
g_qUnreadyQueue.push(g_pPlayBuf);
LeaveCriticalSection(&g_csUnreadyQueue);
mr = waveOutPrepareHeader(hwo, &hdr1, sizeof(hdr1));
MRCHECK1(mr, waveOutPrepareHeader,ERROR_PLAY);
mr = waveOutPrepareHeader(hwo, &hdr2, sizeof(hdr2));
MRCHECK1(mr, waveOutPrepareHeader, ERROR_PLAY);
mr = waveOutWrite(hwo, &hdr1, sizeof(hdr1));
MRCHECK1(mr, waveOutWrite, ERROR_PLAY);
mr = waveOutWrite(hwo, &hdr2, sizeof(hdr2));
MRCHECK1(mr, waveOutWrite, ERROR_PLAY);
count++;
}
}
RETAILMSG(1, (TEXT("PlayThread End!\r\n")));
ERROR_PLAY:
mr = waveOutReset(hwo);
MRCHECK1(mr, waveOutReset, ERROR_OPEN);
//Sleep(800);
free(hdr1.lpData);
waveOutPrepareHeader(hwo, &hdr1, sizeof(hdr1));
MRCHECK1(mr, waveOutPrepareHeader, ERROR_OPEN);
free(hdr2.lpData);
waveOutPrepareHeader(hwo, &hdr2, sizeof(hdr2));
MRCHECK1(mr, waveOutPrepareHeader, ERROR_OPEN);
mr = waveOutClose(hwo);
MRCHECK1(mr, waveOutClose, ERROR_OPEN);
ERROR_OPEN:
delete [] g_pPlayBuf;
delete [] g_pwfx;
ERROR_READ:
return 0;
}
|
|