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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
. b; e% x/ T5 k! S下载以后需要修改bits.c文件:
. y/ y8 ?4 H4 p, s$ W/ R我仔细研究ITUG729代码后发现:
6 T8 S! B7 u: k. }+ _- f/ B; a7 |编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流1 i: `7 w5 J. d1 @2 p8 w% G
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。# W. L4 T7 l& U& E, I& Z& w( p( X
, W  q$ h: T- I& t
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。& l7 s7 m" `0 b: g6 s2 \( w) f! N

9 }6 h  j5 s7 a那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
5 C9 S% V: K) s3 U( Z- Z0 |我们打开bits.c,就能看到里面定义的如下4个函数:/ J% `9 s( q% o* U
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
  L, Z# E% F' M4 m; Ystatic int bin2int(int   no_of_bits, INT16 *bitstream);2 V9 R* W  u4 M" ]% w! V: \9 c- P
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
0 k8 G% M: p+ x5 d: xvoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;
$ V8 A4 o2 U8 U# t. p3 }, ]这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:5 S0 H7 [/ }1 Z; U' X7 v
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; $ y0 P- l: e' {: W( v+ E
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
) f, @. `+ ~9 V" n( K2 V& l  {& q/ G, y9 s( G4 B3 V" L
void prm2bits_ld8k(Word16 *para,unsigned char *bits)
# X3 w. {8 q! S  k- Q/ }. F{
4 o& C( k  o+ ]/ k   int i;
: f; @2 w+ t6 F   int bitpos = 0;
" w( d) ?8 `% |5 [& y   for (i = 0;i' J( ~+ N" w9 A7 p
: o' q9 w  R0 E( A( j; A6 H
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)% t7 q, M% ]% [' b
{
- \* h. H/ @, p! \2 o# r8 {   int i;
7 R: {8 _! ?1 g9 {  V/ w4 K$ P. Z   int bit = 0;  [6 n9 {( f0 }
   unsigned char newbyte = 0;1 ~0 D( Y* t4 {8 p0 {# X
  
( q0 z% K  u: {# Z. C) I   unsigned char *p = bits + (bitpos / 8);$ b; C7 j; J. Z  r, a2 @1 _
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
( \& l3 ^- e& N; Cnewbyte = (1 : [& ]* n: n3 l- ^3 A  [. L
bitpos++;
8 _; A: }  A( o/ _. h: @1 Tif (bitpos % 8 == 0)3 C: O  S" J4 t' u9 q; A
   p++;/ _$ R. Y5 z9 y& @. U
   }
% G+ o, V( B/ ]0 F( J4 W}8 s" ?! Q) b- w7 |/ x. N3 t
4 V* m# [1 P/ J
void bits2prm_ld8k(unsigned char *bits,Word16 *para)
) }2 V' `9 L0 v( @' |1 `, t# S{' p& ]9 m. K1 w8 [" w
   int i;. `: |9 t: ^4 M; ?% c# L
   int bitpos = 0;4 P1 x, w* Y& m! x5 F+ ^' [
   for (i = 0;i' I  z8 ]! R2 P0 L, W% d
+ O* B6 ?0 _3 H
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
! p, z  A) j; q5 Z) u) z7 i0 H: E: I$ c{, S! b  L1 h8 h+ X0 ], ?7 W
   int i;
9 M  ?+ Z+ c* z8 g9 S4 r+ I   int bit = 0;
% Y' ^' x6 [; d9 s" A   Word16 newbyte = 0;. m7 E5 Y; C8 \! y. R$ ]# v5 n
   Word16 value = 0;$ z6 @# L/ Q, e9 z8 G6 h
  
$ E5 v5 r# r8 \1 K2 ^   unsigned char *p = bits + (bitpos / 8);
7 p. V+ T8 Q" g! ^) D1 z  [1 k   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;" X. J" S! x  d6 u; t
if (bit == 1) {
8 k8 P4 D2 p" v: ^, M, M' q% J   newbyte = (1
) g$ ]$ o3 i- e% z   return value;* A, m2 d' B% c6 k% P9 l% i- u
}
2 I8 e, q5 V, \! b% O通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
9 y0 H- i, D# m7 u$ J
" T0 S! ~! C4 k1 M5 y! V编码器的代码能采用如下的修改方法
6 q: ?- S* }6 n& R# b8 B7 d/ s; K(1)修改coder.c:
$ b1 n8 T, F0 y1 uunsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char *// f( S7 d  a0 b1 q0 I
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):; U2 O! ]5 z0 W6 r# D* W' I; z/ ^
   frame =0;: G5 B, y. Y; G6 @2 q/ R
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME); y5 ^: s/ G; G! C% T/ A. j
   {* v0 \, }- C  Q4 c" E5 ~! U
printf("Frame =%d\r", frame++);
' P4 b4 p6 H0 M& ]& S! p6 HPre_Process(new_speech, L_FRAME);
# E, Y0 r# ?# g5 g+ ^2 Z/ J: ]# JCoder_ld8a(prm);7 |+ u7 ~: P' U7 h
prm2bits_ld8k( prm, serial);
6 c: m; L8 T) ]1 m1 k& W9 nfwrite(serial, 1, SERIAL_SIZE, f_serial);
! h# }! s% R! \# t5 Y   }  }9 J; ]( d0 k; b# s/ H# w: N9 L
   return (0);
4 T( B. q2 F+ X
. G2 ~% q. W' G(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:. K+ F$ @- t% e& u# k
#define   SERIAL_SIZE   10
; d4 w- d* N, D6 B5 q- N$ y* U2 o2 t8 g: E- [/ k1 V4 x, m) F/ r( d
(4)解码器decoder.c进行类似的修改(关键部分代码):, p( T5 @( k: s
   frame = 0;
# C, _- F& |  s4 ?  R) O/ ~$ Z   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
3 L% ^3 P$ h0 L, v   {& _+ ]) _2 i! s9 e: l
printf("Frame =%d\r", frame++);7 f, [$ d9 g$ T
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */0 ~# C  x, m( |8 }+ r5 c$ }% P/ j
parm[0] = 0;   /* 假设没有丢帧 */
; w# y1 K  O( L) C- eparm[4] = 0 ; /* 假设数据效验正常 *// c4 X" l: i$ ?+ l/ l1 o8 h9 m: O
Decod_ld8a(parm, synth, Az_dec, T2);7 P0 X0 |) a. h7 c9 T  [
Post_Filter(synth, Az_dec, T2);
2 y0 g9 ~" N' r1 G6 A! [Post_Process(synth, L_FRAME);1 I5 w) a0 _% @7 V5 V$ h
fwrite(synth, sizeof(short), L_FRAME, f_syn);4 _5 T; z) k& Q# G
   }
8 ^8 x, y8 \% J7 t$ O   return (0) ;
. z$ S4 L; f0 @' N' J; _通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。0 b, N9 D9 @+ i5 \, B
$ f0 _3 S: q# T7 e, W  m
修改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]得到,应该就能了。$ ]& m2 `& T5 s# _
封lib:& L# o' E) U* c2 \. I; Z8 C  `
va_g729.h
' L& B  y# Y9 T6 ?1 k#define L_FRAME_COMPRESSED 10
/ P" l8 i$ B6 a1 |8 D# [#define L_FRAME            80  n5 i" Y! ?6 F4 n0 N! v+ x+ D
#ifdef __cplusplus
) L9 V$ D" X$ q6 X- b0 xextern "C" {
& @( @6 H5 q' B, q#endif
$ A" H* `6 z. H, {  Avoid va_g729a_init_encoder();- T+ @1 c7 g2 l3 S' t
void va_g729a_encoder(short *speech, unsigned char *bitstream);
% @2 ]4 p5 b& Z8 G/ pvoid va_g729a_init_decoder();: E. d, d2 O; l* L9 @1 [0 j
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
' k" z% f8 b/ M# M#ifdef __cplusplus . t- z8 o$ j$ d% v
} 0 q& f. T% _9 m8 n9 a& f/ U
#endif, H- z! z: c: [
va_g729.c& i, l6 x3 N$ k* L- }+ c% T- R
#include <stdio.h>
( n. C, q# P! |: S5 O#include <stdlib.h>- I: u$ v/ ~. C/ ?; C' _
#include "typedef.h"8 I: P0 A! s1 l5 T6 Q0 K# H
#include "ld8k.h"
% f  A. G% T) N# F  J" ZWord16 bad_lsf;+ ^7 v8 b; E" H+ g
void va_g729a_init_encoder()
, j' a4 l$ E3 K: o" A( G& p{& u7 L3 ~$ E+ b5 x8 \! q
    Init_Pre_Process();
