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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/" u" Y# s- W2 V1 T' O
下载以后需要修改bits.c文件:+ d2 a/ d" K# }) T8 x6 m# [
我仔细研究ITUG729代码后发现:
; H8 M. O3 u' }  g编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
2 X! v/ z2 W4 |: M; \4 M3 l,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
8 z2 d# ?" S7 D/ P% D( a
0 K6 j) L* n  |: ?( ~ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
5 M+ b$ l! a8 t- G1 _' n  r6 z- ?# @; ~1 y
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
( q5 M/ r5 ~& v: `0 ]我们打开bits.c,就能看到里面定义的如下4个函数:
; ]5 g9 r+ J# @8 b# gstatic void int2bin(int   value, int   no_of_bits, INT16 *bitstream);) T; U# ?" e3 }8 y! T) r" \
static int bin2int(int   no_of_bits, INT16 *bitstream);
: H3 U8 T7 t5 ?9 f" Z2 lvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; . {) P: h4 S% I* d" R2 L! b
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;# ^' S) f& \  @  Y5 U6 h, P
这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:
. F* C7 a% l% {% z$ `, u' Astatic void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
: X: z- P" G! ?3 V" t! Y( istatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; " u: m; D7 m1 x0 j6 S2 A( E' i: Z) L
, M# X& _2 v- S0 S1 ?
void prm2bits_ld8k(Word16 *para,unsigned char *bits)
* M# Q9 u* G7 g# P$ q6 ^; m' V{$ h1 u4 ]0 h' ^' Y7 T% X6 x& A7 x
   int i;6 [" m' _# h2 r$ \. O9 w
   int bitpos = 0;
1 E, W8 h( E8 ^  I0 d0 v   for (i = 0;i6 ]2 s% x, s0 d4 U
* g' N  [" e3 m3 G+ t) R
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
# p: V! v4 ]& a0 H3 y* {# M{
: L% {- ?; @! g6 r- E: s   int i;' @8 r, @/ c. ^3 @/ ^1 r: `5 Z6 z& Y
   int bit = 0;
7 f! D5 T, I& P# f' _   unsigned char newbyte = 0;
/ F, E( S: v1 L9 g, k" Q0 x  0 G* e# Q* w8 ^0 T) w* q
   unsigned char *p = bits + (bitpos / 8);& K4 b! q; P* |4 h, _
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;  q' x& }; c0 O
newbyte = (1 : o5 O, d3 a1 h  o
bitpos++;
  d9 i2 V% ]3 g: f$ oif (bitpos % 8 == 0)* q. I  D- X0 O$ B+ m
   p++;1 h* j9 V) E! d5 F
   }
  e' U: j# m/ n}
% M7 a: w! d" V* j+ i/ b" H. o* b5 b4 I" {' i/ [7 \; W- o
void bits2prm_ld8k(unsigned char *bits,Word16 *para)
" B, _" s7 V2 B; A{
! }, n7 D9 W9 b   int i;
4 i9 |3 ^% t- Q( q   int bitpos = 0;6 C* X, J2 J7 @# z% ?$ T6 W
   for (i = 0;i9 _  K3 J4 V: }- M( `4 e: {& Y
5 |' H: \: A) e" v
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
8 O& F  n. ^2 O0 F$ _+ N. w{
# }6 u6 M5 Y7 o   int i;4 @/ X5 F! p3 f) i
   int bit = 0;
+ x& ]! n; {# {   Word16 newbyte = 0;$ k3 ?9 }0 B! Y3 a% e0 F+ T. a9 D
   Word16 value = 0;; R) Y% Q- u& `7 U
  7 Z  U" B: L# c( b/ S0 z, b
   unsigned char *p = bits + (bitpos / 8);/ U+ E4 F! }* T
   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;- }& m$ S( K2 v6 x: U# k4 l+ T
if (bit == 1) {+ G' D% w( T( L3 j/ M! r
   newbyte = (1
( j: ?5 H) G0 j( w9 a" C4 |   return value;
6 j8 o* Y* f- T) S: L}1 B6 q# e, M% D4 M
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。
7 m  @( n. d- T, B( D0 p9 m
4 [2 d# a! W& G& L- q$ |, n2 ^编码器的代码能采用如下的修改方法# J8 _  e8 H1 e: X* K
(1)修改coder.c:1 D4 s: s* g0 [8 K. M, V$ n
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
7 Z9 v: ~- j1 S  a% U' Q! j9 Y(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
+ u6 c3 o2 l( Y6 x- L% U0 L8 g! ]' W( c9 Y   frame =0;, ~% _$ d1 _1 N5 B) D
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)1 S* [1 P/ }* H, S+ u4 m0 T* I
   {8 B3 ]! f' V$ L4 ]  o5 [
printf("Frame =%d\r", frame++);& p8 M: y0 Y2 B/ c6 f# L  ?
Pre_Process(new_speech, L_FRAME);
; `, S% Q/ i  G. a) fCoder_ld8a(prm);
; f0 q* ?- L- x' \' D1 Q) a. Pprm2bits_ld8k( prm, serial);6 E8 P* A0 V: u
fwrite(serial, 1, SERIAL_SIZE, f_serial);2 j, e2 {9 a" W% m2 Q5 n8 _
   }
( v1 M5 e9 f, ~( c4 d   return (0);
5 ?0 B" s2 x$ w' w3 W- D$ i& ?/ {7 X: O; d4 x% q; X$ f0 q! X
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
. M/ ]5 T  I7 e% ?9 ]9 Z1 g5 E0 @( H#define   SERIAL_SIZE   10/ X% r4 A9 B3 \( M* v& B/ g
/ S" r5 Z" W9 L8 c- h% ~5 s
(4)解码器decoder.c进行类似的修改(关键部分代码):
* T2 r0 V  {6 }2 Z! Q, y# l   frame = 0;
. w% H* W7 u; \3 P- M; [   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
# O/ @/ e7 G" z  `$ ~: j7 e6 d   {
' z' w& m; |* N# A9 e! cprintf("Frame =%d\r", frame++);
  a7 Y" y5 a1 J" j" G' T; Cbits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */  o  @  S2 c% h8 X, l4 [, u' b
parm[0] = 0;   /* 假设没有丢帧 */
0 G- O: n8 u6 R1 Q; ]- G* F6 nparm[4] = 0 ; /* 假设数据效验正常 */
7 a- ?) A" k9 |" N) mDecod_ld8a(parm, synth, Az_dec, T2);
9 Q- q1 s2 Z5 G8 VPost_Filter(synth, Az_dec, T2); $ }: ]/ S% N- E4 I" I; \5 x+ k2 d
Post_Process(synth, L_FRAME);
/ C, i- c8 c4 Kfwrite(synth, sizeof(short), L_FRAME, f_syn);8 B3 y: S- @  t8 i
   }: g6 [4 A1 n5 W: z
   return (0) ; ' C* Y3 J* F2 k* c
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。: w& ]" M- v: ~& w: [* _% S
5 A+ O6 R8 N" S6 ], u' |
修改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]得到,应该就能了。
' `; |: Y. \$ h3 h' _( l% t( [封lib:) j# O6 [5 q3 _, x% |. I
va_g729.h9 g  v! Y" p$ j
#define L_FRAME_COMPRESSED 102 _" Z. R6 s$ R5 h* y' \% s
#define L_FRAME            80
& \; Q$ G$ ~* W, v0 V7 O0 k4 j4 L#ifdef __cplusplus 8 ?5 v# _3 W0 [1 l
extern "C" { $ [6 u6 Z1 V6 p" W  m
#endif, C1 c( F! W+ k. x. K
void va_g729a_init_encoder();4 E- X  y  V0 ~! V
void va_g729a_encoder(short *speech, unsigned char *bitstream);- k; f2 B) n! A' s5 s5 k9 b
void va_g729a_init_decoder();  U6 Q3 a. ]5 G7 u. M
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
8 m2 t" F% I" J+ H7 n#ifdef __cplusplus
' c" a5 F; p. z}
' Q3 a5 m8 {' o* ?; [#endif
/ m- H. u% U- n( e' v( Rva_g729.c* n; `! y" a" r( y1 c! n
#include <stdio.h>! R( g1 j' ~) _5 N
#include <stdlib.h>; z- Z( L/ E/ [
#include "typedef.h"! B/ B0 T0 k1 H0 S
#include "ld8k.h"
% m' J, ?6 s  M# s/ C+ h3 [6 jWord16 bad_lsf;
& J! p/ U6 i6 g7 y" M; wvoid va_g729a_init_encoder(): }- d& x: A* \+ G* P+ f  [
{
, h& o  o. T  X3 Z    Init_Pre_Process();
2 v# S8 O4 m1 Q: M/ Q6 W    Init_Coder_ld8k(); 0 W* D$ m' X9 r! f
}7 q1 C  h" r! K  f0 I- k1 }
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
2 h7 J; e9 g- Y. o' T7 c- M4 N{     9 B) o) \" I0 F0 w  N* f
    extern Word16 *new_speech;       /* Pointer to new speech data           */
5 P: a/ N) F9 Y3 C' b* R! X  }    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */: x! Y' h) U4 Q' A9 j: P- w
    Word16 i;
3 d7 i- B* ]2 P9 O" y( ZWord16 syn[L_FRAME];
5 k' F! s9 d4 A, n) F, |    for(i=0;i<L_FRAME;i++)
6 X( V& z- c  g4 |$ G) S5 X{) `9 l8 m/ B2 T) U" D
   new_speech = SpeechBuf;  U& U1 j2 {' j: p8 C! g' Y/ q/ B
}! t& G% ^2 b& D7 u
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
' o: `5 U/ h, T4 R- ]) ~    Pre_Process(new_speech, L_FRAME);6 z' X" X$ [- G- l+ T9 u
    Coder_ld8k(prm,syn);
' z/ {- m' q! Z2 b    prm2bits_ld8k( prm, serial);4 T7 x9 S! q( p3 `! S/ T7 Y9 o
}& z$ P1 y$ o9 o4 J% O$ x
void va_g729a_init_decoder(): F: _: T8 [: U: a! ]+ J9 O
{: s$ Q  X& R5 Z) q
extern Word16 *synth;
& Q' w( }0 f: R6 E8 p6 c    bad_lsf = 0;          /* Initialize bad LSF indicator */
& [. f& W' T; |" D    Init_Decod_ld8k();5 I8 {) T5 A( T
    Init_Post_Filter();0 f. D* I( V3 h4 u8 G4 F* S1 l! w0 L
    Init_Post_Process();; i" M$ U% [) L4 {1 N9 W4 A+ E
}
( C0 V: T) D9 _void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
: _0 @0 }1 z7 c1 S4 _6 S{8 |+ W9 _3 }6 |6 L2 T9 _+ w
extern Word16 *synth; /* Synthesis                   */
4 F  M9 Y& q0 U5 i8 Z$ gWord16 synth_buf[L_FRAME+M];; v. X9 I. t, O# N% V
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
) c8 A2 P( [: x% Y  e  u3 L/ fWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */! x0 d6 f+ V4 E: R
Word16 T2;                           /* Pitch lag for 2 subframes   */
+ |5 s2 _( m+ G; P7 S0 ?5 f# WWord16 i;
" W3 c: ]: E, `Word16 voicing = 60;
4 m/ r3 |5 i) M3 F/ [& V( [5 CWord16 pst_out[L_FRAME];             /* Postfilter output           */
0 g; N! |$ v6 ]/ e. CWord16 sf_voic;                      /* voicing for subframe        */
1 p! ^6 @3 A2 ]) X: z1 E# i8 Wvoicing = 60;
: e3 |& j+ G/ n2 {% s6 V    bits2prm_ld8k( serial, &parm[1]);
) o% Z2 x# X. q/ X7 M    parm[0] = 0;   4 v5 V3 H# k5 q/ m( e
          " ?) k0 @- {  U1 a) A0 L& [
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
2 O4 ]0 c0 C0 w$ a  CDecod_ld8k(parm, voicing, synth, Az_dec, &T2);
( E. N3 W5 [$ G( K//--------------------------------------------------5 C3 d" A6 n  ^; E* k0 k
voicing = 0;
, h( W! w: I# fptr_Az = Az_dec;
) |0 U& U' Z7 f1 cfor(i=0; i<L_FRAME; i+=L_SUBFR) {- C. w2 ]2 _! M7 E# ~4 k
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);5 F. {: h, s6 Z6 H1 m/ V
   if (sf_voic != 0) { voicing = sf_voic;}
) K# \5 ?4 N" t6 N0 n8 M1 n   ptr_Az += MP1;7 M+ V8 a8 [' G8 v4 f
}& j  Y! e8 t3 Y& z/ K! K( d; a+ ?
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
/ M; ~  J& {0 ^//---------------------------------------------------
$ v, p  C& P5 K1 v1 S    Post_Process(speech, L_FRAME);   
0 R" h' L0 _) P6 Q4 z}- Q1 ~/ y$ J0 B: @9 o

2 q3 G* [2 {" L: O5 Q4 H9 D
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 06:46 , Processed in 0.017813 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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