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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
3 V# h1 |5 d5 F4 |: y下载以后需要修改bits.c文件:8 V- w8 `* [/ r. c: ?
我仔细研究ITUG729代码后发现:
3 i- O  \+ V4 w2 s编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流% i$ W7 r0 W+ }/ ^
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
6 Z7 i9 k6 m4 X, p3 i1 \
' D  c2 `2 @' I- n/ H- V* a* CITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
# |! L- d- e4 Q' f$ c3 {( d5 h
# A$ G  j" b! X# E那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。& w! j$ ?) a- W$ H, R
我们打开bits.c,就能看到里面定义的如下4个函数:
3 Q+ P- H$ n3 Pstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);2 k4 g% \$ F& @4 e0 K9 P1 [
static int bin2int(int   no_of_bits, INT16 *bitstream);; S+ o+ w: ?% m8 K8 l
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
& j9 t4 Q  O# i8 V! D6 Evoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;& ^( J$ e! F0 ?5 l
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
& b' D) t* r, S4 ?' k( }: ]9 \static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; 0 C5 W4 x' f7 I% J4 T9 J& P; Q
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; ( N; s% ]' g3 K5 J7 j1 w

/ V- l- p# @- i# ~1 ovoid prm2bits_ld8k(Word16 *para,unsigned char *bits)& k  a& G/ o, ^6 P! K
{1 F  F! J. V0 n* j# v8 B9 Z! ]
   int i;$ I3 T2 g  G6 r) I! g
   int bitpos = 0;
