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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/& [. C" x$ ]1 T: ?2 B. Z
下载以后需要修改bits.c文件:
: b; l5 O0 T5 f0 n; I" b我仔细研究ITUG729代码后发现:
0 ~. v" O8 v, A3 @" s+ U编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
* o& F9 g4 G, v$ H7 ^* l( l,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。6 ?0 `8 F; v7 q3 R

. F% U: e7 ]* z5 HITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。6 n* x. I1 ?& d1 V$ ^

/ n6 m1 y, a3 N3 a0 @. V那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。( G) s: @8 m, Q: e" G" Y& w+ }
我们打开bits.c,就能看到里面定义的如下4个函数:
7 I" G# K9 ]3 K  g( nstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
0 S1 T! h7 S9 f7 u. G$ s/ ystatic int bin2int(int   no_of_bits, INT16 *bitstream);- c  p# n# e: |- X1 b( r0 P; }( @
void prm2bits_ld8k(int   prm[], INT16 bits[]) ; : h, t3 d5 E. `0 n
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;4 S; u; l3 e3 {+ }2 \
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
! l5 l# q; q6 m- Sstatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
* _/ ?3 w1 w) x$ D3 J& z& e+ fstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
9 q+ i5 r! n' \2 y, a" G3 \: E  g# C
void prm2bits_ld8k(Word16 *para,unsigned char *bits); U. H  \; I1 @% a. O5 @5 [1 F
{! d" ?9 Y0 o7 e4 H8 i+ ?- W2 ~" l
   int i;' z) N5 [$ a4 L& p
   int bitpos = 0;
+ m/ a. x* Z% R5 ]! D3 D0 _   for (i = 0;i
0 @) G6 h1 A( g9 d$ N4 K' x7 L4 J3 W" t9 \9 i' Q; t+ E( q$ a
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
  J; e) e+ z' z6 [& b{. i1 `4 f& M( @, H! Z
   int i;
3 L& O$ |& G: |# }   int bit = 0;- D' s5 L2 u9 `0 d+ f
   unsigned char newbyte = 0;* ]  R0 S# o. {3 Q) {: ~5 P
  
( n6 b* w) x3 k$ s   unsigned char *p = bits + (bitpos / 8);8 w) @! {) h1 \3 T$ f4 d
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
+ y( r9 M- d# F3 L) Anewbyte = (1 6 z2 v" K# W' P) e: H3 d! v
bitpos++;/ k7 g' w- a. H- w
if (bitpos % 8 == 0)* l( |- i# G( P4 k1 L
   p++;
/ p6 H. F  L1 [2 z   }
* M& m/ |9 O9 n% X- j) j, F6 X' C}
2 e1 I( L# R  ^) O8 K) @" B/ x4 {+ [8 |0 h$ v8 L+ g6 @3 y( }
void bits2prm_ld8k(unsigned char *bits,Word16 *para)! H+ d/ Q: [5 ^, X  I" M
{
# x/ w7 j/ h3 p4 ?! F5 `) v   int i;
. l1 S' y5 m4 g' ~  t9 T1 |   int bitpos = 0;$ D- |/ h! B5 s' i) q5 w
   for (i = 0;i
& U0 i! N+ O, @3 S6 `9 ]6 A6 f" R
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)3 z' _7 I7 D$ ], G0 T
{2 E5 [2 }5 e& d6 J- E/ G
   int i;+ [2 G+ x; C' N6 r7 j  H2 T
   int bit = 0;( y1 M9 `  ]  y* N' I0 X
   Word16 newbyte = 0;
: q% I+ q9 F. T2 M6 n# G   Word16 value = 0;! v2 I* {! e, l) d, L
  
# p6 |0 j! o. t' _( n   unsigned char *p = bits + (bitpos / 8);5 D( C7 E1 E' z: Z
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
$ }5 x( l) m8 C% `% W2 eif (bit == 1) {( @  H& x; ]: H: j4 `
   newbyte = (1
2 w% K6 ^/ A+ h   return value;
# B$ ]  }0 B- u}
" f3 K( T2 Q7 [) }" N4 ]2 [通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。/ |7 E7 L% `5 T" y

: B$ @2 j# D% v  w( j4 `  u3 b编码器的代码能采用如下的修改方法  L) E7 H' b) V+ q3 u$ H- u
(1)修改coder.c:! L& [4 |; e+ F5 j2 V7 Y
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
- C0 u* x3 I7 @4 o7 n6 A4 m0 J(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
9 Y5 r. p! e. [. o9 [; c   frame =0;; M6 b) M& v& R- I
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
2 e9 \9 j9 M2 [1 b   {
" J! Y0 W( }, R2 A! n* Lprintf("Frame =%d\r", frame++);1 T+ ^% d3 I, u: }
Pre_Process(new_speech, L_FRAME);& q  }# ?8 e8 U& u9 Z. i3 K
Coder_ld8a(prm);1 h' v7 y0 h$ J1 t8 p
prm2bits_ld8k( prm, serial);
1 R% Y, P4 }  I1 ~* a0 [fwrite(serial, 1, SERIAL_SIZE, f_serial);
, `+ h3 N. G7 J   }4 f  X7 r. b, o: @" v( i& I
   return (0);
3 x) c5 u1 u  y, F. [% _3 `8 v! I2 a- _0 T8 D
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:7 F5 n" t5 W( l8 |
#define   SERIAL_SIZE   10
2 o( b+ ]6 ?8 Y) ]5 s  u, d+ g) n4 j; E5 \- W0 ~- G5 D* v7 m( ~
(4)解码器decoder.c进行类似的修改(关键部分代码):
$ P' l8 ~4 X7 m" q( E8 O3 H   frame = 0;
( E  z' Z# a- n$ F. l2 p) F2 X; d   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
9 q% c, o9 J7 K   {8 u' Z% ~' ^5 U/ B8 t! O' j" N& w
printf("Frame =%d\r", frame++);
: Y5 b# Q2 M7 x1 \6 ~' o0 o3 Rbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
* }  }( t; T* V  ^- Wparm[0] = 0;   /* 假设没有丢帧 */
& @! V' |: A( B. d# u# {$ C+ Cparm[4] = 0 ; /* 假设数据效验正常 */
; j/ ?( i9 }5 @7 ^2 K) I8 o- MDecod_ld8a(parm, synth, Az_dec, T2);
* ]+ b6 g% S" ^9 IPost_Filter(synth, Az_dec, T2);
% W* b/ N& e* k0 hPost_Process(synth, L_FRAME);, T2 a& j1 u% h* L
fwrite(synth, sizeof(short), L_FRAME, f_syn);# p5 y' ?* C" A* `7 O' l2 v
   }5 R+ V8 o  T4 M% F5 _
   return (0) ;   ]/ w2 i& S6 X7 ]1 `
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
& N& g/ F9 ~. I4 g6 A3 s# \3 w
8 A8 P& _% ]0 v( h6 s9 G& q修改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]得到,应该就能了。
# Y* y' Q: q% ]封lib:* v/ S" W8 e. j, q5 ~" X
va_g729.h5 L8 J2 ~: R+ _) O1 b4 u' h1 ~! c
#define L_FRAME_COMPRESSED 10
5 D* `$ l5 X; R8 u#define L_FRAME            80
6 t. D0 ]3 P, E, E7 T. n" M; X  ^5 W#ifdef __cplusplus
4 o: z3 {7 _. |1 m5 |9 `extern "C" {
! Q  U5 J* u- F0 z/ F) d#endif9 @9 {" d# R5 x
void va_g729a_init_encoder();
! j/ O' ?( X. N; _# Cvoid va_g729a_encoder(short *speech, unsigned char *bitstream);9 }9 {8 V: g# z- c
void va_g729a_init_decoder();" i3 ~2 m) {7 i5 m
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);( K/ p# i5 c. Y& S+ u$ e7 M  H
#ifdef __cplusplus 9 E. H  t5 C& g4 \5 `# E
} 3 C8 ^1 {* W# @5 d
#endif% Y4 Q* d, \3 M/ k  c
va_g729.c$ V6 d- ^8 n9 ?* g9 s, S
#include <stdio.h>0 p/ u& p( r# U" q) [* n: j% Q& H% x
#include <stdlib.h>
5 X. K+ ?8 c, i" I  m( R9 \8 R#include "typedef.h"% b' u8 B4 {0 D, [/ }
#include "ld8k.h"; P4 o5 C; B& k
Word16 bad_lsf;
' G# P5 T% C; B+ U1 U4 u" Z/ U+ N) ]9 ?void va_g729a_init_encoder()
. ?7 r' W6 G1 ~/ J, b6 O{! V& k- V! ^8 a
    Init_Pre_Process();6 ^4 Z7 G  i: l% s
    Init_Coder_ld8k();
! B% y# d; Q) B! @( w$ J}" o! j/ ^- T5 ^& L8 C2 V0 e# T
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)$ r6 G& D5 [9 W  Q) m6 j
{     " ^, X+ q6 {. `0 O4 G3 l
    extern Word16 *new_speech;       /* Pointer to new speech data           */
! s8 q* L3 D: x( c) R+ w: q5 Y% \    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */! \+ f; h: z# P# E3 S( |. [
    Word16 i;
2 C# w! D4 ~4 x, _; {5 ~Word16 syn[L_FRAME];7 P: W' j8 `6 g! M2 l5 D1 A. M. w. O
    for(i=0;i<L_FRAME;i++)
  P' x5 V- y( ^8 t3 X9 c2 M{
& Z& ?$ o& j# Q! L; }: s+ E) x   new_speech = SpeechBuf;8 }' M3 ]* l* S  R8 J
}4 _4 k1 X# r5 P6 H- I) V# |: e
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; / W& k3 `" T) @
    Pre_Process(new_speech, L_FRAME);
0 h. a6 _# ~- _( c" v4 U    Coder_ld8k(prm,syn);2 M$ z0 K+ m) d8 U' ^
    prm2bits_ld8k( prm, serial);
$ y6 ~* \; m8 Z% y- i' D7 R}
! _' ^8 R' K* s* }( U2 X7 Dvoid va_g729a_init_decoder()
! b  x: g" q* e7 I{
0 J# R3 R" U/ ^" \5 Zextern Word16 *synth;
$ O! F) r7 I3 x, A7 z, }8 J- }    bad_lsf = 0;          /* Initialize bad LSF indicator */
, A  t0 n  k" T( P. o    Init_Decod_ld8k();
  ~7 t# a4 T9 z    Init_Post_Filter();7 X/ z; j( F/ v" n; @
    Init_Post_Process();
  a% l8 m; m$ J6 c}+ @6 t. O1 s' N5 O, x
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)" y! b- [; k4 v
{
6 M6 d  W8 m2 z$ R* ~' S- vextern Word16 *synth; /* Synthesis                   */( u) _4 V9 k' c, Q5 n8 g' M
Word16 synth_buf[L_FRAME+M];/ i; }4 f+ }9 r3 f2 k4 _3 F7 K) C
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
" D9 {* e+ Y- G( HWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */) g: i$ q- n! i4 O
Word16 T2;                           /* Pitch lag for 2 subframes   */
' I9 m! Q. L0 k9 v+ j3 QWord16 i;: ]1 ?! X9 n; e; s' f4 r
Word16 voicing = 60;9 g' p6 v8 U9 I+ E( e# u. `/ {
Word16 pst_out[L_FRAME];             /* Postfilter output           */) y( z' g' p% f! N
Word16 sf_voic;                      /* voicing for subframe        */
5 e# Z* M; c) n! K" hvoicing = 60;, z( q+ e, x5 O% v% ^
    bits2prm_ld8k( serial, &parm[1]);
- [% P9 F  m7 d0 N    parm[0] = 0;   
! H0 d5 K& A4 d9 Y; A* |1 m         
3 c4 M  }! k  T( L    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);) q' c0 v8 R. N* p  d: ]2 P, U
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);) O  z- d0 p$ _, v" u6 y
//--------------------------------------------------9 V( q/ j! |. P$ `, r# t1 u
voicing = 0;
/ p1 b; _3 q* @& Yptr_Az = Az_dec;
1 a1 S3 I8 P& V+ c3 ?! ]for(i=0; i<L_FRAME; i+=L_SUBFR) {
( m3 _- P+ u3 U% X, y" o, `! _  p% ^: p   Post(T2, &synth, ptr_Az, &speech, &sf_voic);8 x$ J) e% G; I; U" k* p* E
   if (sf_voic != 0) { voicing = sf_voic;}
- I. G% i! F) ^' b; U# L   ptr_Az += MP1;# U  }$ a0 f! m& V* _- F
}
- u8 ?  f) g$ \) R8 wCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
2 W) B4 Q. X, h' [! r//---------------------------------------------------
2 e4 K8 e; a2 J) |, _& N, e* Q0 _    Post_Process(speech, L_FRAME);   + y# C2 B. T% @& H8 i
}
6 [. h! u* h: U* _1 o* F+ r1 j" y/ J# F! i' p: ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-14 01:06 , Processed in 0.019157 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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