分享:双缓存
来源:互联网 发布:物流园区软件 编辑:程序博客网 时间:2024/05/12 15:41
Windows Mobile下播放PCM音频的双缓冲用法
最近用libmad做了些mp3解码的工作,顺便也研究了一下windows下播放PCM音频数据的双缓冲用法。
libmad的调用在此暂略过不表。
libmad解码出来的是16bit的PCM数据,调用windows API可对其实现播放。不过如果解码一段播放一段,听起来会有一顿一顿的感觉,不流畅,究其原因,是没有使用双缓冲。
吭哧吭哧研究了半天,终于编码实现,播放出来的效果倒也很流畅。
流程如下:
1)声明两个WAVEHDR结构waveHeader1,waveHeader2,并分别对其lpData参数分配缓冲buf1,buf2;
2)声明WAVEFORMATEX结构waveFormat,以及HWAVEOUT结构hWaveOut。调用函数
waveOutOpen( &hWaveOut, WAVE_MAPPER, &waveFormat, (DWORD)waveOutProc, NULL, CALLBACK_FUNCTION );
waveOutProc为回调函数,在后面会提到。
也说一下waveFormat的各参数。根据MSDN解释,nChannels为通道数,nSamplesPerSec为采样率,wFormatTag的值为WAVE_FORMAT_PCM,wBitsPerSample为16,nBlockAlign为nChannels*wBitsPerSample/8,nAvgBytesPerSec为nSamplesPerSec*nBlockAlign;
3)读入buf1,buf2,并设置好相应长度;
4)将waveHeader1,waveHeader2写入wave设备:
waveOutPrepareHeader( hWaveOut, &waveHeader1, sizeof(WAVEHDR));
waveOutPrepareHeader( hWaveOut, &waveHeader2, sizeof(WAVEHDR));
waveOutWrite( hWaveOut, &waveHeader1, sizeof(WAVEHDR) );
waveOutWrite( hWaveOut, &waveHeader2, sizeof(WAVEHDR) );
5)关于回调
void CALLBACK waveOutProc( HWAVEOUT hwo,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2 )
{
if(uMsg == WOM_DONE)
{
LPWAVEHDR pWaveHeader = (LPWAVEHDR)dwParam1;//系统自动识别是哪一个WAVEHDR播放完毕
waveOutUnprepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR) );//播放完后须调用此函数
//此处填充WAVEHDR的lpdate缓冲
waveOutPrepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR));
waveOutWrite( hwo, pWaveHeader, sizeof(WAVEHDR) );
//...
}
return ;
}
6)播放完毕后,调用waveOutClose,释放缓冲。其他的一些waveOut函数,如waveOutPause、waveOutReset等等,在做播放器的时候会用得到。若播放过程中终止,须先调用waveOutReset,再调用waveOutClose。
libmad的调用在此暂略过不表。
libmad解码出来的是16bit的PCM数据,调用windows API可对其实现播放。不过如果解码一段播放一段,听起来会有一顿一顿的感觉,不流畅,究其原因,是没有使用双缓冲。
吭哧吭哧研究了半天,终于编码实现,播放出来的效果倒也很流畅。
流程如下:
1)声明两个WAVEHDR结构waveHeader1,waveHeader2,并分别对其lpData参数分配缓冲buf1,buf2;
2)声明WAVEFORMATEX结构waveFormat,以及HWAVEOUT结构hWaveOut。调用函数
waveOutOpen( &hWaveOut, WAVE_MAPPER, &waveFormat, (DWORD)waveOutProc, NULL, CALLBACK_FUNCTION );
waveOutProc为回调函数,在后面会提到。
也说一下waveFormat的各参数。根据MSDN解释,nChannels为通道数,nSamplesPerSec为采样率,wFormatTag的值为WAVE_FORMAT_PCM,wBitsPerSample为16,nBlockAlign为nChannels*wBitsPerSample/8,nAvgBytesPerSec为nSamplesPerSec*nBlockAlign;
3)读入buf1,buf2,并设置好相应长度;
4)将waveHeader1,waveHeader2写入wave设备:
waveOutPrepareHeader( hWaveOut, &waveHeader1, sizeof(WAVEHDR));
waveOutPrepareHeader( hWaveOut, &waveHeader2, sizeof(WAVEHDR));
waveOutWrite( hWaveOut, &waveHeader1, sizeof(WAVEHDR) );
waveOutWrite( hWaveOut, &waveHeader2, sizeof(WAVEHDR) );
5)关于回调
void CALLBACK waveOutProc( HWAVEOUT hwo,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2 )
{
if(uMsg == WOM_DONE)
{
LPWAVEHDR pWaveHeader = (LPWAVEHDR)dwParam1;//系统自动识别是哪一个WAVEHDR播放完毕
waveOutUnprepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR) );//播放完后须调用此函数
//此处填充WAVEHDR的lpdate缓冲
waveOutPrepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR));
waveOutWrite( hwo, pWaveHeader, sizeof(WAVEHDR) );
//...
}
return ;
}
6)播放完毕后,调用waveOutClose,释放缓冲。其他的一些waveOut函数,如waveOutPause、waveOutReset等等,在做播放器的时候会用得到。若播放过程中终止,须先调用waveOutReset,再调用waveOutClose。
- 分享:双缓存
- LocalCache本地缓存分享
- 分布式缓存系统Memcached[分享]
- 分享Fresco缓存中的图片
- PHP缓存技术的使用技巧分享
- 详细分享IBatis.net缓存的使用方法
- 分享通用基类库-C#通用缓存类
- 分享:Android清除本地数据缓存代码
- 分享:Android清除本地数据缓存代码
- 关于Alamofire缓存机制的分享
- 缓存redis使用经验博客分享
- 互联网应用的缓存实践分享
- 双缓存
- 双缓存
- 双缓存
- 双缓存
- 双缓存
- 双缓存
- C# WebRequest WebClient Post请求
- 方正(SOA中间件)快速开发平台ES2007的安装问题(一)
- 虚拟机ubuntu10.10与xp共享文件夹(samba服务模式)
- 设计模式的形象比喻
- Google搜索技巧
- 分享:双缓存
- 换个角度看敏捷3 - 我心中的敏捷
- jQuery UI 中的sortable("toArray")
- 开博了
- TCPL(The C Programming Language)读书笔记 第二章 类型、运算符与表达式
- 从Twitter应用布局看国内微博应用发展趋势
- 时间复杂度与空间复杂度
- 查找文本并高亮
- js:Array笔记