/**********************************************************************
MPEG-4 Audio VM Module
parameter based codec - individual lines: quantisation & dequantisation



This software module was originally developed by

Heiko Purnhagen (University of Hannover / Deutsche Telekom Berkom)
Bernd Edler (University of Hannover / Deutsche Telekom Berkom)

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) 1996.



Source file: indilineqnt.c

$Id: indilineqnt.c,v 1.10 1998/05/06 19:44:05 purnhage Exp $

Required libraries:
(none)

Required modules:
indilinecom.o		indiline common module

Authors:
HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>
BE    Bernd Edler, Uni Hannover <edler@tnt.uni-hannover.de>

Changes:
01-sep-96   HP    first version based on indiline.c
10-sep-96   BE
11-sep-96   HP
26-sep-96   HP    new indiline module interfaces
04-nov-96   HP    fixed bug in enhancement freq. quant. bit alloc.
23-jun-97   HP    moved ILQ stuff to c file
03-jul-97   HP    fixed minor bug (debug output) in IndiLineEnvDequant()
16-nov-97   HP    harm/indi quant mode
16-feb-98   HP    improved noiseFreq
17-feb-98   HP    fixed fnumbite error
30-mar-98   BE/HP lineValid
31-mar-98   HP    completed IndiLineDecodeFree()
**********************************************************************/


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

#include "indilinecom.h"	/* indiline common module */
#include "indilineqnt.h"	/* indiline quantiser module */

#include "indilinecfg.h"	/* indiline quantiser configuration */


/* units & formats: */
/*  Freq: frequency in Hz */
/*  Ampl: peak amplitude of sine wave */
/*  Phase: phase in rad at frame center */
/*  Index: NumBit LSBs, to be transmitted MSB first */
/*  Pred: line predecessor index: 0=no pred., 1=line[0], 2=line[1], ... */


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

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

#define MINENVAMPL 0.1


/* ---------- declarations (data structures) ---------- */

#define MAX_FBITSE 7		/* max num bits for freq in enhancement strm */

/* status variables and arrays for individual line quantisation (ILQ) */

struct ILQstatusStruct		/* ILQ status handle struct */
{
  /* general parameters */
  int debugMode;		/* debug mode (0=off) */
  int quantMode;		/* quant mode */
  int enhaQuantMode;		/* enha quant mode */
  float maxLineAmpl;		/* max. allowed amplitude */
  int maxNumLine;		/* maximum number of lines */

  /* quantiser parameters */
  float freqMin;
  float freqMax;
  float amplMin;
  float amplMax;
  float deltaFreqMax;
  float deltaAmplMax;
  float envAngle45Time;

  int freqNumBit;
  int amplNumBit;
  int freqNumStep;
  int amplNumStep;
  float freqRange;
  float amplRange;
  float freqRelStep;

  int deltaFreqNumBit;
  int deltaAmplNumBit;
  int deltaFreqNumStep;
  int deltaAmplNumStep;
  float deltaFreqRange;
  float deltaAmplRange;

  int envTmNumBit;
  int envAtkNumBit;
  int envDecNumBit;
  int envTmNumStep;
  int envAtkNumStep;
  int envDecNumStep;

  int freqThrE[MAX_FBITSE];
  int freqNumStepE[MAX_FBITSE];

  int phaseNumBitE;
  int phaseNumStepE;
  float phaseRangeE;

  int envTmNumBitE;
  int envAtkNumBitE;
  int envDecNumBitE;
  int envTmNumStepE;
  int envAtkNumStepE;
  int envDecNumStepE;

  /* pointers to variable content arrays */
  float *quantLineAmplE;	/* line end amplitude  [0..maxNumLine-1] */
  int *freqEnhaNumBit;		/* number of f enh. bits (dequant only) */

  /* pointers to arrays for quantiser return values */
  /* baisc bitstream */
  int *lineParaPred;		/* line predecessor idx in prev frame */
				/*   [0..maxNumLine-1] */
  unsigned int *lineParaIndex;	/* line para bits  [0..maxNumLine-1] */
  int *lineParaNumBit;		/* num line para bits  [0..maxNumLine-1] */

  /* enhancement bitstream */
  unsigned int *lineParaEnhaIndex;
				/* line para bits  [0..maxNumLine-1] */
  int *lineParaEnhaNumBit;	/* num line para bits  [0..maxNumLine-1] */

  /* line transmission sequence */
  int *lineSeq;			/* line transm sequence  [0..maxNumLine-1] */

  /* pointers to arrays for dequantiser return values */
  /* dequantised envelope parameters */
  float *quantEnvPara;		/* envelope parameters  [0..ENVPARANUM-1] */
  float *quantEnvParaEnha;	/* envelope parameters (incl. enha. bits) */
				/*   [0..ENVPARANUM-1] */

  /* dequantised line parameters */
  float *quantLineFreq;		/* line frequency  [0..maxNumLine-1] */
  float *quantLineAmpl;		/* line amplitude  [0..maxNumLine-1] */
  int *quantLineEnv;		/* line envelope flag  [0..maxNumLine-1] */
  int *quantLinePred;		/* line predecessor idx in prev frame */
				/*   [0..maxNumLine-1] */
  float *quantLineFreqEnha;	/* line frequency (incl. enhancement bits) */
				/*   [0..maxNumLine-1] */
  float *quantLineAmplEnha;	/* line amplitude (incl. enhancement bits) */
				/*   [0..maxNumLine-1] */
  float *quantLinePhase;	/* line phase (from enhancement bits) */
				/*   [0..maxNumLine-1] */

  /* variables for IndiLineEnvDequant() memory */
  /* required by IndiLineQuant() and IndiLineDequant() */
  float quantEnvAmplS;		/* env ampl start */
  float quantEnvAmplE;		/* env ampl end */

  /* variables and pointers to arrays for frame-to-frame memory */
  int prevNumLine;		/* num lines transmitted */
  int *prevLineSeq;		/* line transm sequence  [0..maxNumLine-1] */
  float *prevQuantLineFreq;	/* line frequency  [0..maxNumLine-1] */
  float *prevQuantLineAmplE;	/* line end amplitude  [0..maxNumLine-1] */
  int *prevFreqEnhaNumBit;	/* number of f enh. bits from prev. frame */

};

int freqEnhaThr[3][MAX_FBITSE] = {{ 588,  733,  878, 1023, 1023, 1023, 1023},
				  { 954, 1159, 1365, 1570, 1776, 1981, 2047},
				  {1177, 1467, 1757, 2047, 2047, 2047, 2047}};


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

/* IndiLineQuantInit() */
/* Init individual lines quantisation & dequantisation. */