8 C6 ~: _: Y( p4 x7 b" b    Init_Coder_ld8k();
7 n& u! {7 O' A: s% t}
: o5 q8 g  ]6 t& j& R& H  O2 d$ xvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
. z) v  u+ _1 L{     
9 \# _2 i1 W9 s; G$ B    extern Word16 *new_speech;       /* Pointer to new speech data           */. S2 T% n6 c; L) j7 Y2 g- L
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
4 [3 _1 O3 ^7 f. H, R  j0 v    Word16 i;" U$ f; q! M; y" [3 c
Word16 syn[L_FRAME];7 X6 s  x! `3 p2 z' L! d5 J1 e
    for(i=0;i<L_FRAME;i++)
* m4 h% V, Q$ }5 y{  I3 z' C" a1 J) ^# ]5 J. {
   new_speech = SpeechBuf;
% x) x) @$ z6 D+ k1 w}
' `4 [, l, X) b     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; ! X) }. Y8 v8 s7 f
    Pre_Process(new_speech, L_FRAME);* {5 d, ~1 \* E7 z7 l7 v3 Z
    Coder_ld8k(prm,syn);
! o3 R0 Z2 N' j! `9 x    prm2bits_ld8k( prm, serial);7 `- R) [4 p& ?( y, H% y; g# w" ]
}
, y& g5 `" l: z6 e, J/ ?3 M( m  svoid va_g729a_init_decoder()$ R* H% N% p$ Z' y2 b" d
{- @) ~0 Q5 z8 u. c7 H- K
extern Word16 *synth;
$ o3 d1 c* [7 }    bad_lsf = 0;          /* Initialize bad LSF indicator */
( _0 f# r0 Z3 ]    Init_Decod_ld8k();
/ W& b- p" [4 x    Init_Post_Filter();
* P) i- j2 G8 _$ `; w    Init_Post_Process();+ }" l* C7 ]; h1 y! z
}# n) d. z8 I4 g5 K! {8 @. j( o) p/ r
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)/ C1 v5 J+ f9 U+ B; J1 T) ~8 o* J5 M
{
  |& T! x' I2 M# V1 lextern Word16 *synth; /* Synthesis                   */! B& |( @4 V  U4 O0 u
Word16 synth_buf[L_FRAME+M];
' A: [) |  n+ h& qWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */1 H+ ^$ c# _- Z% u6 k' @
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */8 h9 g! _. L% P1 B
Word16 T2;                           /* Pitch lag for 2 subframes   */+ A4 e3 f9 K9 C
Word16 i;
. j7 N3 n, j  O! C  k( \$ y+ F  O9 ^Word16 voicing = 60;
% S+ |; f: j7 l5 X( a; a: nWord16 pst_out[L_FRAME];             /* Postfilter output           */( s9 c) P: S! G# I
Word16 sf_voic;                      /* voicing for subframe        */
7 Z" n9 r  H# q0 jvoicing = 60;
+ N2 w% ^; m' m9 M    bits2prm_ld8k( serial, &parm[1]);
/ l; n8 v$ T* R. [    parm[0] = 0;   
( T# \! \$ {+ p6 L4 P         
1 K1 n. T3 C6 w& d/ D4 Y, C0 s    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);: R$ y. O9 p3 S) c3 T" M* q, s# a
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
% y5 i  u: E& f2 Y( y//--------------------------------------------------1 _$ f& w: k: ~! F
voicing = 0;% w) F- f, u4 o
ptr_Az = Az_dec;
4 ]  _4 h3 y# a$ P8 rfor(i=0; i<L_FRAME; i+=L_SUBFR) {
3 g$ u* s/ Z- c* I0 T, E   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
; j% G7 J- U  e+ T$ i" p; T   if (sf_voic != 0) { voicing = sf_voic;}
% \0 f' H! q) e" x   ptr_Az += MP1;
( p( K6 K4 ~0 U. l) M0 {$ s+ R}
- e6 L* u) g  N1 jCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
' t. K' H5 S, F! }, x! n//---------------------------------------------------9 I# D7 D% B: h$ X  A/ c
    Post_Process(speech, L_FRAME);   % s3 b% g6 R# U8 u
}! i( g5 ^6 {5 ?+ Y

6 M" a% L+ r# O# _
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 04:17 , Processed in 0.017808 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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