最近的工作需要,对Windows的录音方式做了一个大概的了解,下面总结一下。
1.ASIO
时延可控,但驱动有些困难,专用性强。
2.API
使用稍复杂,功能不错。无需DirectX支持。Adobe Audition 2.0之后都对ASIO有很好的支持。
3.Direct Sound或Direct Show
需要Direct X支持,可能实时性较API差一些(未实验证实)。
设计需求:使用特定声卡设备录音之后立即放音,放音结束后停止录音。
放音实现思路:
1.PlaySound可以向默认设备播放WAV文件,但好像仅限于默认设备,测试延时34ms。
2.Waveout系列函数和Wavein系列函数播放WAV文件,可控性强,可选择设备,但过程较为复杂。
设计中选择思路2完成,使用C#。
遇到的问题:
1.播放未结束,录音提前终止。
解决:在回调函数(将wav文件数据填入缓冲区的函数)判断Wav文件是否已经读到文件结束,如果是,仍播放与缓冲区大小一致的空白声音(不一定是0)再停止录音。
2.使用PlaySound放音时提前结束。
解决:放音中属性设为同步,可以让程序等待放音结束后再继续执行。
但这样可能导致程序“假死”,即界面上所有控件不可用,像死掉一样。要解决这个问题,可以再建立一个录放音进程。
3.播放或录音出现卡壳
解决:可能采用了不合适的采样率,或者缓存过小、过大。目前使用了16384Byte X 4组的缓存。
另外还有一种特殊情况,就是声卡的回放混有Line in输入,即选中了监听。这种情况下,输出的信号会和前一些时刻声卡录到的声音叠加在一起,音量时大时小(可以在电平监视器中直观看到)。
经验:
1.使用waveInGetDevCaps、waveOutGetDevCaps等API可以获得声卡的产品名、产品编号、制造商编号和设备性能。(不保证所有声卡的信息都是完整正确的。)
2.waveOutGetID等用途不大,知道句柄了当然了解这个句柄属于哪个设备的,特殊情况除外。
3.waveInGetNumDevs、waveOutGetNumDevs可以返回设备数,声卡的输入设备和输出设备个数未必相等。
4.回调函数可以做硬盘和缓存的数据交换。放音的回调函数可以确定文件播放结束;小改一下,也可以循环播放;恶搞一下还能够做语音实时处理。
5.播放结束的处理是比较考究的,如果简单的将一个bool型置为true作为结束信号,在release时,主程序判断bool值那一句很可能被编译器和谐掉。所以可以参考线程的编程。
---------------------
参考资料:
1.百度百科 http://baike.baidu.com/view/663607.htm2.MSDN
2.MSDN http://msdn2.microsoft.com/en-us/library/ms712879(VS.85).aspx
3.CodeProject上有许多有参考价值的代码,虽然有些还不够完善,但是值得欣赏。 http://www.codeproject.com/KB/audio-video/cswavrec.aspx?df=100&forumid=16677&exp=0&select=1107344
4. Google Code上的例子: http://code.google.com/p/flurrysharp/source/diff?r=11&format=side&path=/trunk/win32/Multimedia.cs
5. 关于线程的文章:Threading in C# 中文版和英文版都有,参见 http://www.albahari.com/threading/
|
请发表评论