📄 decod.c
字号:
/*
**
** File: "decod.c"
**
** Description: Top-level source code for G.723.1 dual-rate decoder
**
** Functions: Init_Decod()
** Decod()
**
**
*/
/*
ITU-T G.723.1 Speech Coder ANSI-C Source Code Version 5.1
copyright (c) 1996, AudioCodes, DSP Group, France Telecom,
Universite de Sherbrooke. All rights reserved.
*/
#define CHANNEL 1 /* <----------------- activate/deactivate error concealment */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if CHANNEL
#include <math.h>
#endif
#include "typedef.h"
#include "basop.h"
#include "cst_lbc.h"
#include "tab_lbc.h"
#include "lbccodec.h"
#include "decod.h"
#include "util_lbc.h"
#include "lpc.h"
#include "lsp.h"
#include "exc_lbc.h"
#include "dec_cng.h"
/*
The following structure contains all the static decoder
variables.
*/
#if CHANNEL
static void SignalConcealment (Word16 Dpnt[], char *Vinp, Word16 sbfrm);
#endif
DECSTATDEF DecStat ;
/*
**
** Function: Init_Decod()
**
** Description: Initializes non-zero state variables
** for the decoder.
**
** Links to text: Section 3.11
**
** Arguments: None
**
** Outputs: None
**
** Return value: None
**
*/
void Init_Decod( )
{
int i ;
/* Initialize encoder data structure with zeros */
memset(&DecStat, 0, sizeof(DECSTATDEF));
/* Initialize the previously decoded LSP vector to the DC vector */
for ( i = 0 ; i < LpcOrder ; i ++ )
DecStat.PrevLsp[i] = LspDcTable[i] ;
/* Initialize the gain scaling unit memory to a constant */
DecStat.Gain = (Word16) 0x1000 ;
return;
}
/*
**
** Function: Decod()
**
** Description: Implements G.723.1 dual-rate decoder for a frame
** of speech
**
** Links to text: Section 3
**
** Arguments:
**
** Word16 *DataBuff Empty buffer
** Word16 Vinp[] Encoded frame (22/26 bytes)
**
** Outputs:
**
** Word16 DataBuff[] Decoded frame (480 bytes)
**
** Return value:
**
** Flag Always True
**
*/
Flag Decod( Word16 *DataBuff, char *Vinp, Word16 Crc )
{
int i,j ;
Word32 Senr ;
Word16 QntLpc[SubFrames*LpcOrder] ;
Word16 AcbkCont[SubFrLen] ;
Word16 LspVect[LpcOrder] ;
Word16 Temp[PitchMax+Frame] ;
Word16 *Dpnt ;
LINEDEF Line ;
PFDEF Pf[SubFrames] ;
Word16 Ftyp;
/*
* Decode the packed bitstream for the frame. (Text: Section 4;
* pars of sections 2.17, 2.18)
*/
Line = Line_Unpk( Vinp, &Ftyp, Crc ) ;
/*
* Update the frame erasure count (Text: Section 3.10)
*/
if ( Line.Crc != (Word16) 0 ) {
if(DecCng.PastFtyp == 1) Ftyp = 1; /* active */
else Ftyp = 0; /* untransmitted */
}
if(Ftyp != 1) {
/* Silence frame : do noise generation */
Dec_Cng(Ftyp, &Line, DataBuff, QntLpc);
}
else {
/*
* Update the frame erasure count (Text: Section 3.10)
*/
if ( Line.Crc != (Word16) 0 )
DecStat.Ecount = add( DecStat.Ecount, (Word16) 1 ) ;
else
DecStat.Ecount = (Word16) 0 ;
if ( DecStat.Ecount > (Word16) ErrMaxNum )
DecStat.Ecount = (Word16) ErrMaxNum ;
/*
* Decode the LSP vector for subframe 3. (Text: Section 3.2)
*/
Lsp_Inq( LspVect, DecStat.PrevLsp, Line.LspId, Line.Crc ) ;
/*
* Interpolate the LSP vectors for subframes 0--2. Convert the
* LSP vectors to LPC coefficients. (Text: Section 3.3)
*/
Lsp_Int( QntLpc, LspVect, DecStat.PrevLsp ) ;
/* Copy the LSP vector for the next frame */
for ( i = 0 ; i < LpcOrder ; i ++ )
DecStat.PrevLsp[i] = LspVect[i] ;
/*
* In case of no erasure, update the interpolation gain memory.
* Otherwise compute the interpolation gain (Text: Section 3.10)
*/
if ( DecStat.Ecount == (Word16) 0 ) {
DecStat.InterGain = add( Line.Sfs[SubFrames-2].Mamp,
Line.Sfs[SubFrames-1].Mamp ) ;
DecStat.InterGain = shr( DecStat.InterGain, (Word16) 1 ) ;
DecStat.InterGain = FcbkGainTable[DecStat.InterGain] ;
}
else
DecStat.InterGain = mult_r( DecStat.InterGain, (Word16) 0x6000 ) ;
/*
* Generate the excitation for the frame
*/
for ( i = 0 ; i < PitchMax ; i ++ )
Temp[i] = DecStat.PrevExc[i] ;
Dpnt = &Temp[PitchMax] ;
if ( DecStat.Ecount == (Word16) 0 ) {
for ( i = 0 ; i < SubFrames ; i ++ ) {
/* Generate the fixed codebook excitation for a
subframe. (Text: Section 3.5) */
Fcbk_Unpk( Dpnt, Line.Sfs[i], Line.Olp[i>>1], (Word16) i ) ;
/* Generate the adaptive codebook excitation for a
subframe. (Text: Section 3.4) */
Decod_Acbk( AcbkCont, &Temp[SubFrLen*i], Line.Olp[i>>1],
Line.Sfs[i].AcLg, Line.Sfs[i].AcGn ) ;
/* Add the adaptive and fixed codebook contributions to
generate the total excitation. */
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Dpnt[j] = shl( Dpnt[j], (Word16) 1 ) ;
Dpnt[j] = add( Dpnt[j], AcbkCont[j] ) ;
}
#if CHANNEL
SignalConcealment (Dpnt,Vinp,i);
#endif
Dpnt += SubFrLen ;
}
/* Save the excitation */
for ( j = 0 ; j < Frame ; j ++ )
DataBuff[j] = Temp[PitchMax+j] ;
/* Compute interpolation index. (Text: Section 3.10) */
/* Use DecCng.SidGain and DecCng.CurGain to store */
/* excitation energy estimation */
DecStat.InterIndx = Comp_Info( Temp, Line.Olp[SubFrames/2-1],
&DecCng.SidGain, &DecCng.CurGain ) ;
/* Compute pitch post filter coefficients. (Text: Section 3.6) */
if ( UsePf )
for ( i = 0 ; i < SubFrames ; i ++ )
Pf[i] = Comp_Lpf( Temp, Line.Olp[i>>1], (Word16) i ) ;
/* Reload the original excitation */
for ( j = 0 ; j < PitchMax ; j ++ )
Temp[j] = DecStat.PrevExc[j] ;
for ( j = 0 ; j < Frame ; j ++ )
Temp[PitchMax+j] = DataBuff[j] ;
/* Perform pitch post filtering for the frame. (Text: Section
3.6) */
if ( UsePf )
for ( i = 0 ; i < SubFrames ; i ++ )
Filt_Lpf( DataBuff, Temp, Pf[i], (Word16) i ) ;
/* Save Lsps --> LspSid */
for(i=0; i< LpcOrder; i++)
DecCng.LspSid[i] = DecStat.PrevLsp[i];
}
else {
/* If a frame erasure has occurred, regenerate the
signal for the frame. (Text: Section 3.10) */
Regen( DataBuff, Temp, DecStat.InterIndx, DecStat.InterGain,
DecStat.Ecount, &DecStat.Rseed ) ;
#if CHANNEL
for (i=0;i<SubFrames;i++)
SignalConcealment (&DataBuff[i*SubFrLen],Vinp,i);
#endif
}
/* Update the previous excitation for the next frame */
for ( j = 0 ; j < PitchMax ; j ++ )
DecStat.PrevExc[j] = Temp[Frame+j] ;
/* Resets random generator for CNG */
DecCng.RandSeed = 12345;
}
/* Save Ftyp information for next frame */
DecCng.PastFtyp = Ftyp;
/*
* Synthesize the speech for the frame
*/
Dpnt = DataBuff ;
for ( i = 0 ; i < SubFrames ; i ++ ) {
/* Compute the synthesized speech signal for a subframe.
* (Text: Section 3.7)
*/
Synt( Dpnt, &QntLpc[i*LpcOrder] ) ;
if ( UsePf ) {
/* Do the formant post filter. (Text: Section 3.8) */
Senr = Spf( Dpnt, &QntLpc[i*LpcOrder] ) ;
/* Do the gain scaling unit. (Text: Section 3.9) */
Scale( Dpnt, Senr ) ;
}
Dpnt += SubFrLen ;
}
return (Flag) True ;
}
#if CHANNEL
static void SignalConcealment (Word16 Dpnt[], char *Vinp, Word16 sbfrm){
double acc, scale;
Word16 i, level, mute, mode, flag_byte, Bfi, Efi, Fii;
static Word16 level_mem = {-72};
static Word16 level_increase[8] = {0,0,3,6,10,15,20,15};
static Word16 allow_mute, Mute_old = {0};
if (sbfrm == 0) {
/* Determine mode and concealment flags */
/* ------------------------------------ */
mode = Vinp[0] & 0x3;
if (mode == 0) flag_byte = 24;
if (mode == 1) flag_byte = 20;
if (mode == 2) flag_byte = 4;
Bfi = Vinp[flag_byte] & 0x1;
Efi = Vinp[flag_byte] & 0x2;
Fii = Vinp[flag_byte] & 0x4;
allow_mute = 0;
/* Allow muting if Efi or Fii set */
/* ------------------------------ */
if ((Bfi == 0) && ((Efi != 0)||(Fii != 0))) allow_mute = 1;
/* Allow muting if badframe is set and last frame was probably erroneous */
/* This controls the repetition of erroneous frames */
/* --------------------------------------------------------------------- */
if ((Bfi != 0) && (Mute_old == 1)) allow_mute = 1;
/* Set Mute_old for next frame */
/* --------------------------- */
if (Bfi == 0) {
Mute_old = 0;
if ((Efi != 0)||(Fii != 0)) Mute_old = 1;
}
}
/* Determine level of subframe excitation */
/* -------------------------------------- */
acc=0.;
for (i=0;i<SubFrLen;i++) acc = acc + ((double) Dpnt[i] * (double) Dpnt[i]);
acc = acc/((double) SubFrLen * 4096. * 4096.);
if (acc > 0) {
level = (Word16) 10.*log10(acc);
}else{
level = -72;
}
if (level < -72) level = (-72);
if (allow_mute == 1){
/* Mute if the level increase of the excitation is higher than allowed */
/* ------------------------------------------------------------------- */
i = (((-level_mem)+5)/10);
if (i < 0) i=0;
if (i > 7) i=7;
mute = level-(level_mem+level_increase[i]);
if (mute > 0){
/* printf ("Signal muted by %d db, Last: %d , Actual: %d\n",
mute,level_mem,level); */
scale = pow(10.,(-(double)mute/20.));
for (i=0;i<SubFrLen;i++) Dpnt[i]=(Word16) ((double) Dpnt[i] * scale);
}
}else{
level_mem = level;
}
return;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -