www.pudn.com > p_voice.rar > UTIL2.C


/* 
** 
** File:    util2.c 
** 
** Description: utility functions for the lbc codec 
** 
** Functions: 
** 
**  I/O functions: 
** 
**      Read_lbc() 
**      Write_lbc() 
** 
**  High-pass filtering: 
** 
**      Rem_Dc() 
** 
**  Miscellaneous signal processing functions: 
** 
**      Vec_Norm() 
**      Mem_Shift() 
**      Scale() 
** 
**  Bit stream packing/unpacking: 
** 
**      Line_Pack() 
**      Line_Unpk() 
** 
**  Mathematical functions: 
** 
**      Rand_lbc() 
*/ 
 
/* 
    ITU-T G.723.1 Floating Point Speech Coder ANSI C Source Code.  Version 5.1F 
 
    Original fixed-point code copyright (c) 1995, 
    AudioCodes, DSP Group, France Telecom, Universite de Sherbrooke. 
    All rights reserved. 
 
    Floating-point code copyright (c) 1995, 
    Intel Corporation and France Telecom (CNET). 
    All rights reserved. 
*/ 
 
#include  
#include  
#include  
#include  
 
#include "typedef2.h" 
#include "cst2.h" 
#include "lbccode2.h" 
#include "coder2.h" 
#include "decod2.h" 
#include "util2.h" 
 
/* 
** 
** Function:        Read_lbc() 
** 
** Description:     Read in a file 
** 
** Links to text:   Sections 2.2 & 4 
** 
** Arguments: 
** 
**  FLOAT  *Dpnt 
**  int     Len 
**  FILE *Fp 
** 
** Outputs: 
** 
**  FLOAT  *Dpnt 
** 
** Return value:    None 
** 
*/ 
void  Read_lbc (FLOAT *Dpnt, int Len, FILE *Fp) 
{ 
    Word16 Ibuf[Frame]; 
    int    i,n; 
 
    n = fread (Ibuf, sizeof(Word16), Len, Fp); 
    for (i=0; i (FLOAT)32766.5) 
            Obuf[i] = 32767; 
        else 
        { 
            if (Dpnt[i] < 0) 
                Obuf[i] = (Word16) (Dpnt[i]-(FLOAT)0.5); 
            else 
                Obuf[i] = (Word16) (Dpnt[i]+(FLOAT)0.5); 
        } 
    } 
    fwrite(Obuf, sizeof(Word16), Len, Fp); 
} 
 
void    Line_Wr(char *Line, FILE *Fp) 
{ 
    Word16    Info; 
    int       Size; 
 
    Info = (Word16) (Line[0] & 0x0003); 
 
    /* Check frame type and rate information */ 
    switch (Info) { 
 
        case 0x0002 : {  /* SID frame */ 
            Size = 4; 
            break; 
        } 
 
        case 0x0003 : {  /* untransmitted silence frame */ 
            Size = 1; 
            break; 
        } 
 
        case 0x0001 : {  /* active frame, low rate */ 
            Size = 20; 
            break; 
        } 
 
        default : {      /* active frame, high rate */ 
            Size = 24; 
        } 
    } 
 
    fwrite(Line, Size, 1, Fp); 
} 
 
int    Line_Rd(char *Line, FILE *Fp) 
{ 
    Word16    Info; 
    int       Size; 
 
    if (fread(Line, 1,1, Fp) != 1) 
        return (-1); 
 
    Info = (Word16) (Line[0] & 0x0003); 
 
    /* Check frame type and rate information */ 
    switch (Info) { 
 
        /* Active frame, high rate */ 
        case 0 : { 
            Size = 23; 
            break; 
        } 
 
        /* Active frame, low rate */ 
        case 1 : { 
            Size = 19; 
            break; 
        } 
 
        /* Sid Frame */ 
        case 2 : { 
            Size = 3; 
            break; 
        } 
 
        /* untransmitted */ 
        default : { 
            return 0; 
        } 
    } 
 
    fread(&Line[1], Size, 1, Fp); 
    return 0; 
} 
 
