/**********************************************************************
MPEG-4 Audio VM
Decoder core (LPC-based)



This software module was originally developed by

Heiko Purnhagen (University of Hannover)
Naoya Tanaka (Matsushita Communication Industrial Co., Ltd.)
Rakesh Taori, Andy Gerrits (Philips Research Laboratories, Eindhoven, The Netherlands),
Toshiyuki Nomura (NEC 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) 1996.



Source file: dec_lpc.c

$Id: dec_lpc.c,v 1.21 1998/05/05 19:42:35 purnhage Exp $

Required modules:
common.o        common module
cmdline.o        command line module
bitstream.o        bits stream module

Authors:
HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>
NT    Naoya Tanaka, Panasonic <natanaka@telecom.mci.mei.co.jp>
AG    Andy Gerrits, Philips <gerritsa@natlab.research.philips.com>
PD    Paul Dillen, Philips Consumer Electronics
TN    Toshiyuki Nomura, NEC <t-nomura@dsp.cl.nec.co.jp>
RF    Ralf Funken, Philips <ralf.funken@ehv.ce.philips.com>

Changes:
24-jun-96   HP    dummy core
15-aug-96   HP    adapted to new dec.h
26-aug-96   HP    CVS
04-Sep-96   NT    LPC Core Ver. 1.11
26-Sep-96   AG    adapted for PHILIPS
25-oct-96   HP    joined Panasonic and Philips LPC frameworks
                  made function names unique
                    e.g.: abs_lpc_decode() -> PAN_abs_lpc_decode()
                    NOTE: pan_xxx() and PAN_xxx() are different functions!
		  I changed the PAN (and not the PHI) function names
                  just because thus less files had to be modified ...
28-oct-96   HP    added auto-select for pan/phi lpc modes
08-Nov-96   NT    Narrowband LPC Ver.2.00
                    - replaced synthesis filter module with Philips module
                    - I/Fs revision for common I/Fs with Philips modules
15-nov-96   HP    adapted to new bitstream module
26-nov-96   AG    changed abs_xxx() to celp_xxx()
27-Feb-97   TN    adapted to rate control functionality
27-Mar-97   AG    new functionalities for decoder added
18-Mar-98   PD    Philips private data (for multi-instance) added
05-May-98   RF    complexity level/postfilter in accordance with FCD: 
                    3 complexity levels, independent of -p option

**********************************************************************/


/* =====================================================================*/
/* Standard Includes                                                    */
/* =====================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* =====================================================================*/
/* MPEG-4 VM Includes                                                   */
/* =====================================================================*/
#include "common.h"        /* common module                             */
#include "cmdline.h"       /* command line module                       */
#include "bitstream.h"     /* bit stream module                         */
#include "dec.h"           /* decoder cores                             */
#include "mp4_lpc.h"       /* common lpc defs                           */

#include "lpc_common.h"		/* HP 961025 */

/* =====================================================================*/
/* PHILIPS Includes                                                     */
/* =====================================================================*/
#include "phi_cons.h"
#include "celp_decoder.h"

/* =====================================================================*/
/* Panasonic Includes                                                   */
/* =====================================================================*/
#include "celp_proto_dec.h"
#include "pan_celp_const.h"

/* =====================================================================*/
/* NEC Includes                                                         */
/* =====================================================================*/
#include "nec_abs_const.h"

/* =====================================================================*/
/* L O C A L     S Y M B O L     D E C L A R A T I O N S                */
/* =====================================================================*/
#define PROGVER "CELP-based decoder core V5.0 13-nov-97"
#define SEPACHAR " ,="

/* =====================================================================*/
/* L O C A L     D A T A      D E C L A R A T I O N S                   */
/* =====================================================================*/
/* configuration inputs                                                 */
/* =====================================================================*/
static long bit_rate;
static long sampling_frequency;
static long frame_size;
static long n_subframes;
static long sbfrm_size;
static long lpc_order;
static long num_lpc_indices;
static float min_pitch_frequency;
static float max_pitch_frequency;
static long num_shape_cbks;
static long num_gain_cbks;
static long num_cbks;

static long *org_frame_bit_allocation;    

static long SampleRateMode     = 1;  /* Default: 16 kHz */
static long QuantizationMode   = 0;  /* Default: Scalar Quantizer */
static long FineRateControl    = 1;  /* Default: FineRateControl is ON */
static long LosslessCodingMode = 0;  /* Default: Lossless coding is OFF */
static long WB_Configuration;
static long Wideband_VQ = 0;
static long NB_Configuration;
static long NumEnhLayers;
static long BandwidthScalabilityMode;
static long BWS_configuration;
static long reduced_order = 0;
static long complexity_level = 0;
static long PostFilterSW;

