我用waveOut API写了一个播放声音的代码。播放声音没有问题,但是如果想在声音播放过程中和声音播放结束后关闭设备就会出问题。具体表现为waveOutReset()和waveOutClose()函数执行的过程中死机。
下面是我的源代码,请大侠多多指教。
class CWaveOut 
{
public:
CWaveOut();
virtual ~CWaveOut();public:
long m_nBufferLen;
WORD  m_nFormatTag;
    WORD  m_nBlockAlign;
DWORD m_nAvgBytesPerSec;
WORD  m_nChannels;
WORD  m_nBitsPerSample;
DWORD m_nSamplesPerSec; DWORD m_ThreadID;    UINT m_nDeviceID;
UINT m_nNumOfDev; CString m_strPath;
BOOL m_bPause;

void SetOutputDevice( const CString str);
void GetFileInfo();
void GetDeviceInfo();
void Open();
void Play();
void Close();
void Pause();};#include "stdafx.h"
#include "WaveOut.h"
#include "mmsystem.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FILE *Outfp = NULL;
BYTE *pBufferOut[2];
long nBuffer = 0;
long nBufferLenOut;
long nBufferNoOut = 0;
int i = 0;WAVEFORMATEX waveformatOut;
WAVEHDR      wavehdrOut[2];
MMRESULT     OutResult;
HWAVEOUT     hwo;void AddBuffer()
{
    int nSize;

    memset( pBufferOut[nBufferNoOut], 0, nBufferLenOut );
        
nSize = fread( pBufferOut[nBufferNoOut], sizeof(char), nBufferLenOut, Outfp ); wavehdrOut[nBufferNoOut].lpData = (char *)pBufferOut[ nBufferNoOut ];
wavehdrOut[nBufferNoOut].dwBufferLength = nSize;
wavehdrOut[nBufferNoOut].dwFlags = 0; waveOutPrepareHeader( hwo, &wavehdrOut[nBufferNoOut], sizeof(WAVEHDR) ); nBuffer++;
}void CALLBACK WaveOutProc( HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, WORD dwParam2 )
{ int end = feof(Outfp);
switch( uMsg )
{
case WOM_DONE:
        
nBuffer--; OutResult = waveOutUnprepareHeader( hwo, &wavehdrOut[nBufferNoOut], sizeof(WAVEHDR) );
if( OutResult != MMSYSERR_NOERROR )
{
AfxMessageBox("Unprepare wave header error!");
return;
}
nBufferNoOut++;
nBufferNoOut = nBufferNoOut % 2;
    if( !end )
{
i++;
TRACE( "turn: %d\tEnd: %d\n", i, end ) ;
    AddBuffer();
     waveOutWrite( hwo, &wavehdrOut[nBufferNoOut], sizeof(WAVEHDR) );
}
else
{
fclose(Outfp); nBufferNoOut = 0;
nBuffer = 0;
i = 0; OutResult = waveOutReset( hwo );
hwo = NULL;
if( OutResult != MMSYSERR_NOERROR )
{
     AfxMessageBox("Close wave device error!");
    return;
}

}
break; case WOM_CLOSE:
TRACE( "wavefile closed!\n" );
break; default:
break;
}
}
CWaveOut::CWaveOut()
{
m_nDeviceID = 0;
m_bPause = FALSE;
m_ThreadID = ::GetCurrentThreadId();
}CWaveOut::~CWaveOut()
{}void CWaveOut::OnMM_WOM_DONE( UINT wParam, long lParam)
{
}void CWaveOut::GetFileInfo()
{
char ctmp; if( Outfp )
fclose( Outfp );

Outfp = fopen( (LPCTSTR)m_strPath, "rb" );
if( !Outfp )
{
AfxMessageBox("Can't open specified file!");
return;
}
else
{
fseek( Outfp, 0, SEEK_SET );
for( int i = 0; i < 22; i++ )
fread( &ctmp, sizeof(char), 1, Outfp ); fread( &m_nChannels, sizeof(WORD), 1, Outfp );
fread( &m_nSamplesPerSec, sizeof(DWORD), 1, Outfp );
fread( &m_nAvgBytesPerSec, sizeof( DWORD), 1, Outfp );
fread( &m_nBlockAlign, sizeof(WORD), 1, Outfp );
fread( &m_nBitsPerSample, sizeof(WORD), 1, Outfp ); for( i = 0; i < 8; i++ )
fread( &ctmp, sizeof(char), 1, Outfp );
}
}void CWaveOut::GetDeviceInfo()
{
 m_nNumOfDev = waveOutGetNumDevs( );
 if( m_nNumOfDev == 0 )
 {
 AfxMessageBox( "No device is avaliable!" );
 return;
 }
}void CWaveOut::SetOutputDevice(const CString str)
{
WAVEOUTCAPS woc;
int i = 0; CString *pStr = new CString [m_nNumOfDev]; for( i = 0; i < m_nNumOfDev; i++ )
{
waveOutGetDevCaps( i, &woc, sizeof(WAVEOUTCAPS) );
pStr[i] = woc.szPname;
} i = 0;
while( pStr[i] != str && i < m_nNumOfDev ) i++;

if( i >= m_nNumOfDev )
{
AfxMessageBox( "The inputed device name is wrong!" );
return;
}
else 
m_nDeviceID = i;      
}void CWaveOut::Open()
{
m_nBufferLen = (long)( m_nAvgBytesPerSec * 5 );
nBufferLenOut = m_nBufferLen;
GetDeviceInfo(); waveformatOut.wFormatTag      = WAVE_FORMAT_PCM;
waveformatOut.nAvgBytesPerSec = m_nAvgBytesPerSec;
waveformatOut.nBlockAlign     = m_nBlockAlign;
waveformatOut.nChannels       = m_nChannels;
waveformatOut.nSamplesPerSec  = m_nSamplesPerSec;
waveformatOut.wBitsPerSample  = m_nBitsPerSample;
waveformatOut.cbSize          = sizeof(waveformatOut);    pBufferOut[0] = new BYTE [ nBufferLenOut ];
pBufferOut[1] = new BYTE [ nBufferLenOut ]; OutResult = waveOutOpen(  &hwo,           
                              m_nDeviceID,            
                              &waveformatOut,       
                              (DWORD)WaveOutProc,          
                              NULL,  
                              CALLBACK_FUNCTION
   ); 
if( OutResult != MMSYSERR_NOERROR  )
{
AfxMessageBox("Audio device open error!");
return;
}

if( !pBufferOut )
{
AfxMessageBox( "Fail to alloc memery!" );
return;
}
}void CWaveOut::Play()
{
  AddBuffer();
OutResult = waveOutWrite( hwo, &wavehdrOut[nBufferNoOut], sizeof(WAVEHDR) );
if( OutResult != MMSYSERR_NOERROR  )
{
AfxMessageBox("Audio device play error!");
return;
}
}void CWaveOut::Close()
{
if( hwo )
{
if( !feof( Outfp ) )
{
OutResult = waveOutReset( hwo );
if( OutResult != MMSYSERR_NOERROR  )
{
AfxMessageBox("Audio device reset error!");
         return;
}
    waveOutUnprepareHeader( hwo, &wavehdrOut[nBufferNoOut], sizeof(WAVEHDR) );
    delete  pBufferOut[ nBufferNoOut ];
}
    nBuffer = 0;
    i = 0;

        OutResult = waveOutClose( hwo );     if( OutResult != MMSYSERR_NOERROR  )
{
     AfxMessageBox("Audio device stop error!");
     return;
}      nBufferNoOut = 0;
     fclose( Outfp );
}
}
void CWaveOut::Pause()
{
if( !m_bPause )
{
waveOutPause( hwo );
m_bPause = TRUE;
}
else
{
waveOutRestart( hwo );
m_bPause = FALSE;
}
}