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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/) I6 e! j4 _$ X, B7 q3 H$ G( m) F
下载以后需要修改bits.c文件:
* ~/ Q: s) O% w' I+ ?我仔细研究ITUG729代码后发现:+ y1 Q& S, C2 ~- M- {
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
/ m  _, _2 R6 ]3 f" V9 X, {,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。2 i* z: j+ E( Z) {4 A/ A7 m+ J
* t* J, k0 Z1 E% T
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。/ X  a) F9 T5 [& y4 F! c

; s* s8 q% d4 Q$ r  o那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。, o; o2 T8 x3 N8 C/ E
我们打开bits.c,就能看到里面定义的如下4个函数:3 V7 O. j( X0 ~. n
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);2 A3 p7 _9 S. W2 E- l
static int bin2int(int   no_of_bits, INT16 *bitstream);
* i9 R. Y7 p: d% g  P& Tvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ;
7 X, F$ x: _; A0 T+ `0 N) Ivoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;
4 w" K* w* }! q* C7 x0 I! M4 T6 K这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:& [' H- K+ V. _) {3 t. C
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
7 n9 X; r' q  [0 f7 _# V/ lstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
0 R4 l$ E* `9 f$ M6 D6 F. t2 h# m3 t5 `6 W6 S# R% E
void prm2bits_ld8k(Word16 *para,unsigned char *bits)+ Q/ M1 M) O. J( N
{; Q3 S  z) y- N8 {# x0 N- {9 t# O
   int i;" U; @& w# r& \0 \3 _1 }
   int bitpos = 0;
0 S9 F4 S$ A% ^: ^   for (i = 0;i
" P, N! f3 P: L& i. I/ X" `/ `% @& c
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
) z1 f* V1 ^; X! ?; r( d{
4 p: }1 k1 y4 g$ p: {   int i;7 H1 F; g7 k0 r5 B% Q9 i; Z
   int bit = 0;
# Y. b7 Y" @; Y+ K1 |   unsigned char newbyte = 0;
3 `! K, b( V( Y! P  & q1 D6 k1 B* j9 Q% Y8 n3 o; U
   unsigned char *p = bits + (bitpos / 8);6 ?+ g9 a. w+ y" E1 i7 W
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
- I4 t5 z0 y0 p0 J0 Snewbyte = (1 7 l* h9 I+ Q# w+ A
bitpos++;
- v% o* m% O' l7 jif (bitpos % 8 == 0)
7 D* o' s7 J* W6 ^6 M   p++;
/ m4 I- E2 O# g  J. m9 g" `: B   }" ~6 P* G6 h- V( M& q! r: k
}
( z8 m' @& S/ M. G/ ^3 x" v) V; a- B1 j# L% x7 q( \
void bits2prm_ld8k(unsigned char *bits,Word16 *para)( t# g3 w+ Y2 l( a* ~
{
- x8 ~$ s9 d+ F0 D0 k   int i;* q1 Q9 t# H; b. p8 ]1 y: D8 Z
   int bitpos = 0;+ k8 a- v$ j- F
   for (i = 0;i' D: o! g8 _6 C3 ~% t6 b; C; i
: Z! E0 o" M. W# t9 c
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
# ~( s) M1 v& E0 |{2 N% z" F$ j9 [8 Z" l& K  |
   int i;& }" U8 |, T( [
   int bit = 0;
% h9 [% q" H0 X9 q3 p% A   Word16 newbyte = 0;
( q6 T- Y# R, V" a+ K! C   Word16 value = 0;8 n  X1 y8 A7 F2 S6 p" n' K" b/ S
  $ i9 `  t& {5 B) `
   unsigned char *p = bits + (bitpos / 8);
3 A/ U0 t" ?; d$ m5 r' [; I: G; o   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
# C( z: M. D6 X# Y9 Cif (bit == 1) {; E* ~; z9 f/ s& r" K( ~+ ~
   newbyte = (1
4 u, I5 j% {6 G/ Y# ?/ i: B) e! L   return value;
8 ?; {* [) F% t}0 [+ q) v" k3 R5 [, M! b2 {* R3 M
通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。0 i7 k( v3 W# V- z& h8 ^+ k, L

2 `. R# a. v7 x. I) R3 `编码器的代码能采用如下的修改方法8 y: g. \& C+ X
(1)修改coder.c:: |* v: N. O3 d! L% w
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */3 _! M8 R' J  C) U
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
2 C) M; ^! n- Z. `* r9 a, e   frame =0;  p7 H) \& `6 A# G! ?, z
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
1 N2 s) H5 x( t+ `1 p   {
8 a' B  ?4 W5 }( N4 ^  ?* M. yprintf("Frame =%d\r", frame++);. a! K" h, }9 l
Pre_Process(new_speech, L_FRAME);1 X; d7 U2 l5 h$ v! _
Coder_ld8a(prm);/ O) C, h3 f, ^; C7 y
prm2bits_ld8k( prm, serial);, {6 Y' r9 J6 X5 F4 v" ^
fwrite(serial, 1, SERIAL_SIZE, f_serial);
/ J4 x3 l0 |% ^$ `* }# B! s   }* x- w& r' Q: r, b& f: H
   return (0);
) E1 L! I5 y( i- {8 ~2 c  j$ x" s4 o1 Q; h" u/ O
(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:
- C5 m0 i; o7 u+ e! H#define   SERIAL_SIZE   10
- c9 L! ^; Q# X! o
, J* @9 j7 i/ n7 B6 c2 u8 G$ o6 t(4)解码器decoder.c进行类似的修改(关键部分代码):" C; e6 S5 S/ N' H6 D, E
   frame = 0;
6 X; _& ^! ~% c/ }" P# j   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
4 z4 e  c$ s5 o& ~+ T& b   {- ~" p: B& o: Z- N0 Q8 I
printf("Frame =%d\r", frame++);
5 T8 [) ]) V$ ~3 [* A- X1 {bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */: F5 l: X) D8 q/ l- u9 v
parm[0] = 0;   /* 假设没有丢帧 */
: {& S5 \2 Q, X5 |4 O* S5 O7 O' Kparm[4] = 0 ; /* 假设数据效验正常 */4 S$ a3 u0 Q9 o% W2 f$ f! y
Decod_ld8a(parm, synth, Az_dec, T2);
: C/ }) c0 D$ d7 V# L; u  T1 KPost_Filter(synth, Az_dec, T2); 1 u9 {! K  V- @% ^7 {9 X
Post_Process(synth, L_FRAME);( a- G2 p$ N/ }5 P- b# [
fwrite(synth, sizeof(short), L_FRAME, f_syn);
. @2 {0 [) @2 y   }/ l+ H# B2 U* A: ?- q4 k8 L
   return (0) ;
# H+ e0 u  i; z+ B通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。! @. v! P9 ?& ]+ n0 V* w& p! w
) a- U2 y, p$ r; V& U+ c
修改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]得到,应该就能了。
7 c, {& N7 U) g$ l. G+ ^封lib:
/ Y; _# z, a5 ~1 k3 W" J& A4 nva_g729.h& y% L& C3 E& ^2 m/ G: C
#define L_FRAME_COMPRESSED 10
$ X8 X0 o0 g* v( W# g- I#define L_FRAME            80
4 V/ Y2 f3 a6 `" U& `+ a#ifdef __cplusplus
/ g* H7 K8 c3 x& pextern "C" { : ?( b6 I: t: P- w2 k
#endif
2 k6 ]" n& h# j* U+ F, bvoid va_g729a_init_encoder();
: N# ?2 b0 W/ Q5 n! Zvoid va_g729a_encoder(short *speech, unsigned char *bitstream);' P! R; |" x5 k" U1 Q( h5 q6 \4 A
void va_g729a_init_decoder();/ n' K2 j9 [) k
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
  b, f6 j  I2 C: ~/ }#ifdef __cplusplus 3 R# z) b* c6 i# P5 w& p
} ! D6 e$ H' _6 V8 \) Q* A. H" ?: F
#endif
' Q. s- _' d4 c, e* X, o- rva_g729.c
; a$ [) r4 C5 y: ?#include <stdio.h>3 z& n4 K  e) Z8 {
#include <stdlib.h>2 ~& [9 O+ k8 ?9 x& @
#include "typedef.h"+ A2 u8 a& D& X4 ~# C6 j
#include "ld8k.h"* D9 m; T/ U0 ~: T/ ]8 y' j- d& y# a  L
Word16 bad_lsf;
4 y) a8 j) F9 V1 Rvoid va_g729a_init_encoder()
6 Y4 ~# Y7 K3 a/ b- V/ e{
/ l& H0 U6 p8 N( J/ _: R    Init_Pre_Process();& `2 v: ~( m1 s
    Init_Coder_ld8k();
3 y  V+ t0 i6 ?: z+ v}. o* O# x+ b' z8 M3 w
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)) E( r$ D+ c8 d. V, D
{     
8 s3 V( {- X1 u, |/ ^- k, f% W    extern Word16 *new_speech;       /* Pointer to new speech data           */, d6 s- Z$ Q) D( v
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
9 D1 }4 o* R- D4 R    Word16 i;
. I) J! h0 ]+ f  I/ Q# J" bWord16 syn[L_FRAME];
8 k+ o8 \2 J6 [6 K    for(i=0;i<L_FRAME;i++)
9 `. }# x- I& H7 d: R  ]5 b) y{
8 ]1 a+ n9 Z0 k5 I7 k1 ~2 ?   new_speech = SpeechBuf;7 f; J# `  n  E3 T0 @
}
. T4 u5 a" x* O" {$ H( q     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
1 f7 m! r; d8 t3 z- h; D: R$ P    Pre_Process(new_speech, L_FRAME);
, o; T- q& d$ ~7 D1 d- |6 L    Coder_ld8k(prm,syn);
* c4 e8 o+ t" h( z0 c+ E    prm2bits_ld8k( prm, serial);# P) E+ M! D; c" S  }  [, [
}( ]& g+ e' y! N% e9 {" X
void va_g729a_init_decoder()
$ h( g! J5 y$ t6 f+ n# N  k{
+ |, o) |' ?9 d0 N) f# Vextern Word16 *synth;$ c4 i8 Z8 ~( b  P4 I" V
    bad_lsf = 0;          /* Initialize bad LSF indicator */
" R! q% e4 q) ]    Init_Decod_ld8k();
: K& ?' A) _1 `+ s8 o. D0 M  |9 c    Init_Post_Filter();
4 s0 h8 s: U( v. [; o    Init_Post_Process();& K; ?! G6 d  u  F% g& t
}& `9 m+ z" a( _- N2 Y% Z! K( P1 H2 f
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
, U+ G1 {9 T9 u, e# a/ G+ S1 f; W8 e{, l+ H4 Q6 t2 l' T0 ]% J8 V
extern Word16 *synth; /* Synthesis                   */% k5 a: u7 p7 u. F+ R. |! d( d
Word16 synth_buf[L_FRAME+M];" L# |5 b# t8 M9 z+ b1 H
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */5 `3 ?: ^- S. t# }+ P
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
  J* P/ k1 u7 wWord16 T2;                           /* Pitch lag for 2 subframes   */3 F; O% C; i. n- w/ M
Word16 i;
; A2 A, x/ G- t% N3 d# F! j) _3 bWord16 voicing = 60;
: l! f- ]# s9 O2 {0 ?Word16 pst_out[L_FRAME];             /* Postfilter output           */8 g( T. r% D. L, r* a; d% E
Word16 sf_voic;                      /* voicing for subframe        */
. I( L  M# X4 R! u2 d2 s  |voicing = 60;2 J" g0 _, X/ O7 u& v
    bits2prm_ld8k( serial, &parm[1]);
4 N" Y, j. ^' ?( ?    parm[0] = 0;   
* F* k; X8 c) D- ~# r% q; r  w/ b          ; s0 H/ T; Q% {7 L
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);
' F! V! |; O; s9 b4 qDecod_ld8k(parm, voicing, synth, Az_dec, &T2);" ?' k+ Q: o& [2 O1 o& B+ D
//--------------------------------------------------
/ x$ m. \- |7 l: c* f; Mvoicing = 0;
% u, j1 W+ D" S) ]8 j' g. b* U; mptr_Az = Az_dec;
) M! m1 ?* k: G0 z+ Ifor(i=0; i<L_FRAME; i+=L_SUBFR) {8 w8 l# {4 M, H: C7 Q
   Post(T2, &synth, ptr_Az, &speech, &sf_voic);6 y4 o4 ^$ Y* W  R: I+ {7 z$ m
   if (sf_voic != 0) { voicing = sf_voic;}9 }# L  N; n" n2 O$ T5 \1 H
   ptr_Az += MP1;4 l; y& @6 G0 a: B
}1 n0 Q# {& v! k
Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
  a* T8 q! b! O0 k; U! c) ^//---------------------------------------------------! I$ k) _8 \5 T
    Post_Process(speech, L_FRAME);   & k7 L& h1 m4 J. c
}& Q) |* A9 P7 x' g

9 B! l- s6 [, t  K
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-12-29 17:40 , Processed in 0.019490 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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