关于SPEEX延迟问题

From:http://www.hxdw.com/bbs/post/view?bid=83&id=144051&sty=3&age=0

这里说的语音延迟问题不是网络延迟,那个取决于网络状况,基本上是固定的,除非换个传输方法

这里说的语音延迟问题造成的原因是这样:

A发送说了十秒钟的话,网络延迟是3秒

那么正常情况B会在3秒后开始听到这句话,并在13秒的时候听完

但如果这时候在第8秒的时候,B的网络卡了1秒(这种情况出现很正常)

那么A说的后面5秒的内容,B会在9~14秒听到

那么这里问题就出来了,如果多卡几次,B听到的内容延迟就会越来越大,缓冲区里面的数据也会越来越多

但是后面收到的数据又必须等到之前收到的数据被播放完以后再播放

所以结果就是延迟会越来越长

那么解决这个问题有下面这些办法

1、因为我现在的这款软件本来就是采用中转式的传输,本来就延迟很慢,很难满足正常通话要求,干脆换成对讲机的形式,就不会有这种情况出现了,按住一个键说话,松开话就被发送出去了,这样本来就是异步的

JS:我还是觉得对讲机不太友好,争取努力解决延迟问题,实在不行的话作为最后的选择吧

2、丢弃掉那些延迟的包,就比如说刚才的问题,B在9秒同时收到了A在5秒和6秒说的内容,这时候直接把5秒的包丢了,播放6秒的内容,用这种方法来赶上对方的说话速度

JS:这种方法固然能解决延迟越来越长的问题,但问题是某些内容被丢弃了,用户体验会很差,老是莫名其妙少了一句话,会让人抓狂的

3、如果积累了很多过多的包,则不播放那些没声音的包。这个方法就是利用人说话的空隙时间,接收方收到了过多的包,则说明出现了网络延迟的问题,这时候去分析包,如果没有声音,就干脆不播放直接丢弃,去播放后面的包,以此来赶上说话放的速度。

上面的方法中我最终选择了第三种,因为首先不会影响用户体验,只丢弃那些没声音的包来空出时间,利用对方不说话那段时间把速度赶上来

谁会无止境的说上几个小时呢是吧

但也有弊端,就是背景太过嘈杂的话,就不好分辨了,无法得知对方对方是不是在说话,但这个问题暂时不考虑吧

最开始我是想去把包解码然后分析wave数据,求这个包的平均值,如果平均值低于某个零界则认为是无声包,丢弃

要做到这个功能其实还挺简单的,因为wave数据还是很好看懂的

不过后来找到了更好的办法,那就是speex本身提供的 静音检测VAD 这个选项来做

静音检测(VAD)将检测被编码的音频数据是语音还是静音或背景噪声。这个特性在用变比特率(VBR)进行编码是总是开启的,所以选项设置只对非变比特率(VBR)起作用。在这种情况下,Speex检测非语音周期并对用足够的比特数重新生成的背景噪声进行编码。这个叫“舒适噪声生成(CNG)”。

int dtx = 1;
speex_encoder_ctl(state, SPEEX_SET_VAD, &dtx);

我跟踪看了一下,不开启这个选项的时候,每个包都是固定大小,如果开启的话,有的包会是15字节,有的则只有2字节

所以我想当积累的过多的包时,直接丢弃掉只有2字节的包,当然现在还是在理论阶段,能不能成功还得试验

另外还有两个与此相关的功能 变比特率(VBR)和 非连续传输(DTX)

变比特率是比较重要的功能,默认情况下speex压缩后每个包大小都是固定的,如果采用了变比特率那么会根据每个段内实际的语音内容而压缩出不同长度的内容

非连续性传输(DTX)是静音检测(VAD)/变比特率(VBR)操作的额外选项,它能够在背景噪声固定时,完全的停止传输。如果是基于文件的操作,由于我们不能停止对文件的写入,会有5个比特被用到这种帧内(相对于250bps)。

如果这三个选项开启,能够极大的减少编码后的数据长度,我测试了一下,大概减少了一倍左右

不过可惜,因为wince上因为性能原因我把浮点运算禁用掉了,而变比特率完全是基于浮点运算的,因此也得禁用掉

不过只开启静音检测和非连续性传输的话也能一定量的减少传输量



pc上测试没有问题后我就去看wince平台上表现怎么样了

结果发现根本就完全没反应,加了VAD和DTX特性后和没加效果一样

后来想起来因为M8上的浮点运算能力有限,所以禁用掉了浮点运算,而VBR是基于浮点运算的,因此得一起禁用

而在到网上找了下资料发现VAD和DTX都是基于VBR的

这下难道又进死胡同啦,难道wince平台上就没法使用VAD特性?

我重新把speex说明书上面关于CPU性能优化那段拿了出来好好看了一下

The single that will affect the CPU usage of Speex the most is whether it is compiled for floating point or fixed-point. If your
CPU/DSP does not have a floating-point unit FPU, then compiling as fixed-point will be orders of magnitudes faster. If there
is an FPU present, then it is important to test which version is faster. On the x86 architecture, floating-point is generally
faster, but not always. To compile Speex as fixed-point, you need to pass –fixed-point to the configure script or define the
FIXED_POINT macro for the compiler. As of 1.2beta3, it is now possible to disable the floating-point compatibility API,
which means that your code can link without a float emulation library. To do that configure with –disable-float-api or define
the DISABLE_FLOAT_API macro. Until the VBR feature is ported to fixed-point, you will also need to configure with
–disable-vbr or define DISABLE_VBR.

这才想起来好像当时在编译speex1.2rc1版时确实看到一个宏定义叫fixed-point,当时也没在意

说不定以M8上这么强大的CPU运行定点数也完全够呢

于是把DISABLE_FLOAT_API和DISABLE_VBR特性删掉以后再次编译了一遍libspeex

然后再次运行wince上的程序,发现速度很快,几乎和禁用掉浮点运算速度差不多

而且因为有了VBR的特性,VAD和DTX都运行得很好

我拿了一个826k 19秒的一个wav文件做测试,因为为了测试静音检测功能,所以19秒中只稍微讲了几句话,其他都是没有声音

统一都采用了speex_uwb_mode的压缩方式

平台 speex版本 不开启任何特性 不开启任何特性 开启VAD和DTX 开启VAD和DTX 开启VAD和DTX和VBR 开启VAD和DTX和VBR
质量8 质量2 质量8 质量2 质量8 质量2
PC 1.0.5 50K 17K 32K 12K 24K 24K
WINCE 1.2rc1 40K 16K 19K 8K 16K 16k



这里测试结果可以看出,不管是高质量还是低质量,VAD和DTX这两个属性都可以减少压缩后的数据量

而VBR这个属性在高品种的时候可以减少数据量,但低品质的时候反而增加了数据量

而且在wince上加入了VBR以后运行速度明显要慢一两秒

最后再汗一个800K压缩到8K,压缩了100倍,而解压后仍然很清晰,技术的力量真强大啊     

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值