/* 
** 
** Function:        Rem_Dc() 
** 
** Description:     High-pass filtering 
** 
** Links to text:   Section 2.3 
** 
** Arguments: 
** 
**  FLOAT  *Dpnt 
** 
** Inputs: 
** 
**  CodStat.HpfZdl  FIR filter memory from previous frame (1 word) 
**  CodStat.HpfPdl  IIR filter memory from previous frame (1 word) 
** 
** Outputs: 
** 
**  FLOAT  *Dpnt 
** 
** Return value:    None 
** 
*/ 
 
void  Rem_Dc(FLOAT *Dpnt) 
{ 
    int   i; 
    FLOAT acc0; 
 
    if (UseHp) 
    { 
        for (i=0; i < Frame; i++) 
        { 
            acc0 = Dpnt[i] - CodStat.HpfZdl; 
            CodStat.HpfZdl = Dpnt[i]; 
 
            Dpnt[i] = CodStat.HpfPdl = 
                            acc0 + CodStat.HpfPdl*((FLOAT)127.0/(FLOAT)128.0); 
        } 
    } 
} 
 
 
/* 
** 
** Function:        Mem_Shift() 
** 
** Description:     Memory shift, update of the high-passed input speech signal 
** 
** Links to text: 
** 
** Arguments: 
** 
**  FLOAT *PrevDat 
**  FLOAT *DataBuff 
** 
** Outputs: 
** 
**  FLOAT *PrevDat 
**  FLOAT *DataBuff 
** 
** Return value:    None 
** 
*/ 
 
void  Mem_Shift(FLOAT *PrevDat, FLOAT *DataBuff) 
{ 
    int  i; 
 
    FLOAT Dpnt[Frame+LpcFrame-SubFrLen]; 
 
    /*  Form Buffer  */ 
 
    for (i=0; i < LpcFrame-SubFrLen; i++) 
        Dpnt[i] = PrevDat[i]; 
    for (i=0; i < Frame; i++) 
        Dpnt[i+LpcFrame-SubFrLen] = DataBuff[i]; 
 
    /*  Update PrevDat  */ 
 
    for (i=0; i < LpcFrame-SubFrLen; i++) 
        PrevDat[i] = Dpnt[Frame+i]; 
 
    /*  Update DataBuff  */ 
 
    for (i=0; i < Frame; i++) 
        DataBuff[i] = Dpnt[(LpcFrame-SubFrLen)/2+i]; 
} 
 