extern int CELPdecDebugLevel;	/* HP 971120 */

static long number_parameters;

static int DLmode;	/* enum MP4ModeLpc */

static long  NumEnhStage;
static long  DecEnhStage;
static long  DecBwsMode;

static CmdLineSwitch switchList[] = {
  {"h",NULL,NULL,NULL,NULL,"print help"},
  {"n",&DecEnhStage,"%d","0",NULL,NULL},
  {"r",&reduced_order,"%d","0",NULL,NULL},
  {"c",&complexity_level,"%d","0",NULL,NULL},
  {"b",&DecBwsMode,"%d","0",NULL,NULL},
  {"p",&PostFilterSW,"%d","0",NULL,NULL},
  {"d",&CELPdecDebugLevel,"%d","0",NULL,"debug level"},
  {NULL,NULL,NULL,NULL,NULL,NULL}
};

/* =====================================================================*/
/* instance context                                                     */
/* =====================================================================*/

static	void	*InstanceContext;	/*handle to one instance context */


/* =====================================================================*/
/* L O C A L    F U N C T I O N      D E F I N I T I O N S              */
/* =====================================================================*/
/* ---------------------------------------------------------------------*/
/* DecLpcInfo()                                                         */
/* Get info about LPC-based decoder core.                               */
/* ---------------------------------------------------------------------*/
char *DecLpcInfo (
  FILE *helpStream)       /* in: print decPara help text to helpStream */
                          /*     if helpStream not NULL                */
                          /* returns: core version string              */
{
  if (helpStream != NULL)
  {
    fprintf(helpStream, "--------------------------------------------------------\n");
    fprintf(helpStream, PROGVER "\n");
    fprintf(helpStream, "Usage: mp4dec -c \"<options>\" <name bitstream file>\n");
    fprintf(helpStream, "       where <options> are:\n");
    fprintf(helpStream, "             c <num>         : Complexity level (1..3). Default: 2\n");
    fprintf(helpStream, "                                  3. Full decoding: LPC interpolation on LSP\n");
    fprintf(helpStream, "                                  2. Simplified LPC interpolation on LAR\n");
    fprintf(helpStream, "                                  1. Reduced order LPC synthesis (use r option)\n");
    fprintf(helpStream, "             r <num>         : The order of LPC (14, 17, 20). Only available\n");
    fprintf(helpStream, "                               in combination with complexity level 1. Default: 20\n");
    fprintf(helpStream, "             n <DecEnhStage> : Decoded number of enhancement layers (0, 1, 2, 3)\n");
    fprintf(helpStream, "             b <0/1>         : Decoding NarrowBand speech (0) or WideBand speech (1)\n");
    fprintf(helpStream, "             p <0/1>         : Post filter OFF (0) or ON (1). Default: OFF\n");
    fprintf(helpStream, "             d <0/1>         : Debug Level OFF (0) or ON (1). Default: OFF\n");
    fprintf(helpStream, "--------------------------------------------------------\n");
  }
  return PROGVER;
}


