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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/- e- ?* b  f" r5 J. t
下载以后需要修改bits.c文件:
/ D  P8 \8 q. m2 A* ?0 V, _我仔细研究ITUG729代码后发现:
1 l7 t" C2 {3 z+ ?: \" ^& ]6 H5 L编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
% c6 V# h0 w& u) t+ J2 I,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
$ N: g0 S5 w' ^/ s% _% F$ ?& n4 H4 z+ X1 U0 q# ~7 ^
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。; W* D* }/ w/ |& @0 H2 c$ @

: p$ \! r& l- H8 {  O- \# t1 }6 P那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
0 X+ Y' Z* F) k# s, n$ ^% X5 c# e. U, K我们打开bits.c,就能看到里面定义的如下4个函数:
4 q7 J- J' H& Z1 bstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
0 K3 Z$ N. G/ _/ F7 H4 ^static int bin2int(int   no_of_bits, INT16 *bitstream);
' V0 r) ]3 J! a, H: T: [void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
/ K6 u4 x& e4 r/ M; Q$ j, Z4 yvoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;) k. e9 [$ P! r0 P! I
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:3 ^* |: {  ]) d# Q$ k; k# o7 p) s2 u4 C
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; " H: W& Q& B8 ^' B) I  I
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
6 U+ G. z. _, `8 ]
, q9 ~* J/ Y# V2 _4 K* j( H: Bvoid prm2bits_ld8k(Word16 *para,unsigned char *bits)
4 D. H: m# B2 C& E6 G$ b{
0 N7 g) g7 p0 i" q9 F# w   int i;
8 C8 s/ e0 ~6 x1 ^2 w9 B8 h   int bitpos = 0;+ C& y- O) }3 N" T
   for (i = 0;i/ P; K* O1 A% C# h) F' X1 A3 b3 J
# r% r: {4 I: g: B+ k6 c6 U) O
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
. k% ]$ \3 w0 R1 [" _; V& d{
* Y7 V( }5 B, \$ `" F( B, z: T! @   int i;3 Z' M2 I3 U  ?/ f
   int bit = 0;
