/**********************************************************************
MPEG-4 Audio VM
Decoder core (parametric)



This software module was originally developed by

Heiko Purnhagen (University of Hannover / Deutsche Telekom Berkom)
Bernd Edler (University of Hannover / Deutsche Telekom Berkom)
Masayuki Nishiguchi, Kazuyuki Iijima, Jun Matsumoto (Sony Corporation)

and edited by

in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
software module or modifications thereof for use in hardware or
software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
standards. Those intending to use this software module in hardware or
software products are advised that this use may infringe existing
patents. The original developer of this software module and his/her
company, the subsequent editors and their companies, and ISO/IEC have
no liability for use of this software module or modifications thereof
in an implementation. Copyright is not released for non MPEG-2
NBC/MPEG-4 Audio conforming products. The original developer retains
full right to use the code for his/her own purpose, assign or donate
the code to a third party and to inhibit third party from using the
code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
copyright notice must be included in all copies or derivative works.

Copyright (c) 1997.



Source file: dec_par.c

$Id: dec_par.c,v 1.24 1997/11/20 21:22:28 purnhage Exp $

Required modules:
common.o		common module
cmdline.o		command line module
bitstream.o		bits stream module
indilinedec.o		indiline bitstream decoder module
indilinesyn.o		indiline synthesiser module

Authors:
HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>
BE    Bernd Edler, Uni Hannover <edler@tnt.uni-hannover.de>
MN    Masayuki Nishiguchi, Sony IPC <nishi@pcrd.sony.co.jp>

Changes:
18-jun-96   HP    first version (dummy)
25-jun-96   HP    implemented "individual spectral lines"
28-jun-96   HP    joined with HVXC code by Sony IPC
01-jul-96   HP    added HVXC header file, included modifications by IPC
15-aug-96   HP    added DecParInfo(), DecParFree()
                  adapted to new dec.h
26-aug-96   HP    CVS
03-sep-96   HP    added speed change & pitch change for "individual lines"
06-sep-96   HP    incorporated changes by Sony IPC for a new HVXC with
                  speed change & pitch change functionality
10-sep-96   BE
12-sep-96   HP    incorporated indiline modules as source code
26-sep-96   HP    adapted to new indiline module interfaces
26-sep-96   HP    incorporated changes by Sony IPC
15-nov-96   HP    adapted to new bitstream module
04-dec-96   HP    fix call to BsGetBitChar(), included ISO copyright
03-feb-97   HP    splitting enc/dec
06-jul-97   HP    switch/mix
17-jul-97   HP    HXVC delayNumSample
23-oct-97   HP    merged IL/HVXC switching
07-nov-97   MN    bug-fixes
11-nov-97   HP    added HVXC variable rate switches
12-nov-97   HP    fixed mixed HVXC/IL mode

VMIL stuff
10-apr-97   HP    harmonic stuff ...
22-apr-97   HP    noisy stuff ...
10-jun-97   HP    added para file support
23-jun-97   HP    ANSI-C para file fixes
24-jun-97   HP    adapted env/harm/noise interface
29-aug-97   HP    added random start phase
13-nov-97   HP    fixed harm speech change
16-nov-97   HP    adapted HILN decoder config header
**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "common.h"		/* common module */
#include "cmdline.h"		/* command line module */
#include "bitstream.h"		/* bit stream module */

#include "indilinedec.h"	/* indiline bitstream decoder module */
#include "indilinesyn.h"	/* indiline synthesiser module */

#ifdef IL_PARAFILE
#include "uhd_parafile.h"
#endif

#include "dec.h"		/* decoder cores */

#include "mp4_par.h"		/* parametric core common declarations */

#include "hvxc.h"		/* hvxcDec module */
#include "hvxcDec.h"		/* hvxcDec module */


/* ---------- declarations ---------- */

#define PROGVER "parametric decoder core V5.0 12-nov-97"

#define SEPACHAR " ,="

#define MAXSAMPLE 32768		/* full scale sample value */

#define STRLEN 255


/* ---------- variables ---------- */

static float DPfSample;
static float DPbitRate;
static float DPspeedFact;
static float DPpitchFact;
static int DPmode;		/* enum MP4ModePar */
static int DPframeMaxNumSample;
static int DPdelayNumSample;

/* indiline handles */
static ILDstatus *ILD;
static ILSstatus *ILS;

/* command line module */

static int DPdelayMode;
static int DPdebugLevel;
static int DPdebugLevelIl;

/* HILN decoder control HP970514 */
int DPnoIL;
int DPnoHarm;
int DPnoNoise;
int DPenhaFlag;
extern int ILDcontModeTest;
extern int ILDbsFormat;
extern int ILDnoStretch;
extern float ILDcontdf;
extern float ILDcontda;
extern float ILDrndPhase;

static int DPtest;

#ifdef IL_PARAFILE
static char *DPPFmode;
static char *DPPFname;
static char *DPPFpath;
static char *DPPFext;
static int DPPFdebug;
#endif

