Speex手册----Speex编/解码API的使用(libspeex)
jackyhwei 发布于 2010-12-14 15:50 点击:3386次 | 来自:CSDN博客 |
前言:Speex官网:http://speex.org/ 可以再Documentation下找到PDF版或HTML OL版的英文手册。可能会由于英文技能的匮乏或语音解码领域的不熟悉会有翻译错误,所以每段我都会付上英文原段落,也望各位发现后能够不吝赐教,大家共同进步。 PS: 1) 如需转载,注明出处,不胜感激; 2) 如侵您版权,及时通知,速删之 The libspeex library contains all the functions for encoding and decoding speech with the Speex codec. When linking on a UNIX system, one must add -lspeex -lm to the compiler command line. One important thing to know is that libspeex calls are reentrant, but not thread-safe. That means that it is fine to use calls from many threads, but calls using the same state from multiple threads must be protected by mutexes. Examples of code can also be found in Appendix A and the complete API documentation is included in the Documentation section of the Speex website (http://www.speex.org/). Speex编解码器的libspeex包囊括了所有的语音编码和解码函数。在Linux系统中连接时,必须在编译器命令行中加入-lspeex –lm。需要知道的是,虽然libspeex的函数调用是可重入的,但不是线程安全的,所以在多线程调用时,如果使用共享资源需要进行互斥保护。附录A中有代码实例,在Speex站点(http://www.speex.org/ )的文档部分能下到完整的API文档。 5.1 编码In order to encode speech using Speex, one first needs to: void *enc_state; 使用Speex进行语音编码,首先要: #include < speex/speex.h > 在代码中,需要声明Speex比特包结构体,同时设置Speex编码器状态: SpeexBits bits; void * enc_state; 初始化两变量: speex_bits_init( &bits ); enc_state = speex_encoder_init( &speex_nb_mode ); 用speex_wb_mode代替为speex_nb_mode,即可转换为宽带编码。很多时候,你在使用采样率的需要知道帧的大小,可以通过变量frame_size(用样本中的单位表示,不以字节为单位)获得,调用下面函数: speex_encoder_ctl( enc_state, SPEEX_GET_FRAME_SIZE, &frame_size ); 实践表明,在采用8、16或32kHz采样率的时候,frame_size大约对应于20ms。Speex编码器还有很多参数可以设置,其中最有用的一个是质量参数,控制着比特率(bit-rate)交换的质量,通过下面函数设置: quality是一个0~10(包含10)范围内的整数,窄带(narrowband)的质量和比特率(bit-rate)的对应关系如图9.2所示。 初始化成功后,对于每帧的输入: speex_bits_reset( &bits ); speex_encode_int( enc_state, input_frame, &bits ); nbBytes = speex_bits_write( &bits, byte_ptr, MAX_NB_BYTES ); 其中,input_frame是指向每个Speex帧开始的short型指针,byte_ptr是将写入已被编码的帧的char型指针,MAX_NB_BYTES是byte_ptr在不导致溢出时可被写入的最大字节数,nbBytes是byte_ptr实际被写入的字节数(编码大小以字节为单位)。在调用speex_bits_write之前,可能会通过speex_bits_nbytes(&bits)返回的字节数获得需要被写入的字节数,也可能使用speex_encode() 函数,它接受一个携带音频数据的float*型参数。不过这将使缺少浮点运算单元(FPU)的平台(如ARM)变的更为复杂。实际上,speex_encode和speex_encode_int()用同样的方法处理,编码器是否使用定点数取决于编译期的标志位,不由API来控制。 完成编码后,释放所有资源: speex_encoder_destroy( enc_state ); 这是关于编码的部分。 5.2 解码In order to decode speech using Speex, you first need to: 使用Speex解码语音,首先要包含speex.h头文件。 #include < speex/speex.h> 需要声明Speex比特包的结构体和Speex解码器的状态 SpeexBits bits; void* dec_state; 进行初始化 dec_state = speex_decoder_init( &speex_nb_mode ); 用speex_wb_mode代替speex_nb_mode,可转换为宽带(windband)解码。可能过变量frame_size来获得解码的帧大小 speex_decoder_ctl( dec_state, SPEEX_GET_FRAME_SIZE, &frame_size ); 还可以能过下面函数设置是否使用“知觉增强”功能 speex_decoder_ctl( dec_state, SPEEX_SET_ENH, &enh ); 如果enh是0则表是不启用,1则表示启用。在1.2-beta1中,默认是开启的。 做完初始化工作后,则可对每个输入帧进行如下操作: speex_bits_read_from( &bits, input_bytes, nbBytes ); speex_decode_int( dec_state, &bits, output_frame ); 其中,input_bytes是char型指针,包含了一帧的比特流数据,nbBytes是那帧比特流数据的大小(以字节为单位),output_frame是short型指针,指向一块内存区域,存储对语音帧的解码。第二个参数为空值(NULL)意味着没有获得到正确的比特(bit)数据,出现丢帧,Speex解码器会尽可能猜测最为准确的语音信号。 和编码器类似,可以用speex_decode()函数的一个float*型参数获得音频输出。 完成解码后,释放掉所有资源: speex_bits_destory( &bits ); speex_decoder_destory( dec_state ); 5.3 编解码选项(speex_*_ctl)The Speex encoder and decoder support many options and requests that can be accessed through the speex_encoder_ctl and Speex编码器和解码器可以通过访问speex_encoder_ctl和speex_decoder_ctl函数来设置更多选项,类似于系统函数ioctl。它们的原型是: void speex_encoder_ctl( void* encoder, int request, void* ptr ); void speex_decoder_ctl( void* decoder, int request, void* ptr ); 尽管拥有这些函数,但一般的应用程序在默认情况下就足够,如果要设置则需了解并知道为什么需要它们,勿随变设置。 下面列出了各种需求的允许值,其中一些只能应用于编码器或解码器。因为最后一个参数是void指针,所以_ctl()函数不是类型安全的,应小心使用。spx_int32_t类型同C99中的int32_t。 SPEEX_SET_ENH:设置知觉增强,1开启,0关闭(spx_int32_t,默认开启) SPEEX_GET_ENH:获得知觉增强状态( spx_int32_t) SPEEX_SET_QUALITY:设置编码质量(spx_int32_t 从0~10,默认为8 ) SPEEX_GET_QUALITY:获得当前语音编码质量(spx_int32_t 从0~10 ) SPEEX_SET_MODE:设置模式,指明RTP协议规格(spx_int32_t) SPEEX_GET_MODE:获得当前模式,指明的RTP协议规格(spx_int32_t) SPEEX_SET_VBR:设置变比特率(VBR),1开启,0关闭(spx_int32_t, 默认关闭) SPEEX_GET_VBR: 获得变比特率功能当前是否开启(spx_int32_t ) SPEEX_SET_VBR_QUALITY:设置变比特率语音的编码质量(浮点数从0.0~10.0,默认8.0) SPEEX_GET_VBR_QUALITY:获得当前变比特率语音的编码质量( 浮点数从0.0~10.0) SPEEX_SET_COMPLEXITY:设置编码器的可用CPU资源( spx_int32_t从1~10,默认为2) SPEEX_GET_COMPLEXITY:获取编码器的可用CPU资源(spx_int32_t从1~10,默认为2) SPEEX_SET_BITRATE:设置不超过参数设置的最佳比特值(spx_int32_t 单位bits/s ) SPEEX_GET_BITRATE:获取当前使用的比特率( spx_int32_t 单位 bits/s) SPEEX_SET_SAMPLING_RATE:设置实时采样率(spx_int32_t 单位 Hz ) SPEEX_GET_SAMPLING_RATE:获取实时采样率(spx_int32_t 单位 Hz) SPEEX_RESET_STATE:重置编/解码器到原始状态,并清除所有记忆(无参数) SPEEX_SET_VAD:设置静音检测特性(VAD),1为打开,0为关闭( spx_int32_t, 默认为关闭) SPEEX_GET_VAD:获取静音检测是否打开( spx_int32_t ) SPEEX_SET_DTX:设计非连续性传输(DTX),1为打开,0为关闭(spx_int32_t, 默认为关闭) SPEEX_GET_DTX:获取非连续性传输(DTX)是否打开(spx_int32_t ) SPEEX_SET_ABR:设置平均比特率(ABR)值, 单位 bits/s(spx_int32_t,单位 bits/s ) SPEEX_GET_ABR:获得平均比特率设置(spx_int32_t,单位bits/s ) SPEEX_SET_PLC_TUNING:让编码器对一定的失包率开启最优化编码(spx_int32_t,单位 %) SPEEX_GET_PLC_TUNING:获取编码器为PLC的当前调整(spx_int32_t,单位%) SPEEX_SET_VBR_MAX_BITRATE:设置允许变比特率(VBR)使用的最大比特率(spx_int32_t,单位 bits/s ) SPEEX_GET_VBR_MAX_BITRATE:获取允许变比特率(VBR)使用的最大比特率(spx_int32_t,单位 bits/s ) SPEEX_SET_HIGHPASS:设置高通滤波器,1为打开,0为关闭(spx_int32_t,默认为打开) SPEEX_GET_HIGHPASS:获取高通滤波器状态( spx_int32_t ) 仅用于编/解码器。 5.4 模式查询Speex modes have a query system similar to the speex_encoder_ctl and speex_decoder_ctl calls. Since modes are read-only,it is only possible to get information about a particular mode. The function used to do that is: 类似于调用speex_encoder_ctl和speex_decoder_ctl,Speex有模式查询系统。因为模式是只读的,所以只能获得模式的详细信息。使用如下函数: void speex_mode_query( SpeexMode* mode, int request, void* ptr ); The admissible values for request are (unless otherwise note, the values are returned through ptr): 受理的请求值(除非另有说明,要不返回值都是通过ptr): SPEEX_MODE_FRAME_SIZE 获得模式的帧大小(样本中) SPEEX_SUBMODE_BITRATE:获取通过ptr指定的子模式数量的比特率(以bps为单位的整数) 5.5 封包和带内信令Sometimes it is desirable to pack more than one frame per packet (or other basic unit of storage). The proper way to do it is to call speex_encode N times before writing the stream with speex_bits_write. In cases where the number of frames is not determined by an out-of-band mechanism, it is possible to include a terminator code. That terminator consists of the code 15 (decimal) encoded with 5 bits, as shown in Table 9.2. Note that as of version 1.0.2, calling speex_bits_write automatically inserts the terminator so as to fill the last byte. This doesn’t involves any overhead and makes sure Speex can always detect when there is no more frame in a packet. 有时我们打包的数据不只一帧(或其他基本存储单元),正确做法是在用speex_bits_write写入流数据之前调用N次speex_encode。这种情况下的帧数不是由带外机制决定的,它会包含一个终结码。如表9.2所示,这个终结码是由用5bits编码的Mode 15组成。如果是1.0.2版本需注意,调用speex_bits_write时,为了填充最后字节,它会自动添加终结码。这不会增加开销,并能确保Speex一直检测到包中没有更多帧为止。 It is also possible to send in-band “messages” to the other side. All these messages are encoded as “pseudo-frames” of mode 14 which contain a 4-bit message type code, followed by the message. Table 5.1 lists the available codes, their meaning and the size of the message that follows. Most of these messages are requests that are sent to the encoder or decoder on the other end, which is free to comply or ignore them. By default, all in-band messages are ignored. 当然也可以通过带内“消息”的方法,所有这些消息是作为Mode14的“伪帧”编码的,Mode14包含4bit的消息类型代码。表5.1列出了可用代码的说明和大小,发送给编/解码器的的消息大部分都可随意的被接受或被忽略。默认情况下,所有带内消息都被忽略掉了。 表5.1 带内信号代码 Finally, applications may define custom in-band messages using mode 13. The size of the message in bytes is encoded with 5 bits, so that the decoder can skip it if it doesn’t know how to interpret it. 最后,一些应用会使用Mode 13自定义带内消息,消息的字节大小是用5bits编码的,所以如果编码器不知道如何解析它就会跳过。 本是第9章--Speex窄带模式中的图和表格,但本章中需要参考,贴上来 Figure 9.2: Analysis-by-synthesis closed-loop optimization on a sub-frame.
Table 9.2: Quality versus bit-rate
|