* @* Q% o  O$ V& y: c   unsigned char newbyte = 0;
0 P0 S; v) ?8 N+ Q/ ~( M5 h" Z4 x  
7 t% i: D% m7 A( p  t   unsigned char *p = bits + (bitpos / 8);
: Q2 w! a7 t5 Q9 T$ S   for (i = 0 ;i > (bitlen - i -1) ) &0x01;" ]- |7 J) |! _  t: h7 [0 a
newbyte = (1
/ G% c3 n( Y3 nbitpos++;
& C: J1 r/ r) e  h" cif (bitpos % 8 == 0): C4 j/ h% L, u- X
   p++;
  f. V. v& c; c" b* V& A/ X6 _   }
* v" X5 P- n6 G/ I, t}8 k* z4 X. E+ s! Q
" i9 J9 \" A8 b! P, e
void bits2prm_ld8k(unsigned char *bits,Word16 *para). ]8 F9 R8 \( s/ o$ m
{
& Y# R* I  w7 d, _$ E* o   int i;
9 M; d% R$ k7 o, E4 i1 h   int bitpos = 0;
! u* O% v# |7 z' C   for (i = 0;i
. [' J2 y) V8 t' W- v- I8 d( p- Q* C% o
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)) t* U# ?. R$ j. t) y
{9 J+ p4 _0 u/ d+ }7 v5 ~
   int i;, z) v; }4 v" }& {2 I
   int bit = 0;' w" D  a0 c  z  b7 G9 \' S
   Word16 newbyte = 0;) [; z# ^- @( [4 x4 z
   Word16 value = 0;8 h% }& j7 a6 t7 T
  $ b+ V- ~& y1 U( T
   unsigned char *p = bits + (bitpos / 8);$ i7 G3 Z$ D1 [. V
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;5 o$ D/ l* D7 B6 J* P# K( A( f
if (bit == 1) {
& s6 g- _2 L2 t5 L5 N   newbyte = (1 % l; n6 t9 `3 J
   return value;* I' K7 n4 G/ S0 X% e7 ]+ m/ c3 C- e. y
}
1 p1 h; c# R/ g* G- {# c通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。6 u+ }: t/ H& V- s/ f$ b

. L$ }. }7 f" C  o3 A8 k1 t' u编码器的代码能采用如下的修改方法
: g3 i: }: d! Y5 @: }(1)修改coder.c:
( x( ~" A0 f+ F; I/ U' `* |unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
- E5 M' g* a- j" N1 i9 {3 s(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
* Z9 V' l$ R* K. n, [! h   frame =0;
: o* V4 Q6 X( E- ]! V$ `   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
! O8 M7 d* M, t+ r" R1 g   {! X9 [7 k, k) Y
printf("Frame =%d\r", frame++);9 P0 s' x( q0 ^( Q' P8 a8 t
Pre_Process(new_speech, L_FRAME);. W% K2 H# I/ T- i
Coder_ld8a(prm);7 m. l! L4 j" T6 b; ~
prm2bits_ld8k( prm, serial);( t1 A9 l$ f0 E7 I
fwrite(serial, 1, SERIAL_SIZE, f_serial);
8 m; |  B5 u/ S1 v- S' [: {   }
9 R# z, c& a$ Y% a" G   return (0);) H- l4 J* ^, A
2 A, r( H$ M* h, t
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:7 ~0 n1 j0 V5 C
#define   SERIAL_SIZE   10; w; ?# G& N; m  ?; v4 L

( m+ O% A! u3 M, C4 t5 u  A: z7 N(4)解码器decoder.c进行类似的修改(关键部分代码):
# L+ B# u8 j  ?! x5 ?1 X7 j; P4 T   frame = 0;
9 P8 e: p5 x( v& `' ^6 _   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)# u( J8 s/ r1 y
   {2 L. t# {. i  K
printf("Frame =%d\r", frame++);
4 h7 T+ B1 W% Nbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
# a: @5 I/ I( K$ P" Y6 Sparm[0] = 0;   /* 假设没有丢帧 */
- w5 A0 u  [8 ]+ Uparm[4] = 0 ; /* 假设数据效验正常 */
0 `; A9 i; Q& q. i$ x9 Q6 UDecod_ld8a(parm, synth, Az_dec, T2);
7 y1 p" O1 i/ yPost_Filter(synth, Az_dec, T2);
& p$ m- g* i8 k9 N% }! xPost_Process(synth, L_FRAME);3 V/ I/ B3 B; K7 b1 i  K# U8 A
fwrite(synth, sizeof(short), L_FRAME, f_syn);" x! H7 `7 B5 H
   }8 I; g# e* n) G, V4 ]# @6 ~: X
   return (0) ; ! U3 f0 \. ^+ L; L% I, L
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
" @: R/ {# I  U% P
8 {  n' o7 l  h" R修改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 E5 I6 Z. R; i1 q封lib:- S7 s7 x" k8 G6 ^5 b
va_g729.h8 P: M7 g# q4 C
#define L_FRAME_COMPRESSED 10
% N# c$ N& u) U#define L_FRAME            80
. W; l" x# b3 A! S) k#ifdef __cplusplus
, C. {7 A1 Q7 Eextern "C" {
( A' w- @) T) H; ~#endif) r) ]4 c, ], }; G3 Y
void va_g729a_init_encoder();
, b) X5 I+ f5 q. @! q6 d3 B; bvoid va_g729a_encoder(short *speech, unsigned char *bitstream);+ T4 G& M2 }& G1 A6 B! f8 u8 y6 E
void va_g729a_init_decoder();
* S3 [6 l3 _  k) p6 ?- f7 p- lvoid va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);0 E4 C& F( c4 A7 u/ l
#ifdef __cplusplus 3 i9 L" n1 N, j( i+ A9 [
}
9 }& \- W  E0 x+ U$ V. z#endif
# ?, E, T* P% b) u' ava_g729.c- m7 J* ?! M8 {$ |. x! L! c
#include <stdio.h>
: T; Q# x9 J& z( _! x% M#include <stdlib.h>
" i( P5 T: `( w% l8 z* j3 t6 A#include "typedef.h"
" j- Q- q& u# Z3 z  g& p, z#include "ld8k.h"2 G( l+ e! o; l
Word16 bad_lsf;( Q7 ~* \. y. z! y. u
void va_g729a_init_encoder()' l8 n0 p  v1 V
{4 [8 S; b  I% M( v( G
    Init_Pre_Process();; |% k& a- j# N. r
    Init_Coder_ld8k();
/ Y. v8 a) X  E: F& w}& U& n+ W  o" H/ X% ^$ [3 y$ F. S7 c, |
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
/ P0 Y, q: x( u; W6 @" ^! v1 @" \+ D{     
$ ?, ?3 {# ?2 |/ C1 {    extern Word16 *new_speech;       /* Pointer to new speech data           */
1 L; i5 E* \( L( Z# v% H1 O    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
8 K/ j* L7 r( a' \! p+ _5 Z5 A    Word16 i;; a7 X- A! d1 ?5 G* }+ ~
Word16 syn[L_FRAME];
8 Q9 Q6 y. o& E" W- b    for(i=0;i<L_FRAME;i++)6 g" U2 C& i2 n2 p
{
) u! O1 y! |0 f! f% F4 Q   new_speech = SpeechBuf;
9 B0 E) D/ b5 Q9 [}( v, P1 o/ |! O8 R* G
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; # i! @( G. p( z& p) R
    Pre_Process(new_speech, L_FRAME);
. q0 q2 k7 B6 t. S3 p' e, [# e9 g. w    Coder_ld8k(prm,syn);
2 {' n  c) Y) b0 x. E    prm2bits_ld8k( prm, serial);5 [0 S, a# T" r# T: H* Q
}
, _1 y4 f# A. J9 Z+ b# ]! D% m$ @void va_g729a_init_decoder()4 h7 ?' h4 j1 k1 t+ p0 B6 ]( F
{' G% q9 {, n0 F, n3 |1 j. Q
extern Word16 *synth;
, d, @( \# v9 U: A% y% v) y    bad_lsf = 0;          /* Initialize bad LSF indicator */
( `/ o1 g1 D6 R& _    Init_Decod_ld8k();
! Y& T8 o. e" x$ g    Init_Post_Filter();$ ~- v+ H3 T; V7 `6 F  v. Z6 Z
    Init_Post_Process();' W7 a3 @: s5 o+ Y- e. ~8 U
}% H% a  S0 u9 p+ o- o0 W9 r' P" P
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
1 ]: B* ]/ R: x' _: d{
8 y0 B+ U) j0 r8 o' _$ k6 aextern Word16 *synth; /* Synthesis                   */6 l4 V, h, z1 e
Word16 synth_buf[L_FRAME+M];
8 E. f( x1 k. E0 l* ?1 j" ^Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
! U' `# w2 [9 A% X1 @Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */! m% d* j% Y+ ~" o
Word16 T2;                           /* Pitch lag for 2 subframes   */
" y7 h  A( y# KWord16 i;, w$ H1 z1 N: H5 N% ^4 w1 |
Word16 voicing = 60;
, x' h6 K0 V9 H% a( L. dWord16 pst_out[L_FRAME];             /* Postfilter output           */
$ h2 n6 f# z# S( {" `6 FWord16 sf_voic;                      /* voicing for subframe        */" ^/ Y9 o" j$ Q' y6 U6 ?: r: c
voicing = 60;
5 c# w% _8 G, Y9 ]  g8 Q    bits2prm_ld8k( serial, &parm[1]);) |0 \9 u  V' X, C1 V; F
    parm[0] = 0;   
3 I* Y, v' Z/ K5 G: W          / w( I1 W7 M$ p# {
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);5 V4 J+ z' T5 k, i+ N! K
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);8 A; ?8 G+ y, E2 R3 T% Y1 d* M
//--------------------------------------------------
& {; H" _2 |, L4 F$ K$ I9 M2 i9 D' Pvoicing = 0;
& t: L, c" M5 C/ Wptr_Az = Az_dec;
9 \6 P: S% t+ K/ S5 U; t' A) Y7 Xfor(i=0; i<L_FRAME; i+=L_SUBFR) {
/ d5 `: K3 e! [7 ^; e- i% d& W, o   Post(T2, &synth, ptr_Az, &speech, &sf_voic);4 \! u! V  T1 T, E1 E) y
   if (sf_voic != 0) { voicing = sf_voic;}  W0 J) n7 J6 I0 w# z
   ptr_Az += MP1;, T, c5 N+ H6 R% `& |) H
}
) q3 H- \& b& K+ ?& S! d2 f. {Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
# L% p2 H7 O3 c. R2 ^//---------------------------------------------------
! W' R1 S5 @* W! R$ C. R6 Q    Post_Process(speech, L_FRAME);   - Z7 L6 q( L& O1 [9 K. [- P) y
}) g0 E% e5 ?3 i9 c+ [9 A

1 D, j3 @( q: X1 P5 |/ }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 22:52 , Processed in 0.018293 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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