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

g729a修正与lib编译

[复制链接]
发表于 2011-6-8 16:07:23 | 显示全部楼层 |阅读模式
到这里下载:http://xiaokotei.download.csdn.net/user/xiaokotei/all/% P5 F: r0 P( I& U8 \
下载以后需要修改bits.c文件:
, n8 c: q0 C/ O0 E6 q8 O: ^3 H我仔细研究ITUG729代码后发现:, J+ ]0 v$ m5 C8 _
编码器的输出及解码器的输入不是编码生成的参数向量,而是经过1bit->Word16(即2字节)转换的bit流, R+ ?  b' W, d
,从而使得编码器输出数据不是原始PCM的1/16(理论上g.729编码和wav的文件的大小比例约为1:16),而实际上,我们采用他的coder编码出来的文件由于上述“串行化”的原因和原始wav几乎相同大,而且甚至比原始的wav还要大个十几K。
) @+ _# a% U+ c  [( O! Q/ B' g/ u/ {
ITU-T为了在标准化方针中进行丢帧隐藏测试,对语音编解码器参考软件的码流格式一般需求为ITU-T G.192中规定的格式,即用16位的0x007F表示1个比特’0’,用0x0081表示1个比特’1’,每个帧头会有同步字和包的长度。对于同步字,0x6B20表示该帧为坏帧,0x6B21表示该帧为好帧。这样固然非常好,不过。。。导致了编码后数据的增大。/ r' P/ a8 \. m# m
; v) E2 o9 ~/ W0 b% M$ g# s+ l
那么怎么来解决上述问题呢?解决的方法就是??去掉串行化代码,或重新编写串行化代码。( B5 S' E# O8 t1 W2 O
我们打开bits.c,就能看到里面定义的如下4个函数:
0 s, S& _& ]+ Z5 O/ ^$ t! O' @static void int2bin(int   value, int   no_of_bits, INT16 *bitstream);
: c  c9 }" l4 L1 x, g: j& rstatic int bin2int(int   no_of_bits, INT16 *bitstream);
; H7 L; w  s$ J( Xvoid prm2bits_ld8k(int   prm[], INT16 bits[]) ; 8 |% @7 ?, y0 M" r. G. F
void bits2prm_ld8k(INT16 bits[], int   prm[]) ;
* h+ a+ v# F* A; d  {( Y这个文件就是编码后文件大小没有什么变化的关键所在了,能用如下的代码替换:6 y( f3 i% r( E8 ~( E# F. U
static void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos) ; 0 v9 l7 g( x& ~' d  m
static Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos) ; , i. g- |9 [* ]2 {4 I
$ l$ O+ a& b$ G0 D
void prm2bits_ld8k(Word16 *para,unsigned char *bits)
1 N$ \/ v# m# s/ v{
3 f' D( G; f9 q   int i;2 W& d* g0 \5 |9 V
   int bitpos = 0;
( i* ^. k" W7 a/ Y9 I+ z( z   for (i = 0;i
' M5 F9 N8 W7 q, \7 z; o6 W9 Y! p- G
void bit2byte(Word16 para,int bitlen,unsigned char * bits,int bitpos)
$ `8 |" |  n; W# r{
& B( m( E3 ^6 ]6 Q; Q  H   int i;* s- H! e% a) M8 Y' k' \% A
   int bit = 0;5 y3 f: H) Y7 i9 P, S2 ]; p- [/ m
   unsigned char newbyte = 0;1 ^1 r( u4 {$ y& d# P' r1 ~4 M/ q
  
/ x: @9 M2 p! @/ A. {+ e) k/ m   unsigned char *p = bits + (bitpos / 8);
! J8 X5 H: m5 w/ o   for (i = 0 ;i > (bitlen - i -1) ) &0x01;
, y( ?) A, k6 cnewbyte = (1
" F# i8 x5 x, S+ ?bitpos++;1 n- E# k7 |2 \: _/ i6 U
if (bitpos % 8 == 0); M9 n0 i  R. F  i* w) Z- m9 h
   p++;+ D7 |  i, Y. U# u( l
   }
( q2 i! a( G2 g}& w6 y7 R" F  C. p& x- g

+ O. ~/ t6 X  h6 F2 P% kvoid bits2prm_ld8k(unsigned char *bits,Word16 *para)
3 Y1 y6 I1 F; M8 x" }1 z{* r  o" F- d" M, [; ?0 O
   int i;
. W( H8 H& f- p7 O9 V( a0 F   int bitpos = 0;
6 v/ {2 i$ ^8 B   for (i = 0;i
, Y$ h1 ]6 ^% ~* V) R4 |1 C5 z/ x1 @! `0 f
Word16 byte2bit(int bitlen,unsigned char * bits,int bitpos)% m3 X2 T  Q. m3 |) x1 {& R0 K
{3 l( v6 i/ f4 N( Z
   int i;
+ F- P! i$ M0 i   int bit = 0;
* T* {& ^/ B3 s7 ^( ]( `& P   Word16 newbyte = 0;; C9 C) _' O" ^  [* X8 `
   Word16 value = 0;
! ]9 ?) k6 K- M7 t: c# x% Q$ j, \. M8 s  
( Q. f* a% ^; ^, ]* p0 F' `" a$ E   unsigned char *p = bits + (bitpos / 8);
, w6 K; \) }0 Y# G; l, v' e   for (i = 0 ;i > (7 - bitpos % 8)) &0x01;
9 y  G0 ?- t& {& h" {7 Aif (bit == 1) {
. y8 A5 S( {; M1 C! G   newbyte = (1
1 M$ N! G1 K- h& {3 E# k   return value;
4 R% P( p+ ]/ @  w+ A}
1 m, j4 Q9 u; H1 g通过上述的修改,已能确保,每次一帧160个字节的pcm16音频数据流,能编码成为22个字节的编码参数prm,经过改写过的prm2bits_ld8k处理后,会转换成为10个字节的最终语音编码数据,这个时候,才真正体现出g.729a的威力。9 ?; {2 M! }7 J9 G& l( |

! Z( p% Z. M+ N$ f! n' ~编码器的代码能采用如下的修改方法
% Q, |( ]6 m9 h: F+ l# J(1)修改coder.c:
( Q$ L/ g% P& yunsigned char serial[SERIAL_SIZE]; /* 输出数据的数据类型由Word16改为unsigned char */7 x9 R# Z0 q3 d0 _6 L1 b$ W. Y2 g0 Z
(2)修改coder.c文件,对编码器调用方式进行修改(关键部分代码):& q( x; g0 }* J& _
   frame =0;
9 U: m6 q: R* I   while( fread(new_speech, sizeof(Word16), L_FRAME, f_speech) == L_FRAME)
6 s8 l! T$ v  v   {
! K5 l1 {" h( T- Hprintf("Frame =%d\r", frame++);
5 w  T1 X4 p4 k' VPre_Process(new_speech, L_FRAME);
- i9 [& Q* A" q/ dCoder_ld8a(prm);
4 {7 @$ v4 C8 q$ }# ]: S( |# Gprm2bits_ld8k( prm, serial);
% |6 \# f5 n2 g' efwrite(serial, 1, SERIAL_SIZE, f_serial);! K3 \* a6 i$ H) h$ N1 ?
   }: u; n0 z: V; e
   return (0);" ~" e) o% E- N% u

8 I: {+ f& B7 i. S8 Q6 l(3)把ld8a.h头文件中关于“串行化”长度的常量定义修改为10个字节:5 Q$ {4 f) e3 y1 l+ F1 g$ q
#define   SERIAL_SIZE   10) G( W0 }- J1 N$ Z9 D

% \% S" c$ n1 Q* t/ z; ~" Q7 n7 B(4)解码器decoder.c进行类似的修改(关键部分代码):
9 `7 u# `0 v( M, L   frame = 0;
/ {3 m% l/ ]$ z# l8 G   while( fread(serial, 1, SERIAL_SIZE, f_serial) == SERIAL_SIZE)
- i5 M, W' T4 |9 Z   {% V. R; [" i* e0 S  r
printf("Frame =%d\r", frame++);5 Z4 z; q% P1 M/ B0 {
bits2prm_ld8k(serial, &parm[1]); /* 注意这里一定要是&parm[1] */5 v+ |. Y" d, w/ |, F! d! x
parm[0] = 0;   /* 假设没有丢帧 */
. E! q: ?0 `& M3 |- p+ @7 vparm[4] = 0 ; /* 假设数据效验正常 */
) [4 ?; ^- f. `9 k* B% bDecod_ld8a(parm, synth, Az_dec, T2);* U) `5 z7 s/ L" S& @
Post_Filter(synth, Az_dec, T2);
+ }* {! s) C; K6 f4 z* @Post_Process(synth, L_FRAME);
% ]  u1 h% j. a( {4 O. ^' o& Dfwrite(synth, sizeof(short), L_FRAME, f_syn);
. {: s3 I- }1 W% i. {# c5 v   }: P% a+ P4 X$ Y. D7 O& c
   return (0) ; 4 `& U; t2 J0 J% `0 y+ e
通过上面的修改,标准的ITU-T的G.729语音编码器和解码器就基本能达到1:16的编码效率了。
# j* p! O) X) X& b/ h4 w1 n6 E* z8 E# n# R1 E6 A$ L- m
修改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; q; L9 q6 T4 v9 N
封lib:  ^$ O2 i( K0 H$ W4 `! F9 P
va_g729.h8 o- b& {( {) l! z
#define L_FRAME_COMPRESSED 10/ j5 G2 D3 ]  w: i
#define L_FRAME            80$ y! {" N$ x9 ^' ~
#ifdef __cplusplus 1 e1 p7 h6 z+ \1 f' z/ r! _
extern "C" { 1 Z  N: C' d, r# G) M
#endif
$ n* |& O. \% W5 c  @5 hvoid va_g729a_init_encoder();
' ?+ c& O* E) j5 v8 v3 T- Cvoid va_g729a_encoder(short *speech, unsigned char *bitstream);
) }4 F, x' C1 S  u$ C( c5 Vvoid va_g729a_init_decoder();- R! Q, e" J: o" T& f
void va_g729a_decoder(unsigned char *bitstream, short *synth_short, int bfi);
) J; T7 I. o0 n1 @7 x) a#ifdef __cplusplus : `6 E1 K+ J2 a. @; P1 b  ]
}
* O, P( b" D$ P* Y5 @6 N4 C#endif
  D  c) ]! K( |6 ~2 H4 {6 x2 K% Rva_g729.c
! f/ Z/ h& Q$ I* O; b! Z#include <stdio.h>3 }1 \  N+ b4 w5 n1 S! R) B" p, x8 o
#include <stdlib.h>( s: C2 Y" n+ R# a& d/ k
#include "typedef.h"
: k( e. ~% i# ?( M  A3 d$ e#include "ld8k.h"
8 M  Y, }2 s8 ?" M5 aWord16 bad_lsf;1 k6 S  t% F1 ]* b9 Z
void va_g729a_init_encoder()9 t  G  o, y; u: y% k8 C
{
: G' d3 B! k5 u" o, d. v' [4 e1 C    Init_Pre_Process();
% Z: c" Z+ r  w& W+ e- ]    Init_Coder_ld8k();
; \1 D0 b6 z+ H/ L}
5 G$ y1 A8 I) r! r9 ^void va_g729a_encoder(short* SpeechBuf,unsigned char * serial)$ L3 z& K' f/ o0 p
{     # F' Q! C& I4 O. u& Q, [
    extern Word16 *new_speech;       /* Pointer to new speech data           */" u( q' F& \# a( \- r
    Word16 prm[PRM_SIZE];            /* Analysis parameters.               */* P. o* y6 U) C
    Word16 i;( U* W5 o# N3 o! u, i5 J
Word16 syn[L_FRAME];* c2 d/ a/ d% e+ I" I5 C
    for(i=0;i<L_FRAME;i++)
% W2 n$ R6 O5 V, u{' ^' [; l6 {( g) r* |
   new_speech = SpeechBuf;
/ B* B' F: o* `$ a4 I, l+ C8 Y2 v. S}
$ Z' K8 D9 K# _8 Q1 n     for(i=0; i<PRM_SIZE; i++) prm = (Word16)0;
% T; Z3 M+ p1 e7 d    Pre_Process(new_speech, L_FRAME);- W) E6 \' F$ V
    Coder_ld8k(prm,syn);. x% n$ c3 \: E# P! e( n. p
    prm2bits_ld8k( prm, serial);
5 V+ u( q# R, [7 }# l; _  D}
. ]7 T; W4 N' Y, J8 i/ ~$ @2 e7 Evoid va_g729a_init_decoder()
" y" @! N+ V9 C5 ~: l% T# f9 R% O1 V{& g9 @, B0 e' q4 L+ c
extern Word16 *synth;
) P2 V% c9 J% R( x. q    bad_lsf = 0;          /* Initialize bad LSF indicator */2 k! l* K* n+ u1 B2 {0 d
    Init_Decod_ld8k();% A4 G# W4 ^0 u  p
    Init_Post_Filter();! P1 f9 {5 _% j# L8 G# i
    Init_Post_Process();
, R8 g. U% d0 ~# L! z" M: n1 n8 Y}
' B: i: i% ]* U' r7 G0 [2 Hvoid va_g729a_decoder(unsigned char *serial, short *speech, int bfi)
9 e# {$ e$ X% O8 z8 k/ C{3 ~0 i% e6 U5 W# B1 T
extern Word16 *synth; /* Synthesis                   */) m0 @* v4 L: u7 u9 M
Word16 synth_buf[L_FRAME+M];
3 A) C$ T7 B. Y3 k2 J. n+ KWord16 parm[PRM_SIZE+1];             /* Synthesis parameters        */! v2 v+ a. t8 A  ^* ~
Word16 Az_dec[MP1*2], *ptr_Az;       /* Decoded Az for post-filter *// m$ }- v. y! h
Word16 T2;                           /* Pitch lag for 2 subframes   */
/ e  x# [1 g1 z& S. w4 p! i, ?% ^Word16 i;/ e- h  g/ Y$ E8 _- X' Q
Word16 voicing = 60;
/ Y( `9 H- p5 h* P6 {Word16 pst_out[L_FRAME];             /* Postfilter output           */* _" N7 y6 w1 s( U! G: C* U
Word16 sf_voic;                      /* voicing for subframe        */; q" D2 W" F! Y
voicing = 60;
) }# O+ }; V/ j' y- d1 k4 Q$ _$ s    bits2prm_ld8k( serial, &parm[1]);
2 Q  l; s) F4 d, C3 y2 U' z    parm[0] = 0;   
0 s/ S; m! w# k, Y9 \. s          " N. K& ~* s: V% g
    parm[4] = 0;//Check_Parity_Pitch(parm[3], parm[4]);# e" @1 R- D' ^$ t9 L
Decod_ld8k(parm, voicing, synth, Az_dec, &T2);8 i3 w$ y, g& N' |1 {" ~
//--------------------------------------------------
& r7 B0 ^' g& f) ~, D/ p5 jvoicing = 0;
0 k" d  ^! K0 }  P) I6 b. X% Y- Nptr_Az = Az_dec;+ V# F8 P) |9 v( ?
for(i=0; i<L_FRAME; i+=L_SUBFR) {
8 `" \! H3 P% W& Q2 k   Post(T2, &synth, ptr_Az, &speech, &sf_voic);/ p+ B0 r/ V, N9 S: m
   if (sf_voic != 0) { voicing = sf_voic;}' O' {* L+ `  j
   ptr_Az += MP1;. _* \0 t* Z5 v$ h& x/ I- I
}
8 k2 U7 s( x" l' f4 e  ?: `Copy(&synth_buf[L_FRAME], &synth_buf[0], M);
2 A& l$ e% m  z1 {8 ]* x8 `//---------------------------------------------------9 ^' L' o/ o# N' ~6 D5 [, r
    Post_Process(speech, L_FRAME);   
1 q3 N7 O9 l7 w) b9 e4 q}
: @: u  N- ~6 w5 ~$ |5 Y1 C1 u% B, ?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 03:38 , Processed in 0.015513 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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