/* ------------------------------------------------------------------- */
/* DecLpcInit()                                                        */
/* Init LPC-based decoder core.                                        */
/* ------------------------------------------------------------------- */
void DecLpcInit (
  int numChannel,                  /* in: num audio channels           */
  float fSample,                   /* in: sampling frequency [Hz]      */
  float bitRate,                   /* in: total bit rate [bit/sec]     */
  char *decPara,                   /* in: decoder parameter string     */
  BsBitBuffer *bitHeader,          /* in: header from bit stream       */
  int *frameNumSample,             /* out: num samples per frame       */
  int *delayNumSample)             /* out: decoder delay (num samples) */
{
  BsBitStream *hdrStream;
  int parac;
  char **parav;
  int result;
    
  BITSTREAM *p_bitstream;

  if (numChannel != 1 ) 
  {
    CommonExit(1,"EncLpcInit: Multi-channel audio input is not supported");
  }
  
  /* evalute decoder parameter string */
  parav = CmdLineParseString(decPara,SEPACHAR,&parac);
  result = CmdLineEval(parac,parav,NULL,switchList,1,NULL);
  if (result) 
  {
    if (result==1) 
	{
	  DecLpcInfo(stdout);
	  exit (1);
    }
    else
	  CommonExit(1,"Decoder parameter string error");
  }  

  /* -------------------------------------------------------------------*/
  /* Memory allocation                                                  */
  /* -------------------------------------------------------------------*/
  if((p_bitstream=(BITSTREAM*)malloc(sizeof(BITSTREAM)))==NULL) 
  {
    CommonExit(1, "Memory allocation error in enc_lpc");
  }

  if (bitHeader != NULL)
  {
	  p_bitstream->p_bitstream_buffer_start = bitHeader->data;
	  p_bitstream->buffer_length = ((bitHeader->size)+7)/8;
	  p_bitstream->start_offset = 0;
	  p_bitstream->valid_bits = bitHeader->numBit;
  }
  else
  {
	  p_bitstream->p_bitstream_buffer_start = NULL;
	  p_bitstream->buffer_length = 0;
	  p_bitstream->start_offset = 0;
	  p_bitstream->valid_bits = 0;
  }

  /* ---------------------------------------------------------------- */
  /* Conversion of parameters from float to longs                     */
  /* ---------------------------------------------------------------- */
  bit_rate           = (long)(bitRate+.5);
  sampling_frequency = (long)(fSample+.5);

  /* ---------------------------------------------------------------- */
  /* Decoder Initialisation                                           */
  /* ---------------------------------------------------------------- */
  celp_initialisation_decoder(
      p_bitstream, bit_rate, complexity_level, reduced_order, DecEnhStage, DecBwsMode, PostFilterSW, &frame_size, &n_subframes, &sbfrm_size,		
      &lpc_order,&num_lpc_indices,&num_shape_cbks,&num_gain_cbks,&org_frame_bit_allocation,
		  &SampleRateMode, &QuantizationMode, &FineRateControl, &LosslessCodingMode, &WB_Configuration, 
		  &Wideband_VQ, &NB_Configuration, &NumEnhLayers, &BandwidthScalabilityMode, &BWS_configuration,
		  &InstanceContext);

  *frameNumSample = frame_size;
  *delayNumSample = 0;

    free(p_bitstream);
}


/* ------------------------------------------------------------------- */
/* DecLpcFrame()                                                       */
/* Decode one bit stream frame into one audio frame with               */
/* LPC-based decoder core.                                             */
/* ------------------------------------------------------------------- */
void DecLpcFrame (
  BsBitBuffer *bitBuf,    /* in: bit stream frame                      */
  float **sampleBuf,      /* out: audio frame samples                  */
                          /*     sampleBuf[numChannel][frameNumSample] */
  int *usedNumBit)        /* out: num bits used for this frame         */
{
  BITSTREAM *p_bitstream;

  /* ----------------------------------------------------------------- */
  /* Memory allocation                                                 */
  /* ----------------------------------------------------------------- */
  if((p_bitstream=(BITSTREAM *)malloc(sizeof(BITSTREAM)))==NULL) 
  {
    CommonExit(1, "Memory allocation error in dec_lpc");
  }
  
  /* Philips LPC mode */
  if (bitBuf != NULL)
  {
	  p_bitstream->p_bitstream_buffer_start = bitBuf->data;
	  p_bitstream->buffer_length = ((bitBuf->size)+7)/8;
	  p_bitstream->start_offset = 0;
	  p_bitstream->valid_bits = bitBuf->numBit;
  }
  else
  {
	  p_bitstream->p_bitstream_buffer_start = NULL;
	  p_bitstream->buffer_length = 0;
	  p_bitstream->start_offset = 0;
	  p_bitstream->valid_bits =   0;
  }
    
  /* ----------------------------------------------------------------- */
  /*Call Decoder                                                       */
  /* ----------------------------------------------------------------- */
  celp_decoder( p_bitstream, sampleBuf, 	  
		  SampleRateMode, QuantizationMode, FineRateControl, LosslessCodingMode,
		  WB_Configuration, Wideband_VQ, NB_Configuration, NumEnhLayers, BandwidthScalabilityMode,
      BWS_configuration, frame_size,	n_subframes, sbfrm_size, lpc_order,	          
      num_lpc_indices, num_shape_cbks, num_gain_cbks,	          
      org_frame_bit_allocation,
      InstanceContext  );  

  *usedNumBit = p_bitstream->valid_bits;

  free(p_bitstream);
}


/* ------------------------------------------------------------------- */
/* DeLpcrFree()                                                        */
/* Free memory allocated by LPC-based decoder core.                    */
/* ------------------------------------------------------------------- */
void DecLpcFree ()
{
   celp_close_decoder(SampleRateMode, BandwidthScalabilityMode, org_frame_bit_allocation, &InstanceContext);
}


/* end of dec_lpc.c */

