找回密码
 注册
查看: 8223|回复: 0

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
+ \; F' _3 r! U4 P- B, G; i4 U7 E下载以后需要修改bits.c文件:: A5 N# o8 c* E
我仔细研究ITUG729代码后发现:5 ?$ s2 a# R$ a- o2 C
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
0 m: ~: j  Q9 m: U- M,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。- j* d4 v- F3 a6 h" w

5 v' R% I- w* C( \. SITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
! X- ^0 w5 k' W& l8 H# p
% ]5 S/ e6 D5 O! w/ i那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
- D+ s2 ?( ]2 J1 `, q3 }我们打开bits.c,就能看到里面定义的如下4个函数:
+ i' l" b9 d% zstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);0 j, o; S9 F9 @; ^: g) B
static int bin2int(int   no_of_bits, INT16 *bitstream);; ], k7 ?. s! N- p3 r0 ?
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
  z% d, b. I1 ~- ivoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;0 d: z! s$ ?, l3 y5 ^* i" J
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
7 X. X" z* E, L5 b; |. Z) s; J. rstatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; & K: V- z1 l+ z6 S* D
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; / p; f# X- W- c9 Y: {" U+ `& N

9 }0 P, V5 l. S0 O% n4 V. {! Avoid prm2bits_ld8k(Word16 *para,unsigned char *bits)
# m: g" b0 w# B{
# q! G, ?- _. x% A$ r* G' h* n   int i;2 ~; i& K  E1 S
   int bitpos = 0;
# o- A7 N# R5 i- q9 N+ X! ~! g   for (i = 0;i+ W6 G" I2 H) E1 [
! v4 v* f# i1 h: p% ]
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
3 P0 L4 v9 V  [5 i) Q{
- X. B$ U: e" a/ @   int i;- m( C8 L8 c6 }* F7 B% [; R7 A% V0 W
   int bit = 0;
9 Z9 @7 W; _/ W4 E( w4 ?   unsigned char newbyte = 0;
5 ?+ B4 ^: N9 D/ p- ]; {  
# F' O% e5 M+ l/ k9 |: b1 {   unsigned char *p = bits + (bitpos / 8);
& a, B9 U0 J  W# [1 k- b" z   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
) |/ h' k/ e2 m9 k2 P3 c& Anewbyte = (1
$ K6 t. L  ]" f; kbitpos++;- L4 T8 M% [& a$ n- M8 I9 F0 Q
if (bitpos % 8 == 0): W6 F6 @' L0 Q) _! t# Y' Y+ s
   p++;9 W* Y' o( v) x
   }
( B4 l/ z' F$ s( a0 ?" n7 |- D& G}+ i" L4 a) |0 I' }