static CmdLineSwitch switchList[] = {
  {"h",NULL,NULL,NULL,NULL,"print help"},
  {"dm",&DPdelayMode,"%i","0",NULL,"HVXC delay mode (0=short 1=long)"},
  {"dl",&DPdebugLevel,"%i","0",NULL,"debug level"},
  {"dli",&DPdebugLevelIl,"%i","0",NULL,"debug level individual lines"},
  {"noi",&DPnoIL,NULL,NULL,NULL,"disable indiline"},
  {"noh",&DPnoHarm,NULL,NULL,NULL,"disable harm"},
  {"non",&DPnoNoise,NULL,NULL,NULL,"disable noise synthesis"},
  {"hie",&DPenhaFlag,"%d","0",NULL,
   "harm/indi enha flag (0=basic 1=enha)"},
  {"hicm",&ILDcontModeTest,"%d","-1",NULL,
   "harm/indi continue mode\n"
   "(-1=bitstream 0=hi, 1=hi&ii)"},
  {"bsf",&ILDbsFormat,"%d","2",NULL,
   "HILN bitstream format (0=VM 1=9705 2=CD)"},
  {"nos",&ILDnoStretch,NULL,NULL,NULL,"disable stretching"},
  {"cdf",&ILDcontdf,"%f","1.05",NULL,"line continuation df"},
  {"cda",&ILDcontda,"%f","4.0",NULL,"line continuation da"},
  {"rsp",&ILDrndPhase,"%d","1",NULL,"random startphase (0=sin(0) 1=sin(rnd))"},
  {"test",&DPtest,"%i","0",NULL,"for test only (1=hvxc 2=il)"},
#ifdef IL_PARAFILE
  {"pf",&DPPFmode,"%s","",NULL,"para file mode (d=dequan,h=deq&harm,s=synth)"},
  {"pn",&DPPFname,"%s",NULL,NULL,"para file name (dftl: as bitstream)"},
  {"pp",&DPPFpath,"%s",NULL,NULL,"para file path (dftl: as bitstream)"},
  {"pe",&DPPFext,"%s",".par",NULL,"para file extension"},
  {"pd",&DPPFdebug,"%i","0",NULL,"para file debug level"},
#endif
  {NULL,NULL,NULL,NULL,NULL,NULL}
};

/* variables for HVXC */
int ipc_decMode = DEC4K;
int ipc_bitstreamMode = BM_CONSTANT;
int ipc_rateMode = 2;

/* switch/mix stuff */
static float *tmpSampleBuf;
static float *mixSampleBuf;
static int mixSampleBufSize = 0;
static BsBitBuffer *dmyBuf;
static int ILdelayNumSample = 0;
static int HVXdelayNumSample = 0;
static BsBitBuffer *tmpBSbuf;
static BsBitStream *tmpBSstream;

int ipc_decDelayMode = DM_SHORT;

/* HP/MN 971111   for pan_lspdec.c */
extern int ipc_lpc_DEC0K;

#ifdef IL_PARAFILE
static ParaFile *paraFile;
static char paraFileName[STRLEN];
static char paraFileMode;

extern char *PFbitFileName;
extern char *PFbitPath;
#endif


/* ---------- internal functions ---------- */


/* DecParInitIl() */
/* Init: individual lines */

