当前位置:网站首页 > 技术博客 > 正文

s-spec编码



        speex是近年来开发出的一套功能强大的语音引擎,能够实现高质量和低比特率的编码。它不仅提供了基于码激励线性预测(CELP)算法的编/解码模块,而且在其最新发布的版本中还提供了声音预处理和声学回声消除模块,为保障IP网络中的语音通信质量提供了技术手段。此外,Speex还具有压缩后的比特率低(2.15~44.2kbps)的特点,并支持多种比特率。这些特点使得Speex特别适合VoIP, 音视频系统

宽带和超宽带下的比特率

   (1)开源,纯C开发,跨平台,兼容ARM,编译简单

   (2)占用比特率小,提供消除回声功能

   (3)API使用简单

     (4)  码率支持 : 2.15~44.2kbps

   (5)采样率支持:8khz 、16khz、32khz

编码方式

打包时间

带宽

G711

20ms

90.4 Kbit/s

G729

20ms

34.4 Kbit/s

G723

30ms

22.9 Kbit/s

speex

20ms

19.6 Kbit/s

从对比来看,speex占用的带宽是最小的,比较适合在在窄带宽下使用

网络包数据  +  数据包数据  )  /  采样时间

网络包数据 :  58 bytes  由以下五个部分组成

  1. 网络 CRC: 4 bytes
           (2)mac 地址: 14 bytes
           (3)IP 头: 20 bytes
           (4)UDP 头: 8 bytes
           (5)RTP 头: 12 bytes

数据包数据: 20bytes 

采样时间:20ms

Speex 传输率

如果每个rtp包只传输1个数据包:

(58 +20)*8 /20*1000 = 31.2kb/s

如果每个rtp包只传输2个数据包:

(58 +40)*8 /40*1000 = 19.6 kb/s

如果每个rtp包只传输3个数据包:

(58 +60)*8 /60*1000 = 15.7 kb/s

如果每个rtp包只传输3个数据包:

(58 +80)*8 /80*1000 = 13.8 kb/s

码率计算公式:

 码率 = 采样率 * 位声 * 声道数 * 压缩率

 压缩率 = encoded audio size / pcm size

5.1、RTP Speex 头部

        Payload Type (PT): 本格式的负责类型号。

        Marker (M) bit: 此位被用来标志一段无声后有声的开始。打在有声数据的第一个包上。 Speex支持声音检测,可以在无声时不产生帧数据。所以包可能是非连续传输的。

       Extension (X) bit: 见RTP的规定。

       Timestamp: 一个32位的整数,表示一个包中第一帧的采样时间。

5.2、Speex的RTP负载格式

    Speex的RTP负载如图1所示。本格式没有附加的头部,所以只什用标准的RTP头部  头部之后是一个或多个负载数据库(speex帧)。包尾部可能需要一些填补数据。

5.3、 Speex 负载

为了把编码后的数据打包进RTP,我们只需要考虑Speex编码器输出的比特流必须以相同的顺序出现在解码端。此处所说的负载格式保持了这个顺序。

一个典型的Speex帧,最大编码码率大约是110个字节。一个包中所有的Speex帧的总字节数应小用路径MTU以避免被分割。Speex帧绝不能被分割!

必须按时间序把帧打到包里。

一个RTP包中可能包含相同码率的帧也可能包含不同码率的帧。然而码率是在带内传送的,每帧中包含了自己的码率,所以打包时不必在意它。

编码和解码算法可以以20毫秒的帧为边界改变码率。 码率改变的通知是在带内传送的。每个帧都包含采样率(窄带, 宽带, 超宽带)"模式"(码率)信息。所以不需要带外数据通知解码器处理那些变化。

采样率必须是8000 Hz, 16000 Hz, 32000 Hz之一。

RTP负载必须被填补数据以保证能提供整数个字节的数据,这些填补位是LSB(最低有效位)-对齐的并且按网络字节序放置,它是由一个0跟着一群1组成的。填补数据仅被包中最后一个帧所需要。并且仅仅为了保证一个包的内容按字节边界结束。

5.4、 Speex RTP包的例子

下面的示例中,我们的包中一个Speex帧,还有5位的填补数据来保证包的大小是字节对齐的。

5.5、多Speex帧的RTP包

下面的例子演示的是一个RTP包中有两个Speex帧。这个例子中的Speex帧的长度是字节对齐的,所以不需要填补数据。

Speex解码器可以从负载侦测码率,并负责在各帧之间检查20毫秒的的帧界限。

5.6、 媒体类型

媒体类型名字: audio

