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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/
$ z( M7 W7 K7 q" O/ q下载以后需要修改bits.c文件:
7 b! u) W+ s. u6 S5 f0 ?我仔细研究ITUG729代码后发现:
" O4 I( j8 t$ C- G3 i编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流
$ I' G( @, R3 U- B,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
4 I& ?! F. o8 L" U, r
: Z* c: V- j( g& |; `) \ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。
; A) [8 V# z1 W, U; N/ }
; h) k3 s6 O0 \那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。
3 U6 U  d6 G/ _2 B0 M3 J" T9 v6 R  X我们打开bits.c,就能看到里面定义的如下4个函数:7 }7 p' V' B) P% G0 w1 {
static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);& @! y: r& Z( k- \
static int bin2int(int   no_of_bits, INT16 *bitstream);
' O. b9 f, m% w: m" z# ?void prm2bits_ld8k(int   prm[], INT16 bits[]) ;
# Y3 _& p" V) }! z+ b! }void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
0 X* I$ s6 f1 U. [, W4 ?这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:% Y% ]9 ^  q5 K) p# J8 U: `
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ;
* T% u& r$ S- h5 m, N9 G& i# Cstatic Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; * E- R+ Y" _- v7 l+ A

" g$ d2 D5 g# W! Cvoid prm2bits_ld8k(Word16 *para,unsigned char *bits)
* y7 w+ {/ G( }3 d* A0 ~{* R$ ]8 F3 w. I: |
   int i;
" Z4 I5 ^; F1 |: d( H4 R   int bitpos = 0;' O) v" X% j/ d& J7 q  R. M1 d
   for (i = 0;i" l8 a& b# r5 Q+ ?( S- a
4 l4 d# a  g; u$ [
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)9 F) q; B* l# o. _: H. V& w/ Q: e
{
: d3 f0 R: \2 \) g8 m# @   int i;$ Q+ J* n4 A; w0 N3 r8 R. I3 |5 C( K% q
   int bit = 0;9 i5 O  m1 |! x7 u
   unsigned char newbyte = 0;& z) f6 ^6 ]/ V, i
  / T. m' g5 K5 m4 P4 \7 @7 T
   unsigned char *p = bits + (bitpos / 8);& P$ q) ?$ I4 V' f
   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