ILQstatus *IndiLineQuantInit (
	int quantMode,			/* in: quant mode */
					/*     (-1, 0..5) */
	int enhaQuantMode,		/* in: enha quant mode */
					/*     (0..3) */
	float maxLineAmpl,		/* in: max line amplitude */
	int maxNumLine,			/* in: max num lines */
	int onlyDequant,		/* in: 0=init quant & dequant */
					/*     1=init dequant */
	int debugMode)			/* in: debug mode (0=off) */
					/* returns: ILQ status handle */
{
  ILQstatus *ILQ;
  int numBit;
  float maxFreqDev,relFreqDev,freqThr;

  if ((ILQ = (ILQstatus *) malloc(sizeof(ILQstatus)))==NULL)
    IndiLineExit("IndiLineQuantInit: memory allocation error");

  ILQ->maxLineAmpl = maxLineAmpl;
  ILQ->quantMode = quantMode;
  ILQ->enhaQuantMode = enhaQuantMode;
  ILQ->maxNumLine = maxNumLine;
  ILQ->debugMode = debugMode;

  /* allocate memory for arrays */
  if (onlyDequant) {
    ILQ->lineParaPred = NULL;
    ILQ->lineParaIndex = NULL;
    ILQ->lineParaNumBit = NULL;
    ILQ->lineParaEnhaIndex = NULL;
    ILQ->lineParaEnhaNumBit = NULL;
    ILQ->lineSeq = NULL;
    ILQ->prevLineSeq = NULL;
  }
  else if
    (
     /* arrays for quantiser return values */
     (ILQ->lineParaPred =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     (ILQ->lineParaIndex =
      (unsigned int*)malloc(ILQ->maxNumLine*sizeof(unsigned int)))==NULL ||
     (ILQ->lineParaNumBit =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     (ILQ->lineParaEnhaIndex =
      (unsigned int*)malloc(ILQ->maxNumLine*sizeof(unsigned int)))==NULL ||
     (ILQ->lineParaEnhaNumBit =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     (ILQ->lineSeq =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     /* arrays for frame-to-frame memory */
     (ILQ->prevLineSeq =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL)
    IndiLineExit("IndiLineQuantInit: memory allocation error");
  if
    (
     /* pointers to variable content arrays */
     (ILQ->quantLineAmplE =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->freqEnhaNumBit =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     /* arrays for dequantiser return values */
     (ILQ->quantEnvPara =
      (float*)malloc(ENVPARANUM*sizeof(float)))==NULL ||
     (ILQ->quantEnvParaEnha =
      (float*)malloc(ENVPARANUM*sizeof(float)))==NULL ||
     (ILQ->quantLineFreq =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->quantLineAmpl =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->quantLineEnv =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     (ILQ->quantLinePred =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL ||
     (ILQ->quantLineFreqEnha =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->quantLineAmplEnha =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->quantLinePhase =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     /* arrays for frame-to-frame memory */
     (ILQ->prevQuantLineFreq =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->prevQuantLineAmplE =
      (float*)malloc(ILQ->maxNumLine*sizeof(float)))==NULL ||
     (ILQ->prevFreqEnhaNumBit =
      (int*)malloc(ILQ->maxNumLine*sizeof(int)))==NULL)
    IndiLineExit("IndiLineQuantInit: memory allocation error");

  /* clear frame-to-frame memory */
  ILQ->prevNumLine = 0;

  /* select quantisers */
  ILQ->envTmNumBit = ILQ_TMBITS;
  ILQ->envAtkNumBit = ILQ_ATKBITS;
  ILQ->envDecNumBit = ILQ_DECBITS;
  ILQ->envAngle45Time = ILQ_ENV45;
  switch (quantMode) {
  case -1:
    ILQ->freqNumBit = ILQ_FBITS_16;
    ILQ->amplNumBit = ILQ_ABITS_16;
    ILQ->freqMin = ILQ_FMIN_16;
    ILQ->freqMax = ILQ_FMAX_16;
    break;
  case 0:
    ILQ->freqNumBit = 10;
    ILQ->amplNumBit = 4;
    ILQ->freqMin = 30.;
    ILQ->freqMax = 4000.;
    break;
  case 1:
    ILQ->freqNumBit = 10;
    ILQ->amplNumBit = 6;
    ILQ->freqMin = 30.;
    ILQ->freqMax = 4000.;
    break;
  case 2:
  case 4:
    ILQ->freqNumBit = 11;
    ILQ->amplNumBit = 5;
    ILQ->freqMin = 20.;
    ILQ->freqMax = 20000.;
    break;
  case 3:
  case 5:
    ILQ->freqNumBit = 11;
    ILQ->amplNumBit = 6;
    ILQ->freqMin = 20.;
    ILQ->freqMax = 20000.;
    break;
  default:
    IndiLineExit("IndiLineQuantInit: wrong quant mode %d",quantMode);
  }
  ILQ->amplMin = ILQ_AMIN;
  ILQ->amplMax = ILQ_AMAX;
  ILQ->deltaFreqNumBit = ILQ_DFBITS;
  ILQ->deltaAmplNumBit = ILQ_DABITS;
  ILQ->deltaFreqMax = ILQ_DFMAX;
  ILQ->deltaAmplMax = ILQ_DAMAX;
  ILQ->envTmNumBitE = ILQ_TMBITSE;
  ILQ->envAtkNumBitE = ILQ_ATKBITSE;
  ILQ->envDecNumBitE = ILQ_DECBITSE;
  ILQ->phaseNumBitE = ILQ_PBITSE;

  /* init quantisers */
  ILQ->freqNumStep = 1<<ILQ->freqNumBit;
  ILQ->freqRange = log(ILQ->freqMax/ILQ->freqMin);
  ILQ->amplNumStep = 1<<ILQ->amplNumBit;
  ILQ->amplRange = log(ILQ->amplMax/ILQ->amplMin);

  ILQ->deltaFreqNumStep = 1<<ILQ->deltaFreqNumBit;
  ILQ->deltaFreqRange = 2*ILQ->deltaFreqMax;
  ILQ->deltaAmplNumStep = 1<<ILQ->deltaAmplNumBit;
  ILQ->deltaAmplRange = log(ILQ->deltaAmplMax*ILQ->deltaAmplMax);

  ILQ->phaseNumStepE = 1<<ILQ->phaseNumBitE;
  ILQ->phaseRangeE = 2*M_PI;

  ILQ->freqRelStep = exp(1./ILQ->freqNumStep*ILQ->freqRange);

  /*
  maxFreqDev = ILQ_MAXPHASEDEV*(float)(fSampleQuant)/frameLenQuant;
  relFreqDev = (ILQ->freqRelStep-1)*.5;
  numBit = 0;
  do {
    if (numBit>=MAX_FBITSE)
      IndiLineExit("IndiLineQuantInit: internal error");
    ILQ->freqNumStepE[numBit] = 1<<numBit;
    freqThr = maxFreqDev/relFreqDev*ILQ->freqNumStepE[numBit];
    ILQ->freqThrE[numBit] = (int)(log(freqThr/ILQ->freqMin)/ILQ->freqRange*
				  ILQ->freqNumStep);
    if (ILQ->debugMode)
      printf("fNumBitE=%d fthr=%9.3f fthrE=%d\n",
	     numBit,freqThr,ILQ->freqThrE[numBit]);
    numBit++;
  } while (freqThr <= ILQ->freqMax);
  */

  for (numBit=0; numBit<MAX_FBITSE; numBit++) {
    ILQ->freqThrE[numBit] = freqEnhaThr[(ILQ->quantMode<=1)?0:1]
      [min(MAX_FBITSE-1,numBit+3-ILQ->enhaQuantMode)];
    ILQ->freqNumStepE[numBit] = 1<<numBit;
    if (ILQ->debugMode)
      printf("fNumBitE=%d fthrE=%d fthr=%9.3f\n",
	     numBit,ILQ->freqThrE[numBit],
	     exp((ILQ->freqThrE[numBit]+.5)/ILQ->freqNumStep*ILQ->freqRange)*
	     ILQ->freqMin);
 
  }

  ILQ->envTmNumStep = 1<<ILQ->envTmNumBit;
  ILQ->envAtkNumStep = 1<<ILQ->envAtkNumBit;
  ILQ->envDecNumStep = 1<<ILQ->envDecNumBit;

  ILQ->envTmNumStepE = 1<<ILQ->envTmNumBitE;
  ILQ->envAtkNumStepE = 1<<ILQ->envAtkNumBitE;
  ILQ->envDecNumStepE = 1<<ILQ->envDecNumBitE;


  if (ILQ->debugMode)
    printf("quant step size: f=%9.6f a=%9.6f df=%9.6f da=%9.6f\n",
	   exp(1./ILQ->freqNumStep*ILQ->freqRange),
	   exp(1./ILQ->amplNumStep*ILQ->amplRange),
	   ILQ->deltaFreqRange/ILQ->deltaFreqNumStep,
	   exp(1./ILQ->deltaAmplNumStep*ILQ->deltaAmplRange));

  if (ILQ->debugMode)
    printf("maxa=%9.3f maxnumlin=%d quantMode=%d enhaQuantMode=%d \n",
	   ILQ->maxLineAmpl,ILQ->maxNumLine,
	   ILQ->quantMode,ILQ->enhaQuantMode);

  return ILQ;
}


/* IndiLineNumBit */
/* Number of bits in basic bitstream for quantised individual */
/* line parameters and envelope parameters. */
/* If ILQ=NULL: minimum number of bits. */

void IndiLineNumBit (
	ILQstatus *ILQ,			/* in: ILQ status handle */
					/*     or NULL */
					/* BASIC BITSTREAM: */
	int *envNumBit,			/* out: num bits envelope */
	int *newLineNumBit,		/* out: num bits new line */
	int *contLineNumBit)		/* out: num bits continued line */
{
  if (ILQ==NULL) {
    *envNumBit = ILQ_TMBITS+ILQ_ATKBITS+ILQ_DECBITS;
    *newLineNumBit = ILQ_ABITS_8+ILQ_FBITS_8;
    *contLineNumBit = ILQ_DABITS+ILQ_DFBITS;
  }
  else {
    *envNumBit = ILQ->envTmNumBit+ILQ->envAtkNumBit+ILQ->envDecNumBit;
    *newLineNumBit = ILQ->amplNumBit+ILQ->freqNumBit;
    *contLineNumBit = ILQ->deltaAmplNumBit+ILQ->deltaFreqNumBit;
  }
}


/* IndiLineEnhaNumBit */
/* Number of bits in enhancement bitstream for quantised */
/* envelope parameters and individual line parameters. */

void IndiLineEnhaNumBit (
	ILQstatus *ILQ,			/* ILQ status handle */
					/* BASIC BITSTREAM: envelope */
	int envParaFlag,		/* in: envelope flag (1 bit) */
	unsigned int envParaIndex,	/* in: envelope bits */
	int envParaNumBit,		/* in: num envelope bits */
					/* BASIC BITSTREAM: lines */
	int numLine,			/* in: num lines */
	int *lineSeq,			/* in: line transm sequence */
					/*     [0..numLine-1] */
					/*     or NULL if seq OK */
	int *lineParaPred,		/* in: line predecessor idx */
					/*     in prev frame */
					/*     [0..numLine-1] */
	unsigned int *lineParaIndex,	/* in: line para bits */
					/*     [0..numLine-1] */
	int *lineParaNumBit,		/* in: num line para bits */
					/*     [0..numLine-1] */
					/* ENHANCEMENT BITSTREAM: */
	int *envEnhaNumBit,		/* out: num bits envelope */
	int **lineEnhaNumBit)		/* out: num bits line */
					/*      [0..numLine-1] */
{
  int fint;
  int fNumBitE;
  int i,iTrans;

  if (lineEnhaNumBit==NULL)
    IndiLineExit("IndiLineEnhaNumBit: quant not init'ed");

  *envEnhaNumBit = ILQ->envTmNumBitE+ILQ->envAtkNumBitE+ILQ->envDecNumBitE;

  for (iTrans=0;iTrans<numLine;iTrans++) {
    if (lineSeq==NULL)
      i = iTrans;
    else
      i = lineSeq[iTrans];
    if (!lineParaPred[i]) {
      /* new line */
      if (lineParaNumBit[i] != ILQ->amplNumBit+ILQ->freqNumBit)
	IndiLineExit("IndiLineEnhaNumBit: bitnum error (new)");
      fint = lineParaIndex[i] & (1<<ILQ->freqNumBit)-1;
      fNumBitE = 0;
      while (fNumBitE<MAX_FBITSE && fint>ILQ->freqThrE[fNumBitE])
	fNumBitE++;
      if (fNumBitE==MAX_FBITSE)
	IndiLineExit("IndiLineEnhaNumBit: fnumbite error");
      ILQ->lineParaEnhaNumBit[i] = ILQ->phaseNumBitE;
      if (fNumBitE > 0)
	ILQ->lineParaEnhaNumBit[i] += fNumBitE;
    }
    else {
      /* continued line */
      if (lineParaNumBit[i] != ILQ->deltaAmplNumBit+ILQ->deltaFreqNumBit)
	IndiLineExit("IndiLineEnhaNumBit: bitnum error (cont)");
      ILQ->lineParaEnhaNumBit[i] = ILQ->phaseNumBitE
	+ILQ->prevFreqEnhaNumBit[lineParaPred[i]-1];
    }
  }

  /* set pointers to arrays with return values */
  *lineEnhaNumBit = ILQ->lineParaEnhaNumBit;
}


/* IndiLineEnvQuant */
/* Quantisation of individual envelope parameters. */

void IndiLineEnvQuant (
	ILQstatus *ILQ,			/* ILQ status handle */
	float *envPara,			/* in: envelope parameters */
					/*     [0..ENVPARANUM-1] */
					/* BASIC BITSTREAM: */
	int *envParaFlag,		/* out: env flag (1 bit) */
	unsigned int *envParaIndex,	/* out: envelope bits */
	int *envParaNumBit,		/* out: num envelope bits */
					/* ENHANCEMENT BITSTREAM: */
	unsigned int *envParaEnhaIndex,	/* out: envelope bits */
	int *envParaEnhaNumBit)		/* out: num envelope bits */
{
  float tmq,atkq,decq;
  int tmint,atkint,decint;
  int tmintE,atkintE,decintE;
  float envAngle1,envAngle2;

  /* decide whether to use envelope */
  *envParaFlag = 0;
  if (envPara[1]!=0 || envPara[2]!=0)
    *envParaFlag = 1;
  
  if (*envParaFlag) {
    /* quantise envelope parameters */
    envAngle1 = atan(envPara[1]*ILQ->envAngle45Time)/(M_PI/2);
    envAngle2 = atan(envPara[2]*ILQ->envAngle45Time)/(M_PI/2);

    tmint = (int)(envPara[0]*ILQ->envTmNumStep);
    tmint = max(min(tmint,ILQ->envTmNumStep-1),0);
    tmq = (tmint+.5)/ILQ->envTmNumStep;
    tmintE = (int)(((envPara[0]-tmq)*ILQ->envTmNumStep+.5)*ILQ->envTmNumStepE);
    tmintE = max(min(tmintE,ILQ->envTmNumStepE-1),0);
    if (envPara[1] == 0) {
      atkint = atkintE = 0;
      atkq = 0;
    }
    else {
      atkint = (int)(envAngle1*(ILQ->envAtkNumStep-1)+1); 
      atkint = max(min(atkint,ILQ->envAtkNumStep-1),0);
      atkq = (atkint-.5)/(ILQ->envAtkNumStep-1);
      atkintE = (int)(((envAngle1-atkq)*ILQ->envAtkNumStep+.5)*
		      ILQ->envAtkNumStepE);
      atkintE = max(min(atkintE,ILQ->envAtkNumStepE-1),0);
    }
    if (envPara[2] == 0) {
      decint = decintE = 0;
      decq = 0;
    }
    else {
      decint = (int)(envAngle2*(ILQ->envDecNumStep-1)+1); 
      decint = max(min(decint,ILQ->envDecNumStep-1),0);
      decq = (decint-.5)/(ILQ->envDecNumStep-1);
      decintE = (int)(((envAngle2-decq)*ILQ->envDecNumStep+.5)*
		      ILQ->envDecNumStepE);
      decintE = max(min(decintE,ILQ->envDecNumStepE-1),0);
    }
    
    if(atkint==0 && decint==0)
      *envParaFlag = 0;
  }
  
  if (*envParaFlag) {
    /* encode envelope parameters */
    *envParaIndex = 0;
    *envParaNumBit = 0;
    *envParaIndex = *envParaIndex<<ILQ->envTmNumBit | tmint;
    *envParaNumBit += ILQ->envTmNumBit;
    *envParaIndex = *envParaIndex<<ILQ->envAtkNumBit | atkint;
    *envParaNumBit += ILQ->envAtkNumBit;
    *envParaIndex = *envParaIndex<<ILQ->envDecNumBit | decint;
    *envParaNumBit += ILQ->envDecNumBit;
    *envParaEnhaIndex = 0;
    *envParaEnhaNumBit = 0;
    *envParaEnhaIndex = *envParaEnhaIndex<<ILQ->envTmNumBitE | tmintE;
    *envParaEnhaNumBit += ILQ->envTmNumBitE;
    *envParaEnhaIndex = *envParaEnhaIndex<<ILQ->envAtkNumBitE | atkintE;
    *envParaEnhaNumBit += ILQ->envAtkNumBitE;
    *envParaEnhaIndex = *envParaEnhaIndex<<ILQ->envDecNumBitE | decintE;
    *envParaEnhaNumBit += ILQ->envDecNumBitE;
    
    if (ILQ->debugMode) {
      printf("tm=%f atk=%f dec=%f\n",
	     envPara[0],envPara[1],envPara[2]);
      printf("tm=%f i=%d i2=%d q=%f\n",
	     envPara[0],tmint,tmintE,tmq);
      printf("atkang=%f i=%d i2=%d q=%f\n",
	     envAngle1,atkint,atkintE,atkq);
      printf("decang=%f i=%d i2=%d q=%f\n",
	     envAngle2,decint,decintE,decq);
    }
  }
  else {
    *envParaIndex=0;
    *envParaNumBit=0;
    *envParaEnhaIndex=0;
    *envParaEnhaNumBit=0;

    if (ILQ->debugMode)
      printf("envParaFlag==0\n");
  }
}


/* IndiLineEnvDequant */
/* Dequantisation of individual envelope parameters from basic bitstream. */
/* Enhancement bitstream utilised if envParaEnhaNumBit != 0. */

void IndiLineEnvDequant (
	ILQstatus *ILQ,			/* ILQ status handle */
					/* BASIC BITSTREAM: */
	int envParaFlag,		/* in: envelope flag (1 bit) */
	unsigned int envParaIndex,	/* in: envelope bits */
	int envParaNumBit,		/* in: num envelope bits */
					/* ENHANCEMENT BITSTREAM: */
	unsigned int envParaEnhaIndex,	/* in: envelope bits */
	int envParaEnhaNumBit,		/* in: num envelope bits */
					/*     or 0 */
	float **quantEnvPara,		/* out: envelope parameters */
					/*      [0..ENVPARANUM-1] */
	float **quantEnvParaEnha)	/* out: envelope parameters */
					/*      (incl. enhancement bits) */
					/*      [0..ENVPARANUM-1] */
					/*      or NULL */
{
  int tmint,atkint,decint;
  int tmintE,atkintE,decintE;
  float envAngle1,envAngle2;

  if (envParaFlag) {
    /* decode envelope parameters */
    if (envParaNumBit != ILQ->envTmNumBit+ILQ->envAtkNumBit+ILQ->envDecNumBit)
      IndiLineExit("IndiLineEnvDequant: bitnum error");
    tmint = (envParaIndex>>(ILQ->envAtkNumBit+ILQ->envDecNumBit)) &
      (1<<ILQ->envTmNumBit)-1;
    atkint = (envParaIndex>>ILQ->envDecNumBit) & (1<<ILQ->envAtkNumBit)-1;
    decint = envParaIndex & (1<<ILQ->envDecNumBit)-1;

    /* dequantise envelope parameters */
    ILQ->quantEnvPara[0] = (tmint+.5)/ILQ->envTmNumStep;
    if (atkint==0)
      ILQ->quantEnvPara[1] = 0;
    else {
      envAngle1 = (atkint-.5)/(ILQ->envAtkNumStep-1);
      ILQ->quantEnvPara[1] = tan(envAngle1*M_PI/2)/ILQ->envAngle45Time;
    }
    if (decint==0)
      ILQ->quantEnvPara[2] = 0;
    else {
      envAngle2 = (decint-.5)/(ILQ->envDecNumStep-1);
      ILQ->quantEnvPara[2] = tan(envAngle2*M_PI/2)/ILQ->envAngle45Time;
    }

    if (envParaEnhaNumBit != 0) {
      /* decode envelope enhancement parameters */
      if (envParaEnhaNumBit != ILQ->envTmNumBitE+ILQ->envAtkNumBitE+
	  ILQ->envDecNumBitE)
	IndiLineExit("IndiLineEnvDequant: bitnum error (enha)");
      tmintE = (envParaEnhaIndex>>(ILQ->envAtkNumBitE+ILQ->envDecNumBitE)) &
	(1<<ILQ->envTmNumBitE)-1;
      atkintE = (envParaEnhaIndex>>ILQ->envDecNumBitE) &
	(1<<ILQ->envAtkNumBitE)-1;
      decintE = envParaEnhaIndex & (1<<ILQ->envDecNumBitE)-1;

      /* dequantise envelope enhancement parameters */
      ILQ->quantEnvParaEnha[0] = ILQ->quantEnvPara[0]+
	((tmintE+.5)/ILQ->envTmNumStepE-.5)/ILQ->envTmNumStep;
      if (atkint==0)
	ILQ->quantEnvParaEnha[1] = 0;
      else {
	envAngle1 += ((atkintE+.5)/ILQ->envAtkNumStepE-.5)/
	  (ILQ->envAtkNumStep-1);
	ILQ->quantEnvParaEnha[1] = tan(envAngle1*M_PI/2)/ILQ->envAngle45Time;
      }
      if (decint==0)
	ILQ->quantEnvParaEnha[2] = 0;
      else {
	envAngle2 += ((decintE+.5)/ILQ->envDecNumStepE-.5)/
	  (ILQ->envDecNumStep-1);
	ILQ->quantEnvParaEnha[2] = tan(envAngle2*M_PI/2)/ILQ->envAngle45Time;
      }
    }
  }
  else {	/* if (envParaFlag) */
    ILQ->quantEnvPara[0] = 0;
    ILQ->quantEnvPara[1] = 0;
    ILQ->quantEnvPara[2] = 0;
    if (envParaEnhaNumBit != 0) {
      ILQ->quantEnvParaEnha[0] = 0;
      ILQ->quantEnvParaEnha[1] = 0;
      ILQ->quantEnvParaEnha[2] = 0;
    }
  }

  /* set pointers to arrays with return values */
  *quantEnvPara = ILQ->quantEnvPara;
  if (quantEnvParaEnha != NULL)
    *quantEnvParaEnha = ILQ->quantEnvParaEnha;

  /* copy parameters into IndiLineEnvDequant() memory */
  ILQ->quantEnvAmplS = max(MINENVAMPL,
			   1-(ILQ->quantEnvPara[0]*ILQ->quantEnvPara[1]));
  ILQ->quantEnvAmplE = max(MINENVAMPL,
			   1-((1-ILQ->quantEnvPara[0])*ILQ->quantEnvPara[2]));

  if (ILQ->debugMode) {
    printf("tm=%f atk=%f dec=%f as=%f ae=%f\n",
	   ILQ->quantEnvPara[0],ILQ->quantEnvPara[1],ILQ->quantEnvPara[2],
	   ILQ->quantEnvAmplS,ILQ->quantEnvAmplE);
    if (envParaEnhaNumBit != 0)
    printf("enha: tm=%f atk=%f dec=%f\n",
	   ILQ->quantEnvParaEnha[0],ILQ->quantEnvParaEnha[1],
	   ILQ->quantEnvParaEnha[2]);
  }
}


/* IndiLineQuant */
/* Quantisation of individual line parameters. */

void IndiLineQuant (
	ILQstatus *ILQ,			/* ILQ status handle */
					/* Requires: */
					/*   PREVIOUS FRAME: */
					/*   dequantised envelope and lines */
					/*   CURRENT FRAME: */
					/*   dequantised envelope */
	int numLine,			/* in: num lines */
	float *lineFreq,		/* in: line frequency */
					/*     [0..numLine-1] */
	float *lineAmpl,		/* in: line amplitude */
					/*     [0..numLine-1] */
	float *linePhase,		/* in: line phase */
					/*     [0..NumLine-1] */
	int *lineEnv,			/* in: line envelope flag */
					/*     [0..numLine-1] */
	int *linePred,			/* in: line predecessor idx */
					/*     [0..numLine-1] */
					/* BASIC BITSTREAM: */
	int **lineParaPred,		/* out: line predecessor idx */
					/*      in prev transm frame */
					/*      [0..numLine-1] */
	unsigned int **lineParaIndex,	/* out: line para bits */
					/*      [0..numLine-1] */
	int **lineParaNumBit,		/* out: num line para bits */
					/*      [0..numLine-1] */
					/* ENHANCEMENT BITSTREAM: */
	unsigned int **lineParaEnhaIndex,
					/* out: line para bits */
					/*      [0..numLine-1] */
	int **lineParaEnhaNumBit)	/* out: num line para bits */
					/*      [0..numLine-1] */
{
  int fint,aint,dfint,daint;
  int fintE,pintE;
  int fNumBitE;
  float fq,freqRelStep;
  int i,iPred;

  if (lineParaPred==NULL)
    IndiLineExit("IndiLineQuant: quant not init'ed");

  /* quantise lines */
  for (i=0;i<numLine;i++) {
    if (!(linePred[i] && linePred[i]-1<ILQ->prevNumLine)) {
      /* quantise new line */
      if (lineAmpl[i]/ILQ->maxLineAmpl >= ILQ->amplMin) {
	aint = (int)(log(lineAmpl[i]/ILQ->maxLineAmpl/ILQ->amplMin)/
		     ILQ->amplRange*ILQ->amplNumStep);
	aint = max(min(aint,ILQ->amplNumStep-1),0);
      }
      else
	aint = 0;
      if (lineFreq[i] >= ILQ->freqMin) {
	fint = (int)(log(lineFreq[i]/ILQ->freqMin)/ILQ->freqRange*
		     ILQ->freqNumStep);
	fint = max(min(fint,ILQ->freqNumStep-1),0);
      }
      else
	fint = 0;
      fNumBitE = 0;
      while (fNumBitE<MAX_FBITSE && fint>ILQ->freqThrE[fNumBitE])
	fNumBitE++;
      if (fNumBitE==MAX_FBITSE)
	IndiLineExit("IndiLineQuant: fnumbite error");

      /*>>>>>>>>>>*/
      if (ILQ->debugMode>=4) {
	printf("ENHA %2d: n, fNumBitE=%d",i,fNumBitE);
      }
      /*<<<<<<<<<<*/

      if (fNumBitE > 0) {
	fq = exp((fint+.5)/ILQ->freqNumStep*ILQ->freqRange)*ILQ->freqMin;
	fintE = (int)(((lineFreq[i]/fq-1)/(ILQ->freqRelStep-1)+.5)*
		      ILQ->freqNumStepE[fNumBitE]);
	fintE = max(min(fintE,ILQ->freqNumStepE[fNumBitE]-1),0);
      }

      /*>>>>>>>>>>*/
      if (ILQ->debugMode>=4) {
	if (fNumBitE > 0)
	  printf(", fintE=%d\n",fintE);
	else
	  printf("\n");
      }
      /*<<<<<<<<<<*/

      pintE = (int)((linePhase[i]/ILQ->phaseRangeE+.5)*
		    ILQ->phaseNumStepE);
      pintE = max(min(pintE,ILQ->phaseNumStepE-1),0);
      
      /* encode new line */
      ILQ->lineParaPred[i] = 0;
      ILQ->lineParaIndex[i] = 0;
      ILQ->lineParaNumBit[i] = 0;
      ILQ->lineParaIndex[i] = ILQ->lineParaIndex[i]<<ILQ->amplNumBit | aint;
      ILQ->lineParaNumBit[i] += ILQ->amplNumBit;
      ILQ->lineParaIndex[i] = ILQ->lineParaIndex[i]<<ILQ->freqNumBit | fint;
      ILQ->lineParaNumBit[i] += ILQ->freqNumBit;

      ILQ->lineParaEnhaIndex[i] = 0;
      ILQ->lineParaEnhaNumBit[i] = 0;
      if (fNumBitE > 0) {
	ILQ->lineParaEnhaIndex[i] =
	  ILQ->lineParaEnhaIndex[i]<<fNumBitE | fintE;
	ILQ->lineParaEnhaNumBit[i] += fNumBitE;
      }
      ILQ->lineParaEnhaIndex[i] =
	ILQ->lineParaEnhaIndex[i]<<ILQ->phaseNumBitE | pintE;
      ILQ->lineParaEnhaNumBit[i] += ILQ->phaseNumBitE;
    }
    else {
      /* quantise continued line */
      
      iPred=0;
      while (ILQ->prevLineSeq[iPred]!=linePred[i]-1 && iPred<ILQ->prevNumLine)
	iPred++;
      if (iPred>=ILQ->prevNumLine)
	IndiLineExit("IndiLineQuant: pred error");

      ILQ->lineParaPred[i] = iPred+1;
      daint = (int)((log(lineAmpl[i]*((lineEnv[i])?ILQ->quantEnvAmplS:1)/
			 ILQ->prevQuantLineAmplE[iPred])/
		     ILQ->deltaAmplRange+.5)*ILQ->deltaAmplNumStep-.5);
      daint = max(min(daint,ILQ->deltaAmplNumStep-1),0);
      dfint = (int)(((lineFreq[i]/ILQ->prevQuantLineFreq[iPred]-1)/
		     ILQ->deltaFreqRange+.5)*ILQ->deltaFreqNumStep-.5);
      dfint = max(min(dfint,ILQ->deltaFreqNumStep-1),0);

      fNumBitE = ILQ->prevFreqEnhaNumBit[iPred];

      /*>>>>>>>>>>*/
      if (ILQ->debugMode>=4) {
	printf("ENHA %2d: c, fNumBitE=%d",i,fNumBitE);
      }
      /*<<<<<<<<<<*/

      if (fNumBitE > 0) {
	fq = ILQ->prevQuantLineFreq[iPred]*
	  (1+((((dfint+1.0)/ILQ->deltaFreqNumStep)-.5)*ILQ->deltaFreqRange));
	freqRelStep = (ILQ->deltaFreqRange/ILQ->deltaFreqNumStep
		       *ILQ->prevQuantLineFreq[iPred]/fq)+1;
	fintE = (int)(((lineFreq[i]/fq-1)/(freqRelStep-1)+.5)*
		      ILQ->freqNumStepE[fNumBitE]);
	fintE = max(min(fintE,ILQ->freqNumStepE[fNumBitE]-1),0);
      }


      /*>>>>>>>>>>*/
      if (ILQ->debugMode>=4) {
	if (fNumBitE > 0)
	  printf(", fintE=%d\n",fintE);
	else
	  printf("\n");
      }
      /*<<<<<<<<<<*/

      pintE = (int)((linePhase[i]/ILQ->phaseRangeE+.5)*
		    ILQ->phaseNumStepE);
      pintE = max(min(pintE,ILQ->phaseNumStepE-1),0);
      
      /* encode continued line */
      ILQ->lineParaIndex[i] = 0;
      ILQ->lineParaNumBit[i] = 0;
      ILQ->lineParaIndex[i] =
	ILQ->lineParaIndex[i]<<ILQ->deltaAmplNumBit | daint;
      ILQ->lineParaNumBit[i] += ILQ->deltaAmplNumBit;
      ILQ->lineParaIndex[i] =
	ILQ->lineParaIndex[i]<<ILQ->deltaFreqNumBit | dfint;
      ILQ->lineParaNumBit[i] += ILQ->deltaFreqNumBit;

      ILQ->lineParaEnhaIndex[i] = 0;
      ILQ->lineParaEnhaNumBit[i] = 0;
      if (fNumBitE > 0) {
	ILQ->lineParaEnhaIndex[i] =
	  ILQ->lineParaEnhaIndex[i]<<fNumBitE | fintE;
	ILQ->lineParaEnhaNumBit[i] += fNumBitE;
      }
      ILQ->lineParaEnhaIndex[i] =
	ILQ->lineParaEnhaIndex[i]<<ILQ->phaseNumBitE | pintE;
      ILQ->lineParaEnhaNumBit[i] += ILQ->phaseNumBitE;
    }
  }

  /* set pointers to arrays with return values */
  *lineParaPred = ILQ->lineParaPred;
  *lineParaIndex = ILQ->lineParaIndex;
  *lineParaNumBit = ILQ->lineParaNumBit;
  *lineParaEnhaIndex = ILQ->lineParaEnhaIndex;
  *lineParaEnhaNumBit = ILQ->lineParaEnhaNumBit;
}


/* IndiLineSequence */
/* Determine transmission sequence for numLine lines. */

void IndiLineSequence (
	ILQstatus *ILQ,			/* ILQ status handle */
	int numLine,			/* in: num lines to transmit */
	int *lineParaPred,		/* in: line predecessor idx */
					/*     in prev transm frame */
					/*     [0..numLine-1] */
	int **lineSeq)			/* out: line transm sequence */
					/*      [0..numLine-1] */
{
  int il,ilCont,ilPrev,ilMin,ilMax,ilTrans,numCont;

  numCont = 0;
  ilMax = 0;
  for (il=0;il<numLine;il++)
    if (lineParaPred[il]) {
      numCont++;
      if (lineParaPred[il]>ilMax)
	ilMax = lineParaPred[il];
    }
  ilTrans = 0;
  ilPrev = 0;
  while (ilTrans<numCont) {
    ilMin = ilMax;
    for (il=0;il<numLine;il++)
      if (lineParaPred[il]>ilPrev && lineParaPred[il]<=ilMin) {
	ilMin = lineParaPred[il];
	ilCont = il;
      }
    ilPrev = ilMin;
    ILQ->lineSeq[ilTrans++] = ilCont;
  }
  for (il=0;il<numLine;il++)
    if (!lineParaPred[il])
      ILQ->lineSeq[ilTrans++] = il;

  if (ILQ->debugMode) {
    printf("idx:");
    for (il=0;il<numLine;il++)
      printf(" %2d",il);
    printf("\n");
    printf("seq:");
    for (il=0;il<numLine;il++)
      printf(" %2d",ILQ->lineSeq[il]);
    printf("\n");
    printf("pre:");
    for (il=0;il<numLine;il++)
      printf(" %2d",lineParaPred[ILQ->lineSeq[il]]);
    printf("\n");
  }

  /* set pointers to arrays with return values */
  *lineSeq = ILQ->lineSeq;
}


/* IndiLineDequant */
/* Dequantisation of individual line parameters from basic bitstream. */
/* Enhancement bitstream utilised if lineParaEnhaNumBit != NULL. */

void IndiLineDequant (
	ILQstatus *ILQ,			/* ILQ status handle */
					/* Requires: */
					/*   PREVIOUS FRAME: */
					/*   dequantised envelope & lines */
					/*   CURRENT FRAME: */
					/*   dequantised envelope */
	int numLine,			/* in: num lines */
	int *lineSeq,			/* in: line transm sequence */
					/*     [0..numLine-1] */
					/*     or NULL if seq OK */
					/* BASIC BITSTREAM: */
	int *lineParaPred,		/* in: line predecessor idx */
					/*     in prev frame */
					/*     [0..numLine-1] */
	int *lineValid,			/* in: line validity flag */
					/*     [0..numLine-1] */
					/*     or NULL if all valid */
	int *lineParaEnv,		/* in: line para env flag */
					/*     [0..numLine-1] */
	unsigned int *lineParaIndex,	/* in: line para bits */
					/*     [0..numLine-1] */
	int *lineParaNumBit,		/* in: num line para bits */
					/*     [0..numLine-1] */
					/* ENHANCEMENT BITSTREAM: */
	unsigned int *lineParaEnhaIndex,
					/* in: line para bits */
					/*     [0..numLine-1] */
					/*     or NULL */
	int *lineParaEnhaNumBit,	/* in: num line para bits */
					/*     [0..numLine-1] */
					/*     or NULL */
	float **quantLineFreq,		/* out: line frequency */
					/*      [0..numLine-1] */
	float **quantLineAmpl,		/* out: line amplitude */
					/*      [0..numLine-1] */
	int **quantLineEnv,		/* out: line envelope flag */
					/*      [0..numLine-1] */
	int **quantLinePred,		/* out: line predecessor idx */
					/*      in prev frame */
					/*      [0..numLine-1] */
	float **quantLineFreqEnha,	/* out: line frequency */
					/*      (incl. enhancement bits) */
					/*      [0..numLine-1] */
					/*      or NULL */
	float **quantLineAmplEnha,	/* out: line amplitude*/
					/*      (incl. enhancement bits) */
					/*      [0..numLine-1] */
					/*      or NULL */
	float **quantLinePhase)		/* out: line phase */
					/*      (from enhancement bits) */
					/*      [0..numLine-1] */
					/*      or NULL */
{
  int fint,aint,dfint,daint;
  int fintE,pintE;
  int fNumBitE;
  int i,iTrans,iPred;
  int iline;
  float freqRelStep;

  if (lineSeq!=NULL && lineValid!=NULL)
    IndiLineExit("IndiLineDequant: "
		 "lineSeq and lineValid cannot be used simultaneously!");

  /* dequantise lines */
  for (iTrans=0;iTrans<numLine;iTrans++) {
    if (lineSeq==NULL)
      i = iTrans;
    else
      i = lineSeq[iTrans];
    if (!lineParaPred[i]) {
      /* decode new line parameters */
      if (lineParaNumBit[i] != ILQ->amplNumBit+ILQ->freqNumBit)
	IndiLineExit("IndiLineDequant: bitnum error (new)");
      aint = (lineParaIndex[i]>>(ILQ->freqNumBit)) & (1<<ILQ->amplNumBit)-1;
      fint = lineParaIndex[i] & (1<<ILQ->freqNumBit)-1;
      /* dequantise new line parameters */
      ILQ->quantLinePred[iTrans] = 0;
      ILQ->quantLineAmpl[iTrans] = exp((aint+.5)/ILQ->amplNumStep*ILQ->amplRange)*
	ILQ->amplMin*ILQ->maxLineAmpl;
      ILQ->quantLineFreq[iTrans] = exp((fint+.5)/ILQ->freqNumStep*ILQ->freqRange)*
	ILQ->freqMin;

      /* bit numbers for new line enhancement parameters */
      fNumBitE = 0;
      while (fNumBitE<MAX_FBITSE && fint>ILQ->freqThrE[fNumBitE])
	fNumBitE++;
      if (fNumBitE==MAX_FBITSE)
	IndiLineExit("IndiLineDequant: fnumbite error");

      if (lineParaEnhaNumBit != NULL) {

	/*>>>>>>>>>>*/
	if (ILQ->debugMode>=4) {
	  printf("ENHA %2d: n, fNumBitE=%d",i,fNumBitE);
	}
	/*<<<<<<<<<<*/

	/* decode new line enhancement parameters */
	if (lineParaEnhaNumBit[i] != fNumBitE+ILQ->phaseNumBitE)
	  IndiLineExit("IndiLineDequant: bitnum error (new,enha)");
	if (fNumBitE > 0)
	  fintE = (lineParaEnhaIndex[i]>>(ILQ->phaseNumBitE)) &
	    ((1<<fNumBitE)-1);

	/*>>>>>>>>>>*/
	if (ILQ->debugMode>=4) {
	  if (fNumBitE > 0)
	    printf(", fintE=%d\n",fintE);
	  else
	    printf("\n");
	}
	/*<<<<<<<<<<*/

	pintE = lineParaEnhaIndex[i] & ((1<<ILQ->phaseNumBitE)-1);
	/* dequantise new line enhancement parameters */
	if (fNumBitE > 0)
	  ILQ->quantLineFreqEnha[iTrans] = ILQ->quantLineFreq[iTrans]*
	    (1+((fintE+.5)/ILQ->freqNumStepE[fNumBitE]-.5)*
	     (ILQ->freqRelStep-1));
	else
	  ILQ->quantLineFreqEnha[iTrans] = ILQ->quantLineFreq[iTrans];
	ILQ->quantLinePhase[iTrans] = ((pintE+.5)/ILQ->phaseNumStepE-.5)*
	  ILQ->phaseRangeE;
      }
    }
    else {
      /* decode continued line parameters */
      if (lineParaNumBit[i] != ILQ->deltaAmplNumBit+ILQ->deltaFreqNumBit)
	IndiLineExit("IndiLineDequant: bitnum error (cont)");
      daint = (lineParaIndex[i]>>(ILQ->deltaFreqNumBit)) &
	(1<<ILQ->deltaAmplNumBit)-1;
      dfint = lineParaIndex[i] & (1<<ILQ->deltaFreqNumBit)-1;
      /* dequantise continued line parameters */
      iPred = lineParaPred[i]-1;
      ILQ->quantLinePred[iTrans] = iPred+1;

      if (lineValid==NULL || lineValid[i]) {
	ILQ->quantLineAmpl[iTrans] = ILQ->prevQuantLineAmplE[iPred]*
	  exp(((daint+1.0)/ILQ->deltaAmplNumStep-.5)*ILQ->deltaAmplRange)/
	  ((lineParaEnv[i])?ILQ->quantEnvAmplS:1);
	ILQ->quantLineFreq[iTrans] = ILQ->prevQuantLineFreq[iPred]*
	  (1+((((dfint+1.0)/ILQ->deltaFreqNumStep)-.5)*ILQ->deltaFreqRange));
      }
      else {
	ILQ->quantLineAmpl[iTrans] = 0;
	ILQ->quantLineFreq[iTrans] = 0;
      }

      /* bit numbers for continued line enhancement parameters */
      if(lineValid==NULL || lineValid[i])
	fNumBitE = ILQ->prevFreqEnhaNumBit[iPred];
      else
	fNumBitE = 0;

      if (lineParaEnhaNumBit != NULL ) {

	/*>>>>>>>>>>*/
	if (ILQ->debugMode>=4) {
	  printf("ENHA %2d: c, fNumBitE=%d",i,fNumBitE);
	}
	/*<<<<<<<<<<*/

	/* decode continued line enhancement parameters */
	if (lineParaEnhaNumBit[i] != ILQ->phaseNumBitE+fNumBitE)
	  IndiLineExit("IndiLineDequant: bitnum error (cont,enha)");
	if (fNumBitE > 0)
	  fintE = (lineParaEnhaIndex[i]>>(ILQ->phaseNumBitE)) &
	    ((1<<fNumBitE)-1);

	/*>>>>>>>>>>*/
	if (ILQ->debugMode>=4) {
	  if (fNumBitE > 0)
	    printf(", fintE=%d\n",fintE);
	  else
	    printf("\n");
	}
	/*<<<<<<<<<<*/

	pintE = lineParaEnhaIndex[i] & ((1<<ILQ->phaseNumBitE)-1);

	/* dequantise continued line enhancement parameters */
	if (fNumBitE > 0) {
	  freqRelStep = (ILQ->deltaFreqRange/ILQ->deltaFreqNumStep
			 *ILQ->prevQuantLineFreq[iPred]
			 /ILQ->quantLineFreq[iTrans])+1;

	  ILQ->quantLineFreqEnha[iTrans] = ILQ->quantLineFreq[iTrans]*
	    (1+((fintE+.5)/ILQ->freqNumStepE[fNumBitE]-.5)*
	     (ILQ->freqRelStep-1));
	}
	else
	  ILQ->quantLineFreqEnha[iTrans] = ILQ->quantLineFreq[iTrans];

	ILQ->quantLinePhase[iTrans] = ((pintE+.5)/ILQ->phaseNumStepE-.5)*
	  ILQ->phaseRangeE;
      }
    }

    ILQ->freqEnhaNumBit[iTrans] = fNumBitE;
    if (lineParaEnhaNumBit != NULL)
      ILQ->quantLineAmplEnha[iTrans] = ILQ->quantLineAmpl[iTrans];
    ILQ->quantLineEnv[iTrans] = lineParaEnv[i];
    if (ILQ->quantLineEnv[iTrans])
      ILQ->quantLineAmplE[iTrans] =
	ILQ->quantLineAmpl[iTrans]*ILQ->quantEnvAmplE;
    else
      ILQ->quantLineAmplE[iTrans] = ILQ->quantLineAmpl[iTrans];
  }

  /* set pointers to arrays with return values */
  *quantLineFreq = ILQ->quantLineFreq;
  *quantLineAmpl = ILQ->quantLineAmpl;
  *quantLineEnv = ILQ->quantLineEnv;
  *quantLinePred = ILQ->quantLinePred;
  if (quantLineFreqEnha != NULL)
    *quantLineFreqEnha = ILQ->quantLineFreqEnha;
  if (quantLineAmplEnha != NULL)
    *quantLineAmplEnha = ILQ->quantLineAmplEnha;
  if (quantLinePhase != NULL)
    *quantLinePhase = ILQ->quantLinePhase;

  /* copy parameters into frame-to-frame memory */
  ILQ->prevNumLine = numLine;
  for (iline=0;iline<numLine;iline++) {
    ILQ->prevQuantLineFreq[iline] = ILQ->quantLineFreq[iline];
    ILQ->prevQuantLineAmplE[iline] = ILQ->quantLineAmplE[iline];
    ILQ->prevFreqEnhaNumBit[iline] = ILQ->freqEnhaNumBit[iline];
  }
  if (ILQ->prevLineSeq!=NULL)
    for (iline=0;iline<numLine;iline++)
      ILQ->prevLineSeq[iline] = (lineSeq==NULL) ? iline : lineSeq[iline];
}


/* IndiLineQuantFree() */
/* Free memory allocated by IndiLineQuantInit(). */

void IndiLineQuantFree (
	ILQstatus *ILQ)			/* ILQ status handle */
{
  if (ILQ->lineParaPred != NULL) {
    free(ILQ->lineParaPred);
    free(ILQ->lineParaIndex);
    free(ILQ->lineParaNumBit);
    free(ILQ->lineParaEnhaIndex);
    free(ILQ->lineParaEnhaNumBit);
    free(ILQ->lineSeq);
    free(ILQ->prevLineSeq);
  }
  
  free(ILQ->quantLineAmplE);
  free(ILQ->freqEnhaNumBit);
  free(ILQ->quantEnvPara);
  free(ILQ->quantEnvParaEnha);
  free(ILQ->quantLineFreq);
  free(ILQ->quantLineAmpl);
  free(ILQ->quantLineEnv);
  free(ILQ->quantLinePred);
  free(ILQ->quantLineFreqEnha);
  free(ILQ->quantLineAmplEnha);
  free(ILQ->quantLinePhase);
  free(ILQ->prevQuantLineFreq);
  free(ILQ->prevQuantLineAmplE);
  free(ILQ->prevFreqEnhaNumBit);

  free(ILQ);
}


/* end of indilineqnt.c */
