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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
, o, d5 Z: h% I" O4 ?下载以后需要修改bits.c文件:
- ~+ t- d+ R) X% z7 [9 R; _我仔细研究ITUG729代码后发现:3 _' h5 ?% B+ g$ I, o
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
1 o5 b" l- z$ z4 A3 [,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。- s0 T8 ~# v, `2 d; M. O

0 H' T; f' i% r- T# JITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
3 P2 J) ]3 ^$ x: t% ?. q+ I, o+ f, ~- S* T" ?) s0 q2 N' L, }
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。' A0 d' V% }2 D0 ?$ C: m
我们打开bits.c,就能看到里面定义的如下4个函数:- M0 V% S( O7 p+ R9 F
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);4 N( s  ~; j( p7 B
static int bin2int(int   no_of_bits, INT16 *bitstream);
8 G  g3 S% c/ {8 Ovoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; # f" [9 y2 l/ T% a
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;' u3 P& _1 ^+ N9 f, P9 F# ]
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
- }- l; t+ M  e/ t% n- tstatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; ( a* ]2 C: W, @' r
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
3 B' \/ o$ C" `# l" C/ d. M4 Z2 Z1 }( ~2 }! A
void prm2bits_ld8k(Word16 *para,unsigned char *bits)5 f4 A6 D  L0 @
{
% P# r$ V4 e, J3 f: O1 W; p  i   int i;: t# B( r/ m( \0 z/ Z' n
   int bitpos = 0;
7 L7 K% Y( e/ }& ?+ e   for (i = 0;i- `2 g! s7 B% v5 F

) ^# K4 M) }8 s- f1 M8 Xvoid bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)& q6 C/ P) C: K/ N% z
{
+ [: ~+ e- @- {6 w8 Y   int i;) [) R/ f, y, z& Z( u
   int bit = 0;
+ K/ T+ s& p' j/ o* ?   unsigned char newbyte = 0;; I1 k  i5 i/ r% ~* C7 b1 B
  * \% T$ @$ F' p2 `* Y
   unsigned char *p = bits + (bitpos / 8);
& T! P: c0 q# x' b( ~9 I% T* A   for (i = 0 ;i > (bitlen - i -1) ) &0x01;. K. k" ~9 e8 C  i% V/ m
newbyte = (1
7 n6 \# q% _3 w) I2 W* T% Mbitpos++;. e0 H% C( E0 e) z' `
if (bitpos % 8 == 0)
. @' w1 y% J/ l2 q6 @; ?8 e   p++;1 u& T* F0 N( B3 a3 V+ \+ z
   }, H! u  y$ e! Y5 x  W% a# n
}
/ Z( {. `9 Q' u2 {, y) b
( y+ p+ F  Y- Z& Z  B5 wvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)
! a/ b# I5 n  E$ l9 _2 W$ n{- K" _, g) V# F# u" j. V/ {
   int i;& s& S7 q* x$ \1 ^0 g) a
   int bitpos = 0;9 l# j! ?% {2 Z+ [. X
   for (i = 0;i
8 r1 M. j: F' g
/ U6 b) M; v) ?1 M5 `8 w" ], Y1 TWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
. [6 X/ v% G3 Y. R! y2 z{
" h) t1 ~2 K5 D4 g' O7 h   int i;; s) u3 n. Y5 X9 m$ J: ]
   int bit = 0;
- V7 e7 Y5 R# t   Word16 newbyte = 0;+ h5 w! }0 z( v( [4 x/ k. k+ a
   Word16 value = 0;2 o+ Q* ]2 Z1 w: W  j) B
  6 l0 f! r5 m0 j' z" f: S
   unsigned char *p = bits + (bitpos / 8);8 Y+ q- l' y% L- w
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
- A1 i0 R) d+ `3 `if (bit == 1) {: [2 n( ^: n8 ^( ?+ M6 w) g% k
   newbyte = (1
- k! b' o0 k, z9 Q2 \( O   return value;
$ ~) K; o2 u! d: T* x! r}8 U2 W& [% E$ a+ k
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。2 a  C+ M: q7 h5 G
) Z3 R0 B. }3 [( `! y' }
编码器的代码能采用如下的修改方法
! V( d, l" y1 f0 Y8 B! j  p/ X# K(1)修改coder.c:/ {3 V- ~" i) {' P
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */; q' e! z' e1 E+ U) `" l
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
5 U2 q& \) x( C" T. L3 @   frame =0;" M" \8 V0 i- X* L6 b" f% S6 l
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
" n0 U6 x" {' ?4 B5 I& L' x0 H4 B   {
' w( e2 [( o/ I; Rprintf("Frame =%d\r", frame++);
* a# `* i% Z% J  b7 EPre_Process(new_speech, L_FRAME);
+ ^  S: t6 a# v0 a$ f/ I3 K( ^Coder_ld8a(prm);3 f9 d! b3 p/ h# z
prm2bits_ld8k( prm, serial);" ?: a2 u4 V6 S/ d& U) Z" M& l
fwrite(serial, 1, SERIAL_SIZE, f_serial);  e2 ^0 N5 y& u# n2 Z
   }
3 Z; S, ^* t( B   return (0);# m5 @. g9 [: Y) n* n4 ?0 v: z) k
' j4 u0 g4 I- I; j& h" Y
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:% c' B; i8 P* C
#define   SERIAL_SIZE   109 p1 }$ P/ ~. e' b) ~. ]
3 }; f( d' x2 `; x. [( L5 D3 B, r
(4)解码器decoder.c进行类似的修改(关键部分代码):
  K5 x% I  H/ [' p   frame = 0;% [0 K; G4 h5 F# r* Y
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)$ g3 ]  K( l# O: x$ z
   {
, \; C0 k% t# B- P& ?printf("Frame =%d\r", frame++);
, B0 R7 A9 u$ p4 m! H% Ibits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
& ~! O* c" \1 C9 `5 r3 s. cparm[0] = 0;   /* 假设没有丢帧 */" h7 _$ H+ J0 q
parm[4] = 0 ; /* 假设数据效验正常 *// H5 E9 w% \2 O- h; ?
Decod_ld8a(parm, synth, Az_dec, T2);  w" h- o! f. Z4 r! ~6 c6 ~
Post_Filter(synth, Az_dec, T2);
2 g0 o/ `( g  F3 x+ PPost_Process(synth, L_FRAME);7 j9 {, x. \0 t: k  S
fwrite(synth, sizeof(short), L_FRAME, f_syn);
0 \- K/ I& @9 W2 l& S3 H   }. p9 ~1 R3 e3 T6 I; h
   return (0) ;
4 }- x% r' C4 J( M) G3 d0 J通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。$ p& m; g& I; Q( R9 T% u2 r
+ P; I2 k9 @4 J( S  E' ]+ S
修改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]得到,应该就能了。
# R' Z2 ~  M9 c. Z; [封lib:# x5 o, _; R8 \
va_g729.h% R# Z; W# i5 \6 F5 M: u
#define L_FRAME_COMPRESSED 10
0 g' }  w& @5 f) j4 Y# b. Q#define L_FRAME            80, e5 b1 O* V! k! @
#ifdef __cplusplus
. ?: U1 `, u1 Q; t3 k. Yextern "C" { ( {1 I$ T! |9 _
#endif
. @0 k+ d! j2 S, T& U" _void va_g729a_init_encoder();( j. r, ]9 g2 z
void va_g729a_encoder(short *speech, unsigned char *bitstream);/ t3 R% a! O. U* r1 E. ], K
void va_g729a_init_decoder();
" }/ n  t. A+ @$ A+ O" |void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);& {2 b' `( D: R+ V# w
#ifdef __cplusplus / |- z2 B$ G5 c3 |
} 4 Y6 y& @. V. t2 |1 }9 u
#endif
0 Z8 ?' }0 K0 eva_g729.c% U% {, m3 X" {# U  W
#include <stdio.h>9 o' s9 x7 T- \3 }/ W# n9 H
#include <stdlib.h>  x& b2 m2 S# n4 }
#include "typedef.h"/ M$ x: F1 e/ Q& l: h/ V4 N: _
#include "ld8k.h"
. ?, \# s. ?! H# nWord16 bad_lsf;$ G( O4 k+ q& N/ r2 U  _8 m! ~  @- k
void va_g729a_init_encoder()
& I1 S; b7 H1 Y2 p% `% s/ x! U{2 Y: D# l1 Y4 V  j0 T! N$ P
    Init_Pre_Process();" S8 t3 A* x& B9 V3 o' b) J
    Init_Coder_ld8k();
4 V& ]0 _% d' j  ^}- {9 S" M) G8 u8 O+ J
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
/ ~) j  U* _3 y: G{     3 J% X$ Z7 Z2 K% v; V
    extern Word16 *new_speech;       /* Pointer to new speech data           */5 d  g$ h: [* H1 G0 V8 m4 J* o
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */5 S) |) I3 Z+ S6 Z
    Word16 i;
/ {5 w2 j( [, W% o+ TWord16 syn[L_FRAME];& o* J* t$ S+ `' N$ [
    for(i=0;i<L_FRAME;i++)4 z5 }- @2 V: x# w+ c4 V$ e
{
+ Y- j' ~! s$ L1 ~7 m- D3 Y2 K3 l: q! w   new_speech = SpeechBuf;
6 ~9 l& ^' t  e}/ Q# K) I7 [' e% {
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
  X% f! k* b2 x; N    Pre_Process(new_speech, L_FRAME);1 G" i: \, a* ^/ d
    Coder_ld8k(prm,syn);
. y! X7 l+ X4 h; {, A/ D$ A2 H) H    prm2bits_ld8k( prm, serial);
& F. k6 y  v' {; J7 D3 S/ o3 j}) k7 `( S7 A' f% S4 A. t. q8 y/ F+ h2 `& _5 h
void va_g729a_init_decoder(); }# O0 y+ x+ [9 m& W, V; @! i
{; Q5 N; y9 T; R' l( r1 m; f
extern Word16 *synth;; t8 D$ [& k4 Y6 t" l0 p
    bad_lsf = 0;          /* Initialize bad LSF indicator *// q& q; ?3 J! M- f, L, {
    Init_Decod_ld8k();- ?6 N$ I- T7 \* ~5 x' B
    Init_Post_Filter();
3 J" A8 p/ b- _* k3 W/ u: l    Init_Post_Process();) }1 z, ?. @1 S4 ^5 b* q
}9 \1 ?, o5 {, Y2 A+ T7 v5 h9 Z* v9 U
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
$ Y3 b5 ?3 g) G{2 t; y5 D* D1 m' u, q" f0 p
extern Word16 *synth; /* Synthesis                   */
- n, q6 z$ F  K% F( mWord16 synth_buf[L_FRAME+M];
) E- q7 x- E$ ], |$ H9 MWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
4 q3 _5 W3 \. V4 U6 J- \Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */* X: `" P* {0 p, n, R) I
Word16 T2;                           /* Pitch lag for 2 subframes   */
6 w) k  ]' x0 X3 a" C5 uWord16 i;( [1 Q1 ?5 K0 L& I
Word16 voicing = 60;: U$ M" R# P5 q8 j
Word16 pst_out[L_FRAME];             /* Postfilter output           */
9 `' y1 w: u  k$ Y% _8 FWord16 sf_voic;                      /* voicing for subframe        */2 x% E. j( Q0 _0 N! i
voicing = 60;
3 I$ U  w: _  P6 {4 h; j    bits2prm_ld8k( serial, &parm[1]);
6 j# [) O) o: |, d/ w' w    parm[0] = 0;     F+ l8 l/ r9 m: I
          4 C9 [4 J4 e- a4 `, M
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
' ]4 K* ~1 s  s; p. u7 }Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
4 k! v6 s7 g) U2 `* f//--------------------------------------------------' I; J2 A. ^# o9 a
voicing = 0;0 T8 x: u& R) k
ptr_Az = Az_dec;
3 _, e9 j# V  Y' ~for(i=0; i<L_FRAME; i+=L_SUBFR) {
& m1 u/ u9 q1 m1 ?' A& N   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
. n$ h6 ]( t; ?   if (sf_voic != 0) { voicing = sf_voic;}% m& V5 E' Y4 Q% x7 b5 a2 m5 ~: Z
   ptr_Az += MP1;
# w* R3 ]( p2 `}/ o" a* `) Y# h4 r
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);3 O+ O, _: J/ S/ I% T8 {
//---------------------------------------------------: i3 C) B: m$ I& h3 A+ t
    Post_Process(speech, L_FRAME);   ' q" @- J! a5 Y; @! b( n
}
, |% ~) v! v7 N( |! z; ?# j3 s& ?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-8-9 06:54 , Processed in 0.034032 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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