waveout**实现音频播放
来源:互联网 发布:易高网络招聘平台 编辑:程序博客网 时间:2024/05/22 14:55
最近想做一个播放,折腾了1周也没什么效果,最近在互联网上发现篇关于Waveout系
列API实现音频播放器,收获还算不少。
一、初始化设备
bool WinAudioPlay::DevOpen()
{
if (!m_bPalyStata)
{
WAVEFORMATEX wfx;
ZeroMemory(&wfx,sizeof(WAVEFORMATEX));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = 44100L;
wfx.wBitsPerSample = 16;
wfx.cbSize = 0;
wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
wfx.nAvgBytesPerSec = wfx.nChannels * wfx.nSamplesPerSec * wfx.wBitsPerSample / 8;
if(::waveOutOpen (0,0,&wfx,0,0,WAVE_FORMAT_QUERY))
{
Plug::PlugMessageBox(L"wave设备初始化失败~");
return false;
}
if (::waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &wfx, (DWORD)&WinAudioPlay::waveOutProc, (DWORD)this, CALLBACK_FUNCTION))
{
Plug::PlugMessageBox(L"wave设备初始化失败~");
return false;
}
m_iBlockNum = 0;
m_bPalyStata = true;
m_spbrTgthr.reset(new boost::barrier(2));
m_sptrdWaveOutTgthr.reset(new boost::thread(boost::bind(&WinAudioPlay::ThrdWaveOutTogether,this)));
}
return true;
}
二、接收pcm格式数据,并加载到声卡缓冲区
bool __stdcall WinAudioPlay::play_audio( const void* buffer, int len )
{
if (!m_bPalyStata)
return false;
if (BLOCK_MAX <= m_iBlockNum || len <= 0)
{
return true; //超过缓冲最大包,不继续播放
}
LPWAVEHDR pWaveHeader = new WAVEHDR;
memset(pWaveHeader, 0, sizeof(WAVEHDR));
pWaveHeader->dwLoops = 1;
pWaveHeader->dwBufferLength = len;
pWaveHeader->lpData = new char[len];
if (!pWaveHeader->lpData)
{
delete pWaveHeader;
return false;
}
memcpy(pWaveHeader->lpData, buffer, len);
if (::waveOutPrepareHeader(m_hWaveOut, pWaveHeader, sizeof(WAVEHDR)))
{
delete pWaveHeader->lpData;
delete pWaveHeader;
return false;
}
if (::waveOutWrite(m_hWaveOut, pWaveHeader, sizeof(WAVEHDR)))
{
delete pWaveHeader->lpData;
delete pWaveHeader;
return false;
}
m_iBlockNum++;
return true;
}
三、回调函数
void CALLBACK WinAudioPlay::waveOutProc( HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
WinAudioPlay* pThis=(WinAudioPlay*)dwInstance;
if(WOM_DONE == uMsg) //播放完成
{
while(NULL != pThis->m_lpWaveHdrFromCallbackProc)
{
boost::this_thread::interruptible_wait(1);
}
pThis->m_lpWaveHdrFromCallbackProc = (LPWAVEHDR)dwParam1;
pThis->m_spbrTgthr->wait();
}
return ;
}
四、线程同步播放
void WinAudioPlay::ThrdWaveOutTogether()
{
while(!m_b_exit)
{
m_spbrTgthr->wait();
if (NULL != m_lpWaveHdrFromCallbackProc)
{
::waveOutUnprepareHeader(m_hWaveOut, m_lpWaveHdrFromCallbackProc, sizeof(WAVEHDR));
delete[] m_lpWaveHdrFromCallbackProc->lpData;
delete m_lpWaveHdrFromCallbackProc;
m_lpWaveHdrFromCallbackProc = NULL;
(m_iBlockNum > 0)?(m_iBlockNum--):(m_iBlockNum = 0);
}
}
if (m_hWaveOut != NULL)
{
::waveOutReset(m_hWaveOut);
::waveOutClose(m_hWaveOut);
}
}
五、关闭线程,释放资源
WinAudioPlay::~WinAudioPlay()
{
m_bPalyStata = false;
while(0 != m_iBlockNum)
{
Sleep(1);
}
m_b_exit = true;
m_spbrTgthr->wait();
m_sptrdWaveOutTgthr->join();
}
但是需要注意以下几点:
一、waveOutProc回调函数中绝对不能调用waveOut系列函数(可用线程同步实现通知在另一个线程调用)
二、调用waveOutReset函数时,函数执行完毕才返回,期间不可以调用hWaveOut
0 0
- waveout**实现音频播放
- WaveOut播放音频
- win32 音频播放|WaveOut|缓冲区
- 音频播放处理(openal、dsound、waveout)
- c# 利用WaveOut播放音频流
- WaveOut播放音乐
- waveout 播放声音
- waveout 播放流媒体
- 多线程应用---使用WaveOut* API开发AMR音频播放器(含源码下载)
- 多线程应用---使用WaveOut* API开发AMR音频播放器(含源码下载)
- HTML5实现音频播放
- Android实现播放音频
- waveout播放pcm文件总结
- 用Java实现音频播放
- 用Java实现音频播放
- iOS 实现播放本地音频
- 嵌入式音频播放的实现
- iOS音频播放 (六):简单的音频播放器实现
- 软件技术积累
- 文件路径获取目录API
- 《linux 内核完全剖析》chapter 13 内存管理 (不含swap.c)
- NMEA[GPS] 数据格式
- GPS 坐标转换
- waveout**实现音频播放
- 对的时间遇到了对的人
- 驱动层IAT HOOK
- VMWare 网络连接模式(bridged、NAT、host-only)详解
- windbg 调试
- GDT 描述
- WDK/DDK中掉 error C2220: warning treated as error - no ‘object’ file generated
- windows 研究 资料
- BZOJ 3527: [Zjoi2014]力