制造自己的wave音频播放器-使用waveOutOpen与waveOutWrite实现

打造自己的wave音频播放器-使用waveOutOpen与waveOutWrite实现


 本人应用场景:播放采集设备输出的PCM音频,参考了两种网上实现方法,接口做了些调整,因为播放的音频属性经常需要改变,在播放初始化函数Start传入WAVEFORMATEX参数,这样支持的播放音频种类多,经测试,均能正常播放,使用方法:

[html]  view plain  copy
  1. CViWavePlay* m_pWavPlay;  
  2. m_pWavPlay = new CViWavePlay;  
  3. m_pWavPlay->Start(PWAVEFORMATEX(pbFormat));  
  4. m_pWavPlay->PlayAudio((char*)pPData->m_pData,pPData->m_nData);  
  5. m_pWavPlay->Stop();  

Start函数参数WAVEFORMATEX设置方法:

参见头文件的定义:

typedef struct tWAVEFORMATEX
{
    WORD    wFormatTag;        /* format type */// 波形声音格式,单声道双声道使用WAVE_FORMAT_PCM,
    WORD    nChannels;         /* number of channels (i.e. mono, stereo...) *///音频文件的通道数量,单声道为1,立体声为2. 
    DWORD   nSamplesPerSec;    /* sample rate *///样本采样率,对于 WAVE_FORMAT_PCM通常为8.0 kHz, 11.025 kHz, 22.05 kHz和44.1 kHz
    DWORD   nAvgBytesPerSec;   /* for buffer estimation */ 每秒的采样字节数
    WORD    nBlockAlign;       /* block size of data */ 每次采样的字节数
    WORD    wBitsPerSample;    /*采样率。有8.0kHZ,11.025kHZ,22.05kHZ*/
    WORD    cbSize;            /* The count in bytes of the size of// 额外信息的大小,以字节为单位,添加在WAVEFORMATEX的结尾。如果不需要额外的信息,此值必为0
                                    extra information (after cbSize) */

} WAVEFORMATEX;

典型设置示例:

WAVEFORMATEX _wfx;

  _wfx.nSamplesPerSec  = 44100;  /* sample rate */
  _wfx.wBitsPerSample  = 16;     /* sample size */
  _wfx.nChannels       = 2;      /* channels    */
  _wfx.cbSize          = 0;      /* size of _extra_ info */
 _wfx.wFormatTag      = WAVE_FORMAT_PCM;
 _wfx.nBlockAlign     = (_wfx.wBitsPerSample * _wfx.nChannels) >> 3;
 _wfx.nAvgBytesPerSec = _wfx.nBlockAlign * _wfx.nSamplesPerSec;

m_pWavPlay->Start(&_wfx);

 

实现方法一的头文件:

M_Critical_Section 是自用封装好的线程锁,可用afxmt.h中的CCriticalSection来代替

[html]  view plain  copy
  1. #ifndef _WAVEPLAY_4FR567H6_H_  
  2. #define _WAVEPLAY_4FR567H6_H_  
  3.   
  4. #include <mmsystem.h>  
  5. #include "mthread.h"  
  6.   
  7. //音频播放  
  8. class CViWavePlay  
  9. {  
  10. public:  
  11.     CViWavePlay();  
  12.     ~CViWavePlay();  
  13. public:  
  14.     BOOL Start(PWAVEFORMATEX pWaveformat);  
  15.     BOOL PlayAudio(char* buf,unsigned int nSize);  
  16.     void Stop();  
  17. public:  
  18.     UINT GetDeviceNum();  
  19.     WAVEOUTCAPS* GetDeviceCap();  
  20.   
  21. private:  
  22.     static DWORD WINAPI ThreadProc(LPVOID lpParameter);  
  23.     inline int GetBufferNum();  
  24.     inline void AddBuffer();  
  25.     inline void SubBuffer();  
  26.   
  27.     BOOL Open(PWAVEFORMATEX pWaveformat);  
  28.     void Close();  
  29.     BOOL StartThread();  
  30.     void StopThread();  
  31.   
  32. private:  
  33.     WAVEOUTCAPS m_waveCaps;  
  34.     BOOL        m_bDevOpen;  
  35.     BOOL        m_bThread;  
  36.     HWAVEOUT    m_hWave;  
  37.     HANDLE      m_hThread;  
  38.     DWORD       m_ThreadID;  
  39.   
  40.     WAVEFORMATEX m_Waveformat;  
  41.   
  42.     M_Critical_Section  m_Lock;  
  43.     int         m_BufferQueue;  
  44. };  
  45.   
  46.   
  47. #endif //_WAVEPLAY_4FR567H6_H_  