static void DecParInitIl (
  BsBitStream *hdrStream)	/* in: header for bit stream */
{
  int frameLenQuant;
  float fSampleQuant;
  int maxNumLine;
  int maxNumEnv;
  int maxNumHarm;
  int maxNumHarmLine;
  int maxNumNoisePara;
  int maxNumAllLine;
  int enhaFlag;
  int i;
  BsBitStream *dmyStream;

#ifdef IL_PARAFILE
  int paraMaxNumLine,paraMaxNumEnv;
  int paraMaxNumHarm,paraMaxNumHarmLine,paraMaxNumNoisePara;
  float paraFrameDur;
#endif

  /* init modules */
  ILD = IndiLineDecodeInit(hdrStream,MAXSAMPLE,DPdebugLevelIl,
			   &maxNumLine,&maxNumEnv,&maxNumHarm,
			   &maxNumHarmLine,&maxNumNoisePara,&maxNumAllLine,
			   &enhaFlag,&frameLenQuant,&fSampleQuant);

  DPframeMaxNumSample = (int)(frameLenQuant*DPfSample/fSampleQuant/
			      DPspeedFact+0.5);
  DPdelayNumSample = DPframeMaxNumSample/2;

  if (DPenhaFlag && !enhaFlag) {
    CommonWarning("DecParInitIl: no enhancement bitstream available");
    DPenhaFlag = 0;
  }

  ILS = IndiLineSynthInit(DPframeMaxNumSample,DPfSample,
			  maxNumAllLine,maxNumEnv,maxNumNoisePara,
			  DPdebugLevelIl);

#ifdef IL_PARAFILE
  ParaFileInit(DPPFdebug);
  if (paraFileMode=='d' || paraFileMode=='h' || paraFileMode=='s') {
    if (paraFileMode=='d') {
      paraFile = ParaFileOpenWrite(paraFileName,maxNumLine,maxNumEnv,
				   maxNumHarm,maxNumHarmLine,maxNumNoisePara,
				   frameLenQuant/fSampleQuant);
      if (paraFile==NULL)
	CommonExit(1,"DecParInitIl: open para file error");
    }
    else if (paraFileMode=='h') {
      paraFile = ParaFileOpenWrite(paraFileName,maxNumAllLine,maxNumEnv,
				   0,0,maxNumNoisePara,
				   frameLenQuant/fSampleQuant);
      if (paraFile==NULL)
	CommonExit(1,"DecParInitIl: open para file error");
    }
    else {
      paraFile = ParaFileOpenRead(paraFileName,&paraMaxNumLine,&paraMaxNumEnv,
				  &paraMaxNumHarm,&paraMaxNumHarmLine,
				  &paraMaxNumNoisePara,&paraFrameDur);
      if (paraFile==NULL)
	CommonExit(1,"DecParInitIl: open para file error");
      if (paraMaxNumLine > maxNumLine)
	CommonWarning("DecParInitIl: paraMaxNumLine > maxNumLine (%d %d)",
		      paraMaxNumLine,maxNumLine);
      if (paraFrameDur/(frameLenQuant/fSampleQuant) < 0.999 ||
	  paraFrameDur/(frameLenQuant/fSampleQuant) > 1.001)
	CommonWarning("DecParInitIl: paraFrameDur != frameDur (%f %f)",
		      paraFrameDur,frameLenQuant/fSampleQuant);
    }
  }
  else
    paraFile = NULL;
#endif

  if (DPdebugLevel >= 1) {
    printf("DecParInitIl: dbgLvlIl=%d\n",
	   DPdebugLevelIl);
    printf("DecParInitIl: maxNumLine=%d\n",
	   maxNumLine);
    printf("DecParInitIl: fSampleQuant=%f  frameLenQuant=%d\n",
	   fSampleQuant,frameLenQuant);
    printf("DecParInitIl: frmNumSmp=%d  dlyNumSmp=%d\n",
	   DPframeMaxNumSample,DPdelayNumSample);
  }
  dmyBuf=BsAllocBuffer(200);
  dmyStream=BsOpenBufferWrite(dmyBuf);
  for (i=0; i<200; i++)		/* make "silenence" bitstream */
    BsPutBit(dmyStream,0,1);
  BsClose(dmyStream);
}


/* DecParInitHvx() */
/* Init: harmonic vector exitation */

static void DecParInitHvx (
  BsBitStream *hdrStream)	/* in: header for bit stream */
{
  if (BsGetBitInt(hdrStream,(unsigned int*)&ipc_bitstreamMode,1))
    CommonExit(1,"DecParInitHvx: error reading bit stream header");
  if (BsGetBitInt(hdrStream,(unsigned int*)&ipc_rateMode,2))
    CommonExit(1,"DecParInitHvx: error reading bit stream header");

  DPframeMaxNumSample = 160 * (int) ceil(1.0 / DPspeedFact);
  if (ipc_decDelayMode == DM_LONG)	/* HP 971023 */
    DPdelayNumSample = 80;	/* 10 ms */
  else
    DPdelayNumSample = 60;	/* 7.5 ms */
  IPC_HVXCInitDec();
}


/* DecParFrameIl() */
/* Decode frame: individual lines */

