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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
1 I* D8 n6 _$ F, U; h下载以后需要修改bits.c文件:! e( D. u: l$ z  j
我仔细研究ITUG729代码后发现:1 k- ?1 }$ h) u. p
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
$ U. T  j! C7 _,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
" W, y- t6 s; b6 j7 x- s" Y* m9 u+ G& X! V/ H( F7 a9 u0 C
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
, R0 ~/ x" j2 {6 u. Y; D+ }7 o
4 a1 f7 @1 L; A0 [那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
1 K; {# D! M( m3 P' j我们打开bits.c,就能看到里面定义的如下4个函数:: @, U- b& D5 H+ e. r- d
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
& j2 g; N4 @3 h* U5 y, gstatic int bin2int(int   no_of_bits, INT16 *bitstream);& T% m- o! l* w* @/ D, j% Q
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
$ i; Z& N% a6 t' mvoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;9 R# [" j2 G$ ]& B& ^! a: R
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:0 s4 T6 X, [7 M0 \/ p# p
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
8 f9 g6 t- D& j5 X4 [static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
4 p: S& l% E) ?& ~$ H% g9 D$ G& y2 o/ ~1 [3 A: b. N& m) I
void prm2bits_ld8k(Word16 *para,unsigned char *bits)
0 }9 t4 w1 `: M. L4 t9 B# v- W{& M( ]3 G+ h/ y% u
   int i;" ?! c  b' R0 H
   int bitpos = 0;
, ?( O( Y' C' ^3 \* Z   for (i = 0;i
2 n  o4 F( w6 d
& V  Q# S7 G4 |) avoid bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)+ k( T5 _/ m2 ^( G! g) A
{. ]% e% }# H+ b: D* q( l$ @& a
   int i;- \) E/ R$ I( x% i
   int bit = 0;- x* h7 Q& R8 T3 [0 m
   unsigned char newbyte = 0;6 T2 v  s* M% B( a: z
  
# {. ^( l. x1 S   unsigned char *p = bits + (bitpos / 8);
' d$ I1 N( s$ j) z   for (i = 0 ;i > (bitlen - i -1) ) &0x01;, `% \( G  n2 T9 N
newbyte = (1 0 N5 ]. T7 i$ T  ~' T
bitpos++;
# C2 s" X4 i/ a) Eif (bitpos % 8 == 0)* E1 C& l$ z' u5 g6 W& h
   p++;, e) L; e( ]8 u: X# L4 i0 ]
   }/ ]. S4 a# D& |' C! R
}( _, T$ Z+ ~! z0 G- \

6 v3 R: [" [7 b/ k7 z; avoid bits2prm_ld8k(unsigned char *bits,Word16 *para)
- p% ^  F5 X5 H# i' o5 X{
7 `3 f+ b) ~, b% `8 k! \   int i;* B& q" I, _- ?3 v$ b
   int bitpos = 0;
' ], {5 R) \# V/ q6 i   for (i = 0;i
. `/ x! A. ^2 w! A/ ~  `/ A9 R; a7 z4 x8 S1 H0 \% j  Q
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)) x" N& T/ H- l6 _! e
{
3 p* `# `" ?# W+ {2 J9 N   int i;
* m+ h3 S4 {1 z! u" S( [   int bit = 0;
, b8 ?; m$ z! E- @2 w4 x   Word16 newbyte = 0;, f) p) Y' \! [) b
   Word16 value = 0;. R* L5 c1 ^2 [: v" L8 Q( R4 p
  
3 D; r0 i7 J9 b5 p   unsigned char *p = bits + (bitpos / 8);
! d  {9 |! C2 Z   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
# G4 p+ v; _, f( I$ P6 cif (bit == 1) {& X  o1 ~# m4 x  Q- {( b
   newbyte = (1
6 X4 V0 R6 }+ h   return value;
9 ]* w2 n- I) {3 r6 u5 S}
; l1 l8 [" p/ i0 A$ Q( V通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。$ Y* R! s5 r5 u# K2 f4 Q7 w

( V  M$ }9 `7 U" a编码器的代码能采用如下的修改方法" s* T: r; K  e
(1)修改coder.c:
3 m9 O% V" E# }+ Bunsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */) h" w9 |; u  U1 U, i2 ^
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
$ Q9 w3 y4 c3 _" y) G$ j- Z3 k4 m   frame =0;# t/ S" X7 N; A# g! I! A) \  p! z8 N
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)3 u1 ?/ `4 ^. ^- O$ L) v7 @
   {  o0 e* A! o- m& M% A) o! Q
