/* $Id: enc_tf.c,v 1.46 1998/05/08 16:06:33 purnhage Exp $

 ************************* MPEG-2 NBC Audio Decoder **************************
 *                                                                           *
 "This software module was originally developed by 
 Fraunhofer Gesellschaft IIS / University of Erlangen (UER) 
 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.
 *                                                                           *
 ****************************************************************************/

/* CREATED BY :  Bernhard Grill -- June-96  */

/*******************************************************************************************
 *
 * Master module for T/F based codecs
 *
 * Authors:
 * BG    Bernhard Grill, Fraunhofer Gesellshaft / University of Erlangen
 * HP    Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover,de>
 * OS    Otto Schnurr, Motorola <schnurr@email.mot.com>
 * NI    Naoki Iwakami, NTT <iwakami@splab.hil.ntt.jp>
 * TK    Takashi Koike, Sony Corporation <koike@av.crl.sony.co.jp>
 * SK    Sang-Wook Kim, Samsung, <swkim@dspsun.sait.samsung.co.kr>
 * MS    Mikko Suonio, Nokia, <Mikko.Suonio@research.nokia.com>
 *
 *
 * Changes:
 * fixed bit stream handling: Heiko Purnhagen, Uni Hannover, 960705 
 * 29-jul-96   OS   Modified source for 80 column width display.
 * 01-aug-96   OS   Integrated HQ source code module.
 *                  Integrated original TF mapping source code module.
 *                  Re-activated command line strings for run-time selection
 *                  of these modules.
 * 19-aug-96   BG   merge + inclusion of window switching / first short block support 
 * 21-aug-96   HP   renamed to enc_tf.c, adapted to new enc.h
 * 26-aug-96   HP   updated to vm0_tf_02a
 * HP 960826   spectra_index2sf_index alloc bug fix (still repeated alloc !!!)
 * 28-aug-96   NI   Integrated NTT's VQ coder.
 *                  Provided automatic window switching.
 * 05-feb-97   TK   integrated NBC compliant pre processing module
 * 18-apr-97   NI   Integrated scalable coder.
 * 09-may-97   HP   merged contributions by NTT, Sony, FhG
 * 16-may-97   HP   included bug fix by TK (Sony)
 * 28-may-97   HP   -nttScl help
 * 17-Jul-97   NI   add include file for VQ encoder
 * 25-aug-97   NI   bug fixes
 * 29-aug-97   SK   added BSAC
 * 11-sep-97   HP   merged BSAC into current VM
 * 23-oct-97   HP   merged Nokia's predictor 971013 & 971020
 *                  tried to fix nok_PredCalcPrediction() call, PRED_TYPE
 * 26-nov-97   MS   adjusted AAC grouping, energy and allowed distortion
 *                  calculations
 * 08-apr-98   HP   removed LDFB
 ******************************************************************************************/

#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include "bitstream.h"
#include "enc.h"
#include "block.h"
#include "tf_main.h"
#include "psych.h"
#include "common.h"	/* common module */
#include "interface.h"
/* son_AACpp */
#include "sony_local.h"

/* Nokia's predictors */
#include "nok_bwp_enc.h"
#include "nok_ltp_enc.h"

/* aac */
#include "tns3.h"
#include "aac_qc.h"
#include "scaleable.h"

/* SAM BSAC */ /* YB : 970825 */
#include "sam_encode.h"

/* NTT VQ: */
#include "ntt_conf.h"
#include "ntt_scale_conf.h"
#include "ntt_encode.h"
#include "mat_def_ntt.h"
#include "ntt_nok_pred.h"

ntt_PARAM *test_pointer;


static int     block_size_samples = 1024;  /* nr of samples per block in one! audio channel */
static int     coreDelay=-1; /* delay in samples for the timesignal of the core coder , maximum is the block_size_samles */
static int     med_win_in_long    = 2;     /* for NTT */
static int     short_win_in_long  = 8;
static int     bw_lines_long, bw_lines_med, bw_lines_short;  /* no of lines of the spectrum which are processed */
static int     start_line = 0;
static int     max_ch;    /* no of of audio channels */
static int     debugLevel;
static double *spectral_line_vector[MAX_TIME_CHANNELS];
static double *reconstructed_spectrum[MAX_TIME_CHANNELS];
static double *overlap_buffer[MAX_TIME_CHANNELS];
static double *DTimeSigBuf[MAX_TIME_CHANNELS];
static double *DTimeSigLookAheadBuf[MAX_TIME_CHANNELS];
static float *coreTimeSigBuf[MAX_TIME_CHANNELS];
static float *coreTimeSigLookAheadBuf[MAX_TIME_CHANNELS];
static TNS_INFO *tnsInfo[MAX_TIME_CHANNELS];

/* static variables for the pre processing module */
/* son_AACpp */
static int     max_band[MAX_TIME_CHANNELS];
static double *spectral_line_vector_for_gc[MAX_TIME_CHANNELS];
static double *DTimeSigLookAheadBufForGC[MAX_TIME_CHANNELS];
static double *DTimeSigPQFDelayCompensationBuf[MAX_TIME_CHANNELS];
static double **DBandSigLookAheadBuf[MAX_TIME_CHANNELS];
static double **DBandSigBufForGCAnalysis[MAX_TIME_CHANNELS];
static double **DBandSigWithGCBuf[MAX_TIME_CHANNELS];
static GAINC  **gainInfo[MAX_TIME_CHANNELS];

/* static variables used by the T/F mapping */
static enum WIN_SWITCH_MODE win_switch_mode = STATIC_SHORT;
static WINDOW_TYPE last_block_type[MAX_TIME_CHANNELS];
static enum CH_CONFIG        channel_configuration = CHC_MONO;     /* later f(encPara) */
static enum PP_MOD_SELECT    pp_select = NONE;                     /* latef f(encPara) */
static GC_DATA_SWITCH gc_switch = GC_PRESENT; /*later f(encPara)*/
/*static enum GC_DATA_SWITCH gc_switch = GC_NON_PRESENT ; */
static QC_MOD_SELECT    qc_select = NTT_VQ;                   /* later f(encPara) */
static enum TF_MOD_SELECT    tf_select = MDCT_UER;                 /* later f(encPara) */
static enum TRANSPORT_STREAM transport_stream =  LENINFO_TSTREAM;  /* later f(encPara) */
static enum CORE_CODEC coreCodecIdx;                /* alm */

/* Prediction */
static PRED_TYPE pred_type = PRED_NONE;
static NOK_LT_PRED_STATUS nok_lt_status[MAX_TIME_CHANNELS];
static NOK_BW_PRED_STATUS nok_bwp_status[MAX_TIME_CHANNELS];
static int nok_sfb_offset[(MAX_SCFAC_BANDS > ntt_N_CRB_MAX * ntt_N_SUP_MAX ? MAX_SCFAC_BANDS : ntt_N_CRB_MAX * ntt_N_SUP_MAX) + 1];
static double *nok_tmp_DTimeSigBuf[MAX_TIME_CHANNELS]; /* temporary fix to the buffer size problem. */

/* Perceptual weight mode for the NTT_VQ coder */
static enum NTT_PW_SELECT    ntt_pw_select = NTT_PW_INTERNAL;

/* Variable bit switch for the NTT_VQ coder */
static enum NTT_VARBIT ntt_varbit = NTT_VARBIT_OFF;

/* AAC shorter windows 960-480-120 */
static int useShortWindows=0;

static int aacAllowScalefacs=1;

/* TNS options */
int tns_enable = 0;


/********************************************************/
/* functions EncTfInfo() and EncTfFree()   HP 21-aug-96 */
/********************************************************/

#define PROGVER "t/f-based encoder core V5.0 20-nov-97"


/* EncTfInfo() */
/* Get info about t/f-based encoder core. */
char *EncTfInfo (
                 FILE *helpStream)		/* in: print encPara help text to helpStream */
				/*     if helpStream not NULL */
				/* returns: core version string */
{
  if (helpStream != NULL) {
    fprintf(helpStream,
	    PROGVER "\n"
	    "encoder parameter string format:\n"
	    "possible options:\n"
	    "-qc_mdct16\n"
	    "-qc_mdct16_960\n"
	    "-qc_uer\n"
	    "-qc_src\n"
	    "-qc_ntt [-no_syncword] [-ntt_pw_{int,ext}] [-ntt_varbit_{on,off}] \n"
	    "-pp_aac\n"
	    "-qc_aac\n"
            "-qc_aac_960\n"
	    "-aac_sca\n"
	    "-mode <n> :  see below   for more info \n"
	    "-core <n> :  n=0: :g729   n=5: MPEG-4 Celp 6 kbps  n=9: NTT VQ 6 kbps 10: NO_CORE\n"
	    "-aac_raw   caution: works only with framework switch -vr !\n"
	    "-aac_pns <start_band_for_perceptual_noise_subst>\n"
            "-aac_tns"
            "-aac_bsac\n"
	    "-aac_nosfacs: make all scalefacs be equal\n"
	    "-no_tstream\n"
	    "-len_tstream\n"
	    "-pred ltp\n"
	    "-pred nok_bwp\n"
	    "-wsm <win_switch_mode>\n"
	    "-wlp <blksize> <med> <short>\n"
	    "-nttScl <Br1> [<Br2> [<Br3> [<Br4> ...]]] (scalable, Br in kbit/s)\n"
	    "\n");
    printOpModeInfo(helpStream);
  }

  return PROGVER;
}


/* EncTfFree() */
/* Free memory allocated by t/f-based encoder core. */

void EncTfFree ()
{
}



/*****************************************************************************************
 ***
 *** Function: EncTfInit
 ***
 *** Purpose:  Initialize the T/F-part and the macro blocks of the T/F part of the VM
 ***
 *** Description:
 *** 
 ***
 *** Parameters:
 ***
 ***
 *** Return Value:
 ***
 *** **** MPEG-4 VM ****
 ***
 ****************************************************************************************/

