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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/& ^4 @% V1 G4 W. y0 T# Y8 X3 A7 f
下载以后需要修改bits.c文件:8 v. G1 @, p$ M2 @5 U5 [* f
我仔细研究ITUG729代码后发现:
& I" [) w9 [5 {- x1 j1 S编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
1 W, C/ n1 S" c) l2 Z' Z8 u,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
  A9 J: u% t+ }0 I1 Y) O. U
" ~2 A( ^9 S% |- e% g; {ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。0 C6 e" ~4 X* T& n1 w6 M3 @9 n
/ r0 W+ D: ?/ f' t
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
6 d- W" K! t/ `* W0 O0 O  J! \2 g9 ]- V我们打开bits.c,就能看到里面定义的如下4个函数:6 _% _: A) O8 T- ~. @2 k! T
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);7 O$ n6 X+ O' r; {) Y3 y
static int bin2int(int   no_of_bits, INT16 *bitstream);
6 K! x% ~* I; h% |& x7 Bvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; . M. {3 C3 p! W4 R& k' G
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
% y9 X7 E. M: H1 X这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:3 j+ ]) Y5 S1 ~" s
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
1 H; E1 \( `9 l# J. ~  Ostatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; 3 B/ q( N" A, X4 w( U: z
( a  i! P+ ?9 j- P5 y5 ~
void prm2bits_ld8k(Word16 *para,unsigned char *bits)6 `9 m  {1 m" d* [
{
$ g8 h+ N3 j) C. |. c   int i;
! k/ ^% m; E7 x" [   int bitpos = 0;, Y1 _' W3 s, O% E/ H( v. ]
   for (i = 0;i( {* L" w7 V; H5 [7 i: L) C7 y
8 w5 M4 b4 P, `, a* q. m/ I' x  C
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
5 U/ _, o7 W/ `4 h0 ^+ s{9 ]4 K+ U! J+ |. o
   int i;
9 M5 n$ V: M3 r/ ~* O   int bit = 0;- E/ L4 M% Q1 a7 s% m
   unsigned char newbyte = 0;: q# ^" N- I+ G
  6 [8 Q4 E6 \7 l. @$ Q$ M/ w
   unsigned char *p = bits + (bitpos / 8);2 A7 m9 y9 U# t9 [/ r  n
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;  v& R8 E" k) a2 ]+ L# G& ]6 p& t
newbyte = (1
8 B: q! t/ ~4 ]2 E" ~bitpos++;
* Q" o8 n3 }8 l6 u! \  pif (bitpos % 8 == 0)3 R# @  c& [6 |$ w
   p++;( a( D3 `' [* R
   }) P6 \! O7 m8 b, L: ]# m( v
}
; Z6 {! _+ q3 C( v5 S3 X# r
! S  S/ M% Y% d+ F5 Pvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)' p5 f' t: P: D: L2 q& G; G1 p/ g
{
9 I  \, ^9 A$ V* O  X9 z) Q' g   int i;
  Y3 O% i9 J& m1 O1 i0 v   int bitpos = 0;4 u/ u, F" E% m+ l8 I. @( v
   for (i = 0;i7 d( B7 B& b5 \. O( X
+ z- k/ D3 t( h3 G. B
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)# d1 R/ _. _  R" g
{
/ N9 R- o, I- y   int i;0 c. \) c; r3 c0 U
   int bit = 0;6 G+ M0 C& k5 o9 p: u2 F
   Word16 newbyte = 0;
' k1 k# P: d: g3 T, y& j% N: e   Word16 value = 0;
6 p# D0 n* v: V' Q  ' w3 B) A# Q* O% q: _5 O
   unsigned char *p = bits + (bitpos / 8);
0 w! e' D1 Z  y$ o$ u   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
- z' P" k1 w( Dif (bit == 1) {
) ~  g. {& o! g4 \   newbyte = (1 4 E3 t% b$ ]! e1 @
   return value;/ R# p# \, I7 T; Y
}: ]% b2 T5 v" F9 g) t1 z1 L, s  b
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。0 {6 R( l1 `* c, }9 X  F  q- `7 T! V
* G) P% P* i7 U3 m
编码器的代码能采用如下的修改方法9 @  L) V# h! |. v* V! [
(1)修改coder.c:
4 b( m1 y" L1 t6 s7 Punsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */' T: w& O5 O2 T" |. y' |- ?* c
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
, R7 J6 v) c% [* }" X$ B1 |   frame =0;
+ k. u0 D! o5 |+ @   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
3 \& J1 D5 K( L& Y# ]   {
( G+ H- j; a/ a! qprintf("Frame =%d\r", frame++);
% h4 y4 e. Y) d. H) I4 o5 V; V# vPre_Process(new_speech, L_FRAME);
2 C5 ]1 N9 X( g. O& r/ oCoder_ld8a(prm);2 r! Y+ }1 x: `& h1 q
prm2bits_ld8k( prm, serial);
! f, f* G" g' ufwrite(serial, 1, SERIAL_SIZE, f_serial);
. r1 ?) q; N5 Y   }
* n+ Q4 T+ V1 F  `+ N9 i   return (0);
0 }( f$ Q5 M6 K. `' Q2 x+ N2 }% Q3 j
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:9 n& n2 v* `  }* l5 A# p8 h- T
#define   SERIAL_SIZE   10
% J+ E" b8 z# o3 o- r6 A* w( W" p% A* \8 Z
(4)解码器decoder.c进行类似的修改(关键部分代码):
) q  ^+ Z9 S/ x% m1 \7 m   frame = 0;
6 U$ n/ o! c/ r( A   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE). o0 e+ U5 B6 \( O- E# G
   {; `! M  V) Q8 e
printf("Frame =%d\r", frame++);/ y3 J$ w' a. E, F
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
" [) ?* x$ x: E' o+ a4 Fparm[0] = 0;   /* 假设没有丢帧 */) ]. W0 b! c' n5 u* T/ |0 J
parm[4] = 0 ; /* 假设数据效验正常 */
9 z+ Y. I" i" hDecod_ld8a(parm, synth, Az_dec, T2);. o1 T: `# [* k8 i! |' |, v! T
Post_Filter(synth, Az_dec, T2); : ?/ C# G8 y/ ~1 k$ `  `
Post_Process(synth, L_FRAME);
- ]% v) O; C0 rfwrite(synth, sizeof(short), L_FRAME, f_syn);
. D- s# _* p0 G9 ^7 L9 c0 J0 `" J   }
+ M* G) Q0 X0 D6 F. }% R   return (0) ;
' p3 G2 |0 E" D! n6 e通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
/ c# O- C2 U! b/ t! F( q/ L
  H! D8 O$ A) ~% F修改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]得到,应该就能了。5 u4 U& m( ?" P2 x5 E. y8 }
封lib:% q% m$ g+ P  Z# }1 y
va_g729.h
# P; G+ n. N" @2 n#define L_FRAME_COMPRESSED 10
: Y3 p7 |, \, B/ r7 J#define L_FRAME            80) J+ i' ?% S' {$ {* Y
#ifdef __cplusplus
* _. k( w3 G. @extern "C" {
$ Z3 M, b3 k0 U5 P#endif
4 L0 o+ i1 |' o' g+ `void va_g729a_init_encoder();9 w( [" O  [/ B6 P, F8 ?4 s
void va_g729a_encoder(short *speech, unsigned char *bitstream);
' T$ E* V' m/ J- tvoid va_g729a_init_decoder();
4 p4 W0 f& A  H& Y8 Y# e; i, Z# Gvoid va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);1 r' j4 e1 D3 Z* |$ K1 }. ]
#ifdef __cplusplus
$ G. M( h+ U6 C) c% z' O; t} 2 K# e/ D# M/ \* E5 T$ `0 U# _
#endif) G. F0 v7 K9 B7 L! x, Y  F
va_g729.c
/ l  O& S/ g* C5 `, ?% A#include <stdio.h>
) d" R  D; f1 L& J#include <stdlib.h>1 P( t4 t+ K9 `" Y) Q
#include "typedef.h"8 \6 i' g5 p: k' \
#include "ld8k.h"
) `% E6 x) h/ R# [& V; CWord16 bad_lsf;
% w/ W' g6 a; }! C" }void va_g729a_init_encoder()# g! w  R3 S- R- K- R' c6 x* @, \
{
/ {" N2 i) C; O0 X    Init_Pre_Process();5 K) y( Y) _6 P+ `. z9 x5 B0 i1 f5 t
    Init_Coder_ld8k();
" A; t9 p; M% w, i8 M}2 r$ ?2 U$ e6 b$ O2 y0 a7 k$ L
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
/ J- J- B. I% Z{     & r0 b3 M" P, h0 h1 S. y  g6 B
    extern Word16 *new_speech;       /* Pointer to new speech data           */
/ i8 K1 ]' ?; o  F2 N! ^0 `    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */! [6 z- b0 b" V% ]( a" P+ z3 n
    Word16 i;; _; l4 V. ~% K' g; |6 k% B
Word16 syn[L_FRAME];
* F" g# P2 t( D3 \    for(i=0;i<L_FRAME;i++)
, K# f! }, s* B* l- |  n! K: c5 `{
0 l. S. v* {" K& h# K; f: i   new_speech = SpeechBuf;2 M- u! D: _" K/ U1 C1 |7 b
}5 W' e: I& G( |
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
- f1 L: b. x& i' ?8 x    Pre_Process(new_speech, L_FRAME);8 O" m* ]: x* V) C7 U* p
    Coder_ld8k(prm,syn);
5 r+ r# Q3 J! m    prm2bits_ld8k( prm, serial);3 E6 g4 [7 ~. D; ^2 |! U
}: z1 W5 F; C% z6 {, _  W
void va_g729a_init_decoder()$ x9 g) L1 d- }% N8 ]
{
% N6 S2 Q- `6 F0 Y, ]4 w7 eextern Word16 *synth;+ x- S" b! I7 b3 j! E% K
    bad_lsf = 0;          /* Initialize bad LSF indicator */2 Y6 K5 a+ w1 ~; a; b
    Init_Decod_ld8k();
$ O  g: v* X5 B; C    Init_Post_Filter();
) F- g, H: r+ v7 P6 d    Init_Post_Process();# x0 m8 c* X& u/ v8 M+ z1 d! q
}: S* G2 U& j+ Z; }% w8 g
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
) k' z/ R) O9 h$ x6 ^' r6 l' i{1 ~+ q( M: i# @
extern Word16 *synth; /* Synthesis                   */
- ^; q3 s# b9 g8 |, nWord16 synth_buf[L_FRAME+M];( Q$ H8 S+ ~/ r* K
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */6 N6 P+ L4 A' U! w) }
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */2 B, G2 V6 f& C
Word16 T2;                           /* Pitch lag for 2 subframes   */" k; _- C; }$ j7 J( `) |( ]2 r
Word16 i;
( B; q  V3 m+ F) ?) k) Z& [8 jWord16 voicing = 60;1 y6 M, ?" j* B2 h* R  S( t
Word16 pst_out[L_FRAME];             /* Postfilter output           */5 O6 P6 Y" P9 C
Word16 sf_voic;                      /* voicing for subframe        */% p- t$ n. D! x% i# a: I* a
voicing = 60;- \+ [+ [6 [; e1 n- _* N
    bits2prm_ld8k( serial, &parm[1]);) Z' O8 a) j6 o+ s  m- B
    parm[0] = 0;   $ M" X0 i$ j+ A/ ]! {
          ! \  c6 B. l0 b* ~
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
. X9 t% u+ O5 Y; l6 Q6 @0 \Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
6 F+ I2 v( b2 z//--------------------------------------------------: g8 Y6 Y# K$ \+ I/ S. x  S  ~8 A
voicing = 0;
! _6 `2 O1 S, d  I9 optr_Az = Az_dec;* t+ Z' d8 E4 z" q; C5 L
for(i=0; i<L_FRAME; i+=L_SUBFR) {. e* O5 f' T) |- x
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);" w% H, ~7 y# g1 e; J- z  X9 z
   if (sf_voic != 0) { voicing = sf_voic;}! }. ]) M# a) o
   ptr_Az += MP1;+ g; ?/ z7 Y+ @
}1 O' H) w0 p6 u" f3 J
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
4 k% R: F& n6 e6 n//---------------------------------------------------/ |+ M' d! q+ d& C9 w
    Post_Process(speech, L_FRAME);   . ]0 R( F9 i% L) z6 R* k
}
% }4 I. A; P& H6 w3 _; f8 a- b; u% e5 p& g) d3 Y) z
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 19:02 , Processed in 0.018805 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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