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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/5 \1 y" w: d  {; ]3 ^
下载以后需要修改bits.c文件:
% m) }8 }' ?) i8 J我仔细研究ITUG729代码后发现:7 C0 j& k; ^% u( n$ i
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
- \, l8 }* \9 y5 N3 f  B,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。5 y8 @8 C, p3 S
/ O/ J0 a: c  a' s  O* x7 H  a
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。, y3 q) c1 E' O% i5 w) D' K/ q8 U& W
9 s+ K( x) n2 I% l3 f# \
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
- h# U5 ^! {3 w# c我们打开bits.c,就能看到里面定义的如下4个函数:
8 |% A2 H6 e" Ostatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
* C' ?% ~4 E0 S1 Dstatic int bin2int(int   no_of_bits, INT16 *bitstream);
# O5 X5 ]7 K) xvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; 3 U+ S5 e1 R- Y& y1 I- I
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
; d' a; g, q. E0 b: Y这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:4 P& F" B& C. t, ~3 d% f. H
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
- H3 v) b1 t; `7 nstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; $ J0 o! A$ L6 [- ~7 _6 `! Y3 y
9 ?5 r3 i! n4 G/ U8 @- X# z8 G6 a
void prm2bits_ld8k(Word16 *para,unsigned char *bits)& U' H7 q5 q9 m& M* F3 C* h
{$ n9 J. N6 S9 ]" `
   int i;" }+ v6 n9 |8 K+ w
   int bitpos = 0;