/* 
** 
** Function:        Line_Pack() 
** 
** Description:     Packing coded parameters in bitstream of 16-bit words 
** 
** Links to text:   Section 4 
** 
** Arguments: 
** 
**  LINEDEF *Line     Coded parameters for a frame 
**  char    *Vout     bitstream chars 
**  Word16   Ftyp     Voice Activity Indicator 
** 
** Outputs: 
** 
**  Word16 *Vout 
** 
** Return value:    None 
** 
*/ 
void    Line_Pack(LINEDEF *Line, char *Vout, Word16 Ftyp) 
{ 
    int       i; 
    int       BitCount; 
 
    Word16    BitStream[192]; 
    Word16    *Bsp = BitStream; 
    Word32    Temp; 
 
    /* Clear the output vector */ 
    for ( i = 0 ; i < 24 ; i ++ ) 
        Vout[i] = 0 ; 
 
 /* 
  * Add the coder rate info and frame type info to the 2 msb 
  * of the first word of the frame. 
  * The signaling is as follows: 
  *     Ftyp  WrkRate => X1X0 
  *       1     Rate63     00  :   High Rate 
  *       1     Rate53     01  :   Low  Rate 
  *       2       x        10  :   Silence Insertion Descriptor frame 
  *       0       x        11  :   Used only for simulation of 
  *                                 untransmitted silence frames 
  */ 
    switch (Ftyp) { 
 
        case 0 : { 
            Temp = 0x00000003L; 
            break; 
        } 
 
        case 2 : { 
            Temp = 0x00000002L; 
            break; 
        } 
 
        default : { 
            if ( WrkRate == Rate63 ) 
                Temp = 0x00000000L; 
            else 
                Temp = 0x00000001L; 
            break; 
        } 
    } 
 
    /* Serialize Control info */ 
    Bsp = Par2Ser( Temp, Bsp, 2 ) ; 
 
    /* Check for Speech/NonSpeech case */ 
    if ( Ftyp == 1 ) { 
 
        /* 24 bit LspId */ 
        Temp = (*Line).LspId ; 
        Bsp = Par2Ser( Temp, Bsp, 24 ) ; 
 
        /* 
         *  Do the part common to both rates 
         */ 
 
        /* Adaptive code book lags */ 
        Temp = (Word32) (*Line).Olp[0] - (Word32) PitchMin ; 
        Bsp = Par2Ser( Temp, Bsp, 7 ) ; 
 
        Temp = (Word32) (*Line).Sfs[1].AcLg ; 
        Bsp = Par2Ser( Temp, Bsp, 2 ) ; 
 
        Temp = (Word32) (*Line).Olp[1] - (Word32) PitchMin ; 
        Bsp = Par2Ser( Temp, Bsp, 7 ) ; 
 
        Temp = (Word32) (*Line).Sfs[3].AcLg ; 
        Bsp = Par2Ser( Temp, Bsp, 2 ) ; 
 
        /* Write combined 12 bit index of all the gains */ 
        for ( i = 0 ; i < SubFrames ; i ++ ) { 
            Temp = (*Line).Sfs[i].AcGn*NumOfGainLev + (*Line).Sfs[i].Mamp ; 
            if ( WrkRate == Rate63 ) 
                Temp += (Word32) (*Line).Sfs[i].Tran << 11 ; 
            Bsp = Par2Ser( Temp, Bsp, 12 ) ; 
        } 
 
        /* Write all the Grid indices */ 
        for ( i = 0 ; i < SubFrames ; i ++ ) 
            *Bsp ++ = (Word16)(*Line).Sfs[i].Grid ; 
 
        /* High rate only part */ 
        if ( WrkRate == Rate63 ) { 
 
            /* Write the reserved bit as 0 */ 
            *Bsp ++ = (Word16) 0 ; 
 
            /* Write 13 bit combined position index */ 
            Temp = (*Line).Sfs[0].Ppos >> 16 ; 
            Temp = Temp * 9 + ( (*Line).Sfs[1].Ppos >> 14) ; 
            Temp *= 90 ; 
            Temp += ((*Line).Sfs[2].Ppos >> 16) * 9 + ( (*Line).Sfs[3].Ppos >> 14 ) ; 
            Bsp = Par2Ser( Temp, Bsp, 13 ) ; 
 
            /* Write all the pulse positions */ 
            Temp = (*Line).Sfs[0].Ppos & 0x0000ffffL ; 
            Bsp = Par2Ser( Temp, Bsp, 16 ) ; 
 
            Temp = (*Line).Sfs[1].Ppos & 0x00003fffL ; 
            Bsp = Par2Ser( Temp, Bsp, 14 ) ; 
 
            Temp = (*Line).Sfs[2].Ppos & 0x0000ffffL ; 
            Bsp = Par2Ser( Temp, Bsp, 16 ) ; 
 
            Temp = (*Line).Sfs[3].Ppos & 0x00003fffL ; 
            Bsp = Par2Ser( Temp, Bsp, 14 ) ; 
 
            /* Write pulse amplitudes */ 
            Temp = (Word32) (*Line).Sfs[0].Pamp ; 
            Bsp = Par2Ser( Temp, Bsp, 6 ) ; 
 
            Temp = (Word32) (*Line).Sfs[1].Pamp ; 
            Bsp = Par2Ser( Temp, Bsp, 5 ) ; 
 
            Temp = (Word32) (*Line).Sfs[2].Pamp ; 
            Bsp = Par2Ser( Temp, Bsp, 6 ) ; 
 
            Temp = (Word32) (*Line).Sfs[3].Pamp ; 
            Bsp = Par2Ser( Temp, Bsp, 5 ) ; 
        } 
        /* Low rate only part */ 
        else { 
 
            /* Write 12 bits of positions */ 
            for ( i = 0 ; i < SubFrames ; i ++ ) { 
                Temp = (*Line).Sfs[i].Ppos ; 
                Bsp = Par2Ser( Temp, Bsp, 12 ) ; 
            } 
 
            /* Write 4 bit Pamps */ 
            for ( i = 0 ; i < SubFrames ; i ++ ) { 
                Temp = (*Line).Sfs[i].Pamp ; 
                Bsp = Par2Ser( Temp, Bsp, 4 ) ; 
            } 
        } 
 
    } 
    else if (Ftyp == 2) {    /* SID frame */ 
 
        /* 24 bit LspId */ 
        Temp = (*Line).LspId ; 
        Bsp = Par2Ser( Temp, Bsp, 24 ) ; 
 
        /* Do Sid frame gain */ 
        Temp = (Word32)(*Line).Sfs[0].Mamp ; 
        Bsp = Par2Ser( Temp, Bsp, 6 ) ; 
    } 
 
    /* Write out active frames */ 
    if (Ftyp == 1) { 
        if ( WrkRate == Rate63 ) 
            BitCount = 192; 
        else 
            BitCount = 160; 
    } 
    /* Non active frames */ 
    else if (Ftyp == 2) 
        BitCount = 32; 
    else 
        BitCount = 2; 
 
    for ( i = 0 ; i < BitCount ; i ++ ) 
        Vout[i>>3] ^= BitStream[i] << (i & 0x0007) ; 
} 
 