void EncTfInit (
                int         numChannel,	 /* in: num audio channels */
                float       sampling_rate_f,   /* in: sampling frequancy [Hz] */         
                float       bit_rate_f,        /* in: bit rate [bit/sec] */
                char        *encPara,		 /* in: encoder parameter string */
                int         quantDebugLevel,   /* in : quantDebugLevel */
                int         *frameNumSample,	 /* out: num samples per frame */
                int         *delayNumSample,	 /* out: encoder delay (num samples) */
                BsBitBuffer *bitHeader    ,     /* out: header for bit stream */
                ENC_FRAME_DATA* frameData) 
{
  BsBitStream *header_stream;

  int reserved_bits = 0;	/* was earlier given as function parameter */
  int sampling_rate = (int)(sampling_rate_f+.5);
  int bit_rate = (int)(bit_rate_f+.5);
  char *p_ctmp;
  long superframe_blocks     = 1;        /* no of blocks in a superframe; later f(encPara) */
  int   op_mode = NO_CORE  ;
  debugLevel=  quantDebugLevel;


  header_stream = BsOpenBufferWrite(bitHeader);

  if( strstr( encPara, "-qc_mdct16" ) ) {
    qc_select = MDCT_VALUES_16BIT;
  }
  if( strstr( encPara, "-qc_mdct16_960" ) ) {
    qc_select = MDCT_VALUES_16BIT;
    block_size_samples=960;
  }
  if( strstr( encPara, "-qc_uer" ) ) {
    qc_select = UER_QC;
  }
  if( strstr( encPara, "-qc_src" ) ) {
    qc_select = VM_QC_SOURCE;
  }
  if( strstr( encPara, "-qc_ntt" ) ) {
    qc_select = NTT_VQ;
  }
  if( strstr( encPara, "-pp_aac" ) ) {
    pp_select = AAC_PP;
  }
  if( strstr( encPara, "-qc_aac" ) ) {
    qc_select = AAC_QC;
    tf_select = MDCT_AAC;
  }
  
  if( strstr( encPara, "-qc_aac_960" ) ) {
    qc_select = AAC_QC;
    tf_select = MDCT_AAC;
    useShortWindows=1;
    block_size_samples=960;
  }

  /* case aac_sys: allows the use of TVQ as core */
  if( strstr( encPara, "-aac_sys" ) || strstr( encPara, "-aac_sys_bsac" )) {
    qc_select = AAC_SYS;
    if(strstr( encPara, "-aac_sys_bsac"))
      qc_select = AAC_SYS_BSAC;
    tf_select = MDCT_AAC;
    useShortWindows=1;
    win_switch_mode = STATIC_LONG;
    
    frameData->opMode = 2;
    if( (p_ctmp = strstr( encPara, "-mode" )) ) {
      sscanf( p_ctmp+6, "%d", &frameData->opMode );
    }
    frameData->layer[0].sampleRate=sampling_rate ;
    coreCodecIdx=NO_CORE;

    switch (frameData->opMode) {
    case 0 : 
      coreCodecIdx=NTT_TVQ;
      if (p_ctmp=strstr(encPara, "-core")) {
        sscanf(p_ctmp+6,"%d", &coreCodecIdx);
      } 
      if( (p_ctmp=strstr( encPara, "-core_br" )) ) {
        sscanf( p_ctmp+8, "%d", &frameData->layer[0].bitRate  );
      }

      switch(coreCodecIdx) {
      case NTT_TVQ:  
        block_size_samples=1024;
        frameData->layer[0].sampleRate=sampling_rate ;
        break;
      default:
         CommonExit(-1,"core coder not yet supported for this mode"); 
      }
      break;
    case 2 : 
      block_size_samples = 1024; /* AAC sys mode without core codec */
      frameData->layer[0].bitRate=bit_rate ; /* bitrate for AAC */
      frameData->layer[0].sampleRate=sampling_rate ;
      break;
    case 3 : CommonExit(-1,"this mode is not supported for aac_sys"); 
      break;
    case 4 :
      block_size_samples = 1024; /* AAC sys mode with core codec */
      coreCodecIdx=NTT_TVQ;
      if (p_ctmp=strstr(encPara, "-core")) {
        sscanf(p_ctmp+6,"%d", &coreCodecIdx);
      }       
      if( (p_ctmp=strstr( encPara, "-core_br" )) ) {
        sscanf( p_ctmp+8, "%d", &frameData->layer[0].bitRate  );
      }

      switch(coreCodecIdx) {
      case NTT_TVQ:  
        block_size_samples=1024;
        frameData->layer[0].sampleRate=sampling_rate ;
        frameData->layer[1].bitRate=bit_rate - frameData->layer[0].bitRate ; /* bitrate for AAC */
        frameData->layer[1].sampleRate=sampling_rate ;
        break;
      default:
         CommonExit(-1,"core coder not yet supported for this mode"); 
      }
      break;
    case 7 :
      block_size_samples = 1024; /* AAC sys mode without core codec */
      coreCodecIdx=NTT_TVQ;
      if (p_ctmp=strstr(encPara, "-core")) {
        sscanf(p_ctmp+6,"%d", &coreCodecIdx);
      }             
      if( (p_ctmp=strstr( encPara, "-core_br" )) ) {
        sscanf( p_ctmp+8, "%d", &frameData->layer[0].bitRate  );
      }

      switch(coreCodecIdx) {
      case NTT_TVQ:  
        block_size_samples=1024;
        frameData->layer[0].sampleRate=sampling_rate ;
        frameData->layer[1].bitRate= (bit_rate - frameData->layer[0].bitRate)/2 ; /* bitrate for AAC */
        frameData->layer[1].sampleRate=sampling_rate ;
        frameData->layer[2].bitRate=bit_rate 
          -  frameData->layer[1].bitRate - frameData->layer[0].bitRate; /* bitrate for AAC */
        frameData->layer[2].sampleRate=sampling_rate ;
        break;
      default:
         CommonExit(-1,"core coder not yet supported for this mode"); 
      }
      break;
    case 11 : 
      block_size_samples = 1024; /* AAC sys mode without core codec */
      frameData->layer[0].bitRate=bit_rate/2 ; /* bitrate for AAC */
      frameData->layer[0].sampleRate=sampling_rate ;
      frameData->layer[1].bitRate=bit_rate - frameData->layer[0].bitRate ; /* bitrate for AAC */
      frameData->layer[1].sampleRate=sampling_rate ;
      break;

    default: CommonExit(-1,"this mode is not yet supported for aac_sys"); 
      break;
    }

    /* check if core coder is TVQ */

    transport_stream = NO_TSTREAM;    
    win_switch_mode = FFT_PE_WINDOW_SWITCHING ;
  }

  /* case aac_sca: supports only speech codecs as core */
  if( strstr( encPara, "-aac_sca" ) ) {
    qc_select = AAC_SCALEABLE;
    tf_select = MDCT_AAC;
    useShortWindows=1;
    block_size_samples=960;
    transport_stream = NO_TSTREAM;    
    win_switch_mode = STATIC_LONG;

    if( (p_ctmp = strstr( encPara, "-mode" )) ) {
      sscanf( p_ctmp+6, "%d", &op_mode );
    }

    if (p_ctmp=strstr(encPara, "-core")) {
      sscanf(p_ctmp+6,"%1d", &coreCodecIdx);
      if (coreCodecIdx==NTT_TVQ)
        CommonExit(1,"NTT TVQ core not supported in this mode");
    }
  }

  if( strstr( encPara, "-aac_raw" ) ) {
    qc_select = AAC_QC;
    tf_select = MDCT_AAC;
    win_switch_mode = STATIC_LONG;
    transport_stream = AAC_RAWDATA_TSTREAM;
  }

  if( (p_ctmp=strstr( encPara, "-aac_pns" )) ) {
    if( sscanf( p_ctmp+9, "%d",&pns_sfb_start ) == 0 ) {
      CommonExit( 1, "Encode: parameter of -aac_pns switch not found" );
    }
    qc_select = AAC_QC;
    tf_select = MDCT_AAC;
    win_switch_mode = STATIC_LONG;
    transport_stream = AAC_RAWDATA_TSTREAM;
  }

  if( strstr( encPara, "-aac_tns" ) ) {
    int n_ch, i_ch;
    n_ch = numChannel;
    for (i_ch=0; i_ch<n_ch; i_ch++) {
      tnsInfo[i_ch] = (TNS_INFO*)calloc(1, sizeof(TNS_INFO));
      TnsInit( (long)sampling_rate_f, MAIN, tnsInfo[i_ch]);
    }
    tns_enable = 1;
  }

  if( strstr( encPara, "-aac_bsac" ) ) { /* YB : 970825 */
    qc_select = AAC_BSAC;
    tf_select = MDCT_AAC;
    win_switch_mode = STATIC_LONG;
    transport_stream = NO_SYNCWORD;
  }
  if( strstr( encPara, "-aac_nosfacs" ) ) {
    aacAllowScalefacs=0;
  }
  if( strstr( encPara, "-no_tstream" ) ) {
    transport_stream = NO_TSTREAM;
  }
  if( strstr( encPara, "-len_tstream" ) ) {
    transport_stream = LENINFO_TSTREAM;
  }
  if (qc_select == NTT_VQ){
    transport_stream = NO_SYNCWORD;
    win_switch_mode = FFT_PE_WINDOW_SWITCHING;
  }
  if ( strstr( encPara, "-no_syncword") ){ /* supported by NTT_VQ only */
    transport_stream = NO_SYNCWORD;
  }
  if( (p_ctmp=strstr( encPara, "-wsm " )) ) {  /* window length switching parameters */
    if( sscanf( p_ctmp+5, "%d",(int*)&win_switch_mode ) == 0 ) {
      CommonExit( 1, "Encode: parameter of -wsm switch not found" );
    }
  }
  if( (p_ctmp=strstr( encPara, "-wlp " )) ) {  /* window length parameters */
    if( sscanf( p_ctmp+5, "%i %i %i", &block_size_samples, &med_win_in_long, &short_win_in_long) == 0 ) {
      CommonExit( 1, "Encode: parameters of -wlp switch not found" );
    }
  }
  if( (p_ctmp=strstr( encPara, "-cde " )) ) {  /* window length switching parameters */
    if( sscanf( p_ctmp+5, "%d",(int*)&coreDelay ) == 0 ) {
      CommonExit( 1, "Encode: parameter of -cde switch not found (coreDelay)" );
    }
    if (coreDelay>block_size_samples)
      CommonExit( 1, "\nillegal core delay: greater than blocksize" );      
  }
  if( strstr( encPara, "-pred_ltp" ) )
    pred_type = NOK_LTP;
  if(strstr( encPara, "-pred_nok_bwp" ))
    pred_type = NOK_BWP;

  /* set the return values (including NTT_VQ global initialization) */
  /* number of channels */
  max_ch = numChannel;
  {
    if (qc_select != NTT_VQ){ /* set the return values for non NTT_VQ coders */
      *frameNumSample = block_size_samples;
      *delayNumSample = 2*block_size_samples; 
    }
    else{ /* global init. of the NTT_VQ coder */
      int    iscl;
      float  t_bit_rate_scl;
      /* bitrate control */
      ntt_NSclLay = 0;
      if( p_ctmp=strstr( encPara, "-nttScl " ) ) {
	/* HP 970509   added an 8th "%d" */
	if((ntt_NSclLay=sscanf( p_ctmp+8, "%d %d %d %d %d %d %d %d",
                                &ntt_IBPS_SCL[0],
                                &ntt_IBPS_SCL[1],
                                &ntt_IBPS_SCL[2],
                                &ntt_IBPS_SCL[3],
                                &ntt_IBPS_SCL[4],
                                &ntt_IBPS_SCL[5],
                                &ntt_IBPS_SCL[6],
                                &ntt_IBPS_SCL[7])) == 0) {
	  CommonExit(1, "Encode: parameter of -nttScl switch not found");
	}
      }
      t_bit_rate_scl = 0.;
      for (iscl=0; iscl<ntt_NSclLay; iscl++){
	t_bit_rate_scl += (float)ntt_IBPS_SCL[iscl]*1000.;
      }
      /* initialization of base coder */
      ntt_TfInit(sampling_rate_f, bit_rate_f, t_bit_rate_scl, (long)max_ch,
		 frameNumSample, delayNumSample,
		 &med_win_in_long, &short_win_in_long); /* global init. */
      block_size_samples = *frameNumSample;
      /* initialization of scalable coders */
      ntt_TBITS_FR_SCL = 0;

      if(ntt_ISAMPF==48){
	ntt_BAND_LOWER_ID_SCL[0] = ntt_BW_0;   /*2ndlayer 16kbps:from 0 to 8kHz*/
	ntt_BAND_UPPER_ID_SCL[0] = ntt_BW_1_3;
	ntt_BAND_LOWER_ID_SCL[1] = ntt_BW_1_6; /*3rdlayer 24kbps:from 4 to 12kHz*/
	ntt_BAND_UPPER_ID_SCL[1] = ntt_BW_p5;
	ntt_BAND_LOWER_ID_SCL[2] = ntt_BW_0;   /*4thlayer 32kbps:from 0 to 8kHz*/
	ntt_BAND_UPPER_ID_SCL[2] = ntt_BW_1_3;
	ntt_BAND_LOWER_ID_SCL[3] = ntt_BW_1_3; /*5thlayer 40kbps:from 8 to 16kHz*/
	ntt_BAND_UPPER_ID_SCL[3] = ntt_BW_2_3;
	ntt_BAND_LOWER_ID_SCL[4] = ntt_BW_1_3; /*6thlayer 48kbps:from 8 to 16kHz*/
	ntt_BAND_UPPER_ID_SCL[4] = ntt_BW_2_3;
	ntt_BAND_LOWER_ID_SCL[5] = ntt_BW_2_3; /*7thlayer 56kbps:from 16 to 24kHz*/
	ntt_BAND_UPPER_ID_SCL[5] = ntt_BW_1p0;
	ntt_BAND_LOWER_ID_SCL[6] = ntt_BW_0;   /*8thlayer 64kbps:from 0 to 8kHz*/
	ntt_BAND_UPPER_ID_SCL[6] = ntt_BW_1_3;
      }
      else if(ntt_ISAMPF==24){
	ntt_BAND_LOWER_ID_SCL[0] = ntt_BW_0;/*2ndlayer 16kbps:from 0 to 8kHz*/
	ntt_BAND_UPPER_ID_SCL[0] = ntt_BW_2_3;
	ntt_BAND_LOWER_ID_SCL[1] = ntt_BW_1_3;/*3rdlayer 24kbps:from 4 to 12kHz*/
	ntt_BAND_UPPER_ID_SCL[1] = ntt_BW_1p0;
	ntt_BAND_LOWER_ID_SCL[2] = ntt_BW_0;/*4thlayer 32kbps:from 0 to 8kHz*/         ntt_BAND_UPPER_ID_SCL[2] = ntt_BW_2_3;
	ntt_BAND_LOWER_ID_SCL[3] = ntt_BW_1_3;/*5thlayer 40kbps:dummy*/
	ntt_BAND_UPPER_ID_SCL[3] = ntt_BW_1p0;
	ntt_BAND_LOWER_ID_SCL[4] = ntt_BW_0;/*6thlayer 48kbps:dummy*/
	ntt_BAND_UPPER_ID_SCL[4] = ntt_BW_2_3;
	ntt_BAND_LOWER_ID_SCL[5] = ntt_BW_1_3;/*7thlayer 56kbps:dummy*/
	ntt_BAND_UPPER_ID_SCL[5] = ntt_BW_1p0;
	ntt_BAND_LOWER_ID_SCL[6] = ntt_BW_0;  /*8thlayer 64kbps:dummy*/
	ntt_BAND_UPPER_ID_SCL[6] = ntt_BW_2_3;
      }


      for (iscl=0; iscl<ntt_NSclLay; iscl++){
        /*
          ntt_BAND_UPPER_ID_SCL[iscl] = ntt_BW_1_3;
          ntt_BAND_LOWER_ID_SCL[iscl] = ntt_BW_0;
        */
	ntt_scale_init(iscl, ntt_NSclLay);
	ntt_TBITS_FR_SCL += ntt_NBITS_FR_SCL[iscl];
	if( strstr( encPara, "-nttSclMsg" ) ) {
	  ntt_scale_message(iscl);
	}
      }

      if ( strstr( encPara, "-ntt_pw_ext" ) ){/* perceptual weight selection */
	ntt_pw_select = NTT_PW_EXTERNAL;
	if (max_ch > 1)
	  CommonExit(1, "EncTfInit: Error in NTT_VQ: No stereo support with NTT_PW_EXTERNAL.");
      }
      if ( strstr( encPara, "-ntt_pw_int" ) ){
	ntt_pw_select = NTT_PW_INTERNAL;
      }
      if (strstr( encPara, "-ntt_varbit_on") ){ /* Variable bit switch */
	ntt_varbit = NTT_VARBIT_ON;
      }
      if (strstr (encPara, "-ntt_varbit_off")){
	ntt_varbit = NTT_VARBIT_OFF;
      }
    }
  }

  /* ----- if no AAC_RAWDATA, write some header information -----*/
  if( (transport_stream != AAC_RAWDATA_TSTREAM) && 
      (transport_stream != NO_TSTREAM) ) {
    BsPutBit( header_stream, 0x1234, 16 );
    BsPutBit( header_stream, bit_rate, 24 );
    BsPutBit( header_stream, sampling_rate, 24 );
    BsPutBit( header_stream, block_size_samples, 16 );
    BsPutBit( header_stream, med_win_in_long, 16 );
    BsPutBit( header_stream, short_win_in_long, 16 );
    BsPutBit( header_stream, *delayNumSample, 16 );
    BsPutBit( header_stream, channel_configuration, 8 );
    BsPutBit( header_stream, tf_select, 32 );           /* encode T/F mapping select */
    BsPutBit( header_stream, qc_select, 32 );           /* encode Q&C select */
  }
  
  /* -- if AAC_RAWDATA, write  "aacraw" --- */
  /*
    if( transport_stream == AAC_RAWDATA_TSTREAM ) {
    BsPutBit( header_stream, 'a', 8 );
    BsPutBit( header_stream, 'a', 8 );
    BsPutBit( header_stream, 'c', 8 );
    BsPutBit( header_stream, 'r', 8 );
    BsPutBit( header_stream, 'a', 8 );
    BsPutBit( header_stream, 'w', 8 );
    }
  */

  if (qc_select == NTT_VQ){
    int iscl;
    /* NTT_VQ supports both LENINFO_STREAM and NO_SYNCWORD. */
    BsPutBit(header_stream, transport_stream, 2);
    /* put ntt_varbit switch */
    /* If the ntt_varbit is off, number of bits
       per frame should be in the header. */
    BsPutBit(header_stream, ntt_varbit, 1);
    if (ntt_varbit == NTT_VARBIT_OFF){
      int frameNumBit;
      frameNumBit = (int)((double)bit_rate_f*(double)block_size_samples
			  /(double)sampling_rate+0.5);
      BsPutBit(header_stream, frameNumBit, 32);
    }
    /* long term predictor */
    if (pred_type == NOK_LTP){
      ntt_LTP_SW = 1;
      BsPutBit(header_stream, 1, 1);
    }
    else{
      ntt_LTP_SW = 0;
      BsPutBit(header_stream, 0, 1);
    }
    /* header for scalable coder */
    BsPutBit(header_stream, (unsigned long)ntt_NSclLay, ntt_NSclLay_BITS);
    for (iscl=0; iscl<ntt_NSclLay; iscl++){
      BsPutBit(header_stream, (unsigned long)(ntt_IBPS_SCL[iscl]*ntt_N_SUP),
	       ntt_IBPS_BITS_SCL);
      BsPutBit(header_stream, (unsigned long)ntt_BAND_UPPER_ID_SCL[iscl],
	       ntt_BLIM_BITS);
      BsPutBit(header_stream, (unsigned long)ntt_BAND_LOWER_ID_SCL[iscl],
	       ntt_BLIM_BITS);
    }
  }


  /* some global initializations */

  {
    int n_ch, i_ch;
    n_ch = max_ch;
    for (i_ch=0; i_ch<n_ch; i_ch++)
      DTimeSigBuf[i_ch] = (double*)calloc(block_size_samples, sizeof(double));
    for (i_ch=0; i_ch<n_ch; i_ch++)
      DTimeSigLookAheadBuf[i_ch] =
        (double*)calloc(block_size_samples, sizeof(double));

    for (i_ch=0; i_ch<n_ch; i_ch++) {
      coreTimeSigBuf[i_ch] = (float*)calloc(block_size_samples, sizeof(float));
      coreTimeSigLookAheadBuf[i_ch] = (float*)calloc(block_size_samples, sizeof(float));
    }
    for (i_ch=0; i_ch<n_ch; i_ch++)
      spectral_line_vector[i_ch] =
        (double*)calloc(block_size_samples*2, sizeof(double));
    for (i_ch=0; i_ch<n_ch; i_ch++)
      reconstructed_spectrum[i_ch] =
        (double*)calloc(block_size_samples, sizeof(double));
    for (i_ch=0; i_ch<n_ch; i_ch++)
      nok_tmp_DTimeSigBuf[i_ch] = (double*)calloc(2*block_size_samples, sizeof(double));
  }

  /* calc. no of audio channels */
#if 0 /* commented out by NI, because no. of ch. is handed by the framework */
  {
    /* table to get the no. of audio channels depending on the value of channel_configuration */
    static int  chc_2_chan_nr[CHC_MODES] = { 1, 2, 2, 5 };

    max_ch  = chc_2_chan_nr[channel_configuration];
  }
#endif

  /* calculate max. audio bandwidth */
  {
    /* table: audio_bandwidth( bit_rate ) */
    static long bandwidth[8][2] = { {64000,20000},{56000,16000},{48000,14000},
                                    {40000,12000},{32000,9000},{24000,6000},
                                    {16000,3500},{-1,0} 
    };
    int i;

    i = 0;
    while( bandwidth[i][0] > bit_rate ) {
      if( bandwidth[i][0] < 0 ) {
        i--;
        break;
      }
      i++;
    }
    bw_lines_long  = bandwidth[i][1] * block_size_samples *2 / sampling_rate;
    bw_lines_med   = bandwidth[i][1] * block_size_samples *2 / sampling_rate / med_win_in_long;
    bw_lines_short = bandwidth[i][1] * block_size_samples *2 / sampling_rate / short_win_in_long;


    /* Use a minimal band-width for a bit rate <= 6 kbps. */
    start_line = 0;
    if ( bit_rate <= 6000 )
      {
        bw_lines_long = 140;
        start_line = 6;
      }
  }
  

  /* initialize pre-processing */
  last_block_type[MONO_CHAN] = ONLY_LONG_WINDOW;
  if ((qc_select != NTT_VQ) && 
      (win_switch_mode == FFT_PE_WINDOW_SWITCHING)){ /* automatic window sw. */
    ntt_win_sw_init(max_ch, block_size_samples, sampling_rate,
		    bit_rate, short_win_in_long);
  }


  /* son_AACpp */
  if (pp_select == AAC_PP)
    {
      int band;
      /* added 971010 YT */
      int i_ch, n_ch;
      n_ch = max_ch;
      for (i_ch=0; i_ch<n_ch; i_ch++){

        max_band[i_ch] = (NBANDS * (start_line + bw_lines_long - 1) /
                          block_size_samples); /* max_bands[] =0,1,2,3 */
        spectral_line_vector_for_gc[i_ch]      = (double *)calloc(block_size_samples, sizeof(double));
        DTimeSigPQFDelayCompensationBuf[i_ch]  = (double *)calloc(PQFDELAY, sizeof(double));
        DTimeSigLookAheadBufForGC[i_ch]        = (double *)calloc(block_size_samples, sizeof(double));
        DBandSigLookAheadBuf[i_ch]             = (double **)calloc(NBANDS, sizeof(double *));
        DBandSigBufForGCAnalysis[i_ch]         = (double **)calloc(NBANDS, sizeof(double *));
        DBandSigWithGCBuf[i_ch]                = (double **)calloc(NBANDS, sizeof(double *));
        gainInfo[i_ch]                         = (GAINC  **)calloc(NBANDS, sizeof(GAINC *));
    
        for (band = 0; band < NBANDS; band++) {
          DBandSigLookAheadBuf[i_ch][band]     = (double *)calloc(block_size_samples/NBANDS, sizeof(double));
          DBandSigBufForGCAnalysis[i_ch][band] = (double *)calloc(block_size_samples/NBANDS*3, sizeof(double));
          DBandSigWithGCBuf[i_ch][band]        = (double *)calloc(block_size_samples/NBANDS*2, sizeof(double));
          gainInfo[i_ch][band]                 = (GAINC  *)calloc(short_win_in_long,sizeof(GAINC));
        }
      } /* for(i_ch...*/
    }/* if (pp_select...*/

  /* initialize psychoacoustic module */
  EncTf_psycho_acoustic_init();

  /* initialize t/f mapping */
  {
    int i_ch, n_ch;
    n_ch = max_ch;
    for (i_ch=0; i_ch<n_ch; i_ch++)
      overlap_buffer[i_ch] =
        (double*)calloc(block_size_samples, sizeof(double));
  }

  /* initialize spectrum processing */
  

  /* initialize quantization and coding */
  {
    int average_block_bits;

    /* calculate the avaerage amount of bits available for one block */
    average_block_bits = (int)((double)bit_rate*(double)block_size_samples*(double)max_ch/(double)sampling_rate);

    /* the frame program may reserve a constant amount of bits e.g. for other 
       scalability layers or ancillary bits or ... 
    */
    average_block_bits -= ((reserved_bits/superframe_blocks)+1);

    /* The above two lines make shure that the used bit no is smaller than the
       available amount by (line 1) integer division and (line 2) the +1 
       Any integer or non integer remaining bits are counted and accumulated
       in the master frame program, and may be made available via the bit reservoir 
       technique to the coding process 
    */

    /* The maximum allowed and actual value of bits in the bit reservoir is calculated
       in the master frame program. The numbers are updated for every block and are
       parameters to the tf_encoder module */

    /* maybe it is better to move the above two lines to the master frame program */
      
    switch( qc_select ) {
    case AAC_QC:
    case AAC_BSAC: /* YB : 971106 */
      tf_init_encode_spectrum_aac( qc_select, quantDebugLevel);	/* YB : 971106 */
      break;
    case  AAC_SCALEABLE:
    case AAC_SYS:
    case AAC_SYS_BSAC:
     {
      int tmp;

      tf_init_encode_spectrum_aac( qc_select, quantDebugLevel); 	/* YB : 971106 */
      tmp = aacScaleEncInit( header_stream, encPara, numChannel, 
                             block_size_samples, sampling_rate,
                             frameData, coreCodecIdx,op_mode);
      if( coreDelay < 0 ) {  /* if not set from the cmdline */
        coreDelay = tmp;
      }
     }
      break;

    case UER_QC:
      /* tf_init_encode_spectrum( ); */
      CommonExit(1,"tf_init_encode_spectrum() is no more available\n"); 
      break;

    case NTT_VQ:
      /* just for avoiding unnecessary warning */
      break;
      
    default:
      /*   CommonExit(-1,"\ncase not handled in swicht" ); */
      CommonWarning("case not handled in swicht" );	/* HP 970509 */
      break;
    }
    switch( qc_select ) {
    case AAC_BSAC:
    case AAC_SYS_BSAC:
      sam_init_encode_bsac(numChannel, sampling_rate, bit_rate, block_size_samples, coreCodecIdx);
      break;
    default:
      break;
    }
  }
  
  /* initialize local T/F bitstream mux */
  {
    /* adjust/set absolute level/gain factor depending on the arithmetic and algorithmit
       implementation (T/F- module normalization factors, ... ) */

  }

  /* initialize Nokia's predictors */
  if (pred_type == NOK_LTP)
    nok_init_lt_pred (&nok_lt_status[MONO_CHAN]);

  if (pred_type == NOK_BWP)
    nok_InitPrediction (quantDebugLevel);

  BsClose(header_stream);

}