媒体字类型名字: speex

所需参数:

rate: RTP 时间戳时钟频率,等于采样率Hz。采样率必须是8000, 16000, 或 32000。

可选的参数:

ptime: 必须能被20毫秒整除 [RFC4566]

maxptime: 必须能被20毫秒整除 [RFC4566]

vbr: 可变码率 - 可为 'on', 'off', 或 'vad' (默认是'off')。如果是'on',可变码率被使用。如果是 'off',则不被使用。如果是'vad',那么固定码率被使用,但是无声时段将被编码为特殊的短帧来表明那段时间没有声音。这个参数

用于编码器。

cng: 产生舒适噪音 - 可为 'on' 或 'off' (默认是'off')。如果为 'off',无声帧就是无声,如果为'on',那么这些帧将被以舒适噪音填充。此参数被用于编码器。

mode: 以逗号分隔的多个speex支持的解码模式,按优先度排列。第一个具有最优先级,剩余的依次排列。对于窄带和宽带可用的模式值不一样,见以下定义:

* {1,2,3,4,5,6,7,8,any} 用于窄带

* {0,1,2,3,4,5,6,7,8,9,10,any} 用于宽带

mode'参数可能包含多个值。这此情况下,远端的编码器必须被配置成能支持模式列表中的第一个值。 当 'any' 被使用时,表明自己支持所有的解码模式。'mode' 参数必须永远有值。如果'mode' 没有出现,那么mode的值被置为:在

窄带下是'mode="3,any"',在宽带和超宽带下是'mode="8,any"' 。注意每个包含mode(或码率)的Speex帧必须被解码。因此,一个应用程序必须能解码任何Speex帧,除非在SDP中明确指明某些模式不被支持(例如,不含'mode="any"')。

解码端指定支持哪些模式意味着编码端也支持那些模式。

6.1 、speex 编码流程

1、定义一个SpeexBits类型变量bits和一个Speex编码器状态变量enc_state

2 调用speex_bits_init(&bits)初始化bits

3 调用speex_encoder_init(&speex_nb_mode)来初始化enc_state。其中speex_nb_modeSpeexMode类型的变量,表示的是窄带模式。还有speex_wb_mode表示宽带模式、speex_uwb_mode表示超宽带模式。

4  调用函数int speex_encoder_ ctl(void *state, int request, void *ptr)来设定编码器的参数,其中参数state表示编码器的状态;参数request表示要定义的参数类型,如SPEEX_ GET_ FRAME_SIZE表示设置帧大小,SPEEX_ SET_QUALITY表示量化大小,这决定了编码的质量;参数ptr表示要设定的值。

   可通过speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &frame_size) speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &quality)来设定编码器的参数。

5 初始化完毕后,对每一帧声音作如下处理:调用函数speex_bits_reset(&bits)再次设定SpeexBits,然后调用函数speex_encode(enc_state, input_frame, &bits),参数bits中保存编码后的数据流。

6 编码结束后,调用函数speex_bits_destroy (&bits)speex_encoder_destroy (enc_state)

编码demo 代码

 

6.2 、speex 解码流程

对已经编码过的音频数据进行解码要经过以下步骤:

1、定义一个SpeexBits类型变量bits和一个Speex编码状态变量enc_state。

2、调用speex_bits_init(&bits)初始化bits。

3、调用speex_decoder_init (&speex_nb_mode)来初始化enc_state。

4、调用函数speex_decoder_ctl (void *state, int request, void *ptr)来设定编码器的参数。

5、调用函数 speex_decode(void *state, SpeexBits *bits, float *out)对参数bits中的音频数             据进行解编码,参数out中保存解码后的数据流。

6、调用函数speex_bits_destroy(&bits), speex_ decoder_ destroy (void *state)来关闭和销毁              SpeexBits和解码器。

解码demo 代码

 

  • 上一篇: seo的相关优化
  • 下一篇: java接口的定义
  • 版权声明


    相关文章:

  • seo的相关优化2025-01-20 08:01:02
  • 游标oracle有啥用2025-01-20 08:01:02
  • nat作用和类型2025-01-20 08:01:02
  • elb的基本概念2025-01-20 08:01:02
  • linux在线升级ssh版本2025-01-20 08:01:02
  • java接口的定义2025-01-20 08:01:02
  • linux系统ifconfig命令2025-01-20 08:01:02
  • 美孚shc630齿轮油2025-01-20 08:01:02
  • 弹性负载均衡的基本概念2025-01-20 08:01:02
  • 安卓硬件模拟器2025-01-20 08:01:02