$ e: Y5 \  h* v) ^  u' g3 H   for (i = 0;i% R3 W0 N5 k, C& L: J1 n6 @2 W( }% E
  |; M  n' s5 h8 v4 w8 n3 b
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
- q* ^! M- o  {, O{
5 O  h$ X$ u& b   int i;
6 ]1 E7 y5 n7 x' p( q   int bit = 0;
* J+ ?7 c( F0 e2 o% ~5 c   unsigned char newbyte = 0;% s; U8 i9 |6 s( E: e% h
  
" @, f( m2 m' W: s: {: m1 \; Q/ F5 P   unsigned char *p = bits + (bitpos / 8);
! e2 Q3 _0 H0 o/ j( }* s   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
  \- ?* p& D  H" S& W: vnewbyte = (1
+ @6 {: Y! P+ |/ E1 ~( x- n( s9 Wbitpos++;
* f6 T! b4 P& e/ xif (bitpos % 8 == 0)4 _% B9 `! g. Z) V
   p++;: X' i/ [. W2 e1 L
   }0 {& e" r# b. W! V
}+ q8 r$ ^: `6 S3 g2 j
* X8 {0 a' \& _7 U
void bits2prm_ld8k(unsigned char *bits,Word16 *para)
3 `3 u: I2 \6 |4 [{, a3 o: |- G/ h2 Q3 O
   int i;
( Q6 u8 E2 F* b8 i5 r   int bitpos = 0;
, }* g" E6 i; q   for (i = 0;i
/ I6 J7 |0 {; t* ~' f) j6 e$ F0 n5 v9 N. M  S
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)" o$ e1 f% \/ h% V  z
{
7 y- ]; x, S/ |: C: n4 e& @   int i;
& N; h* ^$ ?& r+ |  `   int bit = 0;/ h8 d7 X" `/ w. s
   Word16 newbyte = 0;4 l) ]. x  P" P
   Word16 value = 0;. J' e/ n& U8 I: q7 U+ G
  
" q% Z) {8 R' G7 a7 L, x+ S+ e0 L   unsigned char *p = bits + (bitpos / 8);8 T6 C9 U1 K% M3 X% c' q
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
. `: a) h. ]# V7 A! Zif (bit == 1) {' ~) N( W+ Q% z. N0 Q# u
   newbyte = (1
" x; {: i, n7 x6 D' @* S   return value;
# K6 I/ p, \; H' P$ N% l}2 z8 j8 q3 I$ K9 a  |7 p, M2 i
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
6 @8 q1 g/ H. Z- Y2 g
# n* q; s) J. j* Y5 [, o" W编码器的代码能采用如下的修改方法. ^' R+ Z4 G% E: j8 m8 b5 f
(1)修改coder.c:" q) a/ M* `0 k8 l! t
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
. R) Z2 P1 W- F/ N(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):' k, z8 D- t, d; r4 U5 R
   frame =0;
: ]+ d2 F9 B- C   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)0 o) D: @4 x$ W7 E
   {. V5 ~  B5 O8 p0 C: H
printf("Frame =%d\r", frame++);5 U+ Q: v% i5 g
Pre_Process(new_speech, L_FRAME);
& h7 ~& \1 i4 JCoder_ld8a(prm);
% t; D3 }" V/ _  ?( f, |  @prm2bits_ld8k( prm, serial);
  |7 ^+ t! _8 f( L4 R/ T: n( wfwrite(serial, 1, SERIAL_SIZE, f_serial);
  e7 Y3 M3 Y4 H! o4 A2 \# t. g   }
3 Y  k- N/ A$ Q2 m   return (0);
5 V' t5 S7 n- e& B
1 o3 h9 N7 Z& w" q" g(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:2 C7 i$ {, z2 \' |4 y
#define   SERIAL_SIZE   10  p1 D! Q  V- I7 A# u# N
) J4 U$ ]0 @5 w( O
(4)解码器decoder.c进行类似的修改(关键部分代码):
- k2 o% ]! s- ^   frame = 0;
( S" c5 g* X$ J7 y  W   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)# x7 n: J, _2 i" N) v9 K
   {
7 F% C; q8 i" J' \2 l) g1 Pprintf("Frame =%d\r", frame++);
2 a) D5 z/ d% F; T- G; Sbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */# p8 x6 U# f( f0 @
parm[0] = 0;   /* 假设没有丢帧 */
2 p+ A% X% J" ~8 M- Sparm[4] = 0 ; /* 假设数据效验正常 */6 E: ]. {3 W8 {, P9 w
Decod_ld8a(parm, synth, Az_dec, T2);
- Q3 t( H; ~' Z" g7 |Post_Filter(synth, Az_dec, T2);
5 ~! J7 j& ~' R/ _Post_Process(synth, L_FRAME);! g3 d# |3 q3 y3 G" j% P
fwrite(synth, sizeof(short), L_FRAME, f_syn);" W# r* q/ ]; B  b% D9 J4 `
   }
. L, _/ |0 `1 r1 Q   return (0) ; 9 V$ }" A7 ]+ G+ O
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
5 n; R& z7 b. Q5 B, v6 r, t  w1 f) u! E* R2 c
修改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]得到,应该就能了。. j6 r# ]9 ^: B+ h' I* Y
封lib:5 k9 O. x. p. A
va_g729.h
& i) E  u" g; Y  d0 r#define L_FRAME_COMPRESSED 10, O* R1 _% e  ], q8 o! x
#define L_FRAME            80' b$ {! N$ [/ h( [" {& y
#ifdef __cplusplus
" g7 Y* i- ?) y* C( Eextern "C" {
* c" K# E; x5 n8 K3 E( n5 @* v8 {#endif$ ?5 n$ c) A0 p! E
void va_g729a_init_encoder();
( M; i6 n- r* g% X9 ?  evoid va_g729a_encoder(short *speech, unsigned char *bitstream);
; k6 j( J% P1 U: n- E4 Lvoid va_g729a_init_decoder();7 s$ m" z) ]! u+ |* @) N; M3 K
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
# ]2 i0 \  ?: F$ \4 h#ifdef __cplusplus ' o7 e( Q6 U) w( D
} / K' l2 n8 F# G/ S& e& R
#endif- b+ M6 v6 Z4 h& h
va_g729.c, F+ `6 \) G; L5 a* d3 x% c8 n
#include <stdio.h>$ P) ?+ x, ~3 R( E+ o
#include <stdlib.h>
9 O# R' R. K, U#include "typedef.h"
. H4 `' r! V; y- Z3 _% q& M#include "ld8k.h"' B% ^! Y8 r; \# l& \( J- C  W: r+ s2 }
Word16 bad_lsf;) [! g2 o7 `. E1 c
void va_g729a_init_encoder()5 ?* J- h6 A  S
{
7 z% }! s8 e$ Q9 L, L1 Z    Init_Pre_Process();
) B4 h* ?9 h& }% _2 U6 a; F    Init_Coder_ld8k();
' M  h5 X+ [- J: S6 D& O9 v$ v}1 i7 Z1 d' i8 M$ m% F
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
# }4 I! s. B: f( D7 s. v{     
( K$ `8 S9 d* W# S9 w/ \+ Q# d    extern Word16 *new_speech;       /* Pointer to new speech data           */. a7 E5 v9 a- b. G) F* r" e
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */. @; g8 @  f. Q) d1 c
    Word16 i;8 F: M1 _+ X; v: l! ^: h0 o& Z
Word16 syn[L_FRAME];6 z4 l' ~9 W8 o8 s9 o) Q: Q
    for(i=0;i<L_FRAME;i++)
1 [3 z0 x( u, c3 ~/ P{
6 O. j; W( m/ e# c, _, [. o. ~( V   new_speech = SpeechBuf;
) z* N* B& F& S1 w8 `' \3 ]3 P  `* _}+ G- H5 D( Q5 F; A; k( b
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
6 j1 }7 y  L8 S1 o: h7 e9 J4 ^: k# A    Pre_Process(new_speech, L_FRAME);
  l) i8 ?. ]/ ^$ H- y7 d) d0 a5 O  D    Coder_ld8k(prm,syn);