printf("Frame =%d\r", frame++);
# F5 ]) d. d! H7 xPre_Process(new_speech, L_FRAME);
$ `2 P2 _% e0 F7 Q% j; Z* iCoder_ld8a(prm);& y" t2 C3 q; @% A
prm2bits_ld8k( prm, serial);
, c8 n8 r, z, y9 b; G& mfwrite(serial, 1, SERIAL_SIZE, f_serial);
" a! Y) x" R2 ?- M, g  W- }1 {& B+ L   }
$ ?0 i0 |8 |5 n6 m) h   return (0);/ p6 e0 u+ e/ N! `

  j7 C% G& q( v' M- h. d1 W5 ](3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
0 q5 c2 h) |0 [" {8 f6 A+ L- Q#define   SERIAL_SIZE   10! o% x# P) T9 y
9 m6 }# P* `, s" G
(4)解码器decoder.c进行类似的修改(关键部分代码):/ A1 X8 T8 D) X, r0 g
   frame = 0;6 [* q- c: x. H6 q
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
; s5 E9 N5 o  V+ N1 u+ a5 a! i' u   {
. t; M9 Y4 _, v7 [0 }9 m5 qprintf("Frame =%d\r", frame++);; V. l# X8 B. ~) A$ ]1 H* }
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
: q# q: s' p: r8 q( o4 W7 U% Aparm[0] = 0;   /* 假设没有丢帧 */9 s! k- @5 v# e/ y; }1 f
parm[4] = 0 ; /* 假设数据效验正常 */
7 h3 f9 t9 a6 bDecod_ld8a(parm, synth, Az_dec, T2);
: O) e# {# ?! M/ \( B/ Q: G2 IPost_Filter(synth, Az_dec, T2); 8 |; Q6 r  w0 j) X. v) {, `1 t
Post_Process(synth, L_FRAME);( b7 s! p! A/ i! K! y2 Y( Z
fwrite(synth, sizeof(short), L_FRAME, f_syn);
+ i4 M- n- \  D- w2 w   }
0 S9 T9 N; T! c0 x$ S   return (0) ; 6 H# i- R0 B2 b* Q; K
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。; @2 ~1 A) b; G" z; h+ u& b
3 K( }/ S$ I8 g1 h) x
修改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]得到,应该就能了。4 g; k' q6 c. j- D9 y
封lib:
& I* L; f3 P" t; H' D; N9 b- hva_g729.h
! T0 D' U/ K& ?3 J#define L_FRAME_COMPRESSED 10" Q! W5 @$ Y+ g8 i  Q# v
#define L_FRAME            80
" a( ~: |; w7 S#ifdef __cplusplus . b! {1 L' d. }. d
extern "C" { # Y% k: M' q  ~% ]( K2 _( V; O$ T" l
#endif
, |# q* o1 f$ k* P# _; Zvoid va_g729a_init_encoder();
; M0 \4 l5 v1 v! ^. J" T: r6 |void va_g729a_encoder(short *speech, unsigned char *bitstream);
3 S" Q) j4 g* v, u* _5 e* g+ tvoid va_g729a_init_decoder();
3 W% Z0 W- r* `' N' svoid va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
- w* s! E7 f( w; d#ifdef __cplusplus 1 B; ~' O1 c  h. f
}
- c: E& z$ W, D7 o8 T#endif
! Q$ z& |( l! K& \6 b5 n* |4 c8 H7 xva_g729.c* d: D: X- T9 E8 Y- c
#include <stdio.h>
' c% i& b# R* \! s- _# O#include <stdlib.h>
- Y  V) S* T) p# m# T#include "typedef.h"
: }' ]' k3 T( \9 p6 R( A#include "ld8k.h"9 M# J& z, O) L' [
Word16 bad_lsf;2 T; f/ O: w* Z3 @6 V9 I  V$ V& k
void va_g729a_init_encoder()1 Z- |- L( n0 k- n& q# K+ z
{5 w/ }1 {9 x; L) V# b: N# I
    Init_Pre_Process();' A. L# Q0 \3 p6 [# R+ m
    Init_Coder_ld8k(); % n. ~# r5 n0 R
}
. @7 w, x* ~9 b3 Y5 cvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
7 ?* L6 p% ]7 t{     
, X, ^( q- @! @- B% k! n, M    extern Word16 *new_speech;       /* Pointer to new speech data           */7 j9 u" V. j+ ~
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
. x3 a- r: c- _    Word16 i;0 L3 |# s* W3 ^# B
Word16 syn[L_FRAME];
5 c; v& s% ~# I7 L, S    for(i=0;i<L_FRAME;i++)
& H+ z  ~! ?5 E0 X' [- h( M2 z{" T5 B  v( }' T; ?0 y
   new_speech = SpeechBuf;2 y8 F' e' D0 `9 c9 d
}
  Y# N: t6 N- p. y' {, l, `     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