实现方法一的cpp文件:

[html]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "WavPlay.h"  
  3. #pragma comment(lib,"Winmm")  
  4.   
  5. CViWavePlay::CViWavePlay()  
  6. {  
  7.     ZeroMemory(&m_Waveformat,sizeof(WAVEFORMATEX));   
  8.     memset(&m_waveCaps,0,sizeof(m_waveCaps));  
  9.     m_bDevOpen = FALSE;  
  10.     m_bThread = FALSE;  
  11.     m_hWave = 0;  
  12.     m_hThread = 0;  
  13.     m_ThreadID = 0;  
  14.     m_BufferQueue = 0;  
  15.     m_Lock.init();  
  16. }  
  17.   
  18. CViWavePlay::~CViWavePlay()  
  19. {  
  20.     Stop();  
  21.     m_Lock.cleanup();  
  22. }  
  23.   
  24. UINT CViWavePlay::GetDeviceNum()  
  25. {  
  26.     return waveOutGetNumDevs();  
  27. }  
  28.   
  29. WAVEOUTCAPS* CViWavePlay::GetDeviceCap()  
  30. {  
  31.     MMRESULT mRet = waveOutGetDevCaps(WAVE_MAPPER,&m_waveCaps,sizeof(m_waveCaps));  
  32.     if( mRet == MMSYSERR_NOERROR )  
  33.         return &m_waveCaps;  
  34.     return NULL;  
  35. }  
  36. // 典型参数设置方法 longf120823  
  37. //  _wfx.nSamplesPerSec  = 44100;  /* sample rate */  
  38. //  _wfx.wBitsPerSample  = 16;     /* sample size */  
  39. //  _wfx.nChannels       = 2;      /* channels    */  
  40. //  _wfx.cbSize          = 0;      /* size of _extra_ info */  
  41. //  _wfx.wFormatTag      = WAVE_FORMAT_PCM;  
  42. //  _wfx.nBlockAlign     = (_wfx.wBitsPerSample * _wfx.nChannels) >> 3;  
  43. //  _wfx.nAvgBytesPerSec = _wfx.nBlockAlign * _wfx.nSamplesPerSec;  
  44. BOOL CViWavePlay::Open(PWAVEFORMATEX pWaveformat)  
  45. {  
  46.     if( m_bDevOpen )  
  47.     {  
  48.         return FALSE;  
  49.     }  
  50.     memcpy(&m_Waveformat,pWaveformat,sizeof(WAVEFORMATEX));  
  51.     m_Waveformat.nBlockAlign     = (m_Waveformat.wBitsPerSample * m_Waveformat.nChannels) >> 3;  
  52.     m_Waveformat.nAvgBytesPerSec = m_Waveformat.nBlockAlign * m_Waveformat.nSamplesPerSec;  
  53.   
  54.     MMRESULT mRet;  
  55.     WAVEFORMATEX wfx;  
  56.   
  57.     //lphWaveOut: PHWaveOut;   {用于返回设备句柄的指针; 如果 dwFlags=WAVE_FORMAT_QUERY, 这里应是 nil}  
  58.     //uDeviceID: UINT;         {设备ID; 可以指定为: WAVE_MAPPER, 这样函数会根据给定的波形格式选择合适的设备}  
  59.     //lpFormat: PWaveFormatEx; {TWaveFormat 结构的指针; TWaveFormat 包含要申请的波形格式}  
  60.     //dwCallback: DWORD        {回调函数地址或窗口句柄; 若不使用回调机制, 设为 nil}  
  61.     //dwInstance: DWORD        {给回调函数的实例数据; 不用于窗口}  
  62.     //dwFlags: DWORD           {打开选项}// long120823  
  63.     mRet = waveOutOpen(0,WAVE_MAPPER,&m_Waveformat,0,0,WAVE_FORMAT_QUERY);  
  64.     if( mRet != MMSYSERR_NOERROR )  
  65.     {  
  66.         return FALSE;  
  67.     }  
  68.   
  69.     mRet = waveOutOpen(&m_hWave,WAVE_MAPPER,&m_Waveformat,m_ThreadID,0,CALLBACK_THREAD);  
  70.     if( mRet != MMSYSERR_NOERROR )  
  71.     {  
  72.         return FALSE;  
  73.     }  
  74.   
  75.     m_bDevOpen = TRUE;  
  76.   
  77.     return TRUE;  
  78. }  
  79.   
  80. void CViWavePlay::Close()  
  81. {  
  82.     if (!m_bDevOpen)  
  83.     {  
  84.         return;  
  85.     }  
  86.   
  87.     if(!m_hWave)  
  88.     {  
  89.         return;  
  90.     }  
  91.   
  92.     MMRESULT mRet = waveOutClose(m_hWave);  
  93.     if( mRet != MMSYSERR_NOERROR )  
  94.     {  
  95.         return;  
  96.     }  
  97.     m_hWave = 0;  
  98.     m_bDevOpen = FALSE;  
  99. }  
  100.   
  101. DWORD WINAPI CViWavePlay::ThreadProc(LPVOID lpParameter)  
  102. {  
  103.     CViWavePlay *pWaveOut;  
  104.     pWaveOut = (CViWavePlay *)lpParameter;  
  105.   
  106.     MSG msg;  
  107.     while(GetMessage(&msg,0,0,0))  
  108.     {  
  109.         switch(msg.message )  
  110.         {  
  111.         case WOM_OPEN:  
  112.             break;  
  113.         case WOM_CLOSE:  
  114.             break;  
  115.         case WOM_DONE:  
  116.             WAVEHDR* pWaveHead = (WAVEHDR*)msg.lParam;  
  117.             waveOutUnprepareHeader((HWAVEOUT)msg.wParam,pWaveHead,sizeof(WAVEHDR));  
  118.             pWaveOut->SubBuffer();  
  119.             delete []pWaveHead->lpData;  
  120.             delete pWaveHead;  
  121.             break;  
  122.         }  
  123.     }  
  124.     return msg.wParam;  
  125. }  
  126.   
  127. BOOL CViWavePlay::StartThread()  
  128. {  
  129.     if( m_bThread )  
  130.     {  
  131.         return FALSE;  
  132.     }  
  133.   
  134.     m_hThread = CreateThread(0,0,ThreadProc,this,0,&m_ThreadID);  
  135.   
  136.     if( !m_hThread )  
  137.     {  
  138.         return FALSE;  
  139.     }  
  140.     m_bThread = TRUE;  
  141.   
  142.     return TRUE;  
  143. }  
  144.   
  145. void CViWavePlay::StopThread()  
  146. {  
  147.     if (!m_bThread)  
  148.     {  
  149.         return;  
  150.     }  
  151.   
  152.     if(m_hThread)  
  153.     {  
  154.         int t=50;  
  155.         DWORD ExitCode;  
  156.         BOOL bEnd=FALSE;  
  157.         PostThreadMessage(m_ThreadID,WM_QUIT,0,0);  
  158.         while(t)  
  159.         {  
  160.             GetExitCodeThread(m_hThread,&ExitCode);  
  161.             if(ExitCode!= STILL_ACTIVE)  
  162.             {  
  163.                 bEnd=TRUE;  
  164.                 break;  
  165.             }  
  166.             else  
  167.                 Sleep(10);  
  168.             t--;  
  169.         }  
  170.         if(!bEnd)  
  171.         {  
  172.             TerminateThread(m_hThread,0);  
  173.         }  
  174.         m_hThread = 0;  
  175.     }  
  176.     m_bThread = FALSE;  
  177. }  
  178.   
  179. BOOL CViWavePlay::Start(PWAVEFORMATEX pWaveformat)  
  180. {  
  181.     if (NULL==pWaveformat)  
  182.     {  
  183.         return FALSE;  
  184.     }  
  185.     if( !StartThread())  
  186.     {  
  187.         return FALSE;  
  188.     }  
  189.     if( !Open(pWaveformat))  
  190.     {  
  191.         StopThread();  
  192.         return FALSE;  
  193.     }  
  194.     return TRUE;  
  195. }  
  196.   
  197. BOOL CViWavePlay::PlayAudio(char* buf,unsigned int  nSize)  
  198. {  
  199.     if( !m_bDevOpen )  
  200.     {  
  201.         return FALSE;  
  202.     }  
  203.   
  204.     if( GetBufferNum() >= 5 )//超过缓冲最大包,不继续播放   
  205.     {  
  206.         return FALSE;  
  207.     }  
  208.     MMRESULT mRet;  
  209.     char*   lpData = NULL;  
  210.     WAVEHDR* pWaveHead = new WAVEHDR;  
  211.   
  212.     ZeroMemory(pWaveHead,sizeof(WAVEHDR));  
  213.   
  214.     lpData = new char[nSize];  
  215.   
  216.     pWaveHead->dwBufferLength = nSize;  
  217.     memcpy(lpData,buf,nSize);  
  218.     pWaveHead->lpData = lpData;  
  219.   
  220.     mRet = waveOutPrepareHeader(m_hWave,pWaveHead,sizeof(WAVEHDR));  
  221.     if( mRet != MMSYSERR_NOERROR )  
  222.     {  
  223.         return FALSE;  
  224.     }  
  225.   
  226.     mRet = waveOutWrite(m_hWave,pWaveHead,sizeof(WAVEHDR));  
  227.     if( mRet != MMSYSERR_NOERROR )  
  228.     {  
  229.         return FALSE;  
  230.     }  
  231.   
  232.     AddBuffer();  
  233.     return TRUE;  
  234. }  
  235.   
  236. void CViWavePlay::Stop()  
  237. {  
  238.     Close();  
  239.     StopThread();  
  240. }  
  241.   
  242.   
  243. int CViWavePlay::GetBufferNum()  
  244. {  
  245.     int nRet = 5;  
  246.     m_Lock.lock();  
  247.     nRet = m_BufferQueue;  
  248.     m_Lock.unlock();  
  249.     return nRet;  
  250. }  
  251.   
  252. void CViWavePlay::AddBuffer()  
  253. {  
  254.     m_Lock.lock();  
  255.     m_BufferQueue++;  
  256.     m_Lock.unlock();  
  257. }  
  258.   
  259. void CViWavePlay::SubBuffer()  
  260. {  
  261.     m_Lock.lock();  
  262.     m_BufferQueue--;  
  263.     m_Lock.unlock();  
  264. }  


