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中的回调函数的主要内容,如果未能解决你的问题,请参考以下文章

将对象的引用传递给jQuery中的回调函数[重复]

回调函数不打印,除非由 Jupyter 运行

Zookeeper C API 指南三(回调函数)(转)

Control.Invoke() 与其委托的调用之间的延迟是多长时间?

如何运行多个异步函数然后执行回调?

跨 C API 边界传递异常