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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
# G8 a/ w" K2 p1 e. W- |下载以后需要修改bits.c文件:
7 b$ k0 a; a6 z我仔细研究ITUG729代码后发现:* X9 b+ U& s0 |) Z7 l
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
0 f) M2 n1 ^2 A1 m8 J,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
: q3 B9 ^  t  R+ B% r, _6 v5 f
7 r" s) t9 x% I# N; e6 QITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
7 k# W3 |0 C8 W. S
6 z; C1 r5 C8 s那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。# Q, K6 T9 Q5 d' j5 C, i( O
我们打开bits.c,就能看到里面定义的如下4个函数:0 K9 @0 x0 a( [$ M, g* }0 M
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);8 x) y( @% A. y  A
static int bin2int(int   no_of_bits, INT16 *bitstream);
4 a2 [0 `7 R7 M( r3 r( \9 ?% |void prm2bits_ld8k(int   prm[], INT16 bits[]) ; 6 G3 ^# [# m% w$ _# P" q
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
0 i: w  V  V7 W6 o1 s: [. B  A1 p这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:$ _6 P. \' m% Z+ U' S. [$ x6 w9 p6 [
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; 0 \$ t6 e9 X1 e
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;   s" y8 j: h7 J# f
+ i7 U+ I& c; @! }+ @% K, Y( o# t
void prm2bits_ld8k(Word16 *para,unsigned char *bits)7 m6 k  V' M4 b: H! \. |
{. ^. h0 O5 V" {# o, T% r) ^0 B9 F
   int i;! L( `3 D4 u9 b( I
   int bitpos = 0;
7 U( E1 Q4 z6 W$ H0 i   for (i = 0;i
9 e- t+ B2 m; V' k( X; i5 d6 W& ^' k% X) @6 s/ y
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)4 r6 z2 o5 a0 G# b- P
{
7 ]0 |6 p: I) j2 [   int i;
2 J; l- i, ~1 i1 ?; O   int bit = 0;
5 M' Z5 L# \" r* Y) g3 j   unsigned char newbyte = 0;
5 s/ p9 U# r$ y% |' ]0 J  
  b6 N% j  U" ]. C/ m   unsigned char *p = bits + (bitpos / 8);
5 f5 V7 h$ m: X   for (i = 0 ;i > (bitlen - i -1) ) &0x01;( f' C- t/ O9 _" K$ T7 g
newbyte = (1
" }) \4 o4 Z! J1 D0 b  `& D% Cbitpos++;
' y) w4 X) A  e9 x8 k5 M6 ?if (bitpos % 8 == 0)8 j" V. H  t0 ?% [2 L% R. _, j
   p++;
( H. ]% [3 f0 S6 S   }
4 G2 f" }/ g  J! {/ h}# I& T% `( i" Z3 P' \8 w
8 P! d; n+ K- {; ^
void bits2prm_ld8k(unsigned char *bits,Word16 *para)7 v" Z, c" D1 p7 ~) s/ l
{! H0 L( L# D: @% T0 y1 {9 G0 Y
   int i;
- D& Q" B$ H2 [& `   int bitpos = 0;
, M( ~" O5 c( p5 p6 f! E4 F4 q   for (i = 0;i) }% J$ ]* y$ _) P

# E6 e( O) y! {* z3 NWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)3 ]- j3 p2 [  N1 m) m6 I: V
{
  U9 j9 ?6 D, [3 C   int i;
* f( x9 \1 w. S+ _: |3 Q% i0 Y; M   int bit = 0;
' G8 P, g& X8 h- V1 b" M2 _   Word16 newbyte = 0;, S# A3 l, {8 k/ Q5 w: |
   Word16 value = 0;; ^2 x  C4 j* x! w# G- L
  
- M, e9 z; V" B$ Y   unsigned char *p = bits + (bitpos / 8);1 a% p) j) v$ ]8 y$ L8 H9 M; Y
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
8 l$ Z5 O8 w0 [: _9 _7 Wif (bit == 1) {
2 \9 i* q5 Q5 R! ~8 E4 Y   newbyte = (1
4 }; V2 r* _6 I9 h; P   return value;" @9 y2 D$ w5 |" ^, p  F
}
3 J8 x/ X: J5 q/ y0 @0 S7 D$ T通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。& q  u: Q. T% W  s. l: B
6 E0 V5 F* G0 S. Z
编码器的代码能采用如下的修改方法
7 R' S; B$ J9 ~8 N" u(1)修改coder.c:* [/ Y! G  j+ D
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
6 L7 U& u7 N, [6 J7 B; n# i(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
+ O5 W3 f% @) ^" T3 s   frame =0;
- s( J5 t8 m3 `) G1 w' d   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
9 o# P  c+ O7 n/ U6 J, ^! I   {
  Q* m2 p  x. y% @% Uprintf("Frame =%d\r", frame++);
- \2 T" X& D' g+ s( L" Q- U) [Pre_Process(new_speech, L_FRAME);* {$ ]6 J- B! n3 t
Coder_ld8a(prm);# L' l. D9 a% c
prm2bits_ld8k( prm, serial);
9 `: R1 B1 r  lfwrite(serial, 1, SERIAL_SIZE, f_serial);6 B: a  n) q! ]8 V/ g  I
   }# t3 Q( N2 V' s. P! q
   return (0);0 @9 Y4 K  L. g$ s

) u& D7 G# X1 S; [" }(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
: |% U. H/ z- U+ L& {#define   SERIAL_SIZE   10
( G& w" u" u0 X+ ~; Z! l, f1 p- q7 p! @0 x( S8 S6 S
(4)解码器decoder.c进行类似的修改(关键部分代码):
, L0 B1 b/ F2 p+ Q   frame = 0;3 a0 _, O. b- \
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
3 _# F* @1 l1 H, V" n   {: ^4 y6 i2 B! z( U' X% s
printf("Frame =%d\r", frame++);
; I- P1 `; m- a- }$ k' wbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
  B4 j' L5 Z( M' [+ f1 F) X4 h4 U( d9 C0 fparm[0] = 0;   /* 假设没有丢帧 */5 C! @& Y$ b) H- r) e3 j
parm[4] = 0 ; /* 假设数据效验正常 */
  B0 E" V; D- P! Q0 s  M7 x: S4 UDecod_ld8a(parm, synth, Az_dec, T2);
  D$ S2 `- t' m. L! vPost_Filter(synth, Az_dec, T2); 4 n& M/ u: Y& R$ _! [* t
Post_Process(synth, L_FRAME);" P1 V( e1 P; c  K  t
fwrite(synth, sizeof(short), L_FRAME, f_syn);* P$ U$ z& E9 M' i
   }6 O/ X$ R/ t" V
   return (0) ;
, c8 f: E! }. X, U: h通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。0 ^3 x2 k/ `0 W- a, N
0 D6 Z; q) `" \! C1 w" ?" b4 |
修改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]得到,应该就能了。- D. ?8 O* F  V$ [; _
封lib:3 l/ o. l8 g  C* z, U. F
va_g729.h! \2 q& C8 |7 X7 A
#define L_FRAME_COMPRESSED 10+ r& G9 z2 S! E: {
#define L_FRAME            80
% R3 l4 L* C, C2 ~$ i( }3 u$ `% l#ifdef __cplusplus ; X' H/ C8 X0 P1 a3 |# q
extern "C" {
# z9 T2 D$ q, u- [  E) u#endif4 q; r4 S8 U7 a) c3 z4 q: v
void va_g729a_init_encoder();; }$ H# f  g4 N$ @) V  V) [1 {  K; S
void va_g729a_encoder(short *speech, unsigned char *bitstream);
0 F+ e: \- a+ X" S! Avoid va_g729a_init_decoder();) D+ O! D& i( S9 T# {- Z( D
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
2 M8 Q) R/ x8 E- D( t% h# G2 {#ifdef __cplusplus ) E6 W) e/ h' p9 q3 b
}
/ R* C. r9 h$ J#endif' I- L1 O( u7 L. x
va_g729.c
7 m* E7 M  K: c2 |) T& A1 X#include <stdio.h>
0 g4 C* x: h( B" ^#include <stdlib.h>
0 w' W; z* o. S" }1 Y+ _2 }* S#include "typedef.h"* w" Q! t2 W# F  @$ U
#include "ld8k.h"2 U% o! Y! i/ H1 N
Word16 bad_lsf;" `- C( U/ h' l1 M1 M- R
void va_g729a_init_encoder()$ i4 U1 t+ P, N) k% B5 P
{: j" n( Y! S% \& ~8 @5 o; y( |5 N
    Init_Pre_Process();
1 w9 ?; u0 F; x" ^    Init_Coder_ld8k(); 3 d" d! v7 {2 C
}8 R  z' B% a; r, O  w- Y
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
0 _9 l% }1 b7 Y, G! R: B+ b{     
- o( _) Q* N8 x/ z4 @* _' X$ x9 O    extern Word16 *new_speech;       /* Pointer to new speech data           */% C8 s# O$ `4 [
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
' x, z$ G* t4 Y% c' w. I  b    Word16 i;9 {9 H# V  C5 E
Word16 syn[L_FRAME];
* `& r7 u$ k: g8 i. [5 V; `    for(i=0;i<L_FRAME;i++)
0 D6 ~7 Q3 Q( Q6 W- g  L9 I: M{
3 x$ P3 h0 U( Y7 A2 ^2 o! B   new_speech = SpeechBuf;6 o% Q. F# |9 A* a5 O3 E0 K
}# a' D9 o1 M: ]2 E; [+ `
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; # w& s2 }- J0 B  P( J2 [7 x
    Pre_Process(new_speech, L_FRAME);
) ?- s7 K2 _; W1 L) g4 H    Coder_ld8k(prm,syn);: ?, }% {5 y0 p( H
    prm2bits_ld8k( prm, serial);
3 S5 M9 {; C# J+ {/ {$ r- G# m}
) Q5 a9 E) H5 l  l5 _7 hvoid va_g729a_init_decoder(): x( Z# T; ~% f  y$ J* Y9 A( ~) {* l
{
3 ^7 Z. ]; T4 ]  ^5 Aextern Word16 *synth;+ g, P, x: `* S0 e  M
    bad_lsf = 0;          /* Initialize bad LSF indicator */, H9 \- Y& r8 `
    Init_Decod_ld8k();# c* }9 L& Z2 \+ a' d
    Init_Post_Filter();6 d9 W! Y; [$ z. J0 A5 e0 Y9 g/ g
    Init_Post_Process();
. n* S5 L* R% }1 Y}5 y0 D( w$ B2 q7 {: h
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
$ W7 K" g) h  i* ?$ N{. k# Q) X: u4 E" ^# C3 W! L
extern Word16 *synth; /* Synthesis                   */, d4 N- }# B2 f( M' h, Z
Word16 synth_buf[L_FRAME+M];
# W: [% n* K3 w3 Q4 C- ], hWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */. k' y+ }+ ~6 r7 ~( ?
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */9 ]2 R$ ]: c8 W( u
Word16 T2;                           /* Pitch lag for 2 subframes   */: M* m* x6 ^! f2 t; a9 S  ^  X
Word16 i;
* d: S9 d+ f0 @& o% I: S0 CWord16 voicing = 60;8 m: o4 ^# a4 X& Y4 o5 h% T
Word16 pst_out[L_FRAME];             /* Postfilter output           */
; r" ]# d7 Z0 R5 T9 h9 B4 WWord16 sf_voic;                      /* voicing for subframe        */" j2 h. s, f0 a4 M
voicing = 60;
- j6 M& Z/ l% t7 Z( ~, t    bits2prm_ld8k( serial, &parm[1]);
# J; C2 I+ B, W. j# K    parm[0] = 0;   ' h# j! }& t, i4 N6 S
         
0 @/ `; m/ W: s  }    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);1 J+ X, L2 s$ e1 `
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
% H. u( u: n/ @9 y//--------------------------------------------------/ v) R8 e9 [) l+ T8 b+ m$ R- g
voicing = 0;8 }9 b. `& V8 z! Z
ptr_Az = Az_dec;
) M* b+ g2 r+ o- p5 yfor(i=0; i<L_FRAME; i+=L_SUBFR) {
8 Z- V1 h9 @& `: Z   Post(T2, &synth, ptr_Az, &speech, &sf_voic);; ?. T1 Q+ j9 P; Q
   if (sf_voic != 0) { voicing = sf_voic;}
0 W0 t$ w! Z  o7 e$ c2 m   ptr_Az += MP1;
% F/ G' R, A$ E5 J# d}
# a- |, J7 E0 T5 E5 a" V* gCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
5 s  J7 S1 k1 A. K//---------------------------------------------------
" Y/ g3 _. R+ G    Post_Process(speech, L_FRAME);   & D, a! }& V/ D. K% p
}. m! T; m& m# k( ?4 N
9 \& U5 q. b3 p0 x* R. O4 E
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 11:51 , Processed in 0.018822 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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