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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/% }! w- f* p$ a
下载以后需要修改bits.c文件:) @9 @- Y. X& I3 r7 a; p1 v
我仔细研究ITUG729代码后发现:1 M8 w/ P4 R! X3 {) e+ |
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流0 ?- B$ y6 a" @. H  l, f- w
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
, j. r( U6 ~) G1 v
9 ^9 w/ I: W( l! [ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
. @# Y; v2 s2 w1 P) s' _. Y* A, ~
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。2 q0 N3 J( j) `& Z
我们打开bits.c,就能看到里面定义的如下4个函数:
( r) D8 ~* e. Tstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);/ E$ A# J  o, `% l+ Y
static int bin2int(int   no_of_bits, INT16 *bitstream);
7 G5 R9 @: b& k* Z; d) Jvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; 3 G+ F9 u8 w1 @. `% W- Y
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;8 U. K; E- q: y% c$ L
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
1 L+ ?: v' z9 U' I$ ystatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
. Y8 @" x' K9 [& |+ sstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; # J/ L  Q# }! M7 m7 p5 q/ W

+ b: ^+ C) P: I4 H* B4 [void prm2bits_ld8k(Word16 *para,unsigned char *bits)
7 C+ L; @9 Y6 ?{
2 A* D; U# [% g, R7 J1 B   int i;
5 s' m5 t5 E/ W; X3 z8 y0 b   int bitpos = 0;- y+ p8 {- F( F# _  k) \) D
   for (i = 0;i# Y( n' o, ~. V
  i( r9 r. g4 b8 i
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos): [! o) C% e5 T
{
& x" p3 v7 e8 I; x   int i;
5 R- B: p$ M# m6 b   int bit = 0;/ s  k; {( v1 z+ C, H/ i& M& f
   unsigned char newbyte = 0;
% U4 _, l& C( w) P5 g1 V1 E$ x  ; O9 I/ }9 {! s5 J. d  r/ R  x: c
   unsigned char *p = bits + (bitpos / 8);
1 E. f$ {6 \' }4 H3 M6 U: b* W   for (i = 0 ;i > (bitlen - i -1) ) &0x01;* A' ^) X$ z4 p0 L
newbyte = (1
% D2 t, p9 w% m2 G+ ~! U1 H! @bitpos++;
% i7 [9 e3 _- y: \if (bitpos % 8 == 0)- M  v. c* g" @* b7 Y4 x7 C
   p++;; K5 g: u+ t4 i. v9 N' |" a- Z
   }3 x7 _* Y& s$ i2 N1 C2 q: F2 k
}
# @, e7 O7 i- w5 h+ j- d% U/ f1 q  [' W* m( I. j7 L
void bits2prm_ld8k(unsigned char *bits,Word16 *para), e5 S5 S( C* w* A2 o  t! G7 S
{. m0 u& I/ k2 q
   int i;
% e) A" Z! `. z# K' G$ A7 l$ K   int bitpos = 0;1 x$ f+ ]% z+ E* _  m$ m* e3 n) \* X
   for (i = 0;i6 z( ?' R4 q0 D7 X

3 S( U" ?: ]4 B4 kWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
) \# f  T8 q9 n" w{
) ~/ S7 T. E5 n8 o4 _   int i;
7 N% `5 g5 x- p! O. L2 `   int bit = 0;
& m4 X( G% t" u% U   Word16 newbyte = 0;7 M% b7 g5 W# y1 `  Y' C: X6 L
   Word16 value = 0;
7 O+ ]2 {, n, Z8 E) G  3 l7 T. s! a# \/ l1 E
   unsigned char *p = bits + (bitpos / 8);3 U0 _- P% ~* J% H: y. F/ K
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;3 r( p- q' U7 V9 `6 a
if (bit == 1) {  Q9 i& [7 a% \- N" e6 J, B. S1 H
   newbyte = (1
  l: o9 r2 {- [. C   return value;. e" ^7 w: O  I
}/ x; R/ M; x& M0 u' _/ z1 x9 r
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。- t3 V0 c7 W1 T; }# _

6 i/ U! n3 A8 s3 n7 m编码器的代码能采用如下的修改方法
& M: w1 F0 K" e8 x1 [: ]( Q(1)修改coder.c:
- `: t! Y& P( ~unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */# B1 o8 N! n; t( q- }3 D
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
8 [- Y- T& Y( c* [7 b   frame =0;; _( j, k' n6 y3 L
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
; x' w0 u: _$ A# h   {
; p7 f, W% Q4 Hprintf("Frame =%d\r", frame++);" Y5 v: Z: B& R1 `+ D
Pre_Process(new_speech, L_FRAME);- J. C3 z- r- o% u( E
Coder_ld8a(prm);% }, ?& w9 k3 S0 |) d% o* d/ k
prm2bits_ld8k( prm, serial);
+ l' d# Q! q, l7 `7 E" N  dfwrite(serial, 1, SERIAL_SIZE, f_serial);. J, l9 I% O9 y: Z
   }; x, D4 R- Q" d; G5 y
   return (0);: _: o. Y: d9 J4 o) G' c+ C
* d4 B# D- j: Q$ y) `' d6 D, u
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:5 w5 r, r0 a8 ]- f
#define   SERIAL_SIZE   10
4 b8 o3 x8 w+ u5 g) ]( ~3 j8 b' l* f& _0 p3 b, N
(4)解码器decoder.c进行类似的修改(关键部分代码):
% E& r  X) @; _' I- N   frame = 0;
. C# r3 D& c" A& l. O8 x   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)9 e3 f! M1 B7 i) `' {# ?* Q% K0 a
   {! Y" ~# E, h: l! i9 e
printf("Frame =%d\r", frame++);+ e( t: G9 w; |0 o6 ]
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */* ~) R# P+ I: Q2 O; H# n! \
parm[0] = 0;   /* 假设没有丢帧 */% p+ T6 j' O# [' k: G
parm[4] = 0 ; /* 假设数据效验正常 */
' d  }% ]  S! }. k2 uDecod_ld8a(parm, synth, Az_dec, T2);
$ Y1 Y( {% s. }9 c( ?2 T. x( ~Post_Filter(synth, Az_dec, T2); & ^. d- t2 F& ?$ b
Post_Process(synth, L_FRAME);7 G" t3 ]* j: D: n) b
fwrite(synth, sizeof(short), L_FRAME, f_syn);
0 c8 \! d: Q. I* g2 b   }  j: V+ I6 f3 }/ O$ ?7 f$ O
   return (0) ;
! d) S. D, z( E/ J' z3 ?8 o$ k3 H通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。- _- o; o* V' e2 f6 U
9 b1 u9 {5 c0 ^
修改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]得到,应该就能了。
  J/ X- C& A0 j$ g) Z; [: `封lib:
" n& B6 V$ ?" Sva_g729.h0 |5 _: F# B( F. Y% C- c4 a
#define L_FRAME_COMPRESSED 101 q- v, e1 S6 p
#define L_FRAME            80  m$ x8 [+ ^- F
#ifdef __cplusplus 7 z0 L* O" p3 W# ]1 b/ y) K/ ^
extern "C" { ; L, G; h0 K$ T. A7 G5 J
#endif
( a1 R2 }5 i1 d' w3 k9 f& l) G. Rvoid va_g729a_init_encoder();
3 @+ A" w( H$ d+ Z/ Q; Xvoid va_g729a_encoder(short *speech, unsigned char *bitstream);$ ^& u0 X: M- V9 _2 L( P
void va_g729a_init_decoder();) `; v8 B3 i) @: ~
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);" p2 G7 H( Q  A* Z) a
#ifdef __cplusplus - k3 A0 R0 y$ ~: K: a3 C5 ]7 S
}
. F6 k- c. l% I2 l0 A$ u, O#endif
% T( r0 M0 }+ J1 A" f5 y5 ?va_g729.c
# ~; ]5 f5 M' C5 H8 B, a8 ?#include <stdio.h>
& o8 t$ A: g5 n( t; k, P2 a; d#include <stdlib.h>
: [2 ^$ T* C$ W, ?#include "typedef.h"  x& Z' d" f) A) P9 C' {' f4 ?
#include "ld8k.h"
- y& s# V1 Q: oWord16 bad_lsf;
0 S5 \$ ~; p( a* I; wvoid va_g729a_init_encoder()( |4 {5 q1 b+ J# h" H
{; _# ~2 {( r8 K! a& ~4 Q3 a  U" H
    Init_Pre_Process();
; ?& g, I# S# p8 D( B3 @    Init_Coder_ld8k(); ! ~- P; w0 [7 N
}9 D# g4 t0 I# Y/ _3 c( y
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)6 @3 l1 m! t- j! c* o7 a8 n8 j
{     0 z6 z( u. Q' b0 \1 w
    extern Word16 *new_speech;       /* Pointer to new speech data           */, ]3 E; k' `$ U
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */, r8 b+ p# o7 ]& c  u. e6 V
    Word16 i;
7 h" z6 y$ k0 e2 S3 f5 WWord16 syn[L_FRAME];
+ m6 G: ?6 ?9 f+ [8 n. M    for(i=0;i<L_FRAME;i++)
% G7 k, \, V# ?5 F9 q! }{
3 X% O4 i1 L- d5 R. R  g   new_speech = SpeechBuf;* [0 v, M* w: \# ]- _/ G2 R  }
}8 D' e6 I, D4 D9 O* [
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
6 S4 ]2 E/ o% o0 h! W3 ^    Pre_Process(new_speech, L_FRAME);% L4 j+ {" D4 C; ]
    Coder_ld8k(prm,syn);
0 K" I2 g2 g/ y3 n$ S& ?" j    prm2bits_ld8k( prm, serial);
" p6 `) x7 w7 z$ l}
9 I8 g* T, x# ~" ^8 r: q& ?+ t5 R" qvoid va_g729a_init_decoder()& U* K! B  E1 O# G4 X
{
/ u1 X; e& [: C1 f6 o4 e9 z% Oextern Word16 *synth;; R/ t" q# h  A
    bad_lsf = 0;          /* Initialize bad LSF indicator */: |( T5 i! `. \! v" j8 x
    Init_Decod_ld8k();
! Q5 L% j, D/ Q0 g; \( T: ~    Init_Post_Filter();
0 X" q1 g4 |- T" g' D; }" k9 A    Init_Post_Process();
' k4 l. I( M* Z}/ J: V! L; \( ~: h" R- v! S+ E/ A
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)8 K! H2 U6 o( F  K: F  v
{* u: ?% f) t6 W* ~/ D( l
extern Word16 *synth; /* Synthesis                   */0 a! ^  w( d$ Z, {$ b6 b* ]
Word16 synth_buf[L_FRAME+M];, j: P4 Y* I2 V8 [. _) \3 r' I
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */! b/ X. Y" ~4 _9 Q) n" G- \
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
* i5 @' k" H1 T: D2 q% l+ UWord16 T2;                           /* Pitch lag for 2 subframes   */: E( ]0 ]" v1 ]+ E9 x
Word16 i;
1 D( G/ Z( k5 F4 SWord16 voicing = 60;
7 o( e" j4 _5 C) tWord16 pst_out[L_FRAME];             /* Postfilter output           */
6 p9 R! `2 F& Y  U* YWord16 sf_voic;                      /* voicing for subframe        */
6 a# A" V0 E: B7 S% c4 Mvoicing = 60;: M# \9 E, N1 l* S0 F
    bits2prm_ld8k( serial, &parm[1]);
7 \: p6 \# f1 ^0 E4 S" k7 U    parm[0] = 0;   
$ o: T2 Z7 z; ]& E          ! T: f9 Q7 M( ?) S$ n: n% M
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
' {  `% ]* Q: O8 A$ }Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
  g' H: q8 `! ~; ]1 X//--------------------------------------------------# \  T( ?- b8 F# ~4 y, e7 r
voicing = 0;- \) y. m6 M* M+ N7 `4 m
ptr_Az = Az_dec;
; D  O! i+ U0 W# l: s4 J' [2 W& i, kfor(i=0; i<L_FRAME; i+=L_SUBFR) {) {" `( V' i% t& ^. s
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
8 \; ^6 O5 ?( w" s9 o; a   if (sf_voic != 0) { voicing = sf_voic;}! p  z4 l9 B+ `8 _
   ptr_Az += MP1;
& W& D, ~, w. E  \6 D}
2 m+ F0 R: u6 ~, j; M1 o/ VCopy(&synth_buf[L_FRAME], &synth_buf[0], M);+ D- U% v8 [0 P  |8 q5 S0 a% ~
//---------------------------------------------------7 E3 X/ ~4 F. B4 x1 F. v. b
    Post_Process(speech, L_FRAME);   % C0 \* M  J7 ~, X" L0 @) z" @) h  r/ _: s
}
6 A+ y3 S% H/ A' w) ^: M' [
8 T$ o9 V) D2 F7 F/ r5 {$ Q
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 08:53 , Processed in 0.035009 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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