语音录制的关键是解决好声音的连续和延迟这两个问题,可以采用五个内存块循环使用,每个内存块录制声音的长度为100ms,在录音开始前,用 waveInPrepareHeader和waveInAddBuffer函数把所有的五个内存块都添加到录音设备以保存录音数据,这样就可以连续录制长 达500ms的语音数据,当每个内存块录满数据后,消息响应函数处理完相应的操作后,马上通过调用waveInAddBuffer函数把缓冲区重新添加到 录音设备,这样就保证了总存在可用的缓冲区保存录音数据,不会产生录音中断。事实也证明这样的处理方法在连续性和延迟性都有良好的表现。这里还有一个技巧 值得注意:因为是五个同样的缓冲区在循环使用,因此对每个缓冲区调用一次waveInPrepareHeader函数就可以了,实现缓冲区的重复使用只要 反复调用waveInAddBuffer函数把相应的缓冲区重新添加到录音设备就行了,直到录音结束才调用waveInUnprepareHeader函 数清空内存块。
像录音一样,放音也必须首先打开播放设备和指定录音格式,然后调用waveOutPrepareHeader函数为播放设备准备缓冲区,随后就可以用 waveOutWrite函数把需要播放的音频数据块发送到播放设备的缓存进行播放,直到放音结束才取消分配给放音设备的内存块,关闭放音设备。为了避免 频繁的调用waveOutPrepareHeader和waveOutUnprepareHeader这两个函数,像录音一样采用若干缓冲区成队列地进行 循环,这样在整个放音过程只分别调用这两个函数一次,节省了时间开销,对提高语音播放的连续性很有帮助的。当从网络中接收到压缩了的音频数据,解压后就拷 贝到当前WAVEHDR结构的lpData成员指向的内存块,调用waveOutWrite函数进行播放,在缓冲区队列循环中用一个int变量标记当前的 WAVEHDR结构用以控制队列的循环,但这样做有可能发生错误,就是当播放线程被阻塞时,有可能一个缓冲区的音频数据还没有播放完毕又对同一个缓冲区写 数据,这是不允许的。解决的办法是尽量增加缓冲区的数目,事实证明使用20个缓冲区(每个缓冲区存放100ms的音频数据)可以有效的防止这种错误的发 生,当然这样并不能完全地避免错误,此时就必须调用waveOutReset对放音设备重置,这就会丢失一些数据,但对于语音来说是可以容忍的。对于语音 通讯来说,延时不能太长,否则就会令人感到很别扭的,因为采用的缓冲区多就有可能会把延迟累积下来,使得延迟越来越长,这时可以每隔一分钟调用 waveOutReset对放音设备重置一次,可以再设一个int变量标记缓冲区队列的循环次数,当每达到30次(刚好一分钟)就重置一次,消除积累延迟 (会丢失一些数据)。
像录音一样,放音也必须首先打开播放设备和指定录音格式,然后调用waveOutPrepareHeader函数为播放设备准备缓冲区,随后就可以用 waveOutWrite函数把需要播放的音频数据块发送到播放设备的缓存进行播放,直到放音结束才取消分配给放音设备的内存块,关闭放音设备。为了避免 频繁的调用waveOutPrepareHeader和waveOutUnprepareHeader这两个函数,像录音一样采用若干缓冲区成队列地进行 循环,这样在整个放音过程只分别调用这两个函数一次,节省了时间开销,对提高语音播放的连续性很有帮助的。当从网络中接收到压缩了的音频数据,解压后就拷 贝到当前WAVEHDR结构的lpData成员指向的内存块,调用waveOutWrite函数进行播放,在缓冲区队列循环中用一个int变量标记当前的 WAVEHDR结构用以控制队列的循环,但这样做有可能发生错误,就是当播放线程被阻塞时,有可能一个缓冲区的音频数据还没有播放完毕又对同一个缓冲区写 数据,这是不允许的。解决的办法是尽量增加缓冲区的数目,事实证明使用20个缓冲区(每个缓冲区存放100ms的音频数据)可以有效的防止这种错误的发 生,当然这样并不能完全地避免错误,此时就必须调用waveOutReset对放音设备重置,这就会丢失一些数据,但对于语音来说是可以容忍的。对于语音 通讯来说,延时不能太长,否则就会令人感到很别扭的,因为采用的缓冲区多就有可能会把延迟累积下来,使得延迟越来越长,这时可以每隔一分钟调用 waveOutReset对放音设备重置一次,可以再设一个int变量标记缓冲区队列的循环次数,当每达到30次(刚好一分钟)就重置一次,消除积累延迟 (会丢失一些数据)。