首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > WinCE >

wince 下音频延迟有关问题该怎么解决

2012-03-24 
wince 下音频延迟问题该如何解决?1.我用wince提供的waveform audio API函数wavein和waveout系列函数实现语

wince 下音频延迟问题该如何解决?
1.我用wince提供的waveform audio API函数wavein和waveout系列函数实现语言的采集和播放。从网络上接收到的音频数据放入接收缓冲队列,然后准备播放缓冲区头部,进行音频的播放,一开始准备的播放缓冲区是两个缓冲区,采用回调函数的方式来处理播放缓冲区为空时的处理操作。但是测试结果发现播放出来的声音有大约一秒的延迟。反复修改程序,如修改缓冲区大小,改变播放的缓冲区个数等都不能明显改善延迟问题。通过分析代码发现,接收到的音频数据放入接收队列中,音频在播放的时候,音频队列中滞留了大约20包未播放的音频数据包。我的音频数据包大小为512字节,采样率8k,量化位数为8.这样20包数据造成的延迟是20/32s=0.625s。找到了造成音频延迟的原因,就是网络接收来的音频数据不能很快的及时的放入播放缓冲区,造成音频数据的滞留。而缓冲区播放完之后要响应wom-done消息,处理消息响应的过程要花费时间,这样就不能将滞留的数据包快速播放!

问题很长,不知道大家看懂没,请问该怎么解决呢?

2. 另外,我考虑过用单缓冲区来实现播放,即采集的数据直接放到播放缓冲区,不采用回调机制,查阅MSDN说明如下:
http://msdn.microsoft.com/en-us/library/ee487530.aspx
Use the WHDR_BEGINLOOP and WHDR_ENDLOOP flags in the dwFlags member to specify the beginning and ending data blocks for looping. To loop on a single block, specify both flags for the same block. Use the dwLoops member in the WAVEHDR structure for the first block in the loop to specify the number of times to play the loop.

The lpData, dwBufferLength, and dwFlags members must be set before calling the waveInPrepareHeader or waveOutPrepareHeader function. For either function, the dwFlags member must be set to zero.
请问若采用单缓冲区,不采用回调机制,该怎么实现呢?



[解决办法]
1,缓冲设的很小,所以响应wom-done消息是很快的,应该不会造成这个问题。我觉得可能哪里没处理好,回调函数里发现网络传过来的音频数据还没过来,你是怎么处理的;另外开始接收数据时,播放音频部分准备好了吗?
2,不必
[解决办法]
不懂,纯帮顶。
[解决办法]
你理解错了我的意思,我说的是因为缓冲小(512B),所以响应wom-done消息是很快的,我没说你缓冲设的不适当。
WaitForSingleObject(m_hEvent,INFINITE);
这个干吗用?已经拦截到WOM_DONE了,还等待什么?

探讨

引用:
1,缓冲设的很小,所以响应wom-done消息是很快的,应该不会造成这个问题。我觉得可能哪里没处理好,回调函数里发现网络传过来的音频数据还没过来,你是怎么处理的;另外开始接收数据时,播放音频部分准备好了吗?
2,不必


你说是缓冲区太小,但是我试过不同的缓冲区对它的影响,最后发现512B时有0.8s的延时,这是最好的情况,所以应该不是缓冲区……

[解决办法]
探讨
引用:
你理解错了我的意思,我说的是因为缓冲小(512B),所以响应wom-done消息是很快的,我没说你缓冲设的不适当。
WaitForSingleObject(m_hEvent,INFINITE);
这个干吗用?已经拦截到WOM_DONE了,还等待什么?

引用:

引用:
……

[解决办法]
另外 楼主这样在waveOutProc里面再调用WaitForSingleObject不会死锁么?
void CALLBACK waveOutProc(
HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2
);

Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.


[解决办法]
刚才仔细看了看你的代码 不知道你的音频数据在接收之前有没有压缩解压的过程 如果没有 是直接原始PCM数据发送的 那其实数据量蛮大的 而本来网络传输就会造成延时 而你在接收的时候的处理是有至少两个连续的数据时才waveOutWrite开始播放 这又使这个延时增大了一倍 而且setevent和waitfor也是不必要的(不会造成死锁??)
其实完全没有必要 你只需要收到一报数据就马上waveOutWrite就行了 至于具体的缓冲处理 你再改下就行了
[解决办法]
楼主要是不嫌弃 留下邮箱 我发个自己做的东东给你参考下吧
[解决办法]
探讨
引用:
刚才仔细看了看你的代码 不知道你的音频数据在接收之前有没有压缩解压的过程 如果没有 是直接原始PCM数据发送的 那其实数据量蛮大的 而本来网络传输就会造成延时 而你在接收的时候的处理是有至少两个连续的数据时才waveOutWrite开始播放 这又使这个延时增大了一倍 而且setevent和waitfor也是不必要的(不会造成死锁??)
其实完全没有……

[解决办法]
探讨
引用:
引用:
引用:


引用:
刚才仔细看了看你的代码 不知道你的音频数据在接收之前有没有压缩解压的过程 如果没有 是直接原始PCM数据发送的 那其实数据量蛮大的 而本来网络传输就会造成延时 而你在接收的时候的处理是有至少两个连续的数据时才wa……


[解决办法]
PCM数据要压缩,不压缩,很容易出现丢包等问题。
比如100Mbps的局域网,实际传输速率远低于这个值。你发10秒PCM音频数据,可能还没10S压缩数据+快速解码来的快。
缓冲音频要用ring buffer,调整ring buffer阈值和策略可以控制一定延时。
音频驱动里面也有类似的buffer,大部分情况通过注册表可以调,也会有一定的效果。如果使用dshows audio capture filter,有公共接口调这个值。
最后一般的solution,音频延时只能减少,无法消除,声音的延时和质量,控制到一定的范围即可。
[解决办法]
补充一点:发多媒体数据用UDP或者RTP,少用TCP。

热点排行