找回密码
 注册
搜索
查看: 7489|回复: 0

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
6 l8 ~7 g0 o# A. l下载以后需要修改bits.c文件:
( f/ h& F$ m. [8 r! ?) p. n我仔细研究ITUG729代码后发现:
/ U1 @& U( S! D编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
. y, V9 T8 r( s8 ^( ~8 ?,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。  j' a5 D0 j$ N# q1 C; p+ ]8 s. {
  W/ Z% b4 R1 m+ J2 I% p/ d" y1 S& `
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
  }$ X) @6 M* g5 I+ W8 R
( F2 ]( P! m, @8 G  C3 L那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
/ B" A' i, e6 ?# C9 L我们打开bits.c,就能看到里面定义的如下4个函数:
4 t6 E& O1 \# Mstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);+ }4 D$ }: v9 G$ T( v! S
static int bin2int(int   no_of_bits, INT16 *bitstream);! ?! \% T# x; o; n. Z+ @- |. e
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
' u) q* \+ d1 h! Q) \void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
; @* K+ X( O2 O这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
) v5 [0 p8 P; ]6 b! T# h0 M7 Hstatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; % a+ Y" O: V: k4 K$ f4 B
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
3 _+ X- n8 _% G# G4 P/ _
: q) p) M' o& T3 Cvoid prm2bits_ld8k(Word16 *para,unsigned char *bits)- {; ]2 P1 d* O8 f0 m5 I
{$ B9 U) C3 o5 c# M1 i
   int i;1 [* |" j; v0 z8 }% l$ r, I$ Q  ~
   int bitpos = 0;# d3 C3 C7 B: ?8 N
   for (i = 0;i
8 ?6 a& C. t7 b4 g) |* n. p3 p  M, ?# R! Q8 X( ?! p
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
, Z  J+ f& r7 U8 z6 n{+ @% [7 o2 ?+ C- \5 z" g. ]* ?
   int i;( x$ z0 H+ t) V4 w4 W
   int bit = 0;8 J5 b& F4 ^9 b, n6 }  R5 J  Z
   unsigned char newbyte = 0;
3 r0 N6 K' W/ R# e9 X+ G  ~  0 r+ X- G  L% y3 U' N, y  h" c/ F
   unsigned char *p = bits + (bitpos / 8);+ p6 M) ^  o9 ^- z7 \
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;3 [+ k# g. g* V# f; |
newbyte = (1
4 j0 m+ V1 i) o, Y1 xbitpos++;. V' S& F4 h' ~- ?) h5 v9 R
if (bitpos % 8 == 0)
7 v0 D' Z7 ^+ ?& Y   p++;- m; W, N% @3 G/ F1 v! d
   }
4 q+ f1 B, W$ W& {, o; W}
6 U4 o$ x% b  ^' O6 o8 R& i; p; L# `6 m0 Q
void bits2prm_ld8k(unsigned char *bits,Word16 *para)* c# O5 G/ m6 O- q3 I
{
$ h2 a4 R- L4 |   int i;, Z. d0 H! z0 I9 z! z& |
   int bitpos = 0;
6 R9 u, E0 C8 G   for (i = 0;i
7 ]- F9 ?, w9 B5 W# b2 J' B2 b# H* p  P7 |
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)! _) ?3 y4 Z8 G$ Z  h3 g3 D" r3 r6 N3 o
{
+ r; Y; L* i7 b4 R$ a; ~+ F- P   int i;
. D' L5 Z' W+ t   int bit = 0;
2 q& _0 P0 P' L* [   Word16 newbyte = 0;: @. O+ `" K& g: ^
   Word16 value = 0;* h& m) e3 H4 `4 a
  
: D$ R6 u5 x2 m' p4 e   unsigned char *p = bits + (bitpos / 8);
" \7 a+ X6 w5 ~! H2 k' L7 V   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;1 d! V/ k/ Q' l
if (bit == 1) {. q: E" I  |7 _
   newbyte = (1 $ J* n1 f* I+ F6 M/ g* a
   return value;2 l" c  c! l8 v
}0 O4 J& r2 g+ E4 H* H- R: j
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
) f4 A! [8 D1 J2 k
+ }' Z5 T1 _; }% L+ l- m编码器的代码能采用如下的修改方法: M# H  M2 Y) _9 y$ Y
(1)修改coder.c:) \- A' L) J% J5 S! r
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
  _, w+ C8 c  N2 [/ P(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):: c9 I' y. V7 [3 |4 }# B0 H! ?
   frame =0;6 q& x# c) H$ r/ T: r. c! S
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
9 ~. g# Z( B9 C: U* J. \6 [   {4 s0 |1 m3 N' P' K8 k* |
printf("Frame =%d\r", frame++);
- w9 u) V  ?) f4 k0 Y( C0 qPre_Process(new_speech, L_FRAME);' V' l% z( a# Z( H- c- s. s
Coder_ld8a(prm);/ U8 d- Y, j7 @+ i' H* z
prm2bits_ld8k( prm, serial);
# P" j; s# ?! }' S0 W! }  Gfwrite(serial, 1, SERIAL_SIZE, f_serial);
0 {. C/ j9 i  Z" ^   }
5 D6 {: t  A/ \7 `   return (0);3 g" ]2 k' R) M. n3 r3 C

