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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/4 p3 J. x1 p- y1 N" O3 b) _
下载以后需要修改bits.c文件:/ l. [& t% E. D( P
我仔细研究ITUG729代码后发现:4 Y5 t, ^' X+ r0 P# l  z
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流" ~  b) n8 I5 D- K
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
) v7 ~3 K& c: R+ z- k# [; I6 V  G0 l9 N; Q2 X0 ^
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。: [7 y1 H# i% V  C: W
. t9 R0 Y- `( m( ?' ?5 A
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。! `- n1 K8 ~+ y
我们打开bits.c,就能看到里面定义的如下4个函数:# z- D; r& z- F3 H
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
& k2 m$ C5 W* s- rstatic int bin2int(int   no_of_bits, INT16 *bitstream);
4 @# ~' U+ o2 T' }void prm2bits_ld8k(int   prm[], INT16 bits[]) ; % T# e2 W4 O1 u( s8 d0 D
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;. k* p# j  M7 e0 U$ b  e2 A+ O! b
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
" F+ ^: I; e6 a3 d6 m8 O7 Bstatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; 2 @) x8 l% `: q0 z( W5 a* \
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
  ~" l( T" K& y3 Z7 |* v2 J" K& b. {/ l3 l- l5 @2 m+ m8 R& e
void prm2bits_ld8k(Word16 *para,unsigned char *bits)
9 K4 k2 Z5 z2 L- K# L& b{
" q9 s3 L3 v/ T6 ~" `   int i;$ z0 F. W. X4 t) {  \
   int bitpos = 0;
( c) N7 J0 i0 p; L   for (i = 0;i
' Z0 |+ i! y( b- o$ k. i
" `9 {% k! q" }$ f" \void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)4 \  F5 e% I6 `: k* Y2 |
{
8 E# K5 q4 }+ i- ~/ H" N% w# D   int i;
0 W% x9 O7 Y; I( m$ V: O( R. l6 H   int bit = 0;
0 O! w9 d- j! |( e0 t( T' d   unsigned char newbyte = 0;
: [  }7 D  t8 c9 l$ d) I  
8 B. J8 S4 D# [- Z5 s' v   unsigned char *p = bits + (bitpos / 8);
# s7 x0 s/ r! o5 l   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
& S6 A) l  G7 g/ m% r0 e" d. rnewbyte = (1
5 r- v8 V& l( `  [* fbitpos++;
/ Y9 M2 p; y& J8 m' M4 O4 wif (bitpos % 8 == 0)
' k3 l9 l( k5 x8 Q& |2 e- o. a& S   p++;! h6 D. }2 x+ Q% p+ R. ?" B
   }
' u8 z. ~4 e# Z}: i6 [& v/ c+ P4 Y  A) y5 d7 a/ N

  W- ~: Y6 O& @* U6 yvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)
- O# w) |( @6 f5 l: h' r{
! C) K$ G5 T  ]1 x/ E4 [   int i;8 l. d; s  B- N" B) N; j
   int bitpos = 0;
3 R# z! U. Q  {* z. O& h: \   for (i = 0;i
0 f$ D& h6 ~" d  P/ a1 u
+ ^  C) U' f9 L* `Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)8 X( X, {) {; Q. s% s' D' R
{+ c1 n) m6 n' A2 {) {
   int i;4 X  y) b7 y0 g( o. u" m2 k
   int bit = 0;
0 g5 T, {2 U; f   Word16 newbyte = 0;( |* m! S3 ?$ M1 L9 K4 e
   Word16 value = 0;- U& h5 z- h& M7 w
  
  q. m! d( o5 b+ z$ s3 Y% ?   unsigned char *p = bits + (bitpos / 8);* ]# v' y0 y- D& K, m
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
" @: m  e+ _" ~$ J: g+ d5 ^if (bit == 1) {; R2 i" v% n( m, L8 l
   newbyte = (1 2 R8 n. P7 G' \- o4 D7 `) F$ A
   return value;
, z: v" W* R* A( X3 {- L}
) M% y- E! F- x/ Z& D2 o通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
1 K( S- e1 \- k( I5 O. l4 \& Q0 p: Y
( k# C- C$ R. h, h, A' o* b编码器的代码能采用如下的修改方法2 h/ t3 B: b0 ^# {
(1)修改coder.c:
% J9 \" N" f5 i3 p5 I$ Nunsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */$ w! I& X. p, G$ Z# ], [- s8 m
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
( p! K$ W% R& g6 I7 B   frame =0;4 P  B. K* _" y& Y9 Z& t) ^# y6 R
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)1 e) R! u" S! h4 Z
   {5 i8 d0 Q3 p, ~! Z2 E
printf("Frame =%d\r", frame++);
0 ~5 t: h% h# x6 y5 e: e* R' G# zPre_Process(new_speech, L_FRAME);
# q+ w% ?( X6 \8 CCoder_ld8a(prm);0 E) B6 n* N. _+ @
prm2bits_ld8k( prm, serial);
7 F. R* [& T& tfwrite(serial, 1, SERIAL_SIZE, f_serial);( H4 t  w! H8 @+ d2 x" E5 L
   }
" r  E7 F, z* l% v4 [   return (0);
8 _, M0 J1 [0 [5 ?& o$ Q2 |7 d: [* a
3 H% u0 j5 G1 }4 ]. o/ b(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:* `$ P: n( }6 [* K  P6 i
#define   SERIAL_SIZE   107 O: U) ~. N4 |9 M, t  f9 O

/ K- {6 q' L* z/ y2 k0 ]- M8 J(4)解码器decoder.c进行类似的修改(关键部分代码):8 C3 n- s1 v% F8 @% J
   frame = 0;
% i" l/ X$ W! ]" j   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
2 u' _5 J- n3 _1 f& l$ c! B' ?8 ]) _+ d  J   {
4 t& z6 \" W8 Sprintf("Frame =%d\r", frame++);. ]7 P: Q3 ~* b2 o) v
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */  h) m- R( }1 _2 k4 a0 J3 J0 |$ S
parm[0] = 0;   /* 假设没有丢帧 */
6 k+ P- c6 G9 x. gparm[4] = 0 ; /* 假设数据效验正常 */
, [& ]  p3 S& U6 VDecod_ld8a(parm, synth, Az_dec, T2);
$ Z) \, h/ ?  W, ]) s7 |1 |7 d+ vPost_Filter(synth, Az_dec, T2);
. W! q& A" D9 y! BPost_Process(synth, L_FRAME);
+ w; |( g  r3 L! v6 |fwrite(synth, sizeof(short), L_FRAME, f_syn);0 Z3 l# p; s! a& E" I
   }  a8 i) i6 d) E; e; a8 k3 Y# g
   return (0) ; 2 h$ L7 ?2 P0 {2 x5 B6 ]5 f7 Z
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
, P; |+ q; z( d: V% F
( W# w3 g2 i" b# O8 @: T3 u修改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]得到,应该就能了。2 j8 n* ^/ o' S' j" X4 R; _! r
封lib:. u; }; ?  n; C8 ?. u0 L) k
va_g729.h
7 c1 j, E: F5 y& }# i, D( {#define L_FRAME_COMPRESSED 10
6 V* w) t9 z" z3 g0 |#define L_FRAME            805 v6 I( z8 H6 [
#ifdef __cplusplus ; P: ]4 X. i8 t( P0 @* b' V2 G! v* o
extern "C" { % L( C  q" _) Y$ f7 Q9 B6 |
#endif- d3 e- x, h1 i
void va_g729a_init_encoder();. L- U3 K- I- A9 N
void va_g729a_encoder(short *speech, unsigned char *bitstream);
. M0 X6 a8 d4 r: S* _void va_g729a_init_decoder();* Q5 l& v- M  o
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
, k% T: [1 o* T3 U0 w#ifdef __cplusplus
8 j2 E4 Y8 F# J* i- v: h2 n4 y}
6 E; N: O% N  ]- s#endif# v# w9 G2 r) R) g0 d
va_g729.c
" m3 X$ Z$ _4 M) P1 o% f#include <stdio.h>
: h2 N1 y  G# D+ w* E#include <stdlib.h>
/ @1 \. J% n# q7 o#include "typedef.h"
8 z  H$ I  H) c2 c7 |+ x4 W' g7 ]#include "ld8k.h"
8 _% W! r6 k+ Z! `4 u( W$ eWord16 bad_lsf;9 `7 N# r1 {( D# o0 Z: Y
void va_g729a_init_encoder()
. M; A5 G6 u2 S{5 c6 A4 k0 |* ]
    Init_Pre_Process();
' t; [/ z9 i! N+ ~4 n; F) r8 i' w    Init_Coder_ld8k(); , x9 ?, w( y- H: o& f8 t
}
$ C+ g# ^7 `/ N& ?: f. g9 v; i$ h: fvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
' v! W3 Z  X/ w7 B. n, m- B{     
1 b  t* [+ R5 z% `' {    extern Word16 *new_speech;       /* Pointer to new speech data           */
/ v+ z# b5 [  k9 c2 ~, x3 g    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */4 L) S/ D5 w$ ~# [3 f% T
    Word16 i;
# d8 A* V4 |# M6 ]8 B: r1 KWord16 syn[L_FRAME];7 _- ?" D+ N1 `2 A3 l4 B% I& I
    for(i=0;i<L_FRAME;i++)
3 U: U! A; E/ e* F* z$ Z: x{0 G2 g( d/ [" Q) Z
   new_speech = SpeechBuf;* T: J" T+ \& D" J
}
1 c9 ]7 M* h! ^     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
5 h/ c: ]) m1 f5 P    Pre_Process(new_speech, L_FRAME);
  L  \; z) C7 c8 W, `    Coder_ld8k(prm,syn);6 u2 `4 |% g- r. I/ y. M6 N# \. p9 C
    prm2bits_ld8k( prm, serial);( `6 H. o% q5 L: T3 s# [
}
8 d- i' A+ t7 wvoid va_g729a_init_decoder()9 q. v& o% x& ~
{
3 i5 H; g: H0 a4 h& E, nextern Word16 *synth;( c, O2 a" i) T4 u8 ]0 P5 a
    bad_lsf = 0;          /* Initialize bad LSF indicator */
1 A2 f# d" m) G    Init_Decod_ld8k();
! \' h" }  H4 f    Init_Post_Filter();
$ y# w) p. n: w, L+ S4 C    Init_Post_Process();4 Q4 v6 Z& E. Y
}
9 y* G  j, M4 ivoid va_g729a_decoder(unsigned char *serial, short *speech, int bfi)8 M" g: x, p1 {. }+ q) T  J3 J" Z
{+ X' a# ^3 m0 t3 N4 U1 l
extern Word16 *synth; /* Synthesis                   */
2 C9 }& R' T) f* U& N# sWord16 synth_buf[L_FRAME+M];
$ {8 B  y/ B  c5 F' XWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
+ W, |3 C7 b. y% t: ^5 AWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */+ a2 v% G+ e. j) H/ Q
Word16 T2;                           /* Pitch lag for 2 subframes   */- N0 j" Q* P! x
Word16 i;
5 l0 h* u$ R8 ~  MWord16 voicing = 60;
) ~1 K2 {9 G7 gWord16 pst_out[L_FRAME];             /* Postfilter output           */5 q+ r2 V! {( E
Word16 sf_voic;                      /* voicing for subframe        */3 }+ d- @4 v2 i$ F0 G! T
voicing = 60;
+ Z: ?" M6 |" T3 Y1 M. o    bits2prm_ld8k( serial, &parm[1]);
( ]5 a9 e8 o8 ~, k  c    parm[0] = 0;   ; N/ i6 e9 v7 k$ _
          - e. \% U4 u* J" g/ H- c; x3 W
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);+ y8 o) D4 r- }
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
3 k# A6 I! ~4 B( q& k* p% o. @//--------------------------------------------------
% h+ a+ I: B( g) j% qvoicing = 0;
, i: f- g6 d. Z+ \: j' d! dptr_Az = Az_dec;
. H# V2 h: A9 A4 R. X& f: a  }0 B4 }for(i=0; i<L_FRAME; i+=L_SUBFR) {
& ~! U, [) `6 o# {) m   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
( _9 g7 M8 ?, j4 b! \; `* e   if (sf_voic != 0) { voicing = sf_voic;}0 e; I% y* \7 D. S7 Q% P/ f
   ptr_Az += MP1;9 q# U& S# v8 @: y& Y0 G; P
}
; a, L8 S6 h6 U1 F' Z5 PCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
' L7 N( q, K1 P//---------------------------------------------------
' m+ `: t/ Y- @6 E$ ~0 K    Post_Process(speech, L_FRAME);   
# m. r. P& n; u' s7 J3 u  m}
3 v- v6 ?3 z  r7 b! t& W
6 ^* }. |  n" P
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 12:39 , Processed in 0.037030 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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