zoukankan      html  css  js  c++  java
  • Speex manul中文版

    在VOIP的音频算法中,回音处理已经成为一个关系通话质量的主要问题。

    回声的产生在IP网络主要有两种:
    1.声学回声
    2.电路回声

    声学回声主要又分成以下几种:
    a ) 直接回声:由扬声器产生的声音未经任何反射直接进入麦克风
    b ) 间接回声: 由扬声器发出的声音经过多次反射后,再进入Mic
    对于第二种回声,拥有多路径,时变性的特点.是比较难处理的.

    由于IP网络下的传输的延迟较大,而一般情况下,对于人耳,如果声音延迟达到了10ms以上的话,那么回声就会越来越明显.
    一般来讲,VOIP中的声音延迟主要来自于几个方面:
    1. 编码延迟: 一般情况下编码算法在声音压缩时都会产生延迟,就我们采用的Speex来讲,延迟大概在20ms左右
    2. 处理延迟, 封装时延, 缓冲时延等
    3. 在IP网络中数据的传输过程也会照成延时.这由当前的网络状况决定.

    回声消除的模型:
    a) 建立远端声音模型,进行回声估计, 从采集的值中减去估计值
    b) 声学模型

    Speex manul(手册)中文版

    Speex是一套专门用于压缩声音的库,由于其专门针对声音,所以压缩声音的性能非常高.Speex由于其压缩性能,0.80版后的跨平台的性能,所以在网络声音的传输中有很大的价值.但是需要注意的是speex只能对声音进行压缩,不支持音乐的压缩,如果你需要音乐的压缩你或许需要用vorbis.

           但是的speex资料像其它大都数专用库一样,并没有大多的中文资料.所以在这里我决定将里面最核心的编程技术翻译出来.一来是练习练习自己翻译资料的能力,二来是方便一些英语水平较差的朋友.由于本人能力有限,有些感觉有出入或难理解的地方可以去speex的官方网站www.speex.org找到英文原版的说明.

    翻译的一些说明:

    1,对于一些专有名词如speex,api不过行翻译

    2,对于一些新概念翻译,以及其它的翻译过来也许会产生歧义的文字,用中/英两种方式标出:

           :对话(speech),位采集(bit_packing)

    3,基本做到和英文原行对译.及英文原文一行,中文翻译过来也是一行,使翻译后的文章和原文基本行行对照.

    4,源代码不翻译,SpeexBits bits;

    5,语言中的关健字不译,float

    6,一此不是关健字但英文通常出现的词第一次以中/英文格式给出,之后按具体情况给出英文或中文,:frame(),

    7,对一些有自己翻译起来感觉有歧义的地方,加斜线作标记 

    1,speex的介绍(略)

    2特征描述

    这个章节展示了speex的主要特征,以衣一些关于对话(speech)编码的一个概念,以便

    帮助我们更好的了解下一章节.

    取样率(Sampling rate)

    Speex主要是设计了三种不同的取样率:8kHz,16kHz,32kHz.这些分别代表了窄宽(narrowband),

    多频率,超声.

    质量

    Speex编码大都数时间是被一个范围为010的质量参数来控制  .在一个比特率为常量(CBR)的操作中,质量参数是一个整数,而对于变动的比特率(VBR)参数是一个float;

    复杂性(变量)

    speex,你可以将编码设置成允许的复杂度.这由一个范围为110的整数来控制完成,就像你用选项-1-9来控制gzipbzip2的压缩质量.在通常的运用中,噪声级别的复杂度1是在12dB之间,比复杂度10要高,但是CPU需要复杂度10大概5倍高行复杂度1.在实践中,最好的是设置在24之间,尽管更高的设定通常有用,当编码一个非对话声音(non-speech sounds)DTMF语调(tones).

    变波特率(VBR

    Variable bit-rate (VBR) allows a codec to change its bit-rate dynamically to adapt to

    变波特率(VBR)允许编码动态地改变它的波特率以适应声音编码的难度”.speex举例来说,

    像元音(vowel)和瞬间高音(high-enenrg transients)需要个高的比特率来

    取得一个不错的质量,

    而摩擦音(fricative)可以被充分地用相对较少的字节来进行编码.

    由于上面这个原因,VBR可以调节到一个低的比特率却达到一个同样的质量,或者用

    某个比特率达到更好的质量.尽管有上面这些优点,但是VBR也有两个主要的缺点.

    首先,仅仅靠指定质量值,这里没有一个关于最后平均比特率的保证.(译者注:作者大概是想说没有什么明确的方法知道质量值)此外,对一些即时

    通信,IP电话(VoIP)这种包含着最大的比特率的,必须把比特率设为足够低以适应

    传输通道.

    r

    平均比特率(ABR)

    平均比特率通过动态地调节VBR质量去得到一个确定的目标的比特率,从而解决了VBR中的一个问题..因为质量/比特率被即时的调整了,整体质量将会稍稍低于由VBR对一个

    设置得和目标平均比特率非常接近的质量数编码得到的结果.

     

    声音生动性检测(VAD)

    声音生动性检测将会发觉音频正在被编码成对话,静音,或背景噪音.VAD总在用VBR进行编码时暗中起作用,因此选项仅仅对一个不是VBR的操作起作用.对于不是VBR的操作来说,speex察觉出一个不属于对话的周期,然后对它用足够的字节重新生成为背景噪音.不这叫做舒适的噪音生成(CNG).

    不连续传输(DTX)

    不连续传输是VAD/VBR操作的一个额外选项,当背景噪音一定时,它可以完整地传输.因为在基于文件的操作中,我们不能停止对文件进行写入,所以只有5字节被这种帧所运用.(250bps通信)

    Perceptual enhancement

    知觉增强

    知觉增加是解码的一部分,它在打开的时候用来减少由编码解码所产生的噪音.在大都数

    情况下,知觉增强在客观上使声音离原始值更远(如果用SNR),但是在最后它仍然听起来更好(主观上的改进)

    Algorithmic delay

    迟时算法

    每一个声音编码导致了在传输上的延时.对于speex,这种延时等于frame的大小加上一些

    数量的需要对每一帧进行的前瞻(”look-adhead”).

    在窄宽操作中(8kHz),迟时是30ms,而对于多频率(2-44Hz),迟时是34ms.这些值

    不包括CPU编码,解码帧的时间. 

    speex编程(the libspeex api)

    这个章节出要讲述了如何用speex api进行编程.例子的源代友你也可以在附录B中找到

    4.1 Encoding

    4.1压缩

    为了用Speex压缩对话,你首先需要引用头文件:

    #include <speex.h>

    然后你需要定义一个Speex的位采集(bit-packing)结构

    SpeexBits bits;

    and a Speex encoder state

    以及定义一个speex编码器状态量

    void *enc_state;

    上面定义的这样被初始化:

    The two are initialized by:

    speex_bits_init(&bits);

    enc_state = speex_encoder_init(&speex_nb_mode);

    为了支持多频率的压缩,speex_nb_mode将被sppex_wb_mode取代.在大都数

    情况下,你需要知道你用的模式(mode)的帧(frame)的大小,你可以得到在frame_size变量里得到这值:

    speex_encoder_ctl(enc_state,SPEEX_GET_FRAME_SIZE,&frame_size);

    一但初始化完毕,对于每一个输入帧:

    speex_bits_reset(&bits);

    speex_encode(enc_state, input_frame, &bits);

    nbBytes = speex_bits_write(&bits, byte_ptr, MAX_NB_BYTES);

    上面input_frame是一个指向对话(speech)(frame)float指针(pointing);byte_ptr

    是指向编码帧开始写的地方的char指针,MAX_NB_BYTES是能

    写进byte_ptr而不会造成溢出的最大数.nbBytes是一个实际写入btye_ptr的数,即编码的实际大小

    在调用speex_bits_write,可能你需要调用speex_bits_nbytes(&bits)得到需要写入(write)的字节大小.

    在你已经编码后,释放所有的资源.

    speex_bits_destroy(&bits);

    speex_encoder_destroy(enc_state);

    That’s about it for the encoder.

     

    这就是关于编码的方面.

     

    Speex manul中文版三

    附源代码的翻译:

    B Sample code

    例程源代码

    这个章节演示了一段用speex编码,解码对话(speech)的源代码.

    可以如下用api命令来编码并解码一个文件:

    译者注:这里说的api命令是指unix的用”|”进行管道写入读出.windows下这样并不能实现.

    % sampleenc in_file.sw | sampledec out_file.sw

    这里这两段代码都没有引用其它的头文件,并以16 比特率(bits)进行编码

    natural endianness).

    B.1 sampleenc.c

    Sameleenc 用一个未加工的16比特率(bits)文章,给它编码并产生一个speex (steam)给标准输出.注意已压缩的和speexenc/speexdec不和谐!

    #include <speex.h>

    #include <stdio.h>

    /*帧的大小在这个例程中是一个固定的值,但它并不是必须这样*/

     

    #define FRAME_SIZE 160

    int main(int argc, char **argv)

    {

    char *inFile;

    FILE *fin;

    short in[FRAME_SIZE];

    float input[FRAME_SIZE];

    char cbits[200];

    int nbBytes;

    /*保存编码的状态*/

    void *state;

    /*保存字节因此他们可以被speex常规读写*/

     

    SpeexBits bits;

    int i, tmp;

    //新建一个新的编码状态在窄宽(narrowband)模式下

    state = speex_encoder_init(&speex_nb_mode);

    //设置质量为8(15kbps)

    tmp=8;

    speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);

    inFile = argv[1];

    fin = fopen(inFile, "r");

    //初始化结构使他们保存数据

    speex_bits_init(&bits);

    while (1)

    {

    //读入一帧16bits的声音

    fread(in, sizeof(short), FRAME_SIZE, fin);

    if (feof(fin))

    break;

    //16bits的值转化为float,以便speex库可以在上面工作

    for (i=0;i<FRAME_SIZE;i++)

    input[i]=in[i];

    //清空这个结构体里所有的字节,以便我们可以编码一个新的帧

    speex_bits_reset(&bits);

    //对帧进行编码

    speex_encode(state, input, &bits);

    //bits拷贝到一个利用写出的char型数组

    nbBytes = speex_bits_write(&bits, cbits, 200);

    //首先写出帧的大小,这是sampledec文件需要的一个值,但是你的应用程序中可能不一样

    fwrite(&nbBytes, sizeof(int), 1, stdout);

    //写出压缩后的数组

    fwrite(cbits, 1, nbBytes, stdout);

    }

    //释放编码器状态量

    speex_encoder_destroy(state);

    //释放bit_packing结构

    speex_bits_destroy(&bits);

    fclose(fin);

    return 0;

    }

     

     

    在Speex(www.speex.org)的最新版本中,开始集成了回音消除的模块,而回音消除一直是Voip之中亟待解决的主要问题。
    很多朋友和我说speex的aec模块的效能并不好,我们先来看一下speex的aec的api调用方式。

    /*
    *创建AEC对象
    */
    SpeexEchoState *echo_state = speex_echo_state_init(frame_size, filter_length);

    frame_size 的取值最好是一个编码的frame大小, 在低带宽条件下,一般延迟20ms,而大小为160
    filter_length,最好是房间内反射时间的1/3
    如: 一个房间的反射时延为300ms
        那么这个filter_length就最好是100ms(这个长度又被称为tail length).

    而其中filter_length的设定是一个关键。

    /*
    *执行AEC
    */
    speex_echo_cancel(echo_state, input_frame, echo_frame, output_frame, residue);

    其中:
    input_frame: 就是被声卡捕捉到的声音
    echo_frame: 是由扬声器播放出的声音,这个声音是需要从 input_frame中抵消的声音.

    output_frame 是处理完以后输出的声音

    residue是一个可选参数,如果不使用可以将之设置为NULL, 也可以通过preprocessor 来控制

    问题的关键是 处理input和echo 之间的关系,
    也就是说在捕捉到的信号和播放的信号之间的延迟必须足够的小,才可以提高效率.

    writetosndcard(echo_frame, frame_size)
    readfromsndcard(input_frame, frame_size)
    speex_echo_cancel(echo_state, input_frame, echo_frame, output_frame, residue)
    如果你想要尽可能的减小信号中的回音,那么可以将residue这个参数设置为噪音参数.

    我相信在大多数情况下,都是因为声音捕捉和声音播放之间的同步问题没有处理好,导致的音频质量下降。

    /*
    *销毁和复位
    */
    speex_echo_state_destroy(echo_state);

    speex_echo_state_reset(echo_state);
    不再复述了!

    说明:
    据说在Speex的最新的1.2beta版本上,Speex提供了可选择的,简化的API,来提高echo执行过程中的同步问题。

  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/rosesmall/p/2455395.html
Copyright © 2011-2022 走看看