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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
4 e4 c! n( o* n, E" T, i下载以后需要修改bits.c文件:
, V1 j, B- O5 l4 H我仔细研究ITUG729代码后发现:" _: t& Q  C* [" G/ \3 e
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流6 P- q. c8 Z( G" d6 \
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
' g  L6 I4 ?7 i1 ]
$ ]  z/ y# U: Z8 f5 X" TITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。$ r$ t: `- X7 B/ U1 u

& M. C$ Q$ C. p1 T那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。$ ~$ M3 o3 ?+ x8 i3 F- x# }9 C( u
我们打开bits.c,就能看到里面定义的如下4个函数:
' X% R3 d3 W& h5 y2 Estatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);6 q( ~# s# j0 l8 |5 v4 Z% _$ `1 n  Y
static int bin2int(int   no_of_bits, INT16 *bitstream);
' _" P! H% L; R$ ~7 I) \, pvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; 3 }8 H# i  [  w) g
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
' u, ~4 [9 D% v$ Z% ~/ F/ @  J3 D这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:2 |8 l/ B6 l0 ~# {$ {: ^; k1 @
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
! R' o5 I, }8 z$ A2 {static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; % f: F/ J; ~/ V# s2 ?) {& H

$ H( X6 P: `! n( N; Tvoid prm2bits_ld8k(Word16 *para,unsigned char *bits)  |! E& z0 D  \
{- W' p$ S3 b- v/ t
   int i;
# `# @2 X4 t$ Z, m' j  W   int bitpos = 0;
. T0 q8 x! J) W: ^   for (i = 0;i
* U( L1 j/ _+ ]
/ i8 l* d# f& j% `& Y# g+ P# ]: {void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
- F3 n3 D" B9 ]7 E% Z0 v/ c{  R( [. x( r/ |! i: f/ D4 B
   int i;
* \( R6 }1 j& e' |$ I3 T   int bit = 0;: [: Y9 r3 \+ n9 s4 W
   unsigned char newbyte = 0;
2 o: }# f9 G% {8 y) ^1 v1 D4 M7 w* g  " r6 T7 i5 l5 Y% f
   unsigned char *p = bits + (bitpos / 8);. |9 H% ?3 p8 E* k
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;" U8 Z" c; K: n3 w
newbyte = (1
; m: [0 p' w0 p$ e+ L! C* wbitpos++;/ P; Q. y' D: F
if (bitpos % 8 == 0)
2 A+ U; X- R* y. v1 r   p++;
  G) D0 V' V  j, Z" W   }
2 B( G4 e# l. I) ~& C7 P}
: l* y7 c3 V8 `, K) E( S" A
1 E+ Z0 e3 I% `& A3 v: i9 v$ f  pvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)7 E" Y% j2 e/ G- w
{
4 E. C) `- S; |5 Y2 C3 h   int i;) F3 ~% e( |* m0 B- p' x3 g
   int bitpos = 0;, K& E' p5 p/ {6 e- \1 Q$ t
   for (i = 0;i% q6 f5 L" u" u7 o( `* y

# w% g  B& l$ O% x1 pWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
$ f5 y8 x' `  X) A" @{
" ]/ g. d( y0 }1 c6 N7 [   int i;, g; o/ r3 f2 P( G0 T& S4 Q
   int bit = 0;
" W2 {, C% |8 L8 f- ], u   Word16 newbyte = 0;
2 `( s5 `4 \; u( x   Word16 value = 0;
) T5 H" E9 {9 k: q  , g" |, D6 i7 H. N
   unsigned char *p = bits + (bitpos / 8);
8 X* E- G# A) b- [+ w   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;! E7 L$ [5 k2 Y3 t6 ~* f: b
if (bit == 1) {
) l! R, h3 ~  n# q; d   newbyte = (1 7 i' p% T7 Y$ t8 _) U
   return value;% R- W* b3 U3 j7 z) {, G
}
& W% \: I* H# w" d4 B7 x" I通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
, F6 K) H8 B! l7 y% j3 A! U3 V9 g4 _  i. |0 @
编码器的代码能采用如下的修改方法9 N6 E' ?8 z+ f7 V
(1)修改coder.c:
: W" |: b1 ~5 }6 i2 x% O4 ounsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
# }3 e1 U# x1 V; g% `' _, ]8 K2 g(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
$ X1 x% w7 G2 o8 m! ]- B   frame =0;
5 A1 U" J7 k: e% `   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
% v6 j0 S( Q7 `4 ~. y+ Z9 ?   {/ ~* T! F: {' i+ R
printf("Frame =%d\r", frame++);' {+ i7 |$ _8 A6 J- F- a
Pre_Process(new_speech, L_FRAME);
" s% W$ j5 s' V' h5 }Coder_ld8a(prm);
3 U4 s0 Q2 Q' }1 Hprm2bits_ld8k( prm, serial);: j. L  P9 L9 f6 s
fwrite(serial, 1, SERIAL_SIZE, f_serial);
1 x4 a  o8 f$ ^' A. `7 Z0 d0 r   }, R6 O8 G  g& g& c
   return (0);0 {1 _- n# Y1 O6 o
6 c7 ]* V$ b! {5 i3 l
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
7 ~& K" i( E1 @8 I9 j#define   SERIAL_SIZE   100 a5 L  Z% p' }7 j4 E% j

& ^" R; I7 \  N0 H0 A0 D(4)解码器decoder.c进行类似的修改(关键部分代码):
9 N) s/ b' ~- g1 o5 R, A2 M5 K! m   frame = 0;7 l* c- I' F/ \$ l' ^) Z
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
( a: C4 N; q, M" O$ a   {3 H. x& ]* L+ ?5 I$ _* \
printf("Frame =%d\r", frame++);
0 b5 t. U  g; C6 Q& m/ f( ~' qbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */& K$ P  |' [# @- l8 U
parm[0] = 0;   /* 假设没有丢帧 */
: g3 H5 x5 G& Xparm[4] = 0 ; /* 假设数据效验正常 */4 _& \% l3 K; o
Decod_ld8a(parm, synth, Az_dec, T2);- j) ]9 M. Q# a' V* e: P& |
Post_Filter(synth, Az_dec, T2); + [" _! F5 t8 i0 ~& D' s
Post_Process(synth, L_FRAME);
4 F7 X% v- U( J2 J; S% Pfwrite(synth, sizeof(short), L_FRAME, f_syn);& q3 w, }4 J' k# W% |
   }7 T2 n2 Q3 _  E/ s9 m
   return (0) ; : F' s& g3 T/ ?0 L
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。+ ], g" w/ ?/ a9 }9 l
5 ]% {( Q* j3 ]( l+ O
修改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]得到,应该就能了。, l1 \, u1 `7 Z. ]) [& V6 ?6 |
封lib:
; ]/ {) f  J* M1 x2 Sva_g729.h
7 _) a; k; |7 W: V+ i0 ?#define L_FRAME_COMPRESSED 107 w( ]" l6 O  p  d; `% T
#define L_FRAME            80
) Q( y' o4 P+ o#ifdef __cplusplus
; r( D& W( Q% pextern "C" {
1 J! }. P  G, X5 z) Y$ m#endif
' Q, ?/ X+ _* t0 d- d- _* ]( Q8 bvoid va_g729a_init_encoder();
. H' J1 G7 S4 C7 z+ h0 v: G( M  Nvoid va_g729a_encoder(short *speech, unsigned char *bitstream);
- q* c- x& ], ]) fvoid va_g729a_init_decoder();* X( D6 A% n( m
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);& V8 d$ r4 Y0 k3 }/ M" q9 @
#ifdef __cplusplus : R6 q& o' V- H$ ~
}
6 W9 }, ?3 ]$ H+ a% e# V* z: z0 y#endif
# d" r2 a/ \  Bva_g729.c
- V4 s" _/ \8 B( J# l  d#include <stdio.h>
5 @$ }9 S+ X* ]4 ^$ J#include <stdlib.h>8 K4 z1 @8 M) j  d  {9 e
#include "typedef.h"
( T" s6 q, a6 u; H) q; Z#include "ld8k.h"$ d" b" _4 R6 o+ U: `  Y+ m
Word16 bad_lsf;) [" L* Z" q1 {2 Q% M: R4 n0 j, r
void va_g729a_init_encoder()
' y- G: g$ `, n* {! M& x! O5 t1 K, ~{
" K3 i$ ?: E" R7 R- J6 `8 f    Init_Pre_Process();, |# N  c" _3 p
    Init_Coder_ld8k(); 7 u3 h6 d  H& g; [
}
4 ]. X/ p% L) X  @4 E5 vvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
- ^) T$ t3 k$ t+ I{     # v& ?4 Z, T/ Q$ W+ K
    extern Word16 *new_speech;       /* Pointer to new speech data           */
) M; J6 g8 p- u; @    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
- `- n! G' h" V+ E' u2 ~: d    Word16 i;
) J  @1 p* b6 @7 g2 ZWord16 syn[L_FRAME];
5 O: G) A* u2 \) l, E5 e; y    for(i=0;i<L_FRAME;i++)
5 [' ]: _$ d. S{
2 [8 t; [% B* M4 G" [7 O' q9 H   new_speech = SpeechBuf;
/ _/ |9 n, F3 J% \" L! A, M; [% M}* ~* h( _& P) [, F
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
  V" l) q( [% c9 }! {    Pre_Process(new_speech, L_FRAME);) r( g# ~* g; l& h
    Coder_ld8k(prm,syn);$ ?! b. h1 w7 k$ \. g- K
    prm2bits_ld8k( prm, serial);1 v+ L$ d  J) Z1 t1 U+ G2 v- I
}1 V: [$ T  {: s
void va_g729a_init_decoder(). l0 `8 g; m' l4 V7 S8 K
{
# S; c5 k$ y/ i' s; Oextern Word16 *synth;
% x) U8 P- m% \7 ?! w& J    bad_lsf = 0;          /* Initialize bad LSF indicator */
* l  u& Z3 q  l6 v' R% Q4 s    Init_Decod_ld8k();# N$ x0 ~- n' J! S. o, p
    Init_Post_Filter();( W  l0 O6 M/ k* C+ ^
    Init_Post_Process();! j& m/ }: I  l  J( v) E2 `
}, ?2 w( v) c2 @! ~9 i/ o
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)5 j8 H0 ?3 w$ a! R3 l. [9 l
{8 E+ _) \9 u( e
extern Word16 *synth; /* Synthesis                   */
( O$ m$ F- K/ N0 q* U0 hWord16 synth_buf[L_FRAME+M];
' a4 \7 w4 s+ Z: A1 @7 JWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */: ~) R) T3 R7 u: ~
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
1 K" M* x- `7 m$ b5 vWord16 T2;                           /* Pitch lag for 2 subframes   */
9 J, {) x0 O, i3 rWord16 i;
! E5 t# W& A- B& F, F5 H4 n) I% S$ hWord16 voicing = 60;) s4 x& R9 C4 \
Word16 pst_out[L_FRAME];             /* Postfilter output           */
7 K( B' O8 Q% L% G  a! ]) wWord16 sf_voic;                      /* voicing for subframe        */
( p8 K6 [* f( `% `. {6 [voicing = 60;* ?  A5 w, t1 g* x2 t* {* l3 r
    bits2prm_ld8k( serial, &parm[1]);
( z1 l3 M) V( g4 l2 O8 h" Y    parm[0] = 0;   7 k, o, X( V8 {
          8 E) \, b2 N' @5 [
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
$ w# I& v' a) U# t: x6 ^- NDecod_ld8k(parm, voicing, synth, Az_dec, &T2);$ E+ y& q* g) t% u  q7 b! h
//--------------------------------------------------5 i1 V" E' i( v/ S* {0 l
voicing = 0;
2 d( Z9 k  ?$ Q* }+ n" Bptr_Az = Az_dec;$ V& t  {0 i6 |
for(i=0; i<L_FRAME; i+=L_SUBFR) {7 W7 v  d2 e$ ^+ \3 t2 [
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);  g3 m/ ?; _; s
   if (sf_voic != 0) { voicing = sf_voic;}% w8 |+ X* v. T$ a$ |, S, P* Z
   ptr_Az += MP1;
$ Y  G" b0 f/ \6 n}
3 B( F1 B& V. s! k7 x) v; j& G- vCopy(&synth_buf[L_FRAME], &synth_buf[0], M);7 E' C7 \4 \  e* v+ ]% r" d, V
//---------------------------------------------------
& F! j6 V( |( ?3 l    Post_Process(speech, L_FRAME);   ) x' P/ d2 I2 @# N! \) X
}
9 C; }0 [' S# ]6 W9 N  ~! C8 y7 t6 Q2 H$ h  W' m- K" B9 O4 y" M; k
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 08:45 , Processed in 0.018879 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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