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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/+ ^2 q/ K9 W4 q8 c9 k$ P
下载以后需要修改bits.c文件:
% |2 ?" ?: Z- H( a) B6 Q+ E+ @我仔细研究ITUG729代码后发现:/ H0 m4 I6 W  F8 w
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流+ W9 E9 i  z0 w! Q
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
  H9 _+ z% M4 R& I% l( W  k$ k4 t! Y
1 [/ i3 [8 L, \6 N7 g) |( h: g7 U7 TITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。2 [9 w3 R" c& L  C4 o
; A+ k' U: ^1 g$ t. l( r2 r# \
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。) e! P2 ?3 R! b# q* a' |2 Y) b
我们打开bits.c,就能看到里面定义的如下4个函数:
) I2 S& [& }% Y. o) A  \static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
' E$ u0 B8 Y+ J! Ustatic int bin2int(int   no_of_bits, INT16 *bitstream);! z; S  f* I1 D# q5 G; u
void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
. {8 r& u# @# J, J5 ~1 }) w, Kvoid bits2prm_ld8k(INT16 bits[], int   prm[]) ;
+ v' n- e7 {2 _这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:7 g  R8 n% ]1 F
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
8 \7 g! ]* Z; b; g6 v6 N' Pstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ;
- C$ S2 T" Q8 R( }2 n9 r# U0 M4 c1 J; |! O2 {5 X+ @, H
void prm2bits_ld8k(Word16 *para,unsigned char *bits)8 X4 `, R- N. X- S9 M+ s& s; C
{
7 K1 D4 [" x  E9 p9 S   int i;8 d% h8 r6 d) _/ ~# v2 V
   int bitpos = 0;) r% L5 K2 f& m6 N  M% P
   for (i = 0;i+ U, u  y. ]" J8 G; r

1 B# v7 ?' u6 c. L- z- Z! avoid bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)) q! \- g" c: B6 D: ^: e2 W
{1 J; z  e1 Z3 R- g. o
   int i;7 m0 u! k9 |; O& }# q7 y6 y
   int bit = 0;
0 ?7 b# V+ Q) P) W" n* `   unsigned char newbyte = 0;
5 B8 ?1 O3 h* Z# S# m' {/ o5 f  
2 X$ C/ n- A+ c7 T" `   unsigned char *p = bits + (bitpos / 8);* p+ k% c/ V$ F! V
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
: V* d) N! M! X% s/ @9 d7 `newbyte = (1 4 b9 P3 ^1 u7 q. T0 f
bitpos++;
/ @( }( H( ~: M+ I- [/ c. ]5 Rif (bitpos % 8 == 0)" f2 p/ T1 @5 s# Z) Q! ~! D8 k
   p++;0 I2 J1 h6 U& k# w
   }
5 w6 I  T! Z' `/ `}7 `6 i  v5 T* Z: U) [
6 T, R2 ?& m& o3 I  F/ |
void bits2prm_ld8k(unsigned char *bits,Word16 *para)# j2 B, ~0 c4 [0 `8 u7 J1 J, G  k
{+ s' G& K+ U4 r- T9 [, ?
   int i;
7 U" f1 Y9 A8 m8 M5 ?1 W1 ?+ ~   int bitpos = 0;. a2 L- ~$ Q( [
   for (i = 0;i1 j* [* r. E. C- }% W

- d7 l3 s1 U+ K: C+ XWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)3 \( V2 q5 {8 n  \  u$ Q. }6 [# J
{
' i# K- X. U( i* t* _* U0 K   int i;
0 }% m( a$ F' r3 A   int bit = 0;
7 @0 t! [! R5 Q' z8 B5 d   Word16 newbyte = 0;! J6 c% o9 S1 j% s
   Word16 value = 0;$ {* k0 M/ b5 k; K
  
/ U$ t6 S% ^! ^   unsigned char *p = bits + (bitpos / 8);
2 W7 [' r- \& @) w0 f+ M6 I   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;& ]* Y% c% R  U( p: a
if (bit == 1) {8 p; q& W' u$ _6 ^
   newbyte = (1 * s- A, Z) d2 P7 w$ w
   return value;6 C+ h/ B8 l; r* r' ?5 c4 e& u
}
4 Z4 V* R$ W  T/ S1 \! J通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。1 {7 [; U, k; N, P

0 x8 {# T+ L8 e. i编码器的代码能采用如下的修改方法  k8 `" W/ a5 B$ J' t# }
(1)修改coder.c:
( K4 J: G8 n- {1 Bunsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
. W" |6 A2 h; _: \(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):
4 c7 @+ L4 a" f* ?! |   frame =0;7 S( E. {$ {8 z3 r
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME), g- p2 D1 ]- q1 {+ G% Q& ]
   {: P/ p% }9 }1 D$ U4 @
printf("Frame =%d\r", frame++);
$ _! W, X! y$ s& F" P4 _Pre_Process(new_speech, L_FRAME);3 ^3 ~3 b7 J2 T- g/ w
Coder_ld8a(prm);! |4 h- @( Q* K; e
prm2bits_ld8k( prm, serial);
  o  s& k( b. d5 r. z; g9 Ufwrite(serial, 1, SERIAL_SIZE, f_serial);
  P; E! M: ~: v5 A% B   }
- m# R6 V, l' \5 `   return (0);
9 C7 h6 w; g- s& h
. e; K( F. @+ |1 r8 _(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:! c7 \! V- k' T
#define   SERIAL_SIZE   108 a* w( T% O) V; [' o5 s

. M! ~$ ^: N+ @! A% x(4)解码器decoder.c进行类似的修改(关键部分代码):
% U' p% d  I7 k0 l8 {9 M   frame = 0;
( n: z: Y: v4 P* \( N   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
% h) D$ U) z2 ^; b% L" G. Q   {
' A( K7 T7 O& L% V6 s8 ?( A# M$ w* @printf("Frame =%d\r", frame++);
7 Z, S% k; i: ^, g* G* X: E9 `bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */% I5 h7 C. [! s/ P4 R
parm[0] = 0;   /* 假设没有丢帧 */) L6 z2 x9 J4 z% x' g( E; d
parm[4] = 0 ; /* 假设数据效验正常 */
6 p8 P+ `8 m2 aDecod_ld8a(parm, synth, Az_dec, T2);/ X! e8 L7 @( ^  Z. f
Post_Filter(synth, Az_dec, T2);
, Q1 t$ _5 s# J5 z, `: IPost_Process(synth, L_FRAME);
1 S0 D) t( C; w/ g; }/ afwrite(synth, sizeof(short), L_FRAME, f_syn);9 b' A6 {/ S" ]6 C. O
   }
+ C8 \! d2 a, i2 V; W5 C% U; P   return (0) ;
6 W: [7 W  M+ |" }" t% Y: F) [通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
  M- o. w: P2 t% Y# |
/ p. h% p8 R) h% _/ R8 h) a7 l修改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]得到,应该就能了。2 o4 }" f+ t. y8 e" `: c9 N
封lib:. A0 I+ w& t4 W- l' l8 R! \
va_g729.h
. b# E- k* w" k7 l4 y: q#define L_FRAME_COMPRESSED 10- b9 @2 g7 H7 ~4 F$ `' s! N
#define L_FRAME            80
9 o% @, @1 |/ N7 O3 d5 j#ifdef __cplusplus 2 B' y; r8 f4 G0 Z, ^8 ]  f" A$ J
extern "C" { & `) i, ^- j/ K4 f3 w
#endif7 h" q# r  e! g: _/ C, f: ^4 l3 {
void va_g729a_init_encoder();
7 V2 X2 _% {/ ~: hvoid va_g729a_encoder(short *speech, unsigned char *bitstream);
9 Z5 y1 S0 ^' _) R- J- gvoid va_g729a_init_decoder();2 y3 V' B. W& W5 @) t
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);6 Z- x8 ?$ M' c6 ^) d
#ifdef __cplusplus
/ I5 S' o. ^+ a. G} % i3 \8 S5 r; i, P+ y4 t- a
#endif4 G: {+ U7 K0 @1 j% o
va_g729.c
2 j1 G) M& W4 y+ z0 r% W#include <stdio.h>
+ c# O" {0 u& ~% ]5 m, ?! k#include <stdlib.h>) ~4 \& K2 O2 b+ k) }! Y+ {9 X5 C
#include "typedef.h"* v7 H" d5 s& Z+ l
#include "ld8k.h"7 ^3 y" n/ n6 e  V; s9 r! @
Word16 bad_lsf;
2 W1 ?5 Z( y  o/ k# t6 b: @void va_g729a_init_encoder()
7 [$ r& o6 s4 X9 b' l+ _3 ]{
; w2 X+ a; d1 S" S1 j    Init_Pre_Process();
& S  }2 H* |9 p$ ]- E' K+ l    Init_Coder_ld8k(); , K1 A0 ~* K  D
}
  F* L+ I5 X- ]4 Yvoid va_g729a_encoder(short* SpeechBuf,unsigned char * serial)0 B& o4 |! s; I
{     $ ~3 ?" q' b+ C+ I
    extern Word16 *new_speech;       /* Pointer to new speech data           */
. F% b6 ]& ?% @    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */9 P. k0 d6 ^  n; G8 V9 w
    Word16 i;8 }( r$ L# K0 N, f6 a* Z, ?& M
Word16 syn[L_FRAME];8 U! |0 f8 }& I
    for(i=0;i<L_FRAME;i++)' _" p$ Q( Z' @% Z! U9 K
{" r+ d( C# U' J0 U. V' N; S
   new_speech = SpeechBuf;
9 \$ a! M  F4 u6 [}# s6 _2 J3 l" ?
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0; 0 H  j/ W: e$ h$ U8 _. L1 B" C
    Pre_Process(new_speech, L_FRAME);/ b* J1 Z: ~9 Y
    Coder_ld8k(prm,syn);
& p; T" k; h$ Q' B- v$ B/ k    prm2bits_ld8k( prm, serial);! L$ h9 ^; U9 G8 {4 o! ]: u  N2 m4 q: g
}% Q. B4 q* x3 _7 [& E+ @! q
void va_g729a_init_decoder()
( G- v/ z: \6 v' A2 ]0 ]! U( D2 P{1 W! `: u3 ~) j! \1 X5 u
extern Word16 *synth;/ Q+ T5 s4 N' a3 Y/ [2 [
    bad_lsf = 0;          /* Initialize bad LSF indicator */( }/ C! V( ^$ h" j2 E, Y% J2 r
    Init_Decod_ld8k();  _; |8 h3 G- }* V6 q
    Init_Post_Filter();
# E: }- R# ]; \! v' |5 F+ N9 M6 w    Init_Post_Process();
9 P; M$ v. X" `$ {; T}
) x& B7 ]% c# ~8 \0 a$ n4 B+ @void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
' w9 e! }! u3 h9 ]: b  J2 ^{. E$ t$ E( ]2 H" P; k" F+ k
extern Word16 *synth; /* Synthesis                   */
0 n: i% s# }8 f4 HWord16 synth_buf[L_FRAME+M];
7 u+ x7 y6 v- I% v' Q6 Z, [Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
% e% z9 v0 P, l1 m4 V2 E/ N& C$ zWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */% \: S. I; A6 b; H9 X+ u* c- G- ]( Z
Word16 T2;                           /* Pitch lag for 2 subframes   */$ {# u6 q) N: E7 B0 _0 Z  n
Word16 i;
6 b; `; \! @1 Y) {' O2 J$ wWord16 voicing = 60;# R" a$ q' k7 V9 f( S
Word16 pst_out[L_FRAME];             /* Postfilter output           *// l) m: W1 C& G, n
Word16 sf_voic;                      /* voicing for subframe        */
4 I+ p0 j' k9 @& i/ |6 k* y) [7 uvoicing = 60;
9 ]' Z0 l4 f9 A& g; y    bits2prm_ld8k( serial, &parm[1]);! Z; N/ D! z$ }% I+ }7 y- W# E
    parm[0] = 0;   9 b0 C( f8 \) C! W8 o/ U
          % u6 Q& u7 u8 Q6 c8 Z
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);4 y5 {9 y9 j( r/ ]+ N' }) x
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
9 A5 r/ m) H* Q% X//--------------------------------------------------$ o7 D7 V, Q9 Q4 F8 X: a% w6 `9 e0 C
voicing = 0;; _8 H! M$ ]5 e& B
ptr_Az = Az_dec;. W5 D2 t! K; f
for(i=0; i<L_FRAME; i+=L_SUBFR) {
6 E! d2 d& a7 W4 D# n" e   Post(T2, &synth, ptr_Az, &speech, &sf_voic);& @# `, G+ e! E: _
   if (sf_voic != 0) { voicing = sf_voic;}
+ H3 C. }) `0 C) _  r- l1 X- u$ |8 Q   ptr_Az += MP1;& a  K+ ]& [' g
}
& B' w8 D, j9 v# |! qCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
" @, r' @9 J- r* m' E1 T//---------------------------------------------------1 L$ |& Y1 r; E) H& Z& M: k  H
    Post_Process(speech, L_FRAME);   * O. J* G+ ]# b7 o8 P9 {
}( o0 {7 T3 L6 k
- w5 j" E8 w7 l8 u+ ?% [3 X) t
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 23:53 , Processed in 0.018472 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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