3 w! D  {6 [2 |newbyte = (1
* s, V" V8 ~/ i9 C# k+ ^bitpos++;/ `: a; z) W* Z
if (bitpos % 8 == 0)
0 z) R; K4 B7 U   p++;
1 A) h( }/ v" c4 v; _5 Y  v/ F& d   }
; l- H4 k- X% L& |1 N% u; m: N0 o}$ x. }/ ~* ?9 `
% v) Z1 L, |0 R$ Q
void bits2prm_ld8k(unsigned char *bits,Word16 *para)
; O6 M% x2 G' o. [& k. Z: V{
+ i$ }& M. w/ p6 k   int i;
% m4 S, Z0 G9 V' p2 Z4 u- b   int bitpos = 0;4 A# }4 J+ M) ]9 `
   for (i = 0;i5 r9 j, Q* C' e4 I0 h, p

" p) {7 ^, \% Q3 K; |9 bWord16 byte2bit(int bitlen,unsigned char * bits,int bitpos)
. n" ]$ Y6 Y, y9 A- q% T{# G; \+ Q' u3 Z% c; f1 r% T$ P$ w
   int i;
0 P& l  w  o% u. U- M* R   int bit = 0;
; `# {$ @- m! |: x( A0 Z   Word16 newbyte = 0;. c5 _9 D! t' P( z4 @
   Word16 value = 0;( P/ F2 N5 D2 m
  5 M% c$ c  d9 f5 x# [
   unsigned char *p = bits + (bitpos / 8);
$ y% z( C2 @# J. m/ Q   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;2 C4 f  ^- P8 ~8 k
if (bit == 1) {
: a9 n9 {! @  x: F   newbyte = (1
3 d$ q7 Q7 E4 o* W$ j0 m   return value;: M; L1 X" L/ j- Z; E9 z
}
& ]) [: }' B. \: v1 h1 L通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。) `" n, g* H. t, x
, c2 [0 f* g# Q8 x" x) g9 P
编码器的代码能采用如下的修改方法
& \; y1 g$ n3 N+ P: h(1)修改coder.c:/ Y" z, ]  F( D# V3 T* M( ]
unsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */
+ b4 k. X0 S- z" @! n7 @+ [& m2 l(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):- ?# Y4 w6 {: p) u& `
   frame =0;: r, S" w( h; o; J- q
   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)7 x  A: L) w* h' {
   {
0 `! ?0 M- ~+ G" |4 fprintf("Frame =%d\r", frame++);: D8 C4 r" K; W) i  ]
Pre_Process(new_speech, L_FRAME);
1 v1 I, b0 g& @( f9 S7 iCoder_ld8a(prm);, y. L! t4 i! B: n& b
prm2bits_ld8k( prm, serial);
3 a/ s( `- U4 ?7 `' `) Nfwrite(serial, 1, SERIAL_SIZE, f_serial);
. y* _8 I) q5 k% N3 ]. s   }
! U' k9 a9 n8 B% i! h  N   return (0);
, M% R( V( X6 G: s( D8 `
* t/ x/ ~4 l6 g% G% m(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:* n2 R2 V+ K! V6 E" t: j! T4 H/ Q
#define   SERIAL_SIZE   103 `/ G: p% b2 R' l: t

- b" [4 z! `" j" }( H, i5 w; _(4)解码器decoder.c进行类似的修改(关键部分代码):
' B; _  ?' B5 E1 j   frame = 0;1 d3 B, ]* h& H* A5 y! w: l
   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
2 W* k0 t" T: T- i* r7 S% h   {
& x- K$ N! L$ d5 T/ r" |printf("Frame =%d\r", frame++);( y( Q4 l2 ~# h6 N
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */
, n" {( t3 b. \, s+ @$ Z5 E$ d' o) @; U7 |parm[0] = 0;   /* 假设没有丢帧 */
) \4 c. t% }7 N9 k$ R% ], hparm[4] = 0 ; /* 假设数据效验正常 */
9 a, L# `( e& G% I1 j# p$ |- aDecod_ld8a(parm, synth, Az_dec, T2);
5 F0 }* l9 V$ l( N; t8 nPost_Filter(synth, Az_dec, T2);
5 S. ]/ Y" F: pPost_Process(synth, L_FRAME);
5 D! ]/ P! E% e0 {5 hfwrite(synth, sizeof(short), L_FRAME, f_syn);
1 w. U6 Q6 ?! y. ?2 D$ `  j9 B3 r   }0 J1 g/ n& K/ e. Q9 v+ w8 {: X
   return (0) ;
3 i0 Y  v& F# ~+ x+ h5 Z通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。# H9 E0 N- L. h! _6 E. k; n6 n$ s
8 g* i/ d& i5 M/ s* Y9 K
修改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]得到,应该就能了。: b3 f- Q9 Z1 \- n3 z
封lib:
9 y: D6 G$ d2 {" E# Iva_g729.h
4 Z$ }  @7 @; W7 E#define L_FRAME_COMPRESSED 10' r* C- O/ d. q8 r
#define L_FRAME            80! Q! R! x4 d' l/ D9 I/ \" o
#ifdef __cplusplus
: p2 _- q% R1 J6 Q4 ?+ C5 gextern "C" { 8 T- P' e- h5 Q/ ~; T0 U: o
#endif/ v7 Y9 T1 j6 o+ A/ U
void va_g729a_init_encoder();
( |; b: P* X& `7 b$ v: dvoid va_g729a_encoder(short *speech, unsigned char *bitstream);2 |0 c! ?5 V! {( w* _
void va_g729a_init_decoder();
' x% ~/ ^, V' lvoid va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
& j, w. D! v5 I" h- s% y2 x#ifdef __cplusplus
# v3 w9 m- P. }0 }} 8 H& ]0 V- A6 i4 L' a7 r
#endif! l$ i% R( a' S/ A2 V, U; n
va_g729.c' j: v# n& I  J
#include <stdio.h>1 U/ n" _2 j* R' {7 d8 a
#include <stdlib.h>& V7 t* _  p1 F# {' k3 b* E7 n2 K
#include "typedef.h"2 O$ k  F) @4 Z% H" i
#include "ld8k.h"
% x/ _! ?% m$ j- g9 D# TWord16 bad_lsf;
0 q! r8 @, n5 h9 P' U' `/ P' s" {+ f  Avoid va_g729a_init_encoder()* t$ w* H% N$ x5 a
{
& N' F4 x" Z+ |. @  N; G    Init_Pre_Process();
9 V' D5 Q: X2 z. o    Init_Coder_ld8k();
) T+ r) b/ S) g+ \& e}5 ^7 ]6 B$ Y% e
void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)
" K# z( `! D1 _6 W6 C; l{     
! m) B. j. R+ }9 b: z* U6 {    extern Word16 *new_speech;       /* Pointer to new speech data           */
& C6 D2 i0 d* W; D    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */
' x& I9 P! Q. X& ~) u    Word16 i;! A2 S  z5 m9 v/ j) w3 w$ i
Word16 syn[L_FRAME];
1 \  x( M3 Y# J+ N. a2 O- g1 V    for(i=0;i<L_FRAME;i++), c) U7 S' G7 i" I% y2 _
{/ E5 Y& S6 m3 V& b5 Q6 D& r
   new_speech = SpeechBuf;
# R$ c% R. S6 ^* a+ l8 Z}- m$ Y' w  V1 l, o: x( H
     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
& i6 t* N, r% Y4 i# l6 u    Pre_Process(new_speech, L_FRAME);
6 O9 F9 R3 k. _    Coder_ld8k(prm,syn);8 i" m0 |* h& B8 i$ M
    prm2bits_ld8k( prm, serial);
5 I* v2 {2 @. `' H3 g' U8 P( h+ X}2 F. S  c% V3 J
void va_g729a_init_decoder()
3 [1 B1 [! y5 h{
7 z  j3 x" q- g6 V* Pextern Word16 *synth;/ x. ^8 p' l' R# h9 X4 A
    bad_lsf = 0;          /* Initialize bad LSF indicator */
1 u8 B; C: ]1 \    Init_Decod_ld8k();
3 v7 J6 Q6 p, t: \' R: X5 l6 I    Init_Post_Filter();
2 U# n" k- y/ z. ~- a    Init_Post_Process();
) j( V3 l( l) X& b8 R! V1 R}" i# V( H+ `8 b5 P% ^; c: l
void va_g729a_decoder(unsigned char *serial, short *speech, int bfi)0 [5 {( e# ~+ L7 K! X; x
{1 ?" h" p) ~& B3 c7 {0 I" w* f
extern Word16 *synth; /* Synthesis                   */
/ V. j$ [! V* H5 p& C: V9 }8 |Word16 synth_buf[L_FRAME+M];' h! r9 A4 B3 m! G! B/ B# W9 u
Word16 parm[PRM_SIZE+1];             /* Synthesis parameters        */
$ {% S$ i+ s) w& k9 IWord16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter */
3 ~& j$ D) g( T1 c5 `2 Z) h0 eWord16 T2;                           /* Pitch lag for 2 subframes   */* Y5 `. `9 I! l1 l4 u& q  J
Word16 i;
, _& j! ^. x+ |3 |Word16 voicing = 60;
4 ]$ `7 a& {( @3 Q5 L( eWord16 pst_out[L_FRAME];             /* Postfilter output           */) v2 {9 n; [9 W5 |# J$ |
Word16 sf_voic;                      /* voicing for subframe        */
+ C; ]7 |7 X" i) avoicing = 60;! L  R) Z* }. ]1 K4 H/ |3 {) {
    bits2prm_ld8k( serial, &parm[1]);2 V$ h% k3 p3 Y) }1 l/ x# x
    parm[0] = 0;   
3 ]( G9 w1 L# a" _4 p         
# c6 q3 `0 R' O* X8 [    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);& H2 E& ^5 [+ y4 k  d
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);
  d& S$ E% |, J# ^1 p* @0 b//--------------------------------------------------
; x2 K& m0 E: hvoicing = 0;
) g- r5 _3 h: o' bptr_Az = Az_dec;
( V4 z) g; H2 i; Tfor(i=0; i<L_FRAME; i+=L_SUBFR) {
, E0 ]5 s( q! A$ a4 C8 Q: F   Post(T2, &synth, ptr_Az, &speech, &sf_voic);
3 U3 y6 |8 f7 v4 J3 A5 |, K   if (sf_voic != 0) { voicing = sf_voic;}
( ^7 E. b& g. R( x6 O/ ]" u   ptr_Az += MP1;8 u1 x; O0 k9 Y+ o$ E# K
}
# r* T  y( H1 Z+ I; `* q0 LCopy(&synth_buf[L_FRAME], &synth_buf[0], M);
2 z" E) Z4 a6 i7 \6 |" Z* U//---------------------------------------------------
  Y4 s2 A6 `+ E* e4 T    Post_Process(speech, L_FRAME);   
0 j, ^8 t) Y7 S* E}  S% B' A! E: m" D- F* h8 r

. h7 Q+ b8 O1 i2 W4 I/ Y0 Q8 U
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-1-27 19:34 , Processed in 0.016960 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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