waveOutOpen()API中的回调函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了waveOutOpen()API中的回调函数相关的知识,希望对你有一定的参考价值。
我正在构建一个播放'.wav'文件的音频播放器,我对从waveOutOpen()API调用的回调函数有疑问。
打开输出音频设备进行播放:
MMRESULT mRes = waveOutOpen(m_hWO,WAVE_MAPPER,&wFmt,(DWORD)&waveOutProc,(DWORD)this, CALLBACK_FUNCTION);
回调函数的实现:
void CPlayWave::waveOutProc(HWAVEOUT m_hWO,UINT uMsg,DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
MMRESULT mmRes;
CPlayWave *pPW = (CPlayWave*)dwInstance;
switch(uMsg)
{
case MM_WOM_DONE: //playback finished
mmRes = waveOutUnprepareHeader(m_hWO, &pPW->m_WHdr, sizeof(WAVEHDR));
if(mmRes!=MMSYSERR_NOERROR)
{
//error handling
.....
}
mmRes = waveOutClose(m_hWO);
if(mmRes!=MMSYSERR_NOERROR)
{
//error handling
.....
}
AfxMessageBox("Finished playing the file");
m_bPlay = FALSE; //boolean flag used for pausing
break;
case WIM_DATA:
//for recording completion
break;
}
}
问题是MM_WOM_DONE永远不会发生,并且在文件播放完成后永远不会调用回调函数。如果必须使用线程而不是回调函数,有人可以给我一个关于如何使用回调线程的简单示例(在网上找不到)。
另外waveOutReset()文档建议关闭所有缓冲区并返回系统,因此为了处理我的应用程序中的Stop-button,我使用了waveOutReset()函数,但这会导致应用程序冻结。为什么会这样?当缓冲区仍在队列中进行播放时,是否有其他方法可以停止播放。
回调函数可能不是你的类CPlayWave本身的方法。它必须是您所需的原型的类中的简单功能。
void CALLBACK waveOutProc(HWAVEOUT m_hWO, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
...
}
当然,在调用waveOutOpen()之前,必须声明/定义它。此外,函数名称是指针本身和&符号&不需要。因此调用waveOutOpen()应该是:
MMRESULT mRes = waveOutOpen(m_hWO, WAVE_MAPPER, &wFmt, (DWORD_PTR) waveOutProc, (DWORD_PTR) this, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
另外,您可以从waveOutProc调用的系统函数很少:
“应用程序不应该从回调函数内部调用任何系统定义的函数,除了EnterCriticalSection,LeaveCriticalSection,midiOutLongMsg,midiOutShortMsg,OutputDebugString,PostMessage,PostThreadMessage,SetEvent,timeGetSystemTime,timeGetTime,timeKillEvent和timeSetEvent。调用其他wave函数将导致死锁“。
所以调用像AfxMessageBox或waveOut Unprepared Header这样的函数可能会导致严重的问题。
以上是关于waveOutOpen()API中的回调函数的主要内容,如果未能解决你的问题,请参考以下文章