Word16* Par2Ser( Word32 Inp, Word16 *Pnt, int BitNum ) 
{ 
    int     i; 
    Word16  Temp ; 
 
    for ( i = 0 ; i < BitNum ; i ++ ) { 
        Temp = (Word16)(Inp & 0x0001); 
        Inp >>= 1 ; 
        *Pnt ++ = Temp ; 
    } 
 
    return Pnt ; 
} 
 
/* 
** 
** Function:        Line_Unpk() 
** 
** Description:     unpacking of bitstream, gets coding parameters for a frame 
** 
** Links to text:   Section 4 
** 
** Arguments: 
** 
**  char   *Vinp        bitstream chars 
**  Word16 *Ftyp 
**  Word16 Crc 
** 
** Outputs: 
** 
**  Word16 *Ftyp 
** 
** Return value: 
** 
**  LINEDEF             coded parameters 
**     Word16   Crc 
**     Word32   LspId 
**     Word16   Olp[SubFrames/2] 
**     SFSDEF   Sfs[SubFrames] 
** 
*/ 
LINEDEF  Line_Unpk(char *Vinp, Word16 *Ftyp, Word16 Crc) 
{ 
    int     i  ; 
    Word16  BitStream[192] ; 
    Word16  *Bsp = BitStream ; 
    LINEDEF Line ; 
    Word32  Temp ; 
    Word16  Info ; 
    Word16  Bound_AcGn ; 
 
    Line.Crc = Crc; 
    if (Crc != 0) 
        return Line; 
 
    /* Unpack the byte info to BitStream vector */ 
    for ( i = 0 ; i < 192 ; i ++ ) 
        BitStream[i] = (Word16) (( Vinp[i>>3] >> (i & (Word16)0x0007) ) & 1); 
 
    /* Decode the first two bits */ 
    Info = (Word16)Ser2Par( &Bsp, 2 ) ; 
 
    if (Info == 3) { 
        *Ftyp = 0; 
        Line.LspId = 0L;    /* Dummy : to avoid Borland C3.1 warning */ 
        return Line; 
    } 
 
    /* Decode the LspId */ 
    Line.LspId = Ser2Par( &Bsp, 24 ) ; 
 
    if (Info == 2) { 
        /* Decode the Noise Gain */ 
        Line.Sfs[0].Mamp = (Word16)Ser2Par( &Bsp, 6); 
        *Ftyp = 2; 
        return Line ; 
    } 
 
    /* 
     * Decode the common information to both rates 
     */ 
 
    *Ftyp = 1; 
 
    /* Decode the bit-rate */ 
    WrkRate = (Info == 0) ? Rate63 : Rate53; 
 
    /* Decode the adaptive codebook lags */ 
    Temp = Ser2Par( &Bsp, 7 ) ; 
    /* Test if forbidden code */ 
    if (Temp <= 123) { 
        Line.Olp[0] = (Word16) Temp + (Word16)PitchMin ; 
    } 
    else { 
        /* transmission error */ 
        Line.Crc = 1; 
        return Line; 
    } 
 
    Line.Sfs[1].AcLg = (Word16) Ser2Par( &Bsp, 2 ) ; 
 
    Temp = Ser2Par( &Bsp, 7 ) ; 
    /* Test if forbidden code */ 
    if (Temp <= 123) { 
        Line.Olp[1] = (Word16) Temp + (Word16)PitchMin ; 
    } 
    else { 
        /* transmission error */ 
        Line.Crc = 1; 
        return Line ; 
    } 
 
    Line.Sfs[3].AcLg = (Word16) Ser2Par( &Bsp, 2 ) ; 
 
    Line.Sfs[0].AcLg = 1 ; 
    Line.Sfs[2].AcLg = 1 ; 
 
    /* Decode the combined gains accordingly to the rate */ 
    for ( i = 0 ; i < SubFrames ; i ++ ) { 
 
        Temp = Ser2Par( &Bsp, 12 ) ; 
 
        Line.Sfs[i].Tran = 0 ; 
 
        Bound_AcGn = NbFilt170 ; 
        if ( (WrkRate == Rate63) && (Line.Olp[i>>1] < (SubFrLen-2) ) ) { 
            Line.Sfs[i].Tran = (Word16)(Temp >> 11) ; 
            Temp &= 0x000007ffL ; 
            Bound_AcGn = NbFilt085 ; 
        } 
        Line.Sfs[i].AcGn = (Word16)(Temp / (Word16)NumOfGainLev) ; 
 
        if (Line.Sfs[i].AcGn < Bound_AcGn ) { 
            Line.Sfs[i].Mamp = (Word16)(Temp % (Word16)NumOfGainLev) ; 
        } 
        else { 
            /* error detected */ 
            Line.Crc = 1; 
            return Line ; 
        } 
    } 
 
    /* Decode the grids */ 
    for ( i = 0 ; i < SubFrames ; i ++ ) 
        Line.Sfs[i].Grid = *Bsp ++ ; 
 
    if (Info == 0) { 
 
        /* Skip the reserved bit */ 
        Bsp ++ ; 
 
        /* Decode 13 bit combined position index */ 
        Temp = Ser2Par( &Bsp, 13 ) ; 
        Line.Sfs[0].Ppos = ( Temp/90 ) / 9 ; 
        Line.Sfs[1].Ppos = ( Temp/90 ) % 9 ; 
        Line.Sfs[2].Ppos = ( Temp%90 ) / 9 ; 
        Line.Sfs[3].Ppos = ( Temp%90 ) % 9 ; 
 
        /* Decode all the pulse positions */ 
        Line.Sfs[0].Ppos = ( Line.Sfs[0].Ppos << 16 ) + Ser2Par( &Bsp, 16 ) ; 
        Line.Sfs[1].Ppos = ( Line.Sfs[1].Ppos << 14 ) + Ser2Par( &Bsp, 14 ) ; 
        Line.Sfs[2].Ppos = ( Line.Sfs[2].Ppos << 16 ) + Ser2Par( &Bsp, 16 ) ; 
        Line.Sfs[3].Ppos = ( Line.Sfs[3].Ppos << 14 ) + Ser2Par( &Bsp, 14 ) ; 
 
        /* Decode pulse amplitudes */ 
        Line.Sfs[0].Pamp = (Word16)Ser2Par( &Bsp, 6 ) ; 
        Line.Sfs[1].Pamp = (Word16)Ser2Par( &Bsp, 5 ) ; 
        Line.Sfs[2].Pamp = (Word16)Ser2Par( &Bsp, 6 ) ; 
        Line.Sfs[3].Pamp = (Word16)Ser2Par( &Bsp, 5 ) ; 
    } 
    else { 
 
        /* Decode the positions */ 
        for ( i = 0 ; i < SubFrames ; i ++ ) 
            Line.Sfs[i].Ppos = Ser2Par( &Bsp, 12 ) ; 
 
        /* Decode the amplitudes */ 
        for ( i = 0 ; i < SubFrames ; i ++ ) 
            Line.Sfs[i].Pamp = (Word16)Ser2Par( &Bsp, 4 ) ; 
    } 
    return Line; 
} 
 