void DecParFrameIl (
  BsBitStream *stream,		/* in: bit stream */
  float *sampleBuf,		/* out: frameNumSample audio samples */
  int *frameBufNumSample)	/* out: num samples in sampleBuf[] */
{
  int numEnv;
  float **envPara;
  int numLine;
  float *lineFreq;
  float *lineAmpl;
  float *linePhase;
  int *lineEnv;
  int *linePred;
  int numHarm;
  int *numHarmLine;
  float *harmFreq;
  float *harmFreqStretch;
  int *harmLineIdx;
  int *harmEnv;
  int *harmPred;
  int numNoisePara;
  float noiseFreq;
  float *noisePara;
  int noiseEnv;
  int numAllLine;

  int i,il;
  BsBitStream *dmyStream;

  /* call IndiLineDecodeFrame() to update internal frame-to-frame memory */
  dmyStream = BsOpenBufferRead(dmyBuf);
  IndiLineDecodeFrame(ILD,(stream)?stream:dmyStream,
		      (stream && DPenhaFlag)?stream:NULL,
		      &numEnv,&envPara,&numLine,&lineFreq,
		      &lineAmpl,(stream && DPenhaFlag)?&linePhase:NULL,
		      &lineEnv,&linePred,
		      &numHarm,&numHarmLine,&harmFreq,&harmFreqStretch,
		      &harmLineIdx,&harmEnv,&harmPred,
		      &numNoisePara,&noiseFreq,&noisePara,&noiseEnv);
  BsClose(dmyStream);

#ifdef IL_PARAFILE
  if (paraFileMode=='d')
    ParaFileWriteFrame(paraFile,
		       numEnv,envPara,numLine,lineFreq,
		       lineAmpl,NULL,lineEnv,linePred,
		       numHarm,numHarmLine,harmFreq,harmFreqStretch,
		       harmLineIdx,harmEnv,harmPred,NULL,
		       numNoisePara,noiseFreq,noisePara,
		       noiseEnv,1);
  if (paraFileMode=='s')
    if (ParaFileReadFrame(paraFile,
			  &numEnv,envPara,&numLine,lineFreq,
			  lineAmpl,NULL,lineEnv,linePred,
			  &numHarm,numHarmLine,harmFreq,harmFreqStretch,
			  harmLineIdx,harmEnv,harmPred,NULL,
			  &numNoisePara,&noiseFreq,noisePara,
			  &noiseEnv,NULL)) {
      numEnv = 0;
      numLine = 0;
      numHarm = 0;
      numNoisePara = 0;
      CommonWarning("DecParFrameIl: para file too short");
    }
#endif

  if (DPdebugLevel >= 3) {
    printf("dequan\n");
    for (i=0; i<numEnv; i++)
      printf("env %d: tm=%7.5f atk=%7.5f dec=%7.5f\n",
	     i,envPara[i][0],envPara[i][1],envPara[i][2]);
    for(il=0; il<numLine; il++)
      printf("%2d: f=%7.1f a=%7.1f p=%5.2f e=%1d c=%2d\n",
	     il,lineFreq[il],lineAmpl[il],(DPenhaFlag)?linePhase[il]:0.0,
	     lineEnv[il],linePred[il]);
    for (i=0; i<numHarm; i++) {
      printf("harm %d: n=%2d f=%7.1f fs=%10e e=%1d c=%1d\n",
	     i,numHarmLine[i],harmFreq[i],harmFreqStretch[i],
	     harmEnv[i],harmPred[i]);
      for(il=harmLineIdx[i]; il<harmLineIdx[i]+numHarmLine[i]; il++)
	printf("h %2d: a=%7.1f\n",il-harmLineIdx[i]+1,lineAmpl[il]);
    }
    if (numNoisePara) {
      printf("noise: n=%d f=%7.1f e=%1d\n",
	     numNoisePara,noiseFreq,noiseEnv);
      for (i=0; i<numNoisePara; i++)
	printf("noise %d: p=%10e\n",i,noisePara[i]);
    }
  }

  if (DPnoIL)
    numLine = 0;
  if (DPnoHarm)
    numHarm = 0;
  if (DPnoNoise)
    numNoisePara = 0;

  /* append harm lines and join with individual lines */
  IndiLineDecodeHarm(ILD,numLine,lineFreq,lineAmpl,
		     (DPenhaFlag)?linePhase:NULL,lineEnv,linePred,
		     numHarm,numHarmLine,harmFreq,harmFreqStretch,
		     harmLineIdx,harmEnv,harmPred,
		     &numAllLine);

#ifdef IL_PARAFILE
  if (paraFileMode=='h')
    ParaFileWriteFrame(paraFile,
		       numEnv,envPara,numAllLine,lineFreq,
		       lineAmpl,NULL,lineEnv,linePred,
		       0,NULL,NULL,NULL,
		       NULL,NULL,NULL,NULL,
		       numNoisePara,noiseFreq,noisePara,
		       noiseEnv,1);
#endif

  /* modify frequency if pitch change (only basic mode) */
  for (il=0; il<numAllLine; il++) {
    lineFreq[il] *= DPpitchFact;
    lineAmpl[il] *= 1;
  }
  if (numNoisePara)
    noiseFreq *= DPpitchFact;

  /* synthesise using quantised parameters */
  IndiLineSynth(ILS,(DPenhaFlag)?1:0,
		DPframeMaxNumSample,
		numEnv,envPara,
		numAllLine,lineFreq,lineAmpl,
		(DPenhaFlag)?linePhase:NULL,NULL,lineEnv,linePred,
		numNoisePara,noiseFreq,noisePara,noiseEnv,
		sampleBuf);

  *frameBufNumSample = DPframeMaxNumSample;
}


/* DecParFrameHvx() */
/* Decode frame: harmonic vector exitation */