方法二播放音频,但未经过严格测试

方法二头文件:

[html]  view plain  copy
  1. #if !defined(AFX_WAVPLAYER_ER56782036__INCLUDED_)  
  2. #define AFX_WAVPLAYER_ER56782036__INCLUDED_  
  3.   
  4.   
  5. class CViWavePlay  
  6. {  
  7. public:  
  8.     CViWavePlay();  
  9.     ~CViWavePlay();  
  10.     bool Start(PWAVEFORMATEX pWavHead);  
  11.     void PlayAudio(LPSTR data, int size);  
  12.     void WaveMsg(HWAVEOUT hwo, UINT uMsg, DWORD dwParam1, DWORD dwParam2);  
  13.   
  14. private:  
  15.     bool m_bPalyState;  
  16. private:  
  17.     CRITICAL_SECTION _waveCriticalSection;  
  18.     WAVEHDR*         _waveBlocks;     
  19.     int              _nWaveCurrentBlock;  
  20.     HWAVEOUT _hWaveOut;  
  21.     WAVEFORMATEX _wfx;    
  22.     volatile int     _nWaveFreeBlockCount;    
  23. protected:  
  24.     bool CloseDevice();  
  25.     WAVEHDR* allocateBlocks(int size, int count);  
  26.     void freeBlocks(WAVEHDR* blockArray);  
  27. };  
  28.   
  29. #endif //AFX_WAVPLAYER_ER56782036__INCLUDED_  

