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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
# _5 @7 B) b. |3 W: l: M, r" Q下载以后需要修改bits.c文件:
. V- A6 I+ @: C8 L% l5 v: u* c我仔细研究ITUG729代码后发现:
' B# x1 ~% N% u. V4 J  F编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
& n7 W8 R: f2 A( \/ B% V,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。8 p# X! u7 K$ [8 m

. S6 {: J8 G4 TITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。$ }- V" w6 Z6 o: S! G9 X/ Q( ~

1 a( L. k& G% h% N" H9 U" u那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
3 U" N+ `; K0 k& Q3 h我们打开bits.c,就能看到里面定义的如下4个函数:
, Q9 @& i1 n  R/ M' C5 S, ~static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
# v- e: d4 Z2 G) t/ Mstatic int bin2int(int   no_of_bits, INT16 *bitstream);
: _7 A' F5 Q/ _' Z' y7 cvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ;
1 @# x9 x; @. p- N( R2 G+ rvoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;3 Y  Q% t- H2 y2 l$ y% X
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
0 }9 {1 W; q. e. P% e# C' ystatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; 0 V6 w4 U$ e& c/ a( l( k7 u  ?
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
4 q  z+ _. x& z, }# c+ O
( o# Q4 o$ e& o! D6 r' M* Rvoid prm2bits_ld8k(Word16 *para,unsigned char *bits)
  S' K; Q8 J4 i- _4 k, {- x' B8 ]{
, X+ i3 i; x. J: o1 X  |5 J+ c2 O7 n   int i;# I; U) X  S  `$ k: O# u
   int bitpos = 0;; M4 _1 Y0 z. Q( U* I4 ?
   for (i = 0;i% ^( F7 a# v. h1 _: }# N0 u6 x" q0 g
; s1 z+ J1 Y1 l( v1 `, |
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
! j, n6 C, Z' _5 D$ j{7 t) R( c8 Z  d' g$ b7 C- J. |% n2 B
   int i;* n4 [1 ?2 v4 `
   int bit = 0;+ t" Y6 y( C$ Q& Y2 H( Z! ^" V
   unsigned char newbyte = 0;+ L  t/ g# |/ ^, P0 O
  2 W4 t7 a/ k7 `. Y7 ~9 @
   unsigned char *p = bits + (bitpos / 8);
! ~# }% B8 \' U0 V3 L   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
8 z- u& v8 Z# `+ pnewbyte = (1
# n' u5 ?! l) g: Ubitpos++;: g. f' W5 K1 {- C6 q) G: v( N9 m
if (bitpos % 8 == 0)
$ y6 z; i5 I! u7 r* F   p++;
+ K6 \. P3 F1 ]9 M. p   }4 z8 G$ C1 _. s& ?5 j4 Y4 M7 e5 G
}  H% U# g  \# H0 A) F& H5 Z

) j/ z! t. P5 G. Q: }void bits2prm_ld8k(unsigned char *bits,Word16 *para)
% J6 |, P5 c+ m" A1 h1 T2 ?{! o: }; M( B& p+ A. e
   int i;
0 u. l$ Y0 `( }' H/ i/ A   int bitpos = 0;
/ l, B+ g, a4 D  ]" t0 B   for (i = 0;i7 k# u6 W! B, v) A8 R

: W" e+ ^# }5 [) {Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
+ E1 _6 S6 p2 G% m# L{
& |0 x+ l% s8 G) S/ ^& s% V   int i;4 }% ~9 k* r! ^2 X* c2 Y9 v
   int bit = 0;
7 I* N7 |: V9 }7 u9 c! n   Word16 newbyte = 0;
2 O' ?) k( \4 l6 E% D8 A   Word16 value = 0;* K( i" F' Q: m2 y
  
. @; A1 U& I) z   unsigned char *p = bits + (bitpos / 8);
) Y9 ^6 k  V) {/ a5 r; A! i   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;1 W1 \. [( D/ _" V
if (bit == 1) {
2 X8 C# {' }1 Q$ [1 w. i   newbyte = (1   R8 U! ^2 v; r
   return value;
) |1 ]; L% N% d/ k}+ y8 ?9 @& ^3 F. ~
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。! j$ [4 i! X% @# }! H2 C( W- b7 l

7 Q( ~* R6 x1 {& |: ]/ u编码器的代码能采用如下的修改方法3 Q9 z2 |! B5 r) Z& x2 I
(1)修改coder.c:! G9 O7 e' f  e+ m
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
& v" _% v* b- ~! E% j(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):- L+ J  v1 H. U. S
   frame =0;
. r7 e+ _% l8 G4 f1 M" [   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
& e; H, S( @+ Q" T* w   {
7 Z2 Y- F. i( Z# P$ rprintf("Frame =%d\r", frame++);
' G9 V8 ]$ s% q% oPre_Process(new_speech, L_FRAME);
; y, r: G5 e  yCoder_ld8a(prm);
/ S; G; K( ~2 Kprm2bits_ld8k( prm, serial);
. a+ h" z  g! h2 F& H" |; _fwrite(serial, 1, SERIAL_SIZE, f_serial);
5 [  X7 j3 L! @+ M5 t  k   }
* b* a+ u3 _" T+ X* _1 U   return (0);- _; w, x* c; F4 J
( w4 {1 b  b# h5 a! i* g
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
% W: D, K9 D7 b; O6 u7 l  P/ \#define   SERIAL_SIZE   10
8 n" M- o9 G- y- j% G  J& U3 f) o, K1 q9 |5 B% g: m8 I
(4)解码器decoder.c进行类似的修改(关键部分代码):8 h. {' l) ]) K" p
   frame = 0;7 O" b8 U' s+ ?" T% ~9 ~
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)" l/ j8 _  l9 n( y4 P
   {5 V" O8 h$ t5 t) `& r( i
printf("Frame =%d\r", frame++);
+ i5 M/ H0 \4 O9 m/ nbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */, }* d7 l  K9 _& G0 _
parm[0] = 0;   /* 假设没有丢帧 */
# J8 v& K7 ?% V) A7 H" `parm[4] = 0 ; /* 假设数据效验正常 */% y6 V. ]( b4 {0 l
Decod_ld8a(parm, synth, Az_dec, T2);& N6 I8 k' `- t+ {1 ~; a3 h
Post_Filter(synth, Az_dec, T2); % Z; _9 D. X3 t: w
Post_Process(synth, L_FRAME);9 ^8 j% c2 B6 J; c! b0 z, F$ m  m; {
fwrite(synth, sizeof(short), L_FRAME, f_syn);
' M4 U8 O# }8 L& \6 q& U) T   }
% R, l$ N4 D7 n7 ^8 \. C) C   return (0) ; , M) h, M7 ~( p3 A1 E" X3 p
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。& m" I1 G# y  Y- \2 [, {

1 E" M) n( e, |) I1 T' y修改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]得到,应该就能了。
( v1 `* n* d! U" J" c封lib:) |9 U2 K7 e2 J7 O8 g
va_g729.h: s% k5 Z1 V+ y
#define L_FRAME_COMPRESSED 10- b; p! `( n1 k- ~/ U( t: y
#define L_FRAME            802 e7 R+ P; L/ v8 L$ Q
#ifdef __cplusplus
* m9 O: a9 {1 Mextern "C" {
( O6 c& e  T' Z+ c- p) a; |" S- U; m#endif
; d% W/ u) Y9 @6 j2 W0 U: Vvoid va_g729a_init_encoder();6 D1 I# p- R4 R) X$ F8 P) d
void va_g729a_encoder(short *speech, unsigned char *bitstream);9 F( B8 y) ?, t0 W3 L
void va_g729a_init_decoder();
# A5 K- H7 B" e: d6 `( L+ @void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
8 |- l; }* z( I8 C+ n$ d5 a0 ?#ifdef __cplusplus # o3 @7 Y, q3 x4 A: C$ l0 ]
}
9 x) D. i0 s4 \#endif
6 l5 z. x: a/ ~2 e# ~, P9 [0 }va_g729.c
# L5 l; i' L" k+ ~! c/ g#include <stdio.h>
6 X. F* b" `( e% F* Z# z#include <stdlib.h>+ O% U. i0 W3 F# R/ h
#include "typedef.h"
' l9 p: ?* S1 k, e% m#include "ld8k.h"
) e( n: j8 s$ f1 k/ r! nWord16 bad_lsf;1 i; C3 Z; a/ B. d8 H
void va_g729a_init_encoder()
2 |! @9 Y6 u1 p- s{
* D6 ]0 C. Q# ?. s; G2 T( p    Init_Pre_Process();( V! q' C  A% y# E- p# T
    Init_Coder_ld8k(); / P# i4 p( d+ s5 F) }& B5 Y
}+ ~4 O9 q. v/ N* @. l$ ]7 K, T" o% z
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
3 g1 g( T& N! d! Z& D{     5 U" c: X8 W: }4 U' q/ t
    extern Word16 *new_speech;       /* Pointer to new speech data           */
! g% E- x& H4 c+ `" I4 }    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
6 j; w# i! T" A+ p    Word16 i;+ q; k) Z1 m- n' h2 F! z0 w0 @
Word16 syn[L_FRAME];
2 p6 A+ R$ K/ c- L5 _: h- l9 n% c    for(i=0;i<L_FRAME;i++)/ J* m0 v. s( H$ X/ ^% e6 v
{
; q5 N. Q7 \% r5 e5 y5 Z" F3 y1 ?   new_speech = SpeechBuf;
0 d9 K) x, q) z0 e! R& b}
8 M6 e% J4 A! a8 N+ `     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
; W2 e4 b3 J* M, [    Pre_Process(new_speech, L_FRAME);
% E3 u8 V% p; y- Q5 O) B    Coder_ld8k(prm,syn);
5 j+ I. T) b' q. Q( {  [    prm2bits_ld8k( prm, serial);) u4 F' _! j/ s) A
}' g9 i1 j. G3 S. e" E
void va_g729a_init_decoder()
+ X' J" I) ^: a0 ~/ C/ I, s: G{- m6 b3 M" O6 k$ S8 {2 B0 ~
extern Word16 *synth;
9 Z- l0 w2 h# B# {    bad_lsf = 0;          /* Initialize bad LSF indicator */
% ~/ |& z8 L- F* \7 ^    Init_Decod_ld8k();' w* M, P" m3 g+ z6 q3 I& b, V8 u
    Init_Post_Filter();$ v6 t) u9 Y* j9 k9 q! ]0 B
    Init_Post_Process();8 y9 {6 a. ]# V6 ]. L. _
}4 v, Q7 {/ `3 J1 G3 r7 n6 m) g+ d/ K
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)7 i" z( w4 i( e" Z/ X
{
8 I+ F4 A$ l; p0 V8 t' u& \extern Word16 *synth; /* Synthesis                   */
- J3 X4 g0 `1 h$ K( c8 WWord16 synth_buf[L_FRAME+M];+ F6 T( R, |2 c9 j2 q6 l1 Y: r: x
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */$ C- [5 t9 ]5 z& d
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
  u/ V, x8 L- L) d9 B: m  g# O1 qWord16 T2;                           /* Pitch lag for 2 subframes   */
2 r8 ^: G5 \4 @, ?1 _! ]0 l. q  j# pWord16 i;  H: p2 R" ^9 Z0 t# Q1 q6 I
Word16 voicing = 60;
# R( v0 K& i+ w1 p6 {% u, X" EWord16 pst_out[L_FRAME];             /* Postfilter output           */9 C% w0 L7 T- v6 C2 R% @$ m$ P
Word16 sf_voic;                      /* voicing for subframe        */& g( Y2 Q0 J$ F5 y
voicing = 60;
9 R; P! L4 d/ N  j7 W2 m    bits2prm_ld8k( serial, &parm[1]);8 v% y+ }6 {1 U  J
    parm[0] = 0;   
0 ~) x0 O' n% Y+ X& ]% C8 [          5 D5 w5 I( q9 i! P  C1 b& d
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);: ]' {! e; U4 n- Q3 Q
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
( a, y# Q" b. s* S//--------------------------------------------------
* N2 _% `5 }4 E* Rvoicing = 0;. s1 b* y: c5 X4 c! P
ptr_Az = Az_dec;, l' ~) W% q; R( z, F  d
for(i=0; i<L_FRAME; i+=L_SUBFR) {% q# V) B' v$ f4 `( B% M6 K
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
- V& ?- @3 n# f1 ?) N4 P4 @   if (sf_voic != 0) { voicing = sf_voic;}5 {( F4 I6 u( Z5 \$ t
   ptr_Az += MP1;( j! I9 i; `9 |5 u
}
' S* j2 X% o' M! M3 x/ D6 lCopy(&synth_buf[L_FRAME], &synth_buf[0], M);7 c/ o3 w, f  X; b
//---------------------------------------------------
9 |7 H- s. x$ g9 s  S    Post_Process(speech, L_FRAME);   
6 T8 g% [8 e" B}. S1 X/ P% A/ d$ M+ g
- S' g" q5 V6 A
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 22:44 , Processed in 0.017290 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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