2 N0 z8 ?0 x7 k% }1 {' H% C$ U(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
5 P) ^8 M0 z: H7 K2 J#define   SERIAL_SIZE   10
) c4 t. W% N* j' v$ m; x, D( D. r" l2 q0 ?* _2 P7 q" Q8 O
(4)解码器decoder.c进行类似的修改(关键部分代码):! J# [# b, n3 ~. b) ?! d
   frame = 0;9 u. [, C7 t! t! M' m8 ~, c$ U. f
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)/ @1 K% I% o3 S) z) z. L7 R  Y
   {
$ }& P1 w# a3 eprintf("Frame =%d\r", frame++);
, Y; |/ o- {. Z) g+ [bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
" Z: T! _' n- R; G9 {; |8 }parm[0] = 0;   /* 假设没有丢帧 */, S7 f5 K' H' w' s. ]$ H$ O) K( u
parm[4] = 0 ; /* 假设数据效验正常 */- n7 A  c9 X' p. l# {1 {4 b# F2 l
Decod_ld8a(parm, synth, Az_dec, T2);
9 m& e4 k' G. NPost_Filter(synth, Az_dec, T2); + ?, b* \' g' ~: x# U
Post_Process(synth, L_FRAME);% P) }* a2 a/ ~/ L* q
fwrite(synth, sizeof(short), L_FRAME, f_syn);/ Z$ d9 g2 ^9 R8 g( I4 w
   }
$ B4 g0 F6 E$ f. `6 e   return (0) ;
6 x' S0 Q8 X6 T( \- ^. J2 L/ o通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
. J- b2 j: V3 l2 P/ R
; h: k7 {! h8 d6 J修改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]得到,应该就能了。" C) H0 p0 g# M7 T$ }, u# E3 R
封lib:
& |* v/ S$ ?$ a$ x* l! [va_g729.h
5 t1 R' z1 G5 o4 V: W#define L_FRAME_COMPRESSED 101 n  S$ Y4 Q9 m4 H5 C3 t+ q  z
#define L_FRAME            80( K; a. Q* I+ Z+ Y' S3 i
#ifdef __cplusplus
! I0 n; \3 Y4 D* W) Y+ Sextern "C" {
  G7 @. R- B9 h7 J4 \6 g+ Q# g#endif4 k) {8 \* u9 l/ k1 H' w
void va_g729a_init_encoder();
; N" w4 f3 J# D8 q( L+ }void va_g729a_encoder(short *speech, unsigned char *bitstream);
# q8 l2 j/ u/ ]  N. Ovoid va_g729a_init_decoder();9 g+ W2 A$ k0 d9 l+ t7 }9 V! n
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);- K- S+ f  I' a5 z$ t, m
#ifdef __cplusplus 1 R5 I2 w  X3 a8 d2 K: X# g# h, e! l) z
} " n8 O/ v; H/ }1 _3 r- t
#endif, a( R$ T9 l% r2 Z
va_g729.c
0 O' i* O7 A8 ^( G#include <stdio.h>
( U0 @7 Y$ ?. L; d" I#include <stdlib.h>1 Z* I) q2 u( f+ {1 ?
#include "typedef.h"1 `! O; ~: x1 R$ u
#include "ld8k.h"
2 h. l8 ]  o0 M' h, ?Word16 bad_lsf;- p: F, [( S5 Y8 `* V
void va_g729a_init_encoder()
0 b9 O  `( P+ ~9 Z{
' L; K+ m+ ~5 q# N% o    Init_Pre_Process();% W# Y: ^- ^+ M
    Init_Coder_ld8k(); 7 @1 w# n, H. L* }0 j3 O
}
' z& L% r) r2 h+ A3 Tvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)# h- _& j+ n# {, C6 \8 a
{     
7 J. [  S1 x+ z" L$ A    extern Word16 *new_speech;       /* Pointer to new speech data           */; Q. G% N' S5 |2 Z& e* f
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
' [) l* Z. U' S4 s9 m    Word16 i;
3 ?0 M+ g1 ?$ S: d# ?; WWord16 syn[L_FRAME];4 }  N& y3 ~$ x* z9 d( l1 p
    for(i=0;i<L_FRAME;i++)
1 W  ^$ n  K9 x9 w. q{# {5 L3 C9 ^- B4 O1 w
   new_speech = SpeechBuf;
9 Y5 f6 j' F4 B/ j  R) B* x4 W}' t2 P) [0 l/ a
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; $ b1 n; V2 q3 |# c& m4 e
    Pre_Process(new_speech, L_FRAME);
! o/ c. i% R+ F2 i0 P    Coder_ld8k(prm,syn);) ^! i, H: ^! v8 G" n
    prm2bits_ld8k( prm, serial);( e# \# j# W0 l4 M3 [
}. S. a- O' {; L2 W$ g9 I, k7 m
void va_g729a_init_decoder()
6 F3 p1 h7 ]% q5 `. j2 q2 @{
  ]8 _* [6 e5 k  ]extern Word16 *synth;9 ^" z, \, b$ Z3 Z- Y- |
    bad_lsf = 0;          /* Initialize bad LSF indicator */