方法二cpp文件:

[html]  view plain  copy
  1. #include "stdafx.h"  
  2. #include "WavPlay_.h"  
  3. #include <mmsystem.h>  
  4.   
  5. #define BLOCK_SIZE  8192  
  6. #define BLOCK_COUNT 20  
  7.   
  8. #define BLOCK_MAX 8192  
  9.   
  10.   
  11. //回调函数  
  12. //如果选择窗口接受回调信息, 可能会发送到窗口的消息有:  
  13. //MM_WOM_OPEN  = $3BB;  
  14. // MM_WOM_CLOSE = $3BC;  
  15. // MM_WOM_DONE  = $3BD;  
  16.   
  17. // 如果选择函数接受回调信息, 可能会发送给函数的消息有:  
  18. // WOM_OPEN  = MM_WOM_OPEN;  
  19. // WOM_CLOSE = MM_WOM_CLOSE;  
  20. // WOM_DONE  = MM_WOM_DONE;  
  21.   
  22. void CALLBACK callback_waveOutProc( HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )   
  23. {   
  24.     /*  
  25.      * 忽略打开关闭设备操作  
  26.      */  
  27.     if(uMsg != WOM_DONE)  
  28.         return;  
  29.     CViWavePlay* pThis=(CViWavePlay*)dwInstance;  
  30.     if (NULL==pThis)  
  31.     {  
  32.         return;  
  33.     }  
  34.     pThis->WaveMsg(hwo,uMsg,dwParam1,dwParam2);  
  35.     return;  
  36. }   
  37.   
  38. CViWavePlay::CViWavePlay()  
  39. {  
  40.     m_bPalyState = false;   
  41.     ZeroMemory(&_wfx,sizeof(WAVEFORMATEX));   
  42.     _waveBlocks          = NULL;  
  43.     _nWaveFreeBlockCount = 0;  
  44.     _nWaveCurrentBlock   = 0;  
  45.   
  46.     InitializeCriticalSection(&_waveCriticalSection);  
  47.   
  48. }  
  49. //关闭线程,释放资源  
  50. CViWavePlay::~CViWavePlay()   
  51. {     
  52.     DeleteCriticalSection(&_waveCriticalSection);  
  53.     CloseDevice();  
  54.     m_bPalyState = false;   
  55. }   
  56.   
  57. bool CViWavePlay::CloseDevice()  
  58. {  
  59.     ZeroMemory(&_wfx,sizeof(WAVEFORMATEX));   
  60.      while(_nWaveFreeBlockCount < BLOCK_COUNT)  
  61.         Sleep(10);  
  62.   
  63.     /*  
  64.      * unprepare any blocks that are still prepared  
  65.      */  
  66.     for(int i = 0; i < _nWaveFreeBlockCount; i++)  
  67.     {  
  68.         if(_waveBlocks[i].dwFlags & WHDR_PREPARED)  
  69.         {  
  70.             waveOutUnprepareHeader(_hWaveOut, &_waveBlocks[i], sizeof(WAVEHDR));  
  71.         }  
  72.     }  
  73.     freeBlocks(_waveBlocks);  
  74.     waveOutClose(_hWaveOut);  
  75.     return true;  
  76. }  
  77.   
  78. bool CViWavePlay::Start(PWAVEFORMATEX pWavHead)   
  79. {   
  80.     if (m_bPalyState)   
  81.     {  
  82.         return false;  
  83.     }  
  84.     if (NULL==pWavHead)  
  85.     {  
  86.         return false;  
  87.     }  
  88.     //CloseDevice();  
  89.     _waveBlocks          = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT);  
  90.     _nWaveFreeBlockCount = BLOCK_COUNT;  
  91.     _nWaveCurrentBlock   = 0;  
  92. //  ZeroMemory(&_wfx,sizeof(WAVEFORMATEX));   
  93. //  _wfx.nSamplesPerSec  = 44100;  /* sample rate */  
  94. //  _wfx.wBitsPerSample  = 16;     /* sample size */  
  95. //  _wfx.nChannels       = 2;      /* channels    */  
  96. //  _wfx.cbSize          = 0;      /* size of _extra_ info */  
  97. //  _wfx.wFormatTag      = WAVE_FORMAT_PCM;  
  98. //  _wfx.nBlockAlign     = (_wfx.wBitsPerSample * _wfx.nChannels) >> 3;  
  99. //  _wfx.nAvgBytesPerSec = _wfx.nBlockAlign * _wfx.nSamplesPerSec;  
  100.     memcpy(&_wfx,pWavHead,sizeof(WAVEFORMATEX));  
  101.     _wfx.nBlockAlign     = (_wfx.wBitsPerSample * _wfx.nChannels) >> 3;  
  102.     _wfx.nAvgBytesPerSec = _wfx.nBlockAlign * _wfx.nSamplesPerSec;  
  103.   
  104.     if(::waveOutOpen (0,0,&_wfx,0,0,WAVE_FORMAT_QUERY)) //WAVE_FORMAT_QUERY = $0001;{只是判断设备是否支持给定的格式, 并不打开}  
  105.     {   
  106.         TRACE_ERR2("wave设备初始化失败~");   
  107.         return false;   
  108.     }   
  109.     //lphWaveOut: PHWaveOut;   {用于返回设备句柄的指针; 如果 dwFlags=WAVE_FORMAT_QUERY, 这里应是 nil}  
  110.     //uDeviceID: UINT;         {设备ID; 可以指定为: WAVE_MAPPER, 这样函数会根据给定的波形格式选择合适的设备}  
  111.     //lpFormat: PWaveFormatEx; {TWaveFormat 结构的指针; TWaveFormat 包含要申请的波形格式}  
  112.     //dwCallback: DWORD        {回调函数地址或窗口句柄; 若不使用回调机制, 设为 nil}  
  113.     //dwInstance: DWORD        {给回调函数的实例数据; 不用于窗口}  
  114.     //dwFlags: DWORD           {打开选项}  
  115.     if(waveOutOpen(&_hWaveOut, WAVE_MAPPER, &_wfx, (DWORD_PTR)callback_waveOutProc, (DWORD)this, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)   
  116.     {  
  117.          TRACE_ERR2("wave设备打开失败~");   
  118.          return false;  
  119.     }  
  120.     m_bPalyState    = true;  
  121.     _nWaveCurrentBlock   = 0;  
  122.     return true;  
  123. }   
  124.   
  125.   
  126. void CViWavePlay::WaveMsg(HWAVEOUT hwo, UINT uMsg, DWORD dwParam1, DWORD dwParam2)   
  127. {  
  128.     EnterCriticalSection(&_waveCriticalSection);  
  129.     _nWaveFreeBlockCount++;  
  130.     LeaveCriticalSection(&_waveCriticalSection);  
  131.     return;  
  132. }  
  133.   
  134. void CViWavePlay::PlayAudio(LPSTR data, int size)  
  135. {  
  136.     if (!m_bPalyState)   
  137.         return ;   
  138.   
  139.     WAVEHDR* current;  
  140.     int remain;  
  141.   
  142.     current = &_waveBlocks[_nWaveCurrentBlock];  
  143.       
  144.     while(size > 0) {  
  145.         /*   
  146.          * 首先确定使用的header 是 unprepared  
  147.          */  
  148.         if(current->dwFlags & WHDR_PREPARED)   
  149.             waveOutUnprepareHeader(_hWaveOut, current, sizeof(WAVEHDR));  
  150.   
  151.         if(size < (int)(BLOCK_SIZE - current->dwUser)) {  
  152.             memcpy(current->lpData + current->dwUser, data, size);  
  153.             current->dwUser += size;  
  154.             break;  
  155.         }  
  156.   
  157.         remain = BLOCK_SIZE - current->dwUser;  
  158.         memcpy(current->lpData + current->dwUser, data, remain);  
  159.         size -remain;  
  160.         data += remain;  
  161.         current->dwBufferLength = BLOCK_SIZE;  
  162.          
  163.         waveOutPrepareHeader(_hWaveOut, current, sizeof(WAVEHDR));  
  164.         waveOutWrite(_hWaveOut, current, sizeof(WAVEHDR));  
  165.           
  166.         EnterCriticalSection(&_waveCriticalSection);  
  167.         _nWaveFreeBlockCount--;  
  168.         LeaveCriticalSection(&_waveCriticalSection);  
  169.           
  170.         /*  
  171.          * 等待free一个block  
  172.          */  
  173.         while(!_nWaveFreeBlockCount)  
  174.             Sleep(10);  
  175.   
  176.         /*  
  177.          * 指向下一个block  
  178.          */  
  179.         _nWaveCurrentBlock++;  
  180.         _nWaveCurrentBlock %= BLOCK_COUNT;  
  181.   
  182.         current = &_waveBlocks[_nWaveCurrentBlock];  
  183.         current->dwUser = 0;  
  184.     }  
  185. }  
  186.   
  187.   
  188. WAVEHDR* CViWavePlay::allocateBlocks(int size, int count)  
  189. {  
  190.     unsigned char* buffer;  
  191.     WAVEHDR* blocks;  
  192.     DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count;  
  193.   
  194.     if((buffer = (unsigned char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalBufferSize)) == NULL)   
  195.     {  
  196.         fprintf(stderr, "Memory allocation error\n");  
  197.         ExitProcess(1);  
  198.     }  
  199.     blocks = (WAVEHDR*)buffer;  
  200.     buffer += sizeof(WAVEHDR) * count;  
  201.     for(int i = 0; i < count; i++) {  
  202.         blocks[i].dwBufferLength = size;  
  203.         blocks[i].lpData = (LPSTR)buffer;  
  204.         buffer += size;  
  205.     }  
  206.   
  207.     return blocks;  
  208. }  
  209.   
  210. void CViWavePlay::freeBlocks(WAVEHDR* blockArray)  
  211. {  
  212.     HeapFree(GetProcessHeap(), 0, blockArray);  
  213. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值