/*****************************************************************************************
 ***
 *** Function:    EncTfFrame
 ***
 *** Purpose:     processes a block of time signal input samples into a bitstream
 ***              based on T/F encoding 
 ***
 *** Description:
 *** 
 ***
 *** Parameters:
 ***
 ***
 *** Return Value:  returns the number of used bits
 ***
 *** **** MPEG-4 VM ****
 ***
 ****************************************************************************************/
ntt_PARAM  param_ntt;

void EncTfFrame (
		 float *p_time_signal[MAX_TIME_CHANNELS],   /* array of pointers to the modulo time 
							       signal input buffers for each channel */
		 BsBitBuffer  *fixed_bitstream,             /* bits before bitres size ptr */
		 int frameAvailNumBit,           	    /* in: total num bits available for 
							       this frame (incl. bit reservoir) */
		 int frameNumBit,		            /* in: average num bits per frame */
		 int frameMaxNumBit,		            /* in: max num bits per frame */
		 long bitRateLong,
		 long fSampleLong,
                 ENC_FRAME_DATA* frameData
		 )
{
  /* determine the function parameters used earlier:   HP 21-aug-96 */
  int i;
  int          average_bits = frameNumBit;
  int          available_bitreservoir_bits = frameAvailNumBit-frameNumBit;
  /* actual amount of bits currently in the bit reservoir */
  /* it is the job of this module to determine 
     the no of bits to use in addition to average_block_bits
     max. available: average_block_bits + available_bitreservoir_bits */
  int          max_bitreservoir_bits = frameMaxNumBit-frameNumBit;
  /* max. allowed amount of bits in the reservoir  (used to avoid padding bits) */
  long         num_bits_available;
  /* the generated bitstreams are copied into the buffers designated by the */
  /* two pointers fixed_bitstream and bitres_bitstream */
  BsBitBuffer  *bitres_bitstream = NULL;            /* bits after bitres size ptr */

  double *p_ratio[MAX_TIME_CHANNELS], allowed_distortion[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS], p_energy[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
  int    nr_of_sfb[MAX_TIME_CHANNELS], sfb_width_table[MAX_TIME_CHANNELS][MAX_SCFAC_BANDS];
  WINDOW_TYPE block_type[MAX_TIME_CHANNELS];

  int   win, no_sub_win, sub_win_size, bw_lines;

  
  /*-----------------------------------------------------------------------*/
  /* VQ: Variables for NTT_VQ coder */
  static int ntt_InitFlag=1;
  ntt_INDEX  ntt_index, ntt_index_scl;
  
  /*-----------------------------------------------------------------------*/
  
  /* structures holding the output of the psychoacoustic model */
  CH_PSYCH_OUTPUT chpo_long[MAX_TIME_CHANNELS];
  CH_PSYCH_OUTPUT chpo_short[MAX_TIME_CHANNELS][MAX_SHORT_WINDOWS];

  /* AAC window grouping information */
  int num_window_groups;
  int window_group_length[8];
  
  BsBitStream *fixed_stream;
  BsBitStream *var_stream;
  BsBitStream *tmp_stream;
  BsBitBuffer *tmpBitBuf;
  /* son_AACpp */
  BsBitStream *gc_stream[MAX_TIME_CHANNELS];
  BsBitBuffer *gcBitBuf[MAX_TIME_CHANNELS];	/* bit buffer for gain_control_data() */


  { /* convert float input to double, which is the internal format */
    /* store input data in look ahead buffer which may be necessary for the window switching decision and AAC pre processing */
    int i, i_ch;
    for (i_ch=0; i_ch<max_ch; i_ch++){ 
      for( i=0; i<block_size_samples; i++ ) {
	/* temporary fix: a linear buffer for LTP containing the whole time frame */
	nok_tmp_DTimeSigBuf[i_ch][i] = DTimeSigBuf[i_ch][i];
	nok_tmp_DTimeSigBuf[i_ch][block_size_samples + i] = DTimeSigLookAheadBuf[i_ch][i];
	/* last frame input data are encoded now */
	DTimeSigBuf[i_ch][i]          = DTimeSigLookAheadBuf[i_ch][i];
	/* new data are stored here for use in window switching decision 
	   and AAC pre processing */
	if (pp_select == AAC_PP) {
	  DTimeSigLookAheadBuf[i_ch][i] = (i < PQFDELAY) ? DTimeSigPQFDelayCompensationBuf[i_ch][i] : (double)p_time_signal[i_ch][i-PQFDELAY] ;
	  DTimeSigLookAheadBufForGC[i_ch][i] = (double)p_time_signal[i_ch][i];
	}
	else { /* pp_select != AAC_PP */
	  DTimeSigLookAheadBuf[i_ch][i] = (double)p_time_signal[i_ch][i];
	}
      }
    }
    if (pp_select == AAC_PP) {
      int i, i_ch; /* added 971010 YT*/
      for (i_ch=0; i_ch<max_ch; i_ch++){ 
        for (i = 0; i < PQFDELAY; i++) {
          DTimeSigPQFDelayCompensationBuf[i_ch][i] = (double)p_time_signal[MONO_CHAN][block_size_samples-PQFDELAY+i];
        }
      } /* for i_ch...*/
    }/* if pp_select...*/
  }


  if (fixed_bitstream == NULL)
    return;	/* quick'n'dirty fix for encoder startup    HP 21-aug-96 */

  fixed_stream = BsOpenBufferWrite(fixed_bitstream);
  if (bitres_bitstream != NULL)
    var_stream = BsOpenBufferWrite(bitres_bitstream);
  else
    var_stream = NULL;
  tmpBitBuf = BsAllocBuffer(32768);
  tmp_stream = BsOpenBufferWrite(tmpBitBuf);
  /* son_AACpp */
  /* added 971010 YT*/
  {
    int i, i_ch;
    for (i_ch=0; i_ch<max_ch; i_ch++){ /* added 971010 YT*/
      gcBitBuf[i_ch] = BsAllocBuffer(4096);
      gc_stream[i_ch] = BsOpenBufferWrite(gcBitBuf[i_ch]);
    }
  }



  /*-----------------------------------------------------------------------*/

  /*-----------------------------------------------------------------------*/
  /* VQ: Frame initialization for NTT_VQ coder*/

  param_ntt.ntt_param_set_flag = 0;
  /*-----------------------------------------------------------------------*/



#if 0
  { /* convert float input to double, which is the internal format */
    /* store input data in look ahead buffer which may be necessary for the window switching decision and AAC pre processing */
    for( i=0; i<block_size_samples; i++ ) {
      /* last frame input data are encoded now */
      DTimeSigBuf[MONO_CHAN][i]          = DTimeSigLookAheadBuf[MONO_CHAN][i];
      /* new data are stored here for use in window switching decision 
         and AAC pre processing */
      if (pp_select == AAC_PP) {
        DTimeSigLookAheadBuf[MONO_CHAN][i] = (i < PQFDELAY) ? DTimeSigPQFDelayCompensationBuf[MONO_CHAN][i] : (double)p_time_signal[MONO_CHAN][i-PQFDELAY] ;
        DTimeSigLookAheadBufForGC[MONO_CHAN][i] = (double)p_time_signal[MONO_CHAN][i];
      }
      else { /* pp_select != AAC_PP */
        DTimeSigLookAheadBuf[MONO_CHAN][i] = (double)p_time_signal[MONO_CHAN][i];
      }
    }
    if (pp_select == AAC_PP) {
      for (i = 0; i < PQFDELAY; i++) {
        DTimeSigPQFDelayCompensationBuf[MONO_CHAN][i] = (double)p_time_signal[MONO_CHAN][block_size_samples-PQFDELAY+i];
      }
    }
  }
#endif

  {
    for( i=0; i<coreDelay; i++ ) {
      /* last frame input data are encoded now */
      coreTimeSigBuf[MONO_CHAN][i]          = coreTimeSigLookAheadBuf[MONO_CHAN][i];
      /* new data are stored here for use in window switching decision 
         look ahead can be shorter, but for the moment we don't care */
      coreTimeSigLookAheadBuf[MONO_CHAN][i] = (float)p_time_signal[MONO_CHAN][i+(block_size_samples - coreDelay)];
    }
    for ( i=coreDelay;i<block_size_samples; i++ ) {
      coreTimeSigBuf[MONO_CHAN][i] = (float)p_time_signal[MONO_CHAN][(i - coreDelay)];
    }
  }


  /******************************************************************************************************************************
  *
  * pre processing 
  *
  ******************************************************************************************************************************/

  {
    switch( win_switch_mode ) {
    case STATIC_LONG:
      if (debugLevel>2)
        printf("WSM: ONLY_LONG_WINDOW\n");
      block_type[MONO_CHAN] = ONLY_LONG_WINDOW;
      break;
    case STATIC_MEDIUM :
      if (debugLevel>2) 
	printf("WSM: ONLY_MEDIUM_WINDOW\n");
      block_type[MONO_CHAN] = ONLY_MEDIUM_WINDOW;
      break;
    case STATIC_SHORT :
      if (debugLevel>2)
	printf("WSM:ONLY_SHORT_WINDOW\n");
      block_type[MONO_CHAN] = ONLY_SHORT_WINDOW;
      break;
    case LS_STARTSTOP_SEQUENCE :
      if (debugLevel>2)
	printf("WSM: LS_STARTSTOP_SEQUENCE\n");
      {
        static WINDOW_TYPE long_short_seq[3] = 
        { ONLY_LONG_WINDOW, LONG_SHORT_WINDOW, SHORT_LONG_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 3 ) ls_seq_no = 0;
      }
      break;
    case LM_STARTSTOP_SEQUENCE :
      if (debugLevel>2)
	printf("WSM:LM_STARTSTOP_SEQUENCE\n");
      {
	static WINDOW_TYPE long_short_seq[3] = 
	{ ONLY_LONG_WINDOW, LONG_MEDIUM_WINDOW, MEDIUM_LONG_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 3 ) ls_seq_no = 0;
      }
      break;
    case MS_STARTSTOP_SEQUENCE :
      if (debugLevel>2)
	printf("WSM:LM_STARTSTOP_SEQUENCE\n");
      {
        static WINDOW_TYPE long_short_seq[6] = 
        { ONLY_MEDIUM_WINDOW, MEDIUM_SHORT_WINDOW, SHORT_MEDIUM_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 3 ) ls_seq_no = 0;
      }
      break;
    case LONG_SHORT_SEQUENCE :
      if (debugLevel>2)
	printf("WSM: LONG_SHORT_SEQUENCE\n");
      {
        static WINDOW_TYPE long_short_seq[4] = 
        { ONLY_LONG_WINDOW, LONG_SHORT_WINDOW, ONLY_SHORT_WINDOW, SHORT_LONG_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 4 ) ls_seq_no = 0;
      }
      break;
    case LONG_MEDIUM_SEQUENCE :
      if (debugLevel>2)
	printf("WSM:LONG_MEDIUM_SEQUENCE\n");
      {
        static WINDOW_TYPE long_short_seq[4] = 
        { ONLY_LONG_WINDOW, LONG_MEDIUM_WINDOW, ONLY_MEDIUM_WINDOW, MEDIUM_LONG_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 4 ) ls_seq_no = 0;
      }
      break;
    case MEDIUM_SHORT_SEQUENCE :
      if (debugLevel>2)
	printf("WSM: MEDIUM_SHORT_SEQUENCE \n");
      {
        static WINDOW_TYPE long_short_seq[4+2] = 
        { ONLY_MEDIUM_WINDOW, MEDIUM_SHORT_WINDOW, ONLY_SHORT_WINDOW, SHORT_MEDIUM_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 4 ) ls_seq_no = 0;
      }
      break;
    case LONG_MEDIUM_SHORT_SEQUENCE :
      if (debugLevel>2)
	printf("WSM: LONG_MEDIUM_SHORT_SEQUENCE\n");
      {
        static WINDOW_TYPE long_short_seq[9] = 
        { ONLY_LONG_WINDOW,  LONG_MEDIUM_WINDOW, ONLY_MEDIUM_WINDOW, MEDIUM_SHORT_WINDOW,
          ONLY_SHORT_WINDOW, SHORT_MEDIUM_WINDOW, MEDIUM_LONG_WINDOW, LONG_SHORT_WINDOW, SHORT_LONG_WINDOW };
        static int ls_seq_no;

        block_type[MONO_CHAN] = long_short_seq[ls_seq_no++];
        if( ls_seq_no == 9 ) ls_seq_no = 0;
      }
      break;
    case FFT_PE_WINDOW_SWITCHING :
      /* VQ: Stand-alone automatic window switch provided by NTT */
      {
        static double *sig_tmptmp, *sig_tmp;
        int ismp, med_sw, i_ch, top;
        /* initialize */
        if (ntt_InitFlag){
          sig_tmptmp = (double *)calloc((size_t)(max_ch*block_size_samples*3),
                                        sizeof(double));
          sig_tmp = sig_tmptmp + block_size_samples * max_ch;
          for (i_ch=0; i_ch<max_ch; i_ch++){
            top = i_ch * block_size_samples;
            for (ismp=0; ismp<block_size_samples; ismp++){
              sig_tmp[ismp+top] = DTimeSigBuf[i_ch][ismp];
            }
          }
        }
        for (i_ch=0; i_ch<max_ch; i_ch++){
          top = i_ch * block_size_samples;
          for (ismp=0; ismp<block_size_samples; ismp++){
            sig_tmp[ismp+block_size_samples*max_ch+top] =
              DTimeSigLookAheadBuf[i_ch][ismp];
          }
        }
        /* automatic switching module */
        if (qc_select == NTT_VQ) med_sw = 1; /* if med_sw == 1            */
        else                    med_sw = 0; /* medium block is activated */
        ntt_tf_pre_process(sig_tmp, &ntt_index, &param_ntt, med_sw,
                           ntt_InitFlag);
        block_type[MONO_CHAN] = (WINDOW_TYPE)ntt_index.w_type;
/*         block_type[MONO_CHAN] =     ntt_index.w_type =    ONLY_SHORT_WINDOW; */
        /* prepare for the next frame */
        for (ismp=0; ismp<block_size_samples*2*max_ch; ismp++){
          sig_tmp[ismp-block_size_samples*max_ch] = sig_tmp[ismp];
        }
        param_ntt.ntt_param_set_flag = 1;

      }
      break;

    default:
      CommonExit( 1, "Encode: unsupported window switching mode %d", win_switch_mode );
    }

    if (debugLevel>=1)
      printf("Blocktype   %d \n",block_type[MONO_CHAN] );

    switch( block_type[MONO_CHAN] ) {
    case ONLY_SHORT_WINDOW  :
      no_sub_win   = short_win_in_long;
      sub_win_size = block_size_samples/short_win_in_long;
      bw_lines     = bw_lines_short;
      break;
      
    case ONLY_MEDIUM_WINDOW :
    case SHORT_MEDIUM_WINDOW :
    case MEDIUM_SHORT_WINDOW :
      no_sub_win   = med_win_in_long;
      sub_win_size = block_size_samples/med_win_in_long;
      bw_lines     = bw_lines_med;
      break;

    default:
      no_sub_win   = 1;
      sub_win_size = block_size_samples;
      bw_lines     = bw_lines_long;
      break;
    }
   
    /* son_AACpp */
    if (pp_select == AAC_PP)
      {
        int i_ch; /* 971010 added YT*/
        int band;
	for(i_ch=0;i_ch<max_ch;i_ch++){ /* 971010 added YT*/

          /* polyphase quadrature filter */
          son_pqf_main(DTimeSigLookAheadBufForGC[i_ch], block_size_samples,
                       i_ch, DBandSigLookAheadBuf[i_ch]);
          /* set analysis buffer for gain control */
          for (band = 0; band < NBANDS; band++) {
            memcpy((char *)&DBandSigBufForGCAnalysis[i_ch][band][block_size_samples/NBANDS*2],
                   (char *)DBandSigLookAheadBuf[i_ch][band],
                   block_size_samples/NBANDS*sizeof(double)
                   );
          }

		if(gc_switch == GC_PRESENT){

          /* gain detector */
          son_gc_detect(DBandSigBufForGCAnalysis[i_ch], block_size_samples,
                        block_type[MONO_CHAN],
                        i_ch, gainInfo[i_ch]
                        );
		}
		else { /* if GC_NON_PRESENT */
		son_gc_detect_reset(DBandSigBufForGCAnalysis[i_ch], block_size_samples, block_type[i_ch], i_ch, gainInfo[i_ch]);
		}

          /* gain modifier */
          son_gc_modifier(DBandSigBufForGCAnalysis[i_ch],
                          gainInfo[i_ch],
                          block_size_samples,
                          block_type[MONO_CHAN], i_ch,
                          DBandSigWithGCBuf[i_ch]
                          );
          /* shift analysis buffer */
          for (band = 0; band < NBANDS; band++) {
            memcpy((char *)DBandSigBufForGCAnalysis[i_ch][band],
                   (char *)&DBandSigBufForGCAnalysis[i_ch][band][block_size_samples/NBANDS],
                   block_size_samples/NBANDS*2*sizeof(double)
                   );
          }

		if(gc_switch == GC_PRESENT){
          /* packing gain data into the gc_stream */
          son_gc_pack(gc_stream[i_ch], block_type[MONO_CHAN],
                      max_band[i_ch], gainInfo[i_ch]);
		}

        } /* for i_ch...*/
      } /* if (pp_select == AAC_PP).. */
   
  } /* pre processing */


  /******************************************************************************************************************************
  *
  * psychoacoustic
  *
  ******************************************************************************************************************************/

  if( qc_select != NTT_VQ) {
    EncTf_psycho_acoustic( fSampleLong, 1, &DTimeSigBuf[MONO_CHAN], &block_type[MONO_CHAN], 
                           qc_select,block_size_samples ,chpo_long, chpo_short );
  }

  /******************************************************************************************************************************
  *
  * T/F mapping
  *
  ******************************************************************************************************************************/

  {
    /* son_AACpp */
    if (pp_select == AAC_PP)
      {
	int band;
	/* added 971010 YT*/
        int i_ch, n_ch;
        n_ch = max_ch;
        for (i_ch=0; i_ch<n_ch; i_ch++){

          for (band = 0; band < NBANDS; band++) {
            buffer2freq(
                        DBandSigWithGCBuf[i_ch][band],
                        &spectral_line_vector_for_gc[i_ch][block_size_samples/NBANDS*band],
                        overlap_buffer[i_ch],	/* dummy */
                        block_type[MONO_CHAN],
                        WS_FHG ,
                        block_size_samples/NBANDS, 
                        block_size_samples/NBANDS/med_win_in_long,
                        block_size_samples/NBANDS/short_win_in_long,
                        NON_OVERLAPPED,
                        short_win_in_long,
                        1
                        );
          }
          son_gc_arrangeSpecEnc(
                                spectral_line_vector_for_gc[i_ch],
                                block_size_samples,
                                block_type[MONO_CHAN],
                                spectral_line_vector[i_ch]
                                );
        } /* for(i_ch...*/
      }
    else /* if (pp_select != AAC_PP) */{
      int i_ch, n_ch;
      n_ch = max_ch;
      for (i_ch=0; i_ch<n_ch; i_ch++){
	buffer2freq(
		    DTimeSigBuf[i_ch],
		    spectral_line_vector[i_ch],
		    overlap_buffer[i_ch],
		    block_type[MONO_CHAN],
		    WS_FHG,
		    block_size_samples, 
		    block_size_samples/med_win_in_long,
		    block_size_samples/short_win_in_long,
		    OVERLAPPED,
		    short_win_in_long,		/* HP 971023 */
		    1
		    );
      }
    }
    
  
    /* used_bits += missing if tf_buffer2freq adds something to the fixed stream */

#if 0
    {
      int i, k;
      for( k=0; k<8; k++ ) {
        printf( "\n" );
        for( i=0; i<128; i++ ) {
          printf( "%12.6f ",  spectral_line_vector[MONO_CHAN][(k*128)+i] );
          if( (i%8) ==0 ) printf( "\n" );
        }
      }
    }
#endif
  }



  /******************************************************************************************************************************
  *
  * adapt ratios of psychoacoustic module to codec scale factor bands
  *
  ******************************************************************************************************************************/

  if (!((qc_select==NTT_VQ) && (ntt_pw_select==NTT_PW_INTERNAL)))
    {
      int    sfb, i, sl, par_set;
      double energy, dtmp;

      par_set = 0;

      switch( block_type[MONO_CHAN] ) {
      case ONLY_LONG_WINDOW :
        memcpy( (char*)sfb_width_table[MONO_CHAN], (char*)chpo_long[MONO_CHAN].cb_width, (NSFB_LONG+1)*sizeof(int) );
        nr_of_sfb[MONO_CHAN] = chpo_long[MONO_CHAN].no_of_cb;
        p_ratio[MONO_CHAN]   = chpo_long[MONO_CHAN].p_ratio;
        par_set = 1;
        break;
      case LONG_SHORT_WINDOW :
        memcpy( (char*)sfb_width_table[MONO_CHAN], (char*)chpo_long[MONO_CHAN].cb_width, (NSFB_LONG+1)*sizeof(int) );
        nr_of_sfb[MONO_CHAN] = chpo_long[MONO_CHAN].no_of_cb;
        p_ratio[MONO_CHAN]   = chpo_long[MONO_CHAN].p_ratio;
        par_set = 1;
        break;
      case ONLY_SHORT_WINDOW :
        memcpy( (char*)sfb_width_table[MONO_CHAN], (char*)chpo_short[MONO_CHAN][0].cb_width, (NSFB_SHORT+1)*sizeof(int) );
        nr_of_sfb[MONO_CHAN] = chpo_short[MONO_CHAN][0].no_of_cb;
        p_ratio[MONO_CHAN]   = chpo_short[MONO_CHAN][0].p_ratio;
        par_set = 1;
        break;
      case SHORT_LONG_WINDOW :
        memcpy( (char*)sfb_width_table[MONO_CHAN], (char*)chpo_long[MONO_CHAN].cb_width, (NSFB_LONG+1)*sizeof(int) );
        nr_of_sfb[MONO_CHAN] = chpo_long[MONO_CHAN].no_of_cb;
        p_ratio[MONO_CHAN]   = chpo_long[MONO_CHAN].p_ratio;
        par_set = 1;
        break;
      case SHORT_MEDIUM_WINDOW :
        CommonWarning( "Encode: unsupported block type in adapt ratios: %d", block_type[MONO_CHAN] );
        break;
      case MEDIUM_LONG_WINDOW :
        CommonWarning( "Encode: unsupported block type in adapt ratios: %d", block_type[MONO_CHAN] );
        break;
      case LONG_MEDIUM_WINDOW :
        CommonWarning( "Encode: unsupported block type in adapt ratio:s %d", block_type[MONO_CHAN] );
        break;
      case MEDIUM_SHORT_WINDOW :
        CommonWarning( "Encode: unsupported block type in adapt ratios: %d", block_type[MONO_CHAN] );
        break;
      case ONLY_MEDIUM_WINDOW :
        CommonWarning( "Encode: unsupported block type in adapt ratios: %d", block_type[MONO_CHAN] );
        break;
      default:
        CommonWarning( "Encode: unsupported block type in adapt ratios: %d", block_type[MONO_CHAN] );
        break;
      }

      /* to prevent undefined ptr just use a meaningful value to allow for experiments with the meachanism above */
      if( !par_set) {   
        memcpy( (char*)sfb_width_table[MONO_CHAN], (char*)chpo_long[MONO_CHAN].cb_width, (NSFB_LONG+1)*sizeof(int) );
        nr_of_sfb[MONO_CHAN]  = chpo_long[MONO_CHAN].no_of_cb;
        p_ratio[MONO_CHAN] = chpo_long[MONO_CHAN].p_ratio;
      }
    }

  /* Set the AAC grouping information.  */
  switch( qc_select ) {
  case AAC_QC:
  case AAC_BSAC:
  case AAC_SCALEABLE:
  case AAC_SYS:
  case AAC_SYS_BSAC:
    if (block_type[MONO_CHAN] == ONLY_SHORT_WINDOW) {
#if 1
      num_window_groups=8;
      window_group_length[0] = 1;
      window_group_length[1] = 1;
      window_group_length[2] = 1;
      window_group_length[3] = 1;
      window_group_length[4] = 1;
      window_group_length[5] = 1;
      window_group_length[6] = 1;
      window_group_length[7] = 1;
#else
      num_window_groups=1;
      window_group_length[0] = 8;
      window_group_length[1] = 0;
      window_group_length[2] = 0;
      window_group_length[3] = 0;
#endif
    } else {
      num_window_groups = 1;
      window_group_length[0] = 1;
    }
    break;
  
  default:
    break;
    } /* switch qc_select */


  /******************************************************************************************************************************
  *
  * carry out TNS processing
  *
  ******************************************************************************************************************************/
  if (tns_enable) {
    int i_ch, n_ch;
    int sfb, k, sfb_offset[ 100 ];

    /* calc. sfb offset table */
    for (sfb=k=0; sfb<nr_of_sfb[MONO_CHAN]; sfb++) {
      sfb_offset[sfb] = k;
      k += sfb_width_table[MONO_CHAN][sfb];
    }
    sfb_offset[sfb] = k;
    
    n_ch = max_ch;
    for (i_ch=0; i_ch<n_ch; i_ch++) {
      TnsEncode(nr_of_sfb[MONO_CHAN],                  /* Number of bands per window */
                nr_of_sfb[MONO_CHAN],                  /* max_sfb */ 
                block_type[MONO_CHAN],                 /* block type */
                sfb_offset,                            /* Scalefactor band offset table */
                spectral_line_vector[i_ch],            /* Spectral data array */
                tnsInfo[i_ch]);                        /* TNS info */
        }
  }


  /******************************************************************************************************************************
  *
  * compute energy and allowed distortion from the original spectrum
  *
  ******************************************************************************************************************************/
  /* These have to be done before prediction (not, for example, inside
     the quantizer) since the signal going to the quantizer is changed
     by the prediction. Do not use p_ratio after this. Use
     allowed_distortion (and p_energy) instead.
     1997-11-23 Mikko Suonio  */
  switch( qc_select ) {
  case AAC_QC:
  case AAC_BSAC:
  case AAC_SYS_BSAC:
  case AAC_SCALEABLE:
  case AAC_SYS:
    {
      int group, i_ch, index, i, j, sfb;
      double dtmp;

      for (i_ch = 0; i_ch < max_ch; i_ch++) {
	index = 0;
	/* calculate the scale factor band energy in window groups  */
	for (group = 0; group < num_window_groups; group++) {
	  for (sfb = 0; sfb < nr_of_sfb[i_ch]; sfb++)
	    p_energy[i_ch][sfb + group * nr_of_sfb[i_ch]] = 0.0;
	  for (i = 0; i < window_group_length[group]; i++) {
	    for (sfb = 0; sfb < nr_of_sfb[i_ch]; sfb++) {
	      for (j = 0; j < sfb_width_table[i_ch][sfb]; j++) {
		dtmp = spectral_line_vector[i_ch][index++];   
		p_energy[i_ch][sfb + group * nr_of_sfb[i_ch]] += dtmp * dtmp;

		if (debugLevel > 6 )
		  fprintf(stderr,"enc_tf.c: spectral_line_vector index %d; %d %d %d %d %d\n", index, i_ch, group, i, sfb, j);
	      }
	    }
	  }
	}
	/* calculate the allowed distortion */
	/* Currently the ratios from psychoacoustic model
	   are common for all subwindows, that is, there is only
	   num_of_sfb[i_ch] elements in p_ratio[i_ch]. However, the
	   distortion has to be specified for scalefactor bands in all
	   window groups. */
	for (group = 0; group < num_window_groups; group++) {
	  for (sfb = 0; sfb < nr_of_sfb[i_ch]; sfb++) {
	    index = sfb + group * nr_of_sfb[i_ch];
	    if ((10 * log10(p_energy[i_ch][index] + 1e-15)) > 70)
	      allowed_distortion[i_ch][index] = p_energy[i_ch][index] * p_ratio[i_ch][sfb];
	    else
	      allowed_distortion[i_ch][index] = p_energy[i_ch][index] * 1.1;
	  }
	}
      }
      break;
    }
  default:
    break;
  } /* switch qc_select */


  /******************************************************************************************************************************
  *
  * prediction
  *
  ******************************************************************************************************************************/
  {
    int i, k;
    
    switch (qc_select)
      {
      case AAC_QC:
	if (pred_type == NOK_LTP)
	  {
	    nok_sfb_offset[0] = 0;
	    k=0;
	    for(i = 0; i < nr_of_sfb[MONO_CHAN]; i++ )
	      {
		nok_sfb_offset[i] = k;
		k +=sfb_width_table[MONO_CHAN][i];
	      }
	    nok_sfb_offset[i] = k;        

	    nok_ltp_enc(spectral_line_vector[MONO_CHAN],
			nok_tmp_DTimeSigBuf[MONO_CHAN], 
			block_type[MONO_CHAN], WS_FHG,
			block_size_samples, 
			block_size_samples/med_win_in_long,
			block_size_samples/short_win_in_long,
			nok_sfb_offset, nr_of_sfb[MONO_CHAN],
			&nok_lt_status[MONO_CHAN], 0);
	  }
	else if (pred_type == NOK_BWP)
	  nok_PredCalcPrediction (spectral_line_vector[MONO_CHAN],
				  reconstructed_spectrum[MONO_CHAN],
				  block_type[MONO_CHAN], nr_of_sfb[MONO_CHAN],
				  sfb_width_table[MONO_CHAN],
				  &nok_bwp_status[MONO_CHAN].global_pred_flag,
				  nok_bwp_status[MONO_CHAN].pred_sfb_flag,
				  &nok_bwp_status[MONO_CHAN].reset_flag,
				  &nok_bwp_status[MONO_CHAN].reset_group,
				  &nok_bwp_status[MONO_CHAN].side_info);
	break;
      case NTT_VQ:
	if (pred_type == NOK_LTP)
	  {
	    switch(block_type[MONO_CHAN])
	      {
	      case ONLY_LONG_WINDOW:
	      case LONG_SHORT_WINDOW:
	      case SHORT_LONG_WINDOW:
	      case LONG_MEDIUM_WINDOW:
	      case MEDIUM_LONG_WINDOW:
		nok_sfb_offset[0] = 0;
		for(i = 1; i < ntt_N_CRB; i++ )
		  nok_sfb_offset[i] = ntt_crb_tbl[i];

		nok_ltp_enc(spectral_line_vector[MONO_CHAN],
			    nok_tmp_DTimeSigBuf[MONO_CHAN], 
			    block_type[MONO_CHAN], WS_FHG,
			    block_size_samples, 
			    block_size_samples/med_win_in_long,
			    block_size_samples/short_win_in_long,
			    nok_sfb_offset, ntt_N_CRB,
			    &nok_lt_status[MONO_CHAN], 0);
		nokia_LPTOOL_BITS = nok_lt_status[MONO_CHAN].side_info;
		break;
	      default:
		nokia_LPTOOL_BITS = 0;
		break;
	      }
	  }
	break;
      default:
	break;
      }
  }
  
  
/******************************************************************************************************************************/
/*
 * quantization and coding
 *
 ******************************************************************************************************************************/

  { 
    int used_bits;
    int qc_bits;
    int i_ch;
    int padding_limit = max_bitreservoir_bits;    /* f( max__bitreservoir_bits ) */

    used_bits = 0;

   /* a 7 bit alternative to the strange MPEG-1 audio syncword */
    if( (transport_stream != AAC_RAWDATA_TSTREAM) &&
        (transport_stream != NO_TSTREAM) &&
        (transport_stream != NO_SYNCWORD) ) {
      BsPutBit( fixed_stream, 0x6e, 7 ); 
      used_bits += 7;
    }
   

    /* bit budget */
    num_bits_available = (long)(average_bits + available_bitreservoir_bits - used_bits);

    /* QC selection is currently assumed to be mutually exclusive. */
    switch( qc_select ) {
     
    case AAC_QC:
    case AAC_BSAC: /* YB : 971106 */
      {
        qc_bits = tf_encode_spectrum_aac( spectral_line_vector,
                                          p_energy,
                                          allowed_distortion,
                                          block_type,
                                          sfb_width_table,
                                          nr_of_sfb,
                                          average_bits - used_bits,
                                          available_bitreservoir_bits,
                                          padding_limit,
                                          fixed_stream, /*tmp_stream,*/
                                          var_stream,
                                          gcBitBuf,
                                          max_ch,                        /* nr of audio channels */
                                          reconstructed_spectrum,
                                          useShortWindows,
                                          WS_FHG,
                                          aacAllowScalefacs,
                                          fSampleLong,
                                          qc_select,
                                          pred_type,
                                          nok_lt_status,
                                          nok_bwp_status,
                                          block_size_samples,
                                          num_window_groups,
                                          window_group_length,
                                          tnsInfo,
                                          15000 /* bandwidth in Hz */
                                          );
      

        /* fill in the overall length information 
           if( (transport_stream != AAC_RAWDATA_TSTREAM) && (transport_stream != NO_TSTREAM) ) {
           BsPutBit( fixed_stream, qc_bits+used_bits, 12 );
           }   
        */
     
        used_bits += qc_bits;
        /* add tmp_stream 
           BsPutBuffer ( fixed_stream, tmp_stream->buffer[0] ); */
        /* BsPutBuffer ( fixed_stream, tmpBitBuf ); */
     

        {
          int len, i,j;
          len = BsCurrentBit( fixed_stream );
          /* for( i=0; i<(8-(len%8)); i++ ) {  OLD WAY */
	   
          j = (8 - (len%8))%8;

          if (debugLevel > 2 ) {
            fprintf(stderr,"\nHave to write  %d bits for bytealignment %d (test len=%d) bits", j, qc_bits, len);
          }
          if ((len % 8) == 0) j = 0;
          for( i=0; i<j; i++ ) {
            BsPutBit( fixed_stream, 1, 1 ); 
          }
        }
      }
      break;
    case  AAC_SCALEABLE:
         qc_bits = aacScaleableEncode(  spectral_line_vector,
                                       p_energy,
                                       allowed_distortion,
                                       block_type,
                                       sfb_width_table,
                                       nr_of_sfb,
                                       average_bits - used_bits,
                                       available_bitreservoir_bits,
                                       padding_limit,
                                       fixed_stream, /*tmp_stream,*/
                                       var_stream,
                                       1,                        /* nr of audio channels */
                                       reconstructed_spectrum,
                                       useShortWindows,
                                       WS_FHG,
                                       aacAllowScalefacs,
                                       block_size_samples, 
                                       frameMaxNumBit,
                                       coreTimeSigBuf,
                                       bitRateLong,
                                       fSampleLong,
                                       qc_select,
                                       tnsInfo,
                                       frameData,
                                       coreCodecIdx

                                       );

         used_bits += qc_bits;
         break;
    case AAC_SYS:
    case AAC_SYS_BSAC:
      qc_bits = aacScaleableFlexMuxEncode(  spectral_line_vector,
                                            p_energy,
                                            allowed_distortion,
                                            block_type,
                                            sfb_width_table,
                                            nr_of_sfb,
                                            average_bits - used_bits,
                                            available_bitreservoir_bits,
                                            padding_limit,
                                            fixed_stream, /*tmp_stream,*/
                                            var_stream,
                                            1,                        /* nr of audio channels */
                                            reconstructed_spectrum,
                                            useShortWindows,
                                            WS_FHG,
                                            aacAllowScalefacs,
                                            block_size_samples, 
                                            frameMaxNumBit,
                                            coreTimeSigBuf,
                                            bitRateLong,
                                            fSampleLong,
                                            qc_select,
                                            tnsInfo,                                            
                                            frameData,
                                            coreCodecIdx ,
                                            num_window_groups,
                                            window_group_length,
                                            &param_ntt
                                       );
    
        used_bits += qc_bits;    
        break;

        /* VQ: NTT VQ coder.  The quantizer can work with variable bits, 
           but bit budget control is missing. */
      case NTT_VQ:
        {
          int     ismp, iscl;
          int     ntt_available_bits;
          double  *ntt_external_pw[MAX_TIME_CHANNELS];
          double  lpc_spectrum[ntt_T_FR_MAX];

          /* put the block type */
          BsPutBit(fixed_stream, block_type[MONO_CHAN], 4);
          used_bits += 4;

          /* if ntt_varbit is on, put the available bits */
          if (ntt_varbit == NTT_VARBIT_ON){
            BsPutBit(fixed_stream, ntt_available_bits, 12);
            used_bits += 12;
          }

          /*--- External perceptual weight
            (Supported for long blocks only so far.) ---*/
          if (ntt_pw_select == NTT_PW_EXTERNAL &&
              (block_type[MONO_CHAN] == ONLY_LONG_WINDOW ||
               block_type[MONO_CHAN] == LONG_SHORT_WINDOW ||
               block_type[MONO_CHAN] == SHORT_LONG_WINDOW ||
               block_type[MONO_CHAN] == LONG_MEDIUM_WINDOW ||
               block_type[MONO_CHAN] == MEDIUM_LONG_WINDOW))
            {
              int ii, maxfreqnum;
              double freq_scale;

              if (max_ch > 1)
                CommonExit(1, "EncTfFrame: Error in NTT_VQ ext. PE calc: No stereo support.");
       
              ntt_external_pw[MONO_CHAN] =
                (double *)malloc((size_t)(block_size_samples*sizeof(double)));

              /* calculate maximum frequency number
                 and frequency scaling factor */
              for (ii=0, maxfreqnum=0; ii<chpo_long[MONO_CHAN].no_of_cb; ii++){
                maxfreqnum += chpo_long[MONO_CHAN].cb_width[ii];
              }
              if (maxfreqnum > 0){
                freq_scale = (double)block_size_samples / (double)maxfreqnum;
              }
              else{
                CommonExit(1,
                           "EncTfFrame: Error in NTT_VQ external PE calculation");
              }
       
              /* project the cb-scale "p_ratio" to linear scale */
              maxfreqnum = 0;
              for (ii=0, ismp=0; ii<chpo_long[MONO_CHAN].no_of_cb; ii++){
                maxfreqnum += 
                  (int)((double)chpo_long[MONO_CHAN].cb_width[ii]*freq_scale+0.5);
                for (; ismp<maxfreqnum; ismp++){
                  ntt_external_pw[MONO_CHAN][ismp] =
                    chpo_long[MONO_CHAN].p_ratio[ii];
                }
              }
            }

          /* Calculate available bits */
          ntt_available_bits =
            average_bits + available_bitreservoir_bits
            - used_bits - ntt_TBITS_FR_SCL - nokia_LPTOOL_BITS;
          /* Encoding */
          ntt_vq_coder(DTimeSigBuf,
                       DTimeSigLookAheadBuf,
                       spectral_line_vector,
                       ntt_external_pw[MONO_CHAN],
                       ntt_pw_select,
                       block_type[MONO_CHAN],
                       &ntt_index,
                       &param_ntt,
                       ntt_available_bits,
                       lpc_spectrum,
                       reconstructed_spectrum);
	  /* Pass LTP information */
	  ntt_index.lt_status = &nok_lt_status;
          /* Bit packing */
          used_bits += ntt_BitPack(&ntt_index, fixed_stream);

          /* Scalable encoder */
#if 1
          {
            int iscl;
            for (iscl=0; iscl<ntt_NSclLay; iscl++){
              ntt_scale_vq_coder(spectral_line_vector,
                                 lpc_spectrum,
                                 &ntt_index,
                                 &ntt_index_scl,
                                 &param_ntt,
                                 reconstructed_spectrum, iscl);

              /* Scalable bit packing */
              used_bits += ntt_SclBitPack(&ntt_index_scl, fixed_stream, iscl);
            }
          }
#endif
	 
        }
        break;

     
      case MDCT_VALUES_16BIT:  /* debug option: pack MDCT output values */    
        { 
          double       max, scal;
          int          i, itmp, iscal;
          max = 0.0; /* KEMAL */

          BsPutBit( fixed_stream, block_type[MONO_CHAN], 4 );
          used_bits += 4;

          /* find maximum of spectrum */ 
          for (i=0; i<block_size_samples;i++){
            double dtest = abs(spectral_line_vector[MONO_CHAN][i]);
            max = (max<=dtest)? dtest:max;
          }
          iscal = 0;
          if( max != 0.0 ) {
            while( max > 32767.0 ) {
              max   *= 0.5;
              iscal -= 1;
            }
            while( max < 16383.0 ) {
              max   *= 2.0;
              iscal += 1;
            }
          }
          BsPutBit( fixed_stream, iscal+2048, 12 );
          used_bits += 12;

          scal = pow( 2.0, iscal );
          for( i=0; i<block_size_samples; i++ ) {
            itmp = (int)((scal * spectral_line_vector[MONO_CHAN][i])+.5);
            BsPutBit( fixed_stream, itmp+32768, 16 );
            used_bits += 16;
          }
        }
        break;
     
      default:
        CommonExit(-1,"\ncase not in switch");
        break;

      } /* switch qc_select */


      /* Nokia LTP buffer updates */
      if (pred_type == NOK_LTP)
	switch (qc_select)
	  {
	  case AAC_QC:
	    nok_ltp_enc(reconstructed_spectrum[MONO_CHAN], NULL,
			block_type[MONO_CHAN], WS_FHG,
			block_size_samples, block_size_samples/med_win_in_long,
			block_size_samples/short_win_in_long, nok_sfb_offset,
			nr_of_sfb[MONO_CHAN], &nok_lt_status[MONO_CHAN], 1);
	    break;
	  case NTT_VQ:
	    if (block_type[MONO_CHAN] != ONLY_SHORT_WINDOW)
	      nok_ltp_enc(reconstructed_spectrum[MONO_CHAN], NULL,
			  block_type[MONO_CHAN], WS_FHG,
			  block_size_samples, block_size_samples/med_win_in_long,
			  block_size_samples/short_win_in_long, nok_sfb_offset,
			  ntt_N_CRB, &nok_lt_status[MONO_CHAN], 1);
	    break;
	  default:
	    break;
	  }

      BsClose(fixed_stream);
      if (var_stream != NULL)
        BsClose(var_stream);
      BsClose(tmp_stream);
      BsFreeBuffer(tmpBitBuf);
      { /* added 971010 YT*/
	int i_ch;
	for(i_ch=0;i_ch<max_ch;i_ch++){ 
          BsClose(gc_stream[i_ch]);
          BsFreeBuffer(gcBitBuf[i_ch]);
	} /* for*i_ch...*/
      }


      /* Quantization and coding block */
      /* VQ: preparation for the next frame */
      ntt_InitFlag = 0;
    
  }
}





    
