2012-04-03 1 views
0

Я создаю аудиоплеер, который воспроизводит файлы .wav, и у меня есть проблема с функцией обратного вызова, вызванной из waveOutOpen() API.Функция обратного вызова в 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 в приложении я использовал функцию waveOutReset(), но это заставило приложение замораживать. Почему это происходит? Есть ли альтернативный метод, чтобы остановить воспроизведение, пока буфер все еще находится в очереди для воспроизведения.

ответ

1

Функция обратного вызова, вероятно, не может быть методом вашего класса 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);