1 u+ C) g$ J. k: m0 N- A   for (i = 0;i
7 ~  r; [% S8 c1 Z' J' \/ D3 Y5 `( I6 m  e9 e
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
, j$ K; T& R. j/ f& y{
# m) L- M0 `7 M- _3 _   int i;) Y# i, o1 U! }5 g& n
   int bit = 0;+ u; a4 r" Z; q* i
   unsigned char newbyte = 0;4 w8 K% L, e0 i
  
: j+ S1 ]/ K. g$ h   unsigned char *p = bits + (bitpos / 8);6 }# E* ^, ]" p% O$ C' m; s
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
5 c$ v6 ], v8 o! c  d( V8 C- `& cnewbyte = (1 5 N; U% i6 Q! |4 g: u
bitpos++;
( e: Q% H# Q8 F- Dif (bitpos % 8 == 0)
+ ~7 x* d( @1 q' [   p++;, I, \" E9 B) ?8 K* ~. j5 y0 U
   }; A/ [) C/ v7 |# j
}
  O7 o1 E+ }" a5 t2 }4 m9 k: x) B& M" k9 q, f4 p
void bits2prm_ld8k(unsigned char *bits,Word16 *para)  g, c: S- R4 q6 R. G* i: W
{/ ]: n3 d) c% V0 R1 |) U( k
   int i;
& @* _( P9 y8 w! L8 Q   int bitpos = 0;0 {8 y% k# r7 f5 ?- L$ F+ w
   for (i = 0;i! @' j$ x; S$ O; {9 E
+ A& ^5 j+ p" K( g
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
4 D; a5 I# i0 c& f  a& q! g6 c+ Q{
( E( }: n* }, \% @4 C" ~   int i;
$ X: m3 }( e# Q( l+ \2 _* Q   int bit = 0;  Y7 D7 m# C3 B1 r
   Word16 newbyte = 0;" P' x# y- {" K
   Word16 value = 0;5 p4 f" m5 {0 s0 M, @/ a$ x
  ( _, l) F* f  W* v4 A' I4 X$ n4 k
   unsigned char *p = bits + (bitpos / 8);' a/ ?5 ~+ r  K
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;+ {# c" J, u7 y
if (bit == 1) {
, Z2 c" H) |+ B' ~   newbyte = (1
- ]9 C2 R0 e- i- g5 `" [6 X   return value;
0 \1 n! ?7 P( q4 Y# _2 u}5 g& d! |* _6 c5 M0 Y2 z
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。8 O6 [' z, Y, ~

7 T$ [  r: D* Q- `/ A编码器的代码能采用如下的修改方法
) D# \# s& v2 P2 Z7 H" S5 h" ~(1)修改coder.c:& \. Z. _  Y" Y4 I. i: B. K5 f, ?
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */- y$ N2 n% G& O- j/ W* U" b
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
3 p3 c' {( U4 Z7 [$ g/ n; S* t   frame =0;
  t3 z9 B0 ~* K1 N0 M- }   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
- X0 A5 _" Z2 o5 M6 H   {. j0 z/ M: L" ]. Q" M, m; ~
printf("Frame =%d\r", frame++);
, p. f( c% m; O+ Q2 M; ~6 BPre_Process(new_speech, L_FRAME);  x5 M4 T5 Y+ j/ u
Coder_ld8a(prm);
& g5 i; V2 j& G: Y/ i& mprm2bits_ld8k( prm, serial);
; C7 U( f2 V4 u/ G& lfwrite(serial, 1, SERIAL_SIZE, f_serial);
! G/ Z& o4 g& f7 G3 h   }; ~5 x& O1 L9 x$ Y. G( ^  @; N3 Q
   return (0);
# f0 D5 k$ u3 ?& A/ q5 T: u( C) ]1 Y4 A2 w8 F, y/ g3 N" _& F
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
3 U4 ]2 F7 o' `  [# n5 {; w#define   SERIAL_SIZE   10
2 b* G+ v; `9 [% f, ]% E+ Z6 W0 R8 e
(4)解码器decoder.c进行类似的修改(关键部分代码):1 u0 P- x( v0 O# v& Y
   frame = 0;
2 p& Y' O" H1 U0 `7 c3 Q" r   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
8 c9 ]+ D4 W; |4 k   {
. J( U* T% a6 P7 Kprintf("Frame =%d\r", frame++);  {9 M7 A/ m7 U' _* C6 c: H; b
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */& Z  B0 ~$ n9 T9 Q" c/ N, e& K$ f
parm[0] = 0;   /* 假设没有丢帧 */
& r! r) B. j2 R, Oparm[4] = 0 ; /* 假设数据效验正常 */
! B8 U. z  b5 P: u0 {' ^Decod_ld8a(parm, synth, Az_dec, T2);1 E4 d9 m% a* {* r: A! b1 b
Post_Filter(synth, Az_dec, T2);
8 X+ {7 G; v3 k. dPost_Process(synth, L_FRAME);
# g( y- O( m9 A" U' M. yfwrite(synth, sizeof(short), L_FRAME, f_syn);
' ]+ J* z- g5 _3 P" _* u2 c: ^5 u( O   }  w5 M4 r1 ~4 p! p, z  R' Z1 W. f
   return (0) ;
8 Q. e9 w& \/ n通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
% q6 z4 L2 r# [5 m: v0 P9 J/ v. B: R7 M8 r$ H
修改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]得到,应该就能了。/ i8 d, R- V7 _0 e
封lib:
  O9 t. `/ n  A& k5 [& L* mva_g729.h. O+ ^4 R4 m1 X/ h0 s! G% F7 m
#define L_FRAME_COMPRESSED 105 |+ O( G" s% G
#define L_FRAME            80- N2 W8 w! x; ~" w2 d1 U, y0 }) r
#ifdef __cplusplus
3 M: j/ D3 b4 _; L/ C" vextern "C" { : U9 D! z+ `4 X+ m
#endif# B( g1 |- Y6 N
void va_g729a_init_encoder();
3 Z( p, x, X+ V. U/ Q) {void va_g729a_encoder(short *speech, unsigned char *bitstream);
* ], T/ K1 G8 ^( J( Wvoid va_g729a_init_decoder();
  A  p! F# |( C+ k: }# e* Yvoid va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);+ e9 d3 B, A5 h6 }& ]( x" y: W0 a' I4 J
#ifdef __cplusplus
2 M# J$ k, b, G# U2 {$ |% O2 L# O} 5 t$ Z  E- T4 C8 Z- [7 ]: F" G/ I
#endif
+ d. q) N/ U# B& N9 _  Mva_g729.c
' O9 X- L% e& t% p6 g#include <stdio.h>, |% B# J# D% }% h3 `, T9 G
#include <stdlib.h>/ A+ k2 @2 X0 D/ s; D. Y
#include "typedef.h"
8 F8 ?( B& M% K( ]" }#include "ld8k.h"9 A/ a& D8 x: B; F; }
Word16 bad_lsf;
1 A( B, c" Y' a2 W( @void va_g729a_init_encoder()
& H' z/ n# a) A$ W{% K- X4 J0 _3 A) o, y$ Z% g
    Init_Pre_Process();7 B2 p+ z  g$ W' u9 d* f
    Init_Coder_ld8k(); 2 q/ u  D3 A- I2 z) z6 l  Y3 v( K5 G
}( V& l8 y: m, a6 }6 \2 K+ Y
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)6 T: F6 ~/ g& o9 X
{     5 n3 |$ g$ E& A, A' k6 `
    extern Word16 *new_speech;       /* Pointer to new speech data           */
7 O% t5 x/ ]# D# y, |' t; _* e    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
. f7 W; N! C3 M    Word16 i;* \, @  J2 V2 w/ f3 k- o# T" w
Word16 syn[L_FRAME];' v2 M: j% a, P" ?- u
    for(i=0;i<L_FRAME;i++)
/ H1 Y$ I$ w6 E) I: Z% N{0 s. F! V$ }4 T( l+ F0 w( e) L
   new_speech = SpeechBuf;! s  S4 k- f5 E# O. @7 V& q2 ^
}
: t* i: Q7 s$ g" K( Y1 u     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; 3 @9 }# \5 G7 ?3 j6 v5 E
    Pre_Process(new_speech, L_FRAME);
; `4 n7 J" r* t6 E) H    Coder_ld8k(prm,syn);7 N. y& P$ i; k! H& K* a
    prm2bits_ld8k( prm, serial);
. ~6 [2 Z' H! k3 o}
3 n3 A$ H7 G5 T# R7 D) d6 N8 `void va_g729a_init_decoder()
6 r) p! M- V! ^; r8 T% [/ V{9 G7 q' Z3 k) w. D  j4 E$ R3 F
extern Word16 *synth;
& X$ r# {4 G: x( Q" E' n    bad_lsf = 0;          /* Initialize bad LSF indicator */8 L1 ]+ M) |- S+ b; h
    Init_Decod_ld8k();% t7 d2 c2 j$ b; x- e3 Y
    Init_Post_Filter();$ p& r  O: U. n! e
    Init_Post_Process();( _2 ~/ y! j6 M0 E' b4 m
}
/ ]* F2 i. ?: v$ Ivoid va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
2 C5 B7 ~& w+ x% V{2 q8 L7 _% l3 n2 h! ]
extern Word16 *synth; /* Synthesis                   */
" z' @" V  }3 W: w; uWord16 synth_buf[L_FRAME+M];
0 l2 @" Z5 `1 EWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
+ o9 R, @0 x$ F0 [2 WWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */* {0 `. e) z& q. b! u7 s9 A
Word16 T2;                           /* Pitch lag for 2 subframes   */( S% Y5 z4 s* r; F
Word16 i;, ]* ~+ O! }: s+ f6 {- t/ e
Word16 voicing = 60;
: R  g( M* I+ w! ~! {Word16 pst_out[L_FRAME];             /* Postfilter output           */
3 l/ i7 m! G& z: MWord16 sf_voic;                      /* voicing for subframe        */
$ G4 X. y3 X6 b: N# y" O" {voicing = 60;
' q6 U7 H7 N9 s* p) Q% a    bits2prm_ld8k( serial, &parm[1]);; _* i$ W' o) O5 @' b" w
    parm[0] = 0;   9 R) \" n* N+ H4 f9 ?
         
& c3 Q9 D: Q/ e# k( W    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
/ P# K1 g! r( PDecod_ld8k(parm, voicing, synth, Az_dec, &T2);9 C" i6 f- t9 z0 [, v* S% i
//--------------------------------------------------5 d7 L0 B: c! L0 Y
voicing = 0;0 V- U. I( s; t, e; @
ptr_Az = Az_dec;
7 Q1 l! ]/ u+ y5 \# Bfor(i=0; i<L_FRAME; i+=L_SUBFR) {: c  j$ D' F, C) n. s. Q, Z
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
; m4 ]" W. n! e# v  I) j   if (sf_voic != 0) { voicing = sf_voic;}
. H) O/ P; |1 r8 s$ t   ptr_Az += MP1;; C+ D1 B% Y' s% o! x
}
% ~9 y2 Q9 K0 n! hCopy(&synth_buf[L_FRAME], &synth_buf[0], M);7 u8 f0 C* W+ a1 e8 _) j
//---------------------------------------------------6 e0 c7 o; C0 @/ P: c/ J0 L
    Post_Process(speech, L_FRAME);   
: q* D2 ^! I8 s* v3 i( Y  R}3 V& Q/ e! ?) k& P# l& I
; a0 n  @6 s7 S
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 07:40 , Processed in 0.041130 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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