5 E0 `8 G0 h# \+ I5 ?+ a1 M; ^6 D    Init_Decod_ld8k();: l# C) ^! S: h9 P* T
    Init_Post_Filter();8 g' {% a& w" e' B2 m  C( x
    Init_Post_Process();8 |! u' y, s- G4 P# _/ T
}$ _# q9 R  Z! B/ p5 |  {
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
! `, i* \4 q6 b1 o, u{0 ~6 I" d: X1 M& W; h/ M' ~
extern Word16 *synth; /* Synthesis                   */
2 U- E( m# }4 J, r: c- MWord16 synth_buf[L_FRAME+M];3 d: y3 Y; u- |
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
6 C" H' {' Q/ }% B0 ]1 c1 vWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */7 u$ ^; k7 M/ Z9 M' X0 g
Word16 T2;                           /* Pitch lag for 2 subframes   */
, D* |  [& G0 s3 g- e* o% RWord16 i;
1 }5 N# u8 L- \- }  R1 |- O+ xWord16 voicing = 60;2 _6 k& h$ [: p/ R5 s3 k
Word16 pst_out[L_FRAME];             /* Postfilter output           */# `( v- \: G" o3 J# M! _
Word16 sf_voic;                      /* voicing for subframe        *// a; V, R! Y- ^
voicing = 60;3 X! H3 ]6 O  T/ e0 e& v
    bits2prm_ld8k( serial, &parm[1]);: q& \* Y$ j% l% f* F
    parm[0] = 0;   $ o* R3 W+ \% Y# E1 y% @
          4 s: ~# R5 n' _+ ~/ b- b- m
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);, ^6 P; c+ `4 B3 s1 }4 `$ K+ u
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
8 v- y; X& @% O' E7 L//--------------------------------------------------
; p# t  r1 G& j. a9 R; u( W& {1 |  Bvoicing = 0;
( N1 t/ N8 `# x; V4 N! wptr_Az = Az_dec;( b' c+ I6 }7 v( W; E. i- W4 W
for(i=0; i<L_FRAME; i+=L_SUBFR) {
: R1 i3 B5 O3 Z& E# D   Post(T2, &synth, ptr_Az, &speech, &sf_voic);, {( ]0 J- f* G( D
   if (sf_voic != 0) { voicing = sf_voic;}
  u3 V$ |- g; e; p6 z6 p   ptr_Az += MP1;
) l  f& \" C6 S4 ]- q+ @$ X- ~  b}5 b0 c; |  Q* C1 n- X
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
, H9 P; ~& w% h) K/ I//---------------------------------------------------1 c/ L8 Z# E8 J2 K
    Post_Process(speech, L_FRAME);   / U* l- W6 n5 l. U/ d( E3 ]
}& l2 b2 E  S4 Z4 p

& E: q$ y3 M5 S" \+ Z& i" t
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 09:43 , Processed in 0.016860 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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