void DecParFrameHvx (
  BsBitStream *stream,		/* in: bit stream */
  float *sampleBuf,		/* out: frameNumSample audio samples */
  int *frameBufNumSample)	/* out: num samples in sampleBuf[] */
{
    int	i, j;

    short	frmBuf[FRM];
    int		idVUV;
    float	mfdpch = 0.0;

    float	qLsp[LPCORDER];
    float	am[SAMPLE/2][3];
    float	qRes[FRM];

    int		dcfrm;

    static int		idVUV2[2];
    static int		bgnFlag2[2];
    static float	pch2[2], am2[2][SAMPLE / 2][3];
    static float	qLsp2[2][LPCORDER];
    static float	qRes2[2][FRM];

    static int		nbs = 0;
    static int		frm = 0;
    static int		fr0 = 0;

    static float	ratio = 1.0;
    static IdCelp	idCelp2[2] = {0, 0, 0, 0, 0, 0, 0, 0};
    static float	qLspQueue[4][LPCORDER];
    static float	targetP = 0.0;
    unsigned char	encBit[10];

    unsigned char	tmpIdVUV;
    unsigned char	tmpEncBit;

    /* HP 970706 970708 970709 */
    if (!stream){
      ipc_decMode = DEC0K; 
    }
    else if (!BsEof(stream,80-1)){  /* MN 971107 */
      ipc_decMode = DEC4K; 
    }
    else if (!BsEof(stream,80-6-1)){ /* MN 971107 */
      ipc_decMode = DEC3K;
    }
    else{
      ipc_decMode = DEC2K;
    }

    /* HP/MN 971111   for pan_lspdec.c */
    ipc_lpc_DEC0K = (ipc_decMode == DEC0K) ? 1 : 0;

    if (DPdebugLevel >= 2) {
      printf("DecParFrameHvx: stream=%s\n",stream?"valid":"NULL");
      printf("DecParFrameHvx: decMode=");
      switch (ipc_decMode) {
      case DEC0K : printf("DEC0K\n"); break;
      case DEC2K : printf("DEC2K\n"); break;
      case DEC3K : printf("DEC3K\n"); break;
      case DEC4K : printf("DEC4K\n"); break;
      default : printf("ERROR!!!\n");
      }
    }
    
    if(nbs == 0)
    {
	idVUV2[0] = idVUV2[1] = 0;
	bgnFlag2[0] = bgnFlag2[1] = 0;
	pch2[0] = pch2[1] = 0.0;
	
	
	for(i = 0; i < 4; i++)
	{
	    for(j = 0; j < P; j++)
	    {
		qLspQueue[i][j] = 0.5 / 11.0 * (j + 1);
	    }
	}
    }


    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
	/* Modified on 07/04/97 by Y.Maeda */
    {
      for(j = 0; j < 9; j++)
        if(BsGetBitChar(stream, &encBit[j], 8))
	  CommonExit(1,"DecParFrameHvx: error reading bit stream");
      if (ipc_decMode == DEC4K) {
	if(BsGetBitChar(stream, &encBit[9], 8)) /* MN 971106 */
	  CommonExit(1,"DecParFrameHvx: error reading bit stream");
      }
      else {
	/* MN 971107 */
	if(BsGetBitChar(stream, &tmpEncBit, 8-6))
	  CommonExit(1,"DecParFrameHvx: error reading bit stream");
	encBit[9] = (tmpEncBit & 0x3) << 6;
      }
    }
    else if(ipc_decMode == DEC2K)
    {
      if(ipc_bitstreamMode == BM_VARIABLE)
      {
        if(BsGetBitChar(stream, &tmpIdVUV, 2))
          CommonExit(1,"DecParFrameHvx: error reading bit stream");

	encBit[0] = (tmpIdVUV << 6) & 0xc0;

	/* HP 971111 */
	if (DPdebugLevel >= 2)
	  printf("DecParFrameHVXC: tmpIdVUV=%d\n",
		 tmpIdVUV);

	switch(tmpIdVUV)
        {
        case 0:
	  if(BsGetBitChar(stream, &tmpEncBit, 6))
            CommonExit(1,"DecParFrameHvx: error reading bit stream");
	  encBit[0] |= (tmpEncBit & 0x3f);

          for(j = 1; j < 3; j++)
            if(BsGetBitChar(stream, &encBit[j], 8))
	      CommonExit(1,"DecParFrameHvx: error reading bit stream");

	  if(BsGetBitChar(stream, &tmpEncBit, 4))
            CommonExit(1,"DecParFrameHvx: error reading bit stream");
	  encBit[3] = (tmpEncBit & 0xf) << 4;
	  break;
	case 1:
	  /* no more */
	  break;
	case 2:
	case 3:
	  if(BsGetBitChar(stream, &tmpEncBit, 6))
            CommonExit(1,"DecParFrameHvx: error reading bit stream");
	  encBit[0] |= (tmpEncBit & 0x3f);

          for(j = 1; j < 5; j++)
            if(BsGetBitChar(stream, &encBit[j], 8))
	      CommonExit(1,"DecParFrameHvx: error reading bit stream");
	  break;
	}
      }
      else
      {
        for(j = 0; j < 5; j++)
          if(BsGetBitChar(stream, &encBit[j], 8))
	    CommonExit(1,"DecParFrameHvx: error reading bit stream");
      }
    }

    dcfrm = 0;

    if(ipc_bitstreamMode == BM_VARIABLE)
    {
         IPC_DecParams1stVR(encBit, 1.0 / DPpitchFact, idVUV2, bgnFlag2,
                            qLspQueue, pch2, am2, idCelp2);
    }
    else
    {
        IPC_DecParams1st(encBit, 1.0 / DPpitchFact, idVUV2, qLspQueue,
                         pch2, am2, idCelp2);
    }
/*
    IPC_DecParams1st(encBit, 1.0 / DPpitchFact, idVUV2, qLspQueue, pch2,
		     am2, idCelp2);
*/
    while(nbs == fr0)
    {
        if(ipc_bitstreamMode == BM_VARIABLE)
        {
            IPC_DecParams2ndVR(fr0 - 1, idVUV2, bgnFlag2, qLspQueue, idCelp2,
                               qLsp2, qRes2);
        }
        else
        {
            IPC_DecParams2nd(fr0 - 1, idVUV2, qLspQueue, idCelp2,
                             qLsp2, qRes2);
        }

/*
	IPC_DecParams2nd(fr0 - 1, idVUV2, qLspQueue, idCelp2, qLsp2,
			 qRes2);
*/

	IPC_InterpolateParams(ratio,
			      idVUV2,
			      qLsp2,
			      pch2,
			      am2,
			      qRes2,

			      &idVUV,
			      qLsp,
			      &mfdpch,
			      am,
			      qRes);
	    
	IPC_SynthSC(idVUV, qLsp, mfdpch, am, qRes, frmBuf);
	    
	for(i = 0; i < FRM; i++)
	{
	    sampleBuf[i + FRM * dcfrm] = (float) frmBuf[i];
	}
	frm++;
	targetP = (float) frm * DPspeedFact;
	fr0 = (int) ceil(targetP);
	ratio = targetP - (float) fr0 + 1;
	dcfrm++;
    }
    nbs++;

    *frameBufNumSample = dcfrm * FRM;
}


