winCE下使用一组buffer实现音频回环
来源:互联网 发布:红色经典知多少手抄报 编辑:程序博客网 时间:2024/06/11 04:24
最近有做项目,在WinCE下从一个音频设备获取数据,通过另一个音频设备输出。要求是尽量小的延迟,声音不要有停顿,也不能有丢失,在高的采样率的情况下,尽量少的占用cpu。东西很简单,但要做好也挺麻烦,特别是有了上面的要求。
先简单介绍一下思路:
使用wavein系列API,从一个音频驱动中读数据,然后使用waveout系列的API,把读到的数据写到另外一个音频驱动中。
如何实现比较好的性能。
1、Buffer尽量小,以减小延迟。为了保持声音连续和稳定,可以多开几个buffer。
2、尽量不要搬动数据,当采样率高了以后,数据量其实是挺大的,做一次复制操作就会消耗一定的CPU。经过N次的实验,终于成功让两个驱动使用了一组buffer,避免了数据的复制。
3、读和写一定要使用两个线程,中间使用消息等方式沟通。避免声音的停顿和丢失。
几个重要的变量和空间:
初始化: 先分配buffer空间,打开输入输出设备。Prepare好head。顺序如下。需注意的是写数据时,需要使用线程回调,这样就可以和读数据线程互不影响。
WIM_DATA消息的处理:
这里先讲一下读与写怎么同步。有两个变量,dwValidBlocks,dwValidBlockStart。初始都为0。这两个变量表示了从dwValidBlockStart开始的dwValidBlocks块数据,是新的,有效地。
dwValidBlocks有两个线程同时维护,当读线程读一个block了以后,dwValidBlocks++,写线程写完一个block后dwValidBlocks――。
dwValidBlockStart平时由读线程维护,每读掉一个数据dwValidBlockStart++。但是如果写线程没有及时写掉数据,造成所有block都满了,则由读线程更新掉最远一次的数据,即dwValidBlockStart++。
这里需要注意的是WIM_DATA的响应中,没有必要使用waveInUnprepare,waveInPrepare。因为没有什么参数发生改变,直接扔回去就可以了。
写线程回调处理:
写线程做的事情就是不停的把buffer里面的数据写到输出的音频驱动中。这里需要提的是,写线程不是一有数据就开始写,而是等到有WAV_OUT_BUFFER_COUNT个block后,再开始写。一下子把这几个buffer一起扔下去,这样做的好处是保证一直有buffer在被驱动处理,而不会出现由于数据来不及扔下去造成声音停顿或当中有pop音出现。其实WAV_OUT_BUFFER_COUNT只要=2,应该就可以了。
对于MM_WOM_DONE的处理,需要waveOutUnprepareHeader,修改完那个pWaveOutHdr的结构以后,再扔回去即可。
小结
在写这个程序的过程中,花时间最多的有两个问题。一个是如何直接利用一组buffer,在应用层不搬动任何数据,实现音频回环。使用wav API的时候,很容易造成deadlock。另外一个,就是如何使声音不间断的播放。没有使用线程,经常会卡。写数据时缓存没有连续给到驱动,也会小卡,最后看了很多人的blog后,终于解决了问题。其实无需两个设备,只要一个codec,配置好wavein和waveout的设备ID,就可以用speaker听到mic的呻吟了。
程序小改一下就可以变译运行,但是还有问题,其实线程那部分还很挫,退不出来,而且还有很多其他小问题。没时间修改这个demo,也不能把现在用得代码贴出来,请谅解。
最后感谢不下雨(Norains)大虾,代码是在他的CSoundBase实现录音与播放上修改过来的。希望不要介意。
参考:
http://blog.csdn.net/norains/archive/2007/01/10/1479648.aspx CSoundBase实现录音与播放
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=4422&lngWId=3 Playing Audio in Windows using waveOut Interface
- winCE下使用一组buffer实现音频回环
- 实现一组buffer以便使用
- WinCE下音频频谱显示效果图
- windows下使用wineshark分析抓取本地回环包
- wince下使用activesync
- wince下应用程序使用外部字体实现多国语言
- windows下使用protocol buffer
- wince下用DirectShow播放音频和视频
- wince下用directx播放音频和视频
- wince下用directx播放音频和视频
- wince下用DirectShow播放音频和视频
- wince下用DirectShow播放音频和视频
- wince下用DirectShow播放音频和视频
- wince下音频驱动架构及数据输出流程
- WinCE下看门狗的实现.
- wince 下Transparent的实现
- 在WINCE下实现拨号上网
- 在WINCE下实现拨号上网
- DataTable 修改数据
- 发布一个 JavaScript 右击菜单 支持 ie678,Firefox,Safari
- JavaScript 获取客户端计算机硬件及系统信息
- Flex Builder3 plugin
- HOOK 钩子拦截WM_DEVICECHANGE消息
- winCE下使用一组buffer实现音频回环
- 禁止网页复制和右键菜单(支持IE FF)
- GCF CommConnection Connector实现代码分析
- SQL SERVER 2005 安装错误解决了~
- 适配器
- 确保PHP应用程序的安全
- November 15th Sunday
- 软件包 java.io 的分层结构(http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/io/package-tree.html)
- LINUX路由和QOS限速(转)