Word32  Ser2Par( Word16 **Pnt, int Count ) 
{ 
    int     i; 
    Word32  Rez = 0L; 
 
    for ( i = 0 ; i < Count ; i ++ ) { 
        Rez += (Word32) **Pnt << i ; 
        (*Pnt) ++ ; 
    } 
    return Rez ; 
} 
 
 
/* 
** 
** Function:        Rand_lbc() 
** 
** Description:     Generator of random numbers 
** 
** Links to text:   Section 3.10.2 
** 
** Arguments: 
** 
**  Word16   *p 
** 
** Outputs: 
** 
**  Word16   *p 
** 
** Return value: 
** 
**  Word16    random number 
** 
*/ 
Word16 Rand_lbc(Word16 *p) 
{ 
    *p = (Word16)(((*p)*521L + 259) & 0x0000ffff); 
    return(*p); 
} 
 
 
/* 
** 
** Function:        Scale() 
** 
** Description:     Postfilter gain scaling 
** 
** Links to text:   Section 3.9 
** 
** Arguments: 
** 
**  FLOAT *Tv 
**  FLOAT  Sen 
** 
**  Inputs: 
** 
**  FLOAT DecStat.Gain 
** 
** Outputs: 
** 
**  FLOAT *Tv 
** 
** Return value:    None 
** 
*/ 
void  Scale(FLOAT *Tv, FLOAT Sen) 
{ 
    int  i; 
 
    FLOAT Acc1; 
    FLOAT SfGain; 
 
    Acc1 = DotProd(Tv,Tv,SubFrLen); 
 
    if (Acc1 > (FLOAT) FLT_MIN) 
        SfGain = (FLOAT) sqrt(Sen/Acc1) * (FLOAT)0.0625; 
    else 
        SfGain = (FLOAT)0.0625; 
 
    /* 
     * Update gain and scale the Postfiltered Signal 
     */ 
    for (i=0; i < SubFrLen; i++) 
    { 
        DecStat.Gain = (FLOAT)0.9375*DecStat.Gain + SfGain; 
        Tv[i] = (FLOAT)1.0625*Tv[i]*DecStat.Gain; 
    } 
} 
 
/* 
** 
** Function:        DotProd() 
** 
** Description:     Dot product 
** 
** Links to text:   Section 3.9 
** 
** Arguments: 
** 
**  FLOAT *in1 
**  FLOAT *in2 
**  int   len 
** 
**  Inputs: 
** 
**  Outputs: 
** 
**  Return value: 
** 
**  FLOAT dot product 
** 
*/ 
FLOAT DotProd(FLOAT *in1, FLOAT *in2, int len) 
{ 
    int   i; 
    FLOAT sum; 
 
    sum = (FLOAT)0.0; 
    for (i=0; i