我这有语音聊天的一个CSOUND类  但是没有写完整  关闭waveX函数 总是出问题  没有释放buffer
没有close  wavein和waveout   我在Stop中使用waveoutclose与waveinclose总是出问题
不知哪位能帮我补全Stop函数  实现完整而且正确的关闭语音聊天 非常感谢各位的参与
代码如下
class CSound  
{
public:
void Init(CPhoneDlg* dlg);
void Record();
void Play();
void Stop();
void InBufferZero();
void OutBufferZero();
void FreeRecordBuffer();
void FreePlayBuffer();
CSound();
virtual ~CSound();
public:
CPhoneDlg             * m_dlg;
WAVEFORMATEX            m_soundFormat;
HWAVEIN m_hWaveIn;
HWAVEOUT m_hWaveOut;
WAVEHDR m_pWaveHdrIn[3];
WAVEHDR m_pWaveHdrOut[3];
CHAR m_cBufferIn[MAX_BUFFER_SIZE];
CHAR m_cBufferOut[MAX_BUFFER_SIZE];

};

解决方案 »

  1.   

    // Sound.cpp: implementation of the CSound class.
    //
    //////////////////////////////////////////////////////////////////////CSound::CSound()
    {}CSound::~CSound()
    {
    waveInClose(m_hWaveIn); //关闭录音设备
    waveOutClose(m_hWaveOut); //关闭录音设备
    }void CSound::Init(CPhoneDlg *dlg)
    {
    int retCode;
    m_dlg=dlg;
    if(waveInGetNumDevs()==0)
    {
    AfxMessageBox("There is no sound input device");
    }
    if(waveOutGetNumDevs()==0)
    {
    AfxMessageBox("There is no sound output device");
    }
    m_soundFormat.wFormatTag=WAVE_FORMAT_PCM;
    m_soundFormat.nChannels=1;
    m_soundFormat.nSamplesPerSec=11025;//8000;
    m_soundFormat.nAvgBytesPerSec=111025;//6000;
    m_soundFormat.nBlockAlign=2;
    m_soundFormat.cbSize=0;
    m_soundFormat.wBitsPerSample=16;     //指定录音格式

    retCode=waveInOpen(&m_hWaveIn,WAVE_MAPPER, &m_soundFormat, (DWORD)m_dlg->m_hWnd,0L,CALLBACK_WINDOW); //打开录音设备
    if(retCode!= MMSYSERR_NOERROR)
    {
    AfxMessageBox("Error in waveInOpen function");
    return;
    }
    retCode=waveOutOpen(&m_hWaveOut,WAVE_MAPPER, &m_soundFormat, (DWORD)m_dlg->m_hWnd,0L,CALLBACK_WINDOW); //打开录音设备
    if(retCode!= MMSYSERR_NOERROR)
    {
    AfxMessageBox("Error in waveOutOpen function");
    return;
    }
    //in
    m_pWaveHdrIn[0].lpData=m_cBufferIn;
    m_pWaveHdrIn[0].dwBufferLength=MAX_BUFFER_SIZE;
    m_pWaveHdrIn[0].dwBytesRecorded=0;
    m_pWaveHdrIn[0].dwFlags=0;
    retCode=waveInPrepareHeader(m_hWaveIn,&m_pWaveHdrIn[0],sizeof(WAVEHDR)); //准备内存块录音
        if(retCode!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot InPrepareHeader !"));
            return;
        }

    retCode=waveInAddBuffer(m_hWaveIn,&m_pWaveHdrIn[0],sizeof(WAVEHDR)); //增加内存块
        if(retCode!= MMSYSERR_NOERROR)
    {
    AfxMessageBox(_T("Cannot InAddBuffer !"));
    return;
        }

    //out
    m_pWaveHdrOut[0].lpData=m_cBufferOut;
    m_pWaveHdrOut[0].dwBufferLength=MAX_BUFFER_SIZE;
    m_pWaveHdrOut[0].dwBytesRecorded=0;
    m_pWaveHdrOut[0].dwFlags=0;

    waveOutPrepareHeader(m_hWaveOut,&m_pWaveHdrOut[0],sizeof(WAVEHDR)); //准备内存块录音
    waveOutWrite(m_hWaveOut,&m_pWaveHdrOut[0],sizeof(WAVEHDR));
    }void CSound::Record()
    {
    waveInStart(m_hWaveIn);//开始录音
    }void CSound::Play()
    {
    memcpy(m_cBufferOut,m_cBufferIn,MAX_BUFFER_SIZE);
    }void CSound::Stop()
    {
    waveInStop(m_hWaveIn); //停止录音
    waveOutReset(m_hWaveOut);
    // waveOutClose(m_hWaveOut);
    waveInReset(m_hWaveIn); //清空内存块
    // FreeRecordBuffer();
    // FreePlayBuffer();
    waveInClose(m_hWaveIn);}void CSound::FreeRecordBuffer()
    {
    int retCode;
    retCode =waveInUnprepareHeader(m_hWaveIn,&m_pWaveHdrIn[0],sizeof(WAVEHDR));
        if  (retCode!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot UnInPrepareHeader !"));
            return;
        } //in

    m_pWaveHdrIn[0].lpData=m_cBufferIn;
    m_pWaveHdrIn[0].dwBufferLength=MAX_BUFFER_SIZE;
    m_pWaveHdrIn[0].dwBytesRecorded=0;
    m_pWaveHdrIn[0].dwFlags=0;

    retCode=waveInPrepareHeader(m_hWaveIn,&m_pWaveHdrIn[0],sizeof(WAVEHDR)); //准备内存块录音
        if(retCode!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot InPrepareHeader !"));
            return;
        } retCode=waveInAddBuffer(m_hWaveIn,&m_pWaveHdrIn[0],sizeof(WAVEHDR)); //增加内存块
        if(retCode!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot InAddBuffer !"));
            return;
        }
    }void CSound::FreePlayBuffer()
    {
    static bool once=true;
    int result;
    /*
    result=waveOutUnprepareHeader(m_hWaveOut,&m_pWaveHdrOut[0],sizeof(WAVEHDR));
     
    if  (result!= MMSYSERR_NOERROR) 
        {
    if(once)
    {
    char  errinfor[100];
    waveOutGetErrorText(result,errinfor,100);
    AfxMessageBox(_T("Cannot UnOutPrepareHeader !"));
    AfxMessageBox(errinfor);
    once=false;
    }
    return;
        }; //out */
    // waveOutReset(m_hWaveOut); //清空内存块

    m_pWaveHdrOut[0].lpData=m_cBufferOut;
    m_pWaveHdrOut[0].dwBufferLength=MAX_BUFFER_SIZE;
    m_pWaveHdrOut[0].dwBytesRecorded=0;
    m_pWaveHdrOut[0].dwFlags=0;

    result=waveOutPrepareHeader(m_hWaveOut,&m_pWaveHdrOut[0],sizeof(WAVEHDR)); //准备内存块录音
        if(result!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot OutPrepareHeader !"));
            return;
        }//out

    result=waveOutWrite(m_hWaveOut,&m_pWaveHdrOut[0],sizeof(WAVEHDR)); //增加内存块
        if(result!= MMSYSERR_NOERROR) 
        {
            AfxMessageBox(_T("Cannot OutWrite !"));
            return;
        }//out
    }
    void CSound::InBufferZero()
    {
    int i;
    for(i=0;i<MAX_BUFFER_SIZE;i++)
    {
    m_cBufferIn[i]=0;
    }
    }void CSound::OutBufferZero()
    {
    int i;
    for(i=0;i<MAX_BUFFER_SIZE;i++)
    {
    m_cBufferOut[i]=0;
    }
    }主要就是Stop函数有问题  总是无法关闭
    导致下次语音无法正确开启
      

  2.   

    CSound::~CSound() 

    waveInClose(m_hWaveIn); //关闭录音设备 
    waveOutClose(m_hWaveOut); //关闭录音设备 

    你修改一下,试试,感觉问题应该出在这里
      

  3.   

    我有过同样的问题。
    waveInClose返回“有更多数据“。
    用以下方法可以正常关闭。
    在处理WIM_DATA时.检测关闭标志.检测到关闭时.调用waveInUnprepareBuffer取消当前传入的缓存。然后再调用waveInClose就一切正常了。
      

  4.   

    另外。waveIn和waveOut操作不太爽。建议使用DirectSound.音质不错。操作方便。
      

  5.   


    #if !defined(AFX_PLAYWAVE_H__4B0BD51B_67B7_427A_BD7A_75A066740701__INCLUDED_)
    #define AFX_PLAYWAVE_H__4B0BD51B_67B7_427A_BD7A_75A066740701__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // PlayWave.h : header file
    ///////////////////////////////////////////////////////////////////////////////
    // CPlayWave window
    #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }class CPlayWave
    {
    // Construction
    typedef struct WAVE_HEADER
    {
    char rId[4];      // 固定标记 值为"RIFF"
    long int rLen; // 随后的字节数   值为(wSampleLength +36)
    char wId[4]; // 固定标记 值为"WAVE"
    char fId[4]; // ckID 值为"fmt "
    long int fLen; // nChunkSize Wave文件块的大小  16
    WORD wFormatTag; // 音频数据的编码方式 此值常为1 表示PCM方式
    WORD nChannels;      // 声道数
    long int nSamplesPerSec; // 每秒采样频率
    long int nAvgBytesPerSec;  // 每秒字节数
    WORD nBlockAlign;     // 一次输出的字节数  值为采样位数*声道数/8
    WORD wBitsPerSample;   // 采样位数  一般16位和8位  
    char dId[4];         // 固定标记  值为"data"
    long int wSampleLength; // 采样数据长度 值为文件大小-文件头大小
    }WAVE_HEADER;public:
    CPlayWave();
    virtual ~CPlayWave();// Attributes
    protected:
    LPBYTE _pWaveData;
    HWAVEOUT m_hWaveOut;
    WAVE_HEADER m_WaveHead;
    WAVEFORMATEX m_waveOutForm;
    WAVEHDR m_WaveHdr;
    PLAYSTATE m_Sate;
    UINT m_uDveId;
    // Operations
    public:// Implementation
    public:
    BOOL Stop(); // 停止
    BOOL Continue(); // 继续
    BOOL Pause(); // 暂停
    BOOL Play(LPBYTE lpData, DWORD dwLen); // 拔放一个WAVE数据
    BOOL Play(UINT uResId); // 播放存在资源中的WAVE文件
    BOOL PlayFile(CString strFile); // 播放一个WAVE文件
    BOOL PressKey(CString strKey); // 按键,支持多个按键 0123456789+-
    BOOL SetSoundCard(CString strDevName, UINT uDevId = -1); // 设置播放设备
    PLAYSTATE GetStatus(); // 得到当前状态 protected:
    BOOL BuildNumber(CString strNumber); static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_PLAYWAVE_H__4B0BD51B_67B7_427A_BD7A_75A066740701__INCLUDED_)
      

  6.   


    // PlayWave.cpp : implementation file
    //#include "stdafx.h"
    #include "PlayWave.h"#pragma comment(lib, "winmm.lib")#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CPlayWaveCPlayWave::CPlayWave()
    {
    _pWaveData = NULL;
    m_Sate = Init;
    m_uDveId = -1;
    } CPlayWave::~CPlayWave()
    {
    Stop();
    }BOOL CPlayWave::PlayFile(CString strFile)
    {
    char *lpfile;
    int file_size;
    FILE *f; f = fopen(strFile, "rb");
    if(!f)
    return FALSE;
    fseek(f, 0, SEEK_END);
    file_size = ftell(f);
    fseek(f, 0, SEEK_SET);
    lpfile = new char [file_size];
    fread(lpfile, 1, file_size, f);
    fclose(f); Play((LPBYTE)lpfile, file_size); delete[] lpfile; return TRUE;
    }BOOL CPlayWave::Play(LPBYTE lpData, DWORD dwLen)
    {
    if (m_Sate == Running || m_Sate == Stopped || m_Sate == Paused)
    {
    if(waveOutReset(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutReset Faild!!!");
    return FALSE;
    }

    if(waveOutClose(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutClose Faild!!!");
    return FALSE;
    } SAFE_DELETE_ARRAY(_pWaveData);
    } // 准备数据.
    _pWaveData = new BYTE[dwLen]; if (_pWaveData == NULL)
    {
    AfxMessageBox("内存不足!!!");
    return FALSE;
    } memcpy(_pWaveData, lpData, dwLen); // 准备头
    m_waveOutForm.wFormatTag         = *((WORD* )(_pWaveData + 20));
    m_waveOutForm.nChannels          = *((WORD* )(_pWaveData + 22));
    m_waveOutForm.nSamplesPerSec     = *((DWORD*)(_pWaveData + 24));
    m_waveOutForm.nAvgBytesPerSec    = *((DWORD*)(_pWaveData + 28));
    m_waveOutForm.nBlockAlign        = *((WORD* )(_pWaveData + 32));
    m_waveOutForm.wBitsPerSample     = *((WORD* )(_pWaveData + 34)); m_WaveHdr.lpData          = (LPTSTR)_pWaveData+44;
    m_WaveHdr.dwBufferLength  = dwLen-44;
    m_WaveHdr.dwBytesRecorded = 0;
    m_WaveHdr.dwUser          = 0;
    m_WaveHdr.dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    m_WaveHdr.dwLoops         = 1;
    m_WaveHdr.lpNext          = NULL;
    m_WaveHdr.reserved        = 0; // 开始播放
    if (waveOutOpen(&m_hWaveOut,
    m_uDveId, // 声卡ID
    &m_waveOutForm,
    (DWORD)waveOutProc,
    (DWORD)this,
    CALLBACK_FUNCTION))
    {
    DBTRACE1("Call waveOutOpen Faild!!!");
    return FALSE;
    } m_Sate = Running; if(waveOutPrepareHeader(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutPrepareHeader Faild!!!");
    return FALSE;
    } if(waveOutWrite(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutWrite Faild!!!");
    return FALSE;
    } return TRUE;
    }BOOL CPlayWave::Play(UINT uResId)
    {
        LPSTR lpRes;
        HRSRC hResInfo;
    HGLOBAL hRes;
    DWORD dwWaveSize; if (m_Sate == Running || m_Sate == Stopped || m_Sate == Paused)
    {
    if(waveOutReset(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutReset Faild!!!");
    return FALSE;
    }

    if(waveOutClose(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutClose Faild!!!");
    return FALSE;
    } SAFE_DELETE_ARRAY(_pWaveData);
    }    // Find the WAVE resource. 
    HMODULE hInst = AfxGetInstanceHandle(); hResInfo = FindResource(hInst, MAKEINTRESOURCE(uResId), "WAVE");
    if (hResInfo == NULL) 
    {
    CString strError;
    strError.Format("Call FindResource Faild!!!, Error Id = 0x%08X, hInst = 0x%08X", GetLastError(), hInst);
    DBTRACE1(strError);
    return FALSE; 
    }

    dwWaveSize = SizeofResource(hInst, hResInfo);

    // Load the WAVE resource. 

    hRes = LoadResource(hInst, hResInfo); 
    if (hRes == NULL) 
    return FALSE; 

    // Lock the WAVE resource and play it. 

    lpRes = (LPSTR)LockResource(hRes); _pWaveData = new BYTE[dwWaveSize];
    if (_pWaveData == NULL)
    {
    AfxMessageBox("内存不足!!!");
    return FALSE;
    } // 复制数据.
    memcpy(_pWaveData, lpRes, dwWaveSize); // 准备头
    m_waveOutForm.wFormatTag         = *((WORD* )(_pWaveData + 20));
    m_waveOutForm.nChannels          = *((WORD* )(_pWaveData + 22));
    m_waveOutForm.nSamplesPerSec     = *((DWORD*)(_pWaveData + 24));
    m_waveOutForm.nAvgBytesPerSec    = *((DWORD*)(_pWaveData + 28));
    m_waveOutForm.nBlockAlign        = *((WORD* )(_pWaveData + 32));
    m_waveOutForm.wBitsPerSample     = *((WORD* )(_pWaveData + 34)); m_WaveHdr.lpData          = (LPTSTR)_pWaveData+44;
    m_WaveHdr.dwBufferLength  = dwWaveSize-44;
    m_WaveHdr.dwBytesRecorded = 0;
    m_WaveHdr.dwUser          = 0;
    m_WaveHdr.dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    m_WaveHdr.dwLoops         = 1;
    m_WaveHdr.lpNext          = NULL;
    m_WaveHdr.reserved        = 0; // 释放资源.
    UnlockResource(hRes);
    FreeResource(hRes); // 开始播放
    if (waveOutOpen(&m_hWaveOut,
    m_uDveId, // 声卡ID
    &m_waveOutForm,
    (DWORD)waveOutProc,
    (DWORD)this,
    CALLBACK_FUNCTION))
    {
    DBTRACE1("Call waveOutOpen Faild!!!");
    return FALSE;
    } m_Sate = Running; if(waveOutPrepareHeader(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutPrepareHeader Faild!!!");
    return FALSE;
    } if(waveOutWrite(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutWrite Faild!!!");
    return FALSE;
    } return TRUE;
    }
      

  7.   

    BOOL CPlayWave::PressKey(CString strKey)
    {
    return BuildNumber(strKey);
    }BOOL CPlayWave::BuildNumber(CString strNumber)
    {
    /*
        LPSTR lpRes[MAX_PATH] = {0};
        HRSRC hResInfo;
    HGLOBAL hRes[MAX_PATH] = {0};
    DWORD dwSize = 0;
    DWORD dwWaveSize[MAX_PATH] = {0};
    CString strResource;
    */
    LPSTR* lpRes = NULL;
    HGLOBAL* hRes = NULL;
    DWORD* dwWaveSize = NULL;
        HRSRC hResInfo;
    DWORD dwSize = 0;
    CString strResource; // 不定长号码.
    if (strNumber.GetLength() != 0)
    {
    lpRes = new LPSTR[strNumber.GetLength()];
    hRes  = new HGLOBAL[strNumber.GetLength()];
    dwWaveSize = new DWORD[strNumber.GetLength()]; ZeroMemory(lpRes, strNumber.GetLength() * sizeof(LPSTR*));
    ZeroMemory(hRes, strNumber.GetLength() * sizeof(HGLOBAL*));
    ZeroMemory(dwWaveSize, strNumber.GetLength() * sizeof(DWORD*));
    }
    else
    {
    return FALSE;
    } if (m_Sate == Running || m_Sate == Stopped || m_Sate == Paused)
    {
    if(waveOutReset(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutReset Faild!!!");
    return FALSE;
    }

    if(waveOutClose(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutClose Faild!!!");
    return FALSE;
    }
    SAFE_DELETE_ARRAY(_pWaveData);
    }    // 寻找WAVE资源
    HMODULE hInst = AfxGetInstanceHandle(); for (int i=0; i<strNumber.GetLength(); i++)
    {
    if (CString(strNumber.GetAt(i)) == "*" || 
    CString(strNumber.GetAt(i)) == "#" ||
    CString(strNumber.GetAt(i)) == "+" ||
    CString(strNumber.GetAt(i)) == "-" )
    {
    switch(strNumber.GetAt(i))
    {
    case '*':
    strResource = "IDR_WAVE_XING";
    break;
    case '#':
    strResource = "IDR_WAVE_JIN";
    break;
    case '+':
    strResource = "IDR_WAVE_OFFHOOK";
    break;
    case '-':
    strResource = "IDR_WAVE_HANGUP";
    break;
    default:
    ;
    }
    }
    else
    {
    strResource.Format("IDR_WAVE_%c", strNumber.GetAt(i));
    } hResInfo = FindResource(hInst, strResource.GetBuffer(0), "WAVE"); 
    if (hResInfo == NULL) 
    {
    CString strError;
    strError.Format("0x%08X, %s, hInst = 0x%08X", GetLastError(), strResource, hInst);
    DBTRACE1(strError);
    return FALSE; 
    } dwSize += (dwWaveSize[i] = SizeofResource(hInst, hResInfo));

    hRes[i] = LoadResource(hInst, hResInfo); 
    if (hRes[i] == NULL)
    {
    CString strError;
    strError.Format("0x%08X, %s, hInst = 0x%08X", GetLastError(), strResource, hInst);
    DBTRACE1(strError);
    return FALSE; 
    }

    lpRes[i] = (LPSTR)LockResource(hRes[i]);
    }

    // Wave文件头结构.
    m_WaveHead.wFormatTag = 1;
    m_WaveHead.nChannels = 2;
    m_WaveHead.nSamplesPerSec = 11025;
    m_WaveHead.nAvgBytesPerSec = 22050;
    m_WaveHead.nBlockAlign = 2;
    m_WaveHead.wBitsPerSample = 8;
    strcpy( m_WaveHead.rId, "RIFF" ); // 固定标记 值为"RIFF"
    strcpy( m_WaveHead.wId, "WAVE" ); // 固定标记 值为"WAVE"
    strcpy( m_WaveHead.fId, "fmt " ); // ckID 值为"fmt "
    m_WaveHead.fLen =   16; // nChunkSize Wave文件块的大小  16
    strcpy( m_WaveHead.dId, "data" ); // 固定标记 值为"data"
    m_WaveHead.wSampleLength =   dwSize; // 采样数据长度
    m_WaveHead.rLen = dwSize + 36; // 随后的字节数 值为(wSampleLength +36) DWORD dwHeadSize = sizeof(WAVE_HEADER); _pWaveData = new BYTE[dwHeadSize + dwSize + 256];
    if (_pWaveData == NULL)
    {
    AfxMessageBox("内存不足!!!");
    return FALSE;
    }

    // 准备头
    m_waveOutForm.wFormatTag = m_WaveHead.wFormatTag;
    m_waveOutForm.nChannels = m_WaveHead.nChannels;
    m_waveOutForm.nSamplesPerSec = m_WaveHead.nSamplesPerSec;
    m_waveOutForm.nAvgBytesPerSec = m_WaveHead.nAvgBytesPerSec;
    m_waveOutForm.nBlockAlign = m_WaveHead.nBlockAlign;
    m_waveOutForm.wBitsPerSample = m_WaveHead.wBitsPerSample;
    m_waveOutForm.cbSize = 0; // 复制数据.
    memcpy(_pWaveData, &m_WaveHead, sizeof(m_WaveHead));

    DWORD cpPos = dwHeadSize;
    for (i=0; i<strNumber.GetLength(); i++)
    {
    memcpy(_pWaveData+cpPos, lpRes[i], dwWaveSize[i]);
    cpPos += dwWaveSize[i];
    } m_WaveHdr.lpData          = (LPTSTR)_pWaveData+44;
    m_WaveHdr.dwBufferLength  = m_WaveHead.wSampleLength;
    m_WaveHdr.dwBytesRecorded = 0;
    m_WaveHdr.dwUser          = 0;
    m_WaveHdr.dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    m_WaveHdr.dwLoops         = 1;
    m_WaveHdr.lpNext          = NULL;
    m_WaveHdr.reserved        = 0; // 释放资源.
    for (i=0; i<strNumber.GetLength(); i++)
    {
    UnlockResource(hRes[i]);
    FreeResource(hRes[i]);
    } SAFE_DELETE_ARRAY(lpRes);
    SAFE_DELETE_ARRAY(hRes);
    SAFE_DELETE_ARRAY(dwWaveSize); // 开始播放
    if (waveOutOpen(&m_hWaveOut,
    m_uDveId, // 声卡ID
    &m_waveOutForm,
    (DWORD)waveOutProc,
    (DWORD)this,
    CALLBACK_FUNCTION))
    {
    DBTRACE1("Call waveOutOpen Faild!!!");
    return FALSE;
    }

    m_Sate = Running; if(waveOutPrepareHeader(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutPrepareHeader Faild!!!");
    return FALSE;
    } if(waveOutWrite(m_hWaveOut, &m_WaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutWrite Faild!!!");
    return FALSE;
    } return TRUE;
    }void CALLBACK CPlayWave::waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
    {
    CPlayWave* pThis = (CPlayWave*) dwInstance; switch(uMsg)
    {
    case WOM_CLOSE:
    pThis->m_Sate = Init;
    break;
    case WOM_DONE:
    pThis->m_Sate = Stopped;
    break;
    case WOM_OPEN:
    pThis->m_Sate = Running;
    break;
    default:
    ;
    }
    }// 暂停播放
    BOOL CPlayWave::Pause()
    {
    if (m_Sate == Running)
    {
    if(waveOutPause(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutPause Faild!!!");
    return FALSE;
    } m_Sate = Paused;
    } return TRUE;
    }// 继续播放
    BOOL CPlayWave::Continue()
    {
    if (m_Sate == Paused)
    {
    if(waveOutRestart(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutRestart Faild!!!");
    return FALSE;
    }

    m_Sate = Running;
    }

    return TRUE;
    }// 设置播放设备
    BOOL CPlayWave::SetSoundCard(CString strDevName, UINT uDevId)
    {
    WAVEOUTCAPS woc;
    int nCount = waveOutGetNumDevs(); if (uDevId == -1 && strDevName != "")
    {
    for (int i=-1; i<nCount; i++)
    {
    waveOutGetDevCaps(i, &woc, sizeof(WAVEINCAPS));
    CString strDev = woc.szPname;
    if (strDev.Find(strDevName) != -1)
    {
    m_uDveId = i;
    return TRUE;
    }
    }
    } m_uDveId = uDevId; return FALSE;
    }// 停止播放
    BOOL CPlayWave::Stop()
    {
    if (m_Sate == Running || m_Sate == Stopped || m_Sate == Paused)
    {
    if(waveOutReset(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutReset Faild!!!");
    return FALSE;
    }

    if(waveOutClose(m_hWaveOut) != MMSYSERR_NOERROR)
    {
    DBTRACE1("Call waveOutClose Faild!!!");
    return FALSE;
    }

    m_Sate = Init;
    }

    SAFE_DELETE_ARRAY(_pWaveData);

    return TRUE;
    }// 得到当前播放状态
    PLAYSTATE CPlayWave::GetStatus()
    {
    return m_Sate;
    }