/* $Id: enc_tf.c,v 1.36 1997/11/20 22:02:02 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>
 *
 *
 * 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
 *
 ******************************************************************************************/

#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 "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"


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 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 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) */

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

int LDFB=0;  /* Low Delay Filter Bank, 0: disabled 1: enabled*/

/********************************************************/
/* 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"
	    "-aac_sca_mode <n> :  mono core + (n=4) mono_aac / (n=5) stereo_aac / (n=7) mono+mono / (n=8) mono+stereo  or (n=6) stereo core+stereo aac\n"
	    "-aac_sca_core <n> :  n=0: g729   n=5: MPEG-4 Celp 6 kbps\n"
	    "-aac_raw   caution: works only with framework switch -vr !\n"
	    "-aac_pns <start_band_for_perceptual_noise_subst>\n"
            "-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"
            "-ldfb : enable low delay filter bank, dflt.: MDCT"
	    "\n");
  }
  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 */
                )
{
  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) */

  debugLevel=  quantDebugLevel;


  header_stream = BsOpenBufferWrite(bitHeader);

  if( strstr( encPara, "-ldfb" ) ) {
    printf("Low Delay Filter Bank enabled\n");
    LDFB = 1;
  }

  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;
  }
  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( 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_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((p_ctmp = strstr( encPara, "-pred ")))
    {
      if(strstr( encPara, "ltp"))
        pred_type = NOK_LTP;
      else
        if(strstr( encPara, "nok_bwp"))
          pred_type = NOK_BWP;
        else
          CommonExit( 1, "\nunsupported prediction : %s", p_ctmp);
    }

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


      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;


      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);
    }
  }

  BsClose(header_stream);

  /* 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:
     {
      int tmp;

      tf_init_encode_spectrum_aac( qc_select, quantDebugLevel); 	/* YB : 971106 */
      tmp = aacScaleEncInit( bitHeader, encPara, numChannel, block_size_samples, sampling_rate );
      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;
    }
  }
  
  /* 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 ();
}


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

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
		 )
{
  /* 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];
  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;
  ntt_PARAM  param_ntt;
  
  /*-----------------------------------------------------------------------*/
  
  /* 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];
  
  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() */

#if 1
  { /* 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...*/
  }
#endif

  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 :
#if 0
      /* block_type[MONO_CHAN] = fft_pe_window_switching( DTimeSigLookAheadBuf[MONO_CHAN, ); */
      CommonExit( 1, "Encode: fft-pe window switching not yet implemented" );
#else
      /* 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;
        /* 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;
      }
#endif
      break;

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

    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)
                   );
          }
          /* gain detector */
          son_gc_detect(DBandSigBufForGCAnalysis[i_ch], block_size_samples,
                        block_type[MONO_CHAN],
                        MONO_CHAN, 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)
                   );
          }
          /* packing gain data into the gc_stream */
          /*  used_bits += */
          son_gc_pack(gc_stream[i_ch], block_type[MONO_CHAN],
                      max_band[i_ch], gainInfo[i_ch]);
          /*  BsPutBuffer ( fixed_stream, gcBitBuf ); */
        } /* for i_ch...*/
      }
   
    /* used_bits += missing if preprocessing adds something to the fixed stream (e.g. gain values (Sony) ) */
  }


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

  {
    EncTf_psycho_acoustic( 48000, 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 i, band;
	double tmp;
	/* 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;
      }
    }
  

  /******************************************************************************************************************************
  *
  * prediction
  *
  ******************************************************************************************************************************/
  {
    int i, k;
    
    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,
		    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);
  }
  
  
  /******************************************************************************************************************************
                                                                                                                                *
                                                                                                                                * 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 */
      {
        int num_window_groups;
        int window_group_length[8];

        if (block_type[MONO_CHAN] == ONLY_SHORT_WINDOW) {
          num_window_groups=4;
          window_group_length[0] = 1;
          window_group_length[1] = 2;
          window_group_length[2] = 3;
          window_group_length[3] = 2;
        } else {
          num_window_groups = 1;
          window_group_length[0] = 1;
        }

        qc_bits = tf_encode_spectrum_aac( spectral_line_vector,
                                          p_ratio,
                                          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
                                          );
      

        /* 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_ratio,
                                       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
                                       );
        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;
          /* 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);
          /* Bit packing */
          used_bits += ntt_BitPack(&ntt_index, fixed_stream, ntt_InitFlag);

          /* 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,
                                 ntt_available_bits,
                                 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)
        nok_ltp_enc(reconstructed_spectrum[MONO_CHAN], NULL,
                    block_type[MONO_CHAN], WS_FHG,
                    nok_sfb_offset, nr_of_sfb[MONO_CHAN], &nok_lt_status[MONO_CHAN], 1);

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





    