9 ?" V+ P8 x6 ^  M2 ^4 jvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)
" g( d6 _1 c# D1 f4 }{2 ^* L$ G/ R! [
   int i;& {  l  m+ k! O* w
   int bitpos = 0;
2 d* e# Z* L; ^, B1 @   for (i = 0;i
# c  K8 Q5 e4 S3 {# k8 T
7 {8 U) }7 x2 h: HWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
5 w  D3 Z7 z( a: g: N{/ Z- s% O1 M# V+ l6 O9 B  n
   int i;. W1 A, U8 r4 w; I3 u4 K1 s
   int bit = 0;; R  x# C9 Y; ?; R" _7 [  I
   Word16 newbyte = 0;
" x7 m- H2 ^- _" g7 ^   Word16 value = 0;
: w% a- Q. |  S' n) Y/ @; e  
& b$ E' }6 l2 t$ O   unsigned char *p = bits + (bitpos / 8);
- p+ {1 x# K& {8 o. `  s   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
2 y, t# B9 R; T5 y1 a' yif (bit == 1) {
+ d# {) g9 N4 k8 `  W   newbyte = (1
2 [3 S/ }* Z. |" Q5 D3 J/ D3 ~. M/ [   return value;
' t5 r+ [- U2 z; G}
& W) X" T7 \) c0 [通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。0 y' n/ ^' k7 B- J
  l2 s( i( G. Q' ~
编码器的代码能采用如下的修改方法
/ C/ G* s: w5 ](1)修改coder.c:
6 X; b" z0 i3 Q: {, Punsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */4 g) J2 g& a5 m7 F! X
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
4 {& g& |! C' C0 G1 L3 S- [   frame =0;
! X. G& f3 {  i7 J   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
( D& B4 {5 ?, k2 g  P7 @   {- }: ?2 ]; |# @  q( u7 J
printf("Frame =%d\r", frame++);7 b; `+ [6 P9 D. M$ k
Pre_Process(new_speech, L_FRAME);" l3 A/ B4 i4 {: Y  D
Coder_ld8a(prm);
/ D0 D7 a; R8 r+ \; c& T: Sprm2bits_ld8k( prm, serial);
2 V' Z( x6 x! P1 O* q' r7 ^8 H8 C1 xfwrite(serial, 1, SERIAL_SIZE, f_serial);
7 h8 p. T9 ]* N9 W8 S   }
/ r5 X) D1 w% P. [* T   return (0);) N: _3 }$ U7 K+ {- r' t  r) U& H

6 b& s# h6 j- K& s$ U: S' `  u(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
' l. F5 ~/ D) F- H! r7 H#define   SERIAL_SIZE   109 i# M+ _8 E# \$ F3 E
# h( c( r: `9 C( D. c# f+ }- y
(4)解码器decoder.c进行类似的修改(关键部分代码):
$ M* ]- w$ P5 q/ N$ Y   frame = 0;: C3 c5 c5 j! s
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
' W+ f9 a3 s$ B( K! w* S9 w   {7 f: g& Q0 N3 `0 }
printf("Frame =%d\r", frame++);* T% o3 Y) h/ k3 R- ~
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
" D) y: g9 I: F) i2 {" L; i/ y* bparm[0] = 0;   /* 假设没有丢帧 */4 N0 |6 r  \) |2 d+ x
parm[4] = 0 ; /* 假设数据效验正常 */
3 S$ z+ A5 K$ U8 y+ UDecod_ld8a(parm, synth, Az_dec, T2);
6 E; f  J+ t' R& Q/ ]- BPost_Filter(synth, Az_dec, T2);
  `. U0 O* N( L+ _Post_Process(synth, L_FRAME);
& A8 ]/ ?2 o' n- E. n4 ~. Y6 Gfwrite(synth, sizeof(short), L_FRAME, f_syn);
  w6 L1 I6 y' U6 s6 g" O  {( ?( p   }0 k( x. b) r& Q  I9 i/ B, g
   return (0) ;
: B2 j  o/ n; A! i& |# m/ I3 k通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
' I8 p. I5 X: [- v! x$ l3 h
" @5 y: G3 f) d5 K修改bits2prm_ld8k和prm2bits_ld8k之后的编码的数据其实也不是1/16的,因为编码器中的比特分配并不是均匀的,有的时候一个参数需要用5bit来表示,不过他并不是在内存中用5bit表示,而是用了一个word16来表示的。所以这样编码后得到的数据还是要比1/16大一些,原理上来讲,编完码后的prm[]大小应该是11(共11个参数),不过编码器的bits2prm()在其前面又加了一位校验是否丢包的校验位,这样1个block编码后的prm[0]这位实际上是个校验位。你要注意一下,解码器在读取编码后文件内容的时候,不是直接读取的字节,而是通过一个函数read_frame(),进行读取的,一个block读取prm[]大小为12。这样如果你把bits2prm去掉,编码后一个block用11个word16表示,不过解码的时候一次读取12个,这样就错了。所以需要对解码器作一下相应的修改,使他不再去关注那个prm[0],一次读入11个数据。你看一下解码函数也会发现,在读入12个prm后,开头就是这么一句:bfi = *prm++,你把这个bfi作为参数传入函数,使其不再通过prm[0]得到,应该就能了。
* f4 j- J4 z5 T' R* ^封lib:
* m, r3 g( `. U' X. ^# H7 H# l. iva_g729.h6 P  {- {# h  v
#define L_FRAME_COMPRESSED 10
. _: O, w0 ?0 Y! F1 Y) {# |* ]#define L_FRAME            806 i/ L$ p' o; f9 M
#ifdef __cplusplus 1 e% h1 d& }7 k
extern "C" {
0 g" G5 p5 O5 Y: k( A% Y) J2 P#endif3 b: W" g9 H+ d. \
void va_g729a_init_encoder();
6 f% x/ X: ^3 T5 p" S1 avoid va_g729a_encoder(short *speech, unsigned char *bitstream);. L- o0 t( D- |7 [: L! t; ^
void va_g729a_init_decoder();* }1 m4 E* ?) j4 M) F4 j! R- H0 Z
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);4 t9 S. J, B( }" u( t
#ifdef __cplusplus   z) M& Q5 {- ^& p# M( u
} 8 n- _4 S6 Z' C( m' W
#endif
, T; X3 K- a) X& L" Jva_g729.c" F. G! b) K2 `( j- K, ]
#include <stdio.h>
: ]' B: c, j* o! k* s#include <stdlib.h>
+ k; K% v  t+ U0 U" k#include "typedef.h"
' n0 n9 M6 ]4 `/ N6 v: f#include "ld8k.h"% J# i+ B0 I( z: u) v7 p- z8 p
Word16 bad_lsf;
& k  D$ R- |: N9 o  N! t8 `void va_g729a_init_encoder()
- y  v- k. H% T1 ]" p7 J- y, E" V9 y{
; B  L2 l6 M/ K( G" _    Init_Pre_Process();
5 t1 z& I8 E9 i6 l$ `    Init_Coder_ld8k();
( }3 E' |: ?3 P9 c- a. T! r}
7 V$ }2 x/ g( g1 `3 }3 K0 tvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
( r6 T/ U$ a! ?! W. {4 Z+ E{     / ^* |8 [' C( c
    extern Word16 *new_speech;       /* Pointer to new speech data           */' g1 R1 R/ L) [
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
( f) {: f1 Z5 f    Word16 i;0 X, i1 s# v. ~2 v7 G2 E
Word16 syn[L_FRAME];
/ w; D; e: @+ e5 g) Y( ]; P" Y0 e    for(i=0;i<L_FRAME;i++)
" x+ T0 E2 R& ~" q) D{
, D+ E5 u. E' P% l2 E( z2 c  @   new_speech = SpeechBuf;
0 W7 R, A1 S% ~, o& F}
& c; H. @( a) \9 v; m- A! p     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
6 v8 F; u% A$ b* d& G    Pre_Process(new_speech, L_FRAME);
; [' T: L6 C3 J/ c0 v+ O2 Y    Coder_ld8k(prm,syn);6 m/ I# {9 {9 F- T5 g5 V
    prm2bits_ld8k( prm, serial);
4 y4 }- G' o' E1 U}
7 t+ T& p+ |& r# v! Q  wvoid va_g729a_init_decoder()
5 \0 F5 \; G- U$ \6 M{
1 `# s/ O; h: X& S' U1 z7 Z6 h  `7 _/ Jextern Word16 *synth;
) j- g- g6 R6 j. [) ]    bad_lsf = 0;          /* Initialize bad LSF indicator */0 q9 ]+ e0 K* h0 Y4 Q1 v
    Init_Decod_ld8k();