/* DecParFreeIl() */
/* Free memory: individual lines */

void DecParFreeIl ()
{
  IndiLineDecodeFree(ILD);
  IndiLineSynthFree(ILS);
#ifdef IL_PARAFILE
  if (paraFile != NULL)
    ParaFileClose(paraFile);
#endif
}

/* DecParFreeHvx() */
/* Free memory: harmonic vector exitation */

void DecParFreeHvx ()
{
}


/* ---------- functions ---------- */


char *DecParInfo (
  FILE *helpStream)		/* in: print decPara help text to helpStream */
				/*     if helpStream not NULL */
				/* returns: core version string */
{
  if (helpStream != NULL) {
    fprintf(helpStream,
	    PROGVER "\n"
	    "decoder parameter string format:\n"
	    "  list of tokens (tokens separated by characters in \"%s\")\n",
	    SEPACHAR);
    CmdLineHelp(NULL,NULL,switchList,helpStream);
  }
  return PROGVER;
}


/* DecParInit() */
/* Init parametric decoder core. */

void DecParInit (
  int numChannel,		/* in: num audio channels */
  float fSample,		/* in: sampling frequency [Hz] */
  float bitRate,		/* in: total bit rate [bit/sec] */
  float speedFact,		/* in: speed change factor */
  float pitchFact,		/* in: pitch change factor */
  char *decPara,		/* in: decoder parameter string */
  BsBitBuffer *bitHeader,	/* in: header from bit stream */
  int *frameMaxNumSample,	/* out: max num samples per frame */
  int *delayNumSample)		/* out: decoder delay (num samples) */
{
  int parac;
  char **parav;
  int result;
  BsBitStream *hdrStream;
  char *paraMode;
  int i;

  /* evalute decoder parameter string */
  parav = CmdLineParseString(decPara,SEPACHAR,&parac);
#ifdef IL_PARAFILE
  DPPFname = NULL;
  DPPFpath = NULL;
#endif
  result = CmdLineEval(parac,parav,NULL,switchList,1,NULL);
  if (result) {
    if (result==1) {
      DecParInfo(stdout);
      exit (1);
    }
    else
      CommonExit(1,"decoder parameter string error");
  }

#ifdef IL_PARAFILE
  paraFileMode = *DPPFmode;
  if (paraFileMode=='d' || paraFileMode=='h' || paraFileMode=='s') {
    if (DPPFpath == NULL)
      DPPFpath = PFbitPath;
    if (DPPFname != NULL) {
      if (ComposeFileName(DPPFname,0,DPPFpath,DPPFext,
			  paraFileName,STRLEN))
	CommonExit(1,"composed file name too long");
    }
    else
      if (ComposeFileName(PFbitFileName,1,DPPFpath,DPPFext,
			  paraFileName,STRLEN))
	CommonExit(1,"composed file name too long");
  }
  else {
    if (paraFileMode!='\0')
      CommonExit(1,"DecParInit: unknown para file mode %c",paraFileMode);
    *paraFileName = '\0';
  }
#endif

  if (DPdelayMode)
    ipc_decDelayMode = DM_LONG;
  else
    ipc_decDelayMode = DM_SHORT;

  if (DPdebugLevel >= 1) {
    printf("DecParInit: numChannel=%d  fSample=%f  bitRate=%f\n",
	   numChannel,fSample,bitRate);
    printf("DecParInit: speedFact=%f  pitchFact=%f\n",
	   speedFact,pitchFact);
    printf("DecParInit: decPara=\"%s\"\n",
	   decPara);
    printf("DecParInit: debugLevel=%d\n",
	   DPdebugLevel);
  }

  if (numChannel != 1)
    CommonExit(1,"DecParInit: audio data has more the one channel (%d)",
	       numChannel);

  CmdLineParseFree(parav);

  DPfSample = fSample;
  DPbitRate = bitRate;
  DPspeedFact = speedFact;
  DPpitchFact = pitchFact;

  hdrStream = BsOpenBufferRead(bitHeader);
  if (BsGetBitInt(hdrStream,(unsigned int*)&DPmode,2))
    CommonExit(1,"DecParInit: error reading bit stream header");

  if (DPmode<0 || DPmode>MODEPAR_NUM)
    CommonExit(1,"DecParInit: unknown parametric codec mode %d",DPmode);
  paraMode = MP4ModeParName[DPmode];

  if (DPdebugLevel >= 1)
    printf("DecParInit: modeInt=%d  mode=\"%s\"\n",DPmode,paraMode);

  switch (DPmode) {
  case MODEPAR_HVX:
    DecParInitHvx(hdrStream);
    break;
  case MODEPAR_IL:
    DecParInitIl(hdrStream);
    break;
  case MODEPAR_SWIT:
  case MODEPAR_MIX:
    if (speedFact != 1)
      CommonExit(-1,"DecParInit: "
		 "speed change in switch/mix mode not yet implemented");
    DecParInitHvx(hdrStream);
    HVXdelayNumSample = DPdelayNumSample;
    DecParInitIl(hdrStream);
    ILdelayNumSample = DPdelayNumSample;
    DPframeMaxNumSample = 320; /* 40 ms */
    DPdelayNumSample = max(HVXdelayNumSample,ILdelayNumSample);
    tmpBSbuf = BsAllocBuffer(80);
    break;
  }
  BsClose(hdrStream);

  *frameMaxNumSample = DPframeMaxNumSample;
  *delayNumSample = DPdelayNumSample;
  mixSampleBufSize = DPframeMaxNumSample+
    max(DPdelayNumSample-ILdelayNumSample,DPdelayNumSample-HVXdelayNumSample);

  if (CommonFreeAlloc((void**)&tmpSampleBuf,
		      *frameMaxNumSample*sizeof(float)) == NULL)
    CommonExit(1,"DecParInit: memory allocation error");
  if (CommonFreeAlloc((void**)&mixSampleBuf,
		      mixSampleBufSize*sizeof(float)) == NULL)
    CommonExit(1,"DecParInit: memory allocation error");
  for (i=0; i<mixSampleBufSize; i++)
    mixSampleBuf[i] == 0;

  if (DPdebugLevel >= 1) {
    printf("DecParInit: encDlyMode=%d  vrMode=%d  rateMode=%d\n",
	   ipc_decDelayMode,ipc_bitstreamMode,ipc_rateMode);
    printf("DecParInit: dly=%d  frm=%d  mixBuf=%d  ILdly=%d  HVXdly=%d\n",
	   DPframeMaxNumSample,DPdelayNumSample,
	   mixSampleBufSize,ILdelayNumSample,HVXdelayNumSample);
  }
}