1 l. q* ~1 k7 S8 D; G+ p    prm2bits_ld8k( prm, serial);
, N& L+ u' D* k( g$ y8 E) e9 a}% j' a+ p% {. |" i2 |( j
void va_g729a_init_decoder()- Q/ t. A$ ]' O& T0 k0 T
{8 e! @+ [1 I) G9 x; y
extern Word16 *synth;* h( p/ d2 Z* s
    bad_lsf = 0;          /* Initialize bad LSF indicator */
4 I3 D% Z* w- a/ E2 u4 ?( u    Init_Decod_ld8k();
- B# p& U9 T/ G! ?9 @" H# ~. w' r: T* l# b    Init_Post_Filter();
! ^. l2 D0 x( F    Init_Post_Process();3 u4 v  r; k' t, p$ t  E6 L
}
7 m" h9 t, s/ nvoid va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
# q, Z" W# P. q* Q{
. d- P9 g5 @' q! z& lextern Word16 *synth; /* Synthesis                   *// A" D& s( [5 J8 y7 {2 f3 D4 Q6 n5 q
Word16 synth_buf[L_FRAME+M];. t8 F, n& B" L5 b
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */1 B) M0 U+ C" m$ ^: A. d
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */9 h+ V' n& N  o! @# A( B- y" T3 d
Word16 T2;                           /* Pitch lag for 2 subframes   */+ F8 A, G$ f/ `+ h
Word16 i;
" o5 v0 Y" F9 F. E9 T+ a6 _" UWord16 voicing = 60;
+ K# w# C0 V1 m. ]6 UWord16 pst_out[L_FRAME];             /* Postfilter output           */# {8 H7 O/ ]1 O" B- T
Word16 sf_voic;                      /* voicing for subframe        */
" g' h+ E2 O5 {8 j6 avoicing = 60;# g# U7 d" s: `1 d5 f- k: a
    bits2prm_ld8k( serial, &parm[1]);0 b0 Z( I  D3 N+ c# [+ x3 }9 V
    parm[0] = 0;   
  U" f& j: {: _7 |5 T! J         
, l9 T! S& q6 E- H6 S3 n4 Z5 e' W    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);% b7 O  U# l3 ?0 f; W1 X6 F7 ^
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);7 y9 o2 `+ ?$ b7 X# |# u
//--------------------------------------------------- P, Y, k& I) j: n+ G# i' s5 _0 r
voicing = 0;
) z9 ~0 x/ Z: b7 N8 n) F5 Y  {; lptr_Az = Az_dec;
* f9 z: z6 \4 U5 Y" _( \for(i=0; i<L_FRAME; i+=L_SUBFR) {
* \0 R8 g. u8 f" a; Z6 M   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
7 b  [* A. P! O5 y: M   if (sf_voic != 0) { voicing = sf_voic;}
( ]1 t$ N# T$ _$ Y; l1 u0 s   ptr_Az += MP1;
2 G' z, m+ Y" T3 a. A}
: @: |/ [0 g% ZCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
1 P7 i  V1 @$ F+ j3 G//---------------------------------------------------
# D( o4 _; @* ^& v' O; O3 g    Post_Process(speech, L_FRAME);   
" a0 Z+ A5 N: ]4 z2 s}
, l2 Y7 i  l, x
7 @& N. |3 r2 Y
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 07:57 , Processed in 0.016821 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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