; G# _! y2 N; `8 |    Init_Post_Filter();2 b! E  M1 j1 P
    Init_Post_Process();) C' b/ I# A% Z9 @) K+ i2 I; m; b
}( z" k3 s5 g! N2 p) Y
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
  @. ~- J0 [" N$ M7 G, b{! K% P+ M  U5 p0 ?; _
extern Word16 *synth; /* Synthesis                   */3 x+ t* e) l% q! H, b
Word16 synth_buf[L_FRAME+M];
. n8 ?3 D' L) z) u& |9 e+ BWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
2 N. I, K# o7 v5 ~Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
! I/ N# h9 K8 A. C) X; fWord16 T2;                           /* Pitch lag for 2 subframes   */
/ ]& n+ m3 v8 vWord16 i;
" {& v" ^& R5 A% rWord16 voicing = 60;
9 j4 |( I  W5 {0 z7 w6 {- N5 p5 }5 tWord16 pst_out[L_FRAME];             /* Postfilter output           */) [4 E" Z/ R$ s' P7 w- A% X
Word16 sf_voic;                      /* voicing for subframe        */; C# l( t! `3 E
voicing = 60;: F8 z. k" Z* M" _& |1 E
    bits2prm_ld8k( serial, &parm[1]);$ P7 _5 k* s8 Z& l& ?
    parm[0] = 0;   0 j8 h7 p' n& [+ ]( ~
          / Z4 Z4 _. f; T1 J; n
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
# H" x; }6 @! O0 rDecod_ld8k(parm, voicing, synth, Az_dec, &T2);1 F1 L! x) z" a: n8 T
//--------------------------------------------------
- q. K2 e) Q# p5 A( O2 jvoicing = 0;
& c  v7 w& A/ iptr_Az = Az_dec;
9 p+ H9 N5 ^2 K: g$ @$ i/ ?* Nfor(i=0; i<L_FRAME; i+=L_SUBFR) {
$ O# F5 L/ F% f" O3 Q8 A4 l   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
6 v8 T( u- A5 j' J2 A, e. o   if (sf_voic != 0) { voicing = sf_voic;}
; W# f6 R* t5 n- s" r! b/ ^   ptr_Az += MP1;
. \! m( h2 T! K7 M6 Q, _, p}- H1 w4 M3 a4 f, n* x
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
/ S& k9 o& ]9 ^$ V& R  z//---------------------------------------------------2 Y( ?. }4 A+ e' z
    Post_Process(speech, L_FRAME);   
8 s) h/ j9 a3 @8 N4 n2 h}( y, ^  f% M8 |+ v
- E. V" ?) P" x  {9 W, A, ?: G
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-10-1 23:54 , Processed in 0.016121 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表