/* DecParFrame() */
/* Decode one bit stream frame into one audio frame with */
/* parametric decoder core. */

void DecParFrame (
  BsBitBuffer *bitBuf,		/* in: bit stream frame */
  float **sampleBuf,		/* out: audio frame samples */
				/*     sampleBuf[numChannel][frameNumSample] */
  int *usedNumBit,		/* out: num bits used for this frame */
  int *frameBufNumSample)	/* out: num samples in sampleBuf[][] */
{
  BsBitStream *stream;
  unsigned int il_hvxc;
  int i;
  int hvxcFrame1;

  if (DPdebugLevel >= 1)
    printf("DecParFrame: availNum=%ld\n",BsBufferNumBit(bitBuf));

  stream = BsOpenBufferRead(bitBuf);
  switch (DPmode) {
  case MODEPAR_HVX:
    DecParFrameHvx(stream,sampleBuf[0],frameBufNumSample);
    break;
  case MODEPAR_IL:
    DecParFrameIl(stream,sampleBuf[0],frameBufNumSample);
    break;
  case MODEPAR_SWIT:
    BsGetBitInt(stream,&il_hvxc,1);
    if (DPdebugLevel >= 1)
      printf("switch: %s\n",(il_hvxc)?"il":"hvxc");
    if (il_hvxc) {
      /* HP 971023   swit mode: 2 HVXC frames / 40 ms */
      DecParFrameHvx(NULL,tmpSampleBuf,frameBufNumSample);
      DecParFrameHvx(NULL,tmpSampleBuf+160,frameBufNumSample);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      DecParFrameIl((DPtest==1)?NULL:stream,tmpSampleBuf,frameBufNumSample);
      for (i=0; i<*frameBufNumSample; i++)
	mixSampleBuf[DPdelayNumSample-ILdelayNumSample+i] += tmpSampleBuf[i];
    }
    else {
      /* HP 971023   swit mode: 2 HVXC frames / 40 ms */
      if (!BsEof(stream,40+80-1))
	hvxcFrame1 = 80;
      else
	hvxcFrame1 = 40;
      if (BsGetBuffer(stream,tmpBSbuf,hvxcFrame1))
	CommonExit(-1,"DecParInit: switch: hvxc 1st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf,frameBufNumSample);
      BsClose(tmpBSstream);
      DecParFrameHvx((DPtest==2)?NULL:stream,
		     tmpSampleBuf+160,frameBufNumSample);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      DecParFrameIl(NULL,tmpSampleBuf,frameBufNumSample);
      for (i=0; i<*frameBufNumSample; i++)
	mixSampleBuf[DPdelayNumSample-ILdelayNumSample+i] += tmpSampleBuf[i];
    }
    for (i=0; i<*frameBufNumSample; i++)
      sampleBuf[0][i] = mixSampleBuf[i];
    for (i=0; i<mixSampleBufSize-*frameBufNumSample; i++)
      mixSampleBuf[i] = mixSampleBuf[i+*frameBufNumSample];
    for (i=0; i<*frameBufNumSample; i++)
      mixSampleBuf[i+mixSampleBufSize-*frameBufNumSample] = 0;
    break;
  case MODEPAR_MIX:
    BsGetBitInt(stream,&il_hvxc,2);
    if (DPdebugLevel >= 1)
      switch (il_hvxc) {
      case 0: printf("mix: hvxc\n"); break;
      case 1: printf("mix: hvxc2 + il\n"); break;
      case 2: printf("mix: hvxc4 + il\n"); break;
      case 3: printf("mix: il\n"); break;
      }
    switch (il_hvxc) {
    case 0:
      if (!BsEof(stream,40+80-1))
	hvxcFrame1 = 80;
      else
	hvxcFrame1 = 40;
      if (BsGetBuffer(stream,tmpBSbuf,hvxcFrame1))
	CommonExit(-1,"DecParInit: mix: hvxc 1st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf,frameBufNumSample);
      BsClose(tmpBSstream);
      DecParFrameHvx((DPtest==2)?NULL:stream,
		     tmpSampleBuf+160,frameBufNumSample);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      break;
    case 1:
      if (BsGetBuffer(stream,tmpBSbuf,40))
	CommonExit(-1,"DecParInit: mix: hvxc 1st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf,frameBufNumSample);
      BsClose(tmpBSstream);
      if (BsGetBuffer(stream,tmpBSbuf,40))
	CommonExit(-1,"DecParInit: mix: hvxc 2st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf+160,frameBufNumSample);
      BsClose(tmpBSstream);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      break;
    case 2:
      if (BsGetBuffer(stream,tmpBSbuf,80))
	CommonExit(-1,"DecParInit: mix: hvxc 1st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf,frameBufNumSample);
      BsClose(tmpBSstream);
      if (BsGetBuffer(stream,tmpBSbuf,80))
	CommonExit(-1,"DecParInit: mix: hvxc 2st frame: bits missing");
      tmpBSstream = BsOpenBufferRead(tmpBSbuf);
      DecParFrameHvx((DPtest==2)?NULL:tmpBSstream,
		     tmpSampleBuf+160,frameBufNumSample);
      BsClose(tmpBSstream);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      break;
    case 3:
      DecParFrameHvx(NULL,tmpSampleBuf,frameBufNumSample);
      DecParFrameHvx(NULL,tmpSampleBuf+160,frameBufNumSample);
      for (i=0; i<*frameBufNumSample*2; i++)
	mixSampleBuf[DPdelayNumSample-HVXdelayNumSample+i] += tmpSampleBuf[i];
      break;
    }
    if (il_hvxc != 0) {
      DecParFrameIl((DPtest==1)?NULL:stream,tmpSampleBuf,frameBufNumSample);
      for (i=0; i<*frameBufNumSample; i++)
	mixSampleBuf[DPdelayNumSample-ILdelayNumSample+i] += tmpSampleBuf[i];
    }
    else {
      DecParFrameIl(NULL,tmpSampleBuf,frameBufNumSample);
      for (i=0; i<*frameBufNumSample; i++)
	mixSampleBuf[DPdelayNumSample-ILdelayNumSample+i] += tmpSampleBuf[i];
    }
    for (i=0; i<*frameBufNumSample; i++)
      sampleBuf[0][i] = mixSampleBuf[i];
    for (i=0; i<mixSampleBufSize-*frameBufNumSample; i++)
      mixSampleBuf[i] = mixSampleBuf[i+*frameBufNumSample];
    for (i=0; i<*frameBufNumSample; i++)
      mixSampleBuf[i+mixSampleBufSize-*frameBufNumSample] = 0;
    break;
  }
  *usedNumBit = BsCurrentBit(stream);
  BsClose(stream);

  if (DPdebugLevel >= 1)
    printf("DecParFrame: numBit=%d  numSample=%d\n",
	   *usedNumBit,*frameBufNumSample);

}


/* DecParFree() */
/* Free memory allocated by parametric decoder core. */

void DecParFree ()
{
  if (DPdebugLevel >= 1)
    printf("DecParFree: ...\n");

  if (DPmode != MODEPAR_IL)
    DecParFreeHvx();
  if (DPmode != MODEPAR_HVX)
    DecParFreeIl();
}


/* end of dec_par.c */