3 L& t/ {# W) Y. K    Pre_Process(new_speech, L_FRAME);+ G7 u" Q! J( S/ E6 G
    Coder_ld8k(prm,syn);6 M, _+ V% t. V2 @+ Q* d
    prm2bits_ld8k( prm, serial);" G$ N5 Z- i5 Q5 K0 [2 X5 N
}. R" D, C- l! @  b% r$ L; |
void va_g729a_init_decoder()
- X6 y: T4 b3 L4 u{  U4 {( V3 a3 d' F
extern Word16 *synth;+ o% l. E2 u8 @) R: T  A7 c8 b
    bad_lsf = 0;          /* Initialize bad LSF indicator */4 k( T" \( r# d# M
    Init_Decod_ld8k();/ D: l" k0 C1 c! A
    Init_Post_Filter();
, o( h2 X; B3 c7 x# y. Y    Init_Post_Process();
0 P0 v: i3 R# [}- T5 E& v5 m/ n$ G$ ]3 h
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)& u2 j% M3 r  H% H5 c
{
+ u8 q$ R$ p- Fextern Word16 *synth; /* Synthesis                   */
3 r3 L* Q+ K4 K" Y- sWord16 synth_buf[L_FRAME+M];0 s' ?! [1 A- e6 P. L
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */% H* n$ I9 Z, F. l% M; K4 @
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
$ j5 l/ S) J3 sWord16 T2;                           /* Pitch lag for 2 subframes   */0 _# U  Q  X, k" y% N
Word16 i;
' Q; S, B* I) g6 _: g* hWord16 voicing = 60;& c& L+ i) h, u/ |3 P) ?6 B
Word16 pst_out[L_FRAME];             /* Postfilter output           */
* s( P1 _# i2 [$ a6 p) ~" xWord16 sf_voic;                      /* voicing for subframe        */
" W7 B) U" U8 X: x) Nvoicing = 60;
* x% }1 T8 x0 Z0 R    bits2prm_ld8k( serial, &parm[1]);% v7 P* q5 [. t# Z, S
    parm[0] = 0;   1 \( b* {: P& X& Z
          % [" k$ T; |# G+ W" S3 O
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
, x5 Q8 r' z- Q* }Decod_ld8k(parm, voicing, synth, Az_dec, &T2);( x+ F  m5 x" J) K
//--------------------------------------------------
- }. |& f! e/ E- b& k5 `* Jvoicing = 0;
4 C* g0 Y( P4 o3 K( wptr_Az = Az_dec;0 L+ @* v% t) y# F5 a. ]
for(i=0; i<L_FRAME; i+=L_SUBFR) {+ Y$ h) `4 _; y. p# U# J. o
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
/ A4 Z) [. y  x% O   if (sf_voic != 0) { voicing = sf_voic;}4 w! w+ k" b: Q" d) ~8 L
   ptr_Az += MP1;
# ?- G* D( Q, i  a4 b$ b}. C' K) T- g; A5 ~' M
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
8 B. v! t3 K. j, W/ K' u//---------------------------------------------------
$ T* ^- m8 o, @& w    Post_Process(speech, L_FRAME);   
7 c9 I7 L) C7 ~# e) w( O" [8 p$ h8 Q( u}) X! c2 k/ I+ A, }/ e7 c) ^

- M; `2 V  E% r5 Q  N) j/ z; I/ U
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-8 20:28 , Processed in 0.034593 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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