/*
**
** File:        "decod2.c"
**
** Description:     Top-level source code for G.723.1 dual-rate decoder
**
** Functions:       Init_Decod()
**                  Decod()
**
**
*/

/*
    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 <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "typedef2.h"
#include "cst2.h"
#include "tab2.h"
#include "lbccode2.h"
#include "decod2.h"
#include "util2.h"
#include "lpc2.h"
#include "lsp2.h"
#include "exc2.h"
#include "deccng2.h"


/*
   The following structure contains all the static decoder
      variables.
*/

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(void)
{
    int i;

    /* Initialize decoder 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];

    DecStat.Gain = (FLOAT)1.0;
}

/*
**
** Function:        Decod()
**
** Description:     Implements G.723.1 dual-rate decoder for  a frame
**          of speech
**
** Links to text:   Section 3
**
** Arguments:
**
**  FLOAT  *DataBuff    Empty buffer
**  Word16 Vinp[]       Encoded frame (22/26 bytes)
**

** Outputs:
**
**  FLOAT  DataBuff[]   Decoded frame (480 bytes)
**
** Return value:
**
**  Flag            Always True
**
*/

Flag  Decod(FLOAT *DataBuff, char *Vinp, Word16 Crc)
{
    int      i, j, g;

    FLOAT    Senr;
    FLOAT    QntLpc[SubFrames*LpcOrder];
    FLOAT    AcbkCont[SubFrLen];

    FLOAT    LspVect[LpcOrder];
    FLOAT    Temp[PitchMax+Frame];
    FLOAT   *Dpnt;

    LINEDEF  Line;
    PFDEF    Pf[SubFrames];

    Word16   Ftyp;

    /*
     * Decode the packed bitstream for the frame.  (Text: Section 4;
     * pars of sectio,d 2.17, 2.18)
     */
    Line = Line_Unpk(Vinp, &Ftyp, Crc);

    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 != 0)
            DecStat.Ecount++;
        else
            DecStat.Ecount = 0;

        if (DecStat.Ecount >  ErrMaxNum)
            DecStat.Ecount = 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 == 0) {
            g = (Line.Sfs[SubFrames-2].Mamp + Line.Sfs[SubFrames-1].Mamp) >> 1;
            DecStat.InterGain = FcbkGainTable[g];
        }
        else
            DecStat.InterGain = DecStat.InterGain*(FLOAT)0.75;

        /*
         * Generate the excitation for the frame
         */
        for (i = 0; i < PitchMax; i++)
            Temp[i] = DecStat.PrevExc[i];

        Dpnt = &Temp[PitchMax];

        if (DecStat.Ecount == 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], 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] = Dpnt[j] + AcbkCont[j];

                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 to store                       */
            /* excitation energy estimation                      */
            DecStat.InterIndx = Comp_Info(Temp, Line.Olp[SubFrames/2-1],
                                          &DecCng.SidGain);

            /* 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], 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];

            /* Clip newly generated samples in Temp array */
            for (j = 0; j < Frame; j++) {
                if (Temp[PitchMax+j] < (FLOAT)-32767.5)
                    Temp[PitchMax+j] = (FLOAT)-32768.0;
                else if (Temp[PitchMax+j] > (FLOAT)32766.5)
                    Temp[PitchMax+j] = (FLOAT)32767.0;
            }

            /* 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], 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);
        }

        /* 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;
}
