/*****************************************************************************/
/* This software module was originally developed by                          */
/*   Naoki Iwakami (NTT)                                                     */
/* and edited by                                                             */
/*   Naoki Iwakami (NTT) on 1997-04-18,                                      */
/*   Akio Jin (NTT) on 1997-10-23,                                           */
/* 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.                                                        */
/*****************************************************************************/


/* 25-aug-1997  NI  added bandwidth control */
/* 01-oct-1997  HP  "iscount++" bug fix in line 627 & 631 */
/*                  (as reported by T. Moriya, NTT) */
/* 14-oct-1997  TM  mods by Takehiro Moriya (NTT) */


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

#include "ntt_conf.h"
#include "ntt_encode.h"
#include "ntt_tools.h"
#include  "ntt_relsp.h"

void ntt_tf_proc_spectrum(/* Input */
			  double sig[],            /* input signal */
                          /* In/Out */
			  double spectrum[],       /* spectrum */
			  ntt_INDEX  *index,       /* code indices*/
			  /* Output */
			  double lpc_spectrum[],   /* LPC spectrum */
			  double bark_env[],       /* Bark-scale envelope*/
			  double pitch_sequence[],/*periodic peak components*/
			  double gain[],          /* gain factor */
			  /* Input */
			  ntt_PARAM param_ntt)    /* encoding parameters */
{
  double tc[ntt_T_FR_MAX], pwt[ntt_T_FR_MAX];
  int    current_block, i_ch, i_ma, top;
  static int InitFlag = 1;
  
  /*--- Parameters ---*/
  double band_lower, band_upper;
  int    nfr, nsf, n_ch;
  int    n_crb, *bark_tbl;
  int    fw_ndiv, fw_length, fw_len_max, fw_cb_size;
  double fw_prcpt;
  double *fw_codev;
  double *fw_env_memory, *fw_pdot;
  int    n_pr;
  int    ifr, isf, subtop, ismp, block_size;
  double *lsp_code;
  double *lsp_fgcode;
  int    *lsp_csize, *lsp_cdim;
  int    flag_blim_l;
  /*--- Memories ---*/
  /* Bark-scale envelope */
  static double fw_pdot_long[ntt_T_FR_MAX];
  static double fw_pdot_medium[ntt_T_FR_M_MAX];
  static double fw_pdot_short[ntt_T_FR_S_MAX];
  static double fw_env_memory_long[ntt_N_CRB_MAX*ntt_N_SUP_MAX];
  static double fw_env_memory_medium[ntt_N_CRB_M_MAX*ntt_N_SUP_MAX];
  static double fw_env_memory_short[ntt_N_CRB_S_MAX*ntt_N_SUP_MAX];
  static int    p_w_type;
  /* LPC spectrum */
  static double prev_buf[ntt_N_SUP_MAX][ntt_MA_NP][ntt_N_PR_MAX+1];
  static int ma_np;

  /*--- Set parameters ---*/
  switch(index->w_type){
  case ONLY_LONG_WINDOW: case LONG_SHORT_WINDOW: case SHORT_LONG_WINDOW:
  case LONG_MEDIUM_WINDOW: case MEDIUM_LONG_WINDOW:
    /* subframe */
    nfr = ntt_N_FR;
    nsf = 1;
    n_ch = ntt_N_SUP;
    /* Bark-scale table (Bark-scale envelope) */
    n_crb    = ntt_N_CRB;
    bark_tbl = ntt_crb_tbl;
    /* quantization (Bark-scale envelope) */
    fw_ndiv = ntt_FW_N_DIV;
    fw_cb_size = ntt_FW_CB_SIZE;
    fw_length = ntt_FW_CB_LEN;
    fw_codev = (double *)ntt_fwcodev;
    fw_len_max = ntt_FW_CB_LEN;
    fw_prcpt = 0.4;
    fw_env_memory = fw_env_memory_long;
    /* envelope calculation (Bark-scale envelope) */
    fw_pdot = fw_pdot_long;
    current_block = ntt_BLOCK_LONG;
    /* bandwidth control */
    flag_blim_l = 0;
    break;
  case ONLY_MEDIUM_WINDOW: case MEDIUM_SHORT_WINDOW: case SHORT_MEDIUM_WINDOW:
    /* subframe */
    nfr = ntt_N_FR_M;
    nsf = ntt_N_MID;
    n_ch = ntt_N_SUP;
    /* Bark-scale table (Bark-scale envelope) */
    n_crb    = ntt_N_CRB_M;
    bark_tbl = ntt_crb_tbl_m;
    /* quantization (Bark-scale envelope) */
    fw_ndiv = ntt_FW_N_DIV_M;
    fw_cb_size = ntt_FW_CB_SIZE_M;
    fw_length = ntt_FW_CB_LEN_M;
    fw_codev = (double *)ntt_fwcodevm;
    fw_len_max = ntt_FW_CB_LEN_M;
    fw_prcpt = 0.5;
    fw_env_memory = fw_env_memory_medium;
    /* envelope calculation (Bark-scale envelope) */
    fw_pdot = fw_pdot_medium;
    current_block = ntt_BLOCK_MEDIUM;
    /* bandwidth control */
    flag_blim_l = 1;
    break;
  case ONLY_SHORT_WINDOW:
    /* subframe */
    nfr = ntt_N_FR_S;
    nsf = ntt_N_SHRT;
    n_ch = ntt_N_SUP;
    /* Bark-scale table (Bark-scale envelope) */
    n_crb    = ntt_N_CRB_S;
    bark_tbl = ntt_crb_tbl_s;
    /* quantization (Bark-scale envelope) */
    fw_ndiv = ntt_FW_N_DIV_S;
    fw_cb_size = ntt_FW_CB_SIZE_S;
    fw_length = ntt_FW_CB_LEN_S;
    fw_codev = (double *)ntt_fwcodevs;
    fw_len_max = ntt_FW_CB_LEN_S;
    fw_prcpt = 0.5;
    fw_env_memory = fw_env_memory_short;
    /* envelope calculation (Bark-scale envelope) */
    fw_pdot = fw_pdot_short;
    current_block = ntt_BLOCK_SHORT;
    /* bandwidth control */
    flag_blim_l = 1;
    break;
  }
  /* LPC spectrum */
  n_pr = ntt_N_PR;
  lsp_code   = (double *)lsp_code_base;
  lsp_fgcode = (double *)lsp_fgcode_base;
  lsp_csize      = ntt_lsp_csize_base;
  lsp_cdim       = ntt_lsp_cdim_base;

  /*--- Initialize ---*/
  if (InitFlag){
    /* Bark-scale envelope */
    ntt_setd(ntt_N_FR  *ntt_N_SUP, 0.1, fw_pdot_long);
    ntt_setd(ntt_N_FR_M*ntt_N_SUP, 0.1, fw_pdot_medium);
    ntt_setd(ntt_N_FR_S*ntt_N_SUP, 0.1, fw_pdot_short);

    ntt_zerod(ntt_N_CRB  *ntt_N_SUP, fw_env_memory_long);
    ntt_zerod(ntt_N_CRB_M*ntt_N_SUP, fw_env_memory_medium);
    ntt_zerod(ntt_N_CRB_S*ntt_N_SUP, fw_env_memory_short);

    p_w_type = ntt_BLOCK_LONG;

    /* LPC spectrum */
    for ( i_ch=0; i_ch<n_ch; i_ch++ ){
      for ( i_ma=0; i_ma<ntt_MA_NP; i_ma++ ){
	ntt_zerod( n_pr+1, prev_buf[i_ch][i_ma] );
      }
    }
    ma_np = 0;
  }
  InitFlag=0;

  
  /*--- Encoding tools ---*/
  /* LPC spectrum encoding */
  
  /** old version 
  ntt_enc_lpc_spectrum(nfr, nsf, n_ch, n_pr, lsp_code, lsp_fgcode,
		       lsp_csize, lsp_cdim, prev_buf, ma_np,
		       sig, index->w_type, current_block,
		       index->lsp, lpc_spectrum);
  *** end old version **/
  /** new version moriya informed **/
  if(ntt_ISAMPF==48 && ntt_IBPS < 24){ /* Takehiro Moriya */
       ntt_scalebase_enc_lpc_spectrum(
                           nfr, nsf, n_ch, n_pr, lsp_code, lsp_fgcode,
                            lsp_csize, lsp_cdim, prev_buf, ma_np,
                            spectrum, index->w_type, current_block,
                            index->lsp, lpc_spectrum,
                            ntt_BAND_LOWER, ntt_BAND_UPPER);
  }
  else{
       ntt_enc_lpc_spectrum(nfr, nsf, n_ch, n_pr, lsp_code, lsp_fgcode,
                            lsp_csize, lsp_cdim, prev_buf, ma_np,
                            sig, index->w_type, current_block,
                            index->lsp, lpc_spectrum);
  }
  /** end new version **/
		       

  /* bandwidth control */
  for (i_ch=0; i_ch<n_ch; i_ch++){
    top = i_ch * nsf * nfr;
    if (ntt_BLIM_BITS_H > 0){
      index->blim_h[i_ch] = ntt_BLIM_STEP_H/2;
      band_upper = 
	ntt_BAND_UPPER * 
	  (1. - (1.-ntt_CUT_M_H) *
	   (double)index->blim_h[i_ch]/(double)ntt_BLIM_STEP_H);
    }
    else{
      index->blim_h[i_ch] = 0;
      band_upper = ntt_BAND_UPPER;
    }
    if ((ntt_BLIM_BITS_L > 0) && (flag_blim_l == 1)) index->blim_l[i_ch] = 1;
    else                                             index->blim_l[i_ch] = 0;
    band_lower = ntt_BAND_LOWER + ntt_CUT_M_L * index->blim_l[i_ch];
    ntt_freq_domain_pre_process(nfr, nsf, band_lower, band_upper,
				spectrum+top, lpc_spectrum+top, param_ntt, 
				spectrum+top, lpc_spectrum+top);
  }
  /* periodic peak components encoding */
  if(ntt_TBIT_P > 0){
    ntt_enc_pitch(spectrum, lpc_spectrum, index->w_type,
		  index->pit, index->pls, index->pgain, pitch_sequence);
  }
  else{
    ntt_zerod(ntt_N_FR*ntt_N_SUP, pitch_sequence);
  }
  /* Bark-scale envelope encoding */
/*
  ntt_enc_bark_env(nfr, nsf, n_ch, n_crb, bark_tbl,
		   fw_ndiv, fw_cb_size, fw_length,
		   fw_codev, fw_len_max, fw_prcpt,
		   fw_env_memory, fw_pdot, &p_w_type,
		   spectrum, lpc_spectrum, pitch_sequence, current_block,
		   tc, pwt, index->fw, index->fw_alf, bark_env);
*/
  if(fw_cb_size==1){
    for(ifr=0; ifr<nfr*nsf*n_ch; ifr++){
       bark_env[ifr]=1.0;
   }
   for (i_ch=0; i_ch<n_ch; i_ch++){
    top = i_ch * block_size;
    for(isf=0; isf<nsf; isf++){
      subtop = top + isf*nfr;
      /* make input data */
      for (ismp=0; ismp<nfr; ismp++){
       tc[ismp+subtop] =
         spectrum[ismp+subtop] * lpc_spectrum[ismp+subtop]
           - pitch_sequence[ismp+subtop];
   }
  }
}
}
  else{
    ntt_enc_bark_env(nfr, nsf, n_ch, n_crb, bark_tbl,
                   fw_ndiv, fw_cb_size, fw_length,
                   fw_codev, fw_len_max, fw_prcpt,
                   fw_env_memory, fw_pdot, &p_w_type,
                   spectrum, lpc_spectrum, pitch_sequence, current_block,
                   tc, pwt, index->fw, index->fw_alf, bark_env);
}
  /* gain encoding */
  ntt_enc_gain_t(nfr, nsf, n_ch, bark_env, tc, index->pow, gain);

  /*--- Memory operation ---*/
  ma_np ++;
  if(ma_np > ntt_MA_NP) ma_np = ntt_MA_NP;
}


void ntt_enc_bark_env(/* Parameters */
		      int    nfr,               /* block length */
		      int    nsf,               /* number of sub frames */
		      int    n_ch,
		      int    n_crb,
		      int    *bark_tbl,
		      int    ndiv,              /* number of interleave division */
		      int    cb_size,           /* codebook size */
		      int    length,
		      double *codev,            /* code book */
		      int    len_max,           /* codevector memory length */
		      double prcpt,
		      double *env_memory,
		      double *pdot,
		      int    *p_w_type,
		      /* Input */
		      double spectrum[],        /* spectrum */
		      double lpc_spectrum[],    /* LPC spectrum */
		      double pitch_sequence[],  /* periodic peak components */
		      int    current_block,     /* block length type */
		      /* Output */
		      double tc[ntt_T_FR_MAX],  /* flattened spectrum */
		      double pwt[ntt_T_FR_MAX], /* perceptual weight */
		      int    index_fw[],        /* indices for Bark-scale enveope coding */
		      int    ind_fw_alf[],
		      double bark_env[])        /* Bark-scale envelope */
{
  /*--- Variables ---*/
  int    ismp, i_ch, top, isf, subtop, pred_sw, block_size;
  
  /*--- Initialization ---*/
  block_size = nfr * nsf;
  if ((*p_w_type != current_block)){
    ntt_zerod(nfr*n_ch, pdot);
  }
  
  /*--- Encoding process ---*/
  for (i_ch=0; i_ch<n_ch; i_ch++){
    top = i_ch * block_size;
    /* make weight */
    for (ismp=0; ismp<block_size; ismp++){
      pwt[ismp+top] = 1. / pow(lpc_spectrum[ismp+top], 0.5);
    }

    
    /* set MA prediction switch */
    if (*p_w_type == current_block) pred_sw = 1;
    else                           pred_sw = 0;
    
    for(isf=0; isf<nsf; isf++){
      subtop = top + isf*nfr;
      /* make input data */
      for (ismp=0; ismp<nfr; ismp++){
	tc[ismp+subtop] =
	  spectrum[ismp+subtop] * lpc_spectrum[ismp+subtop]
	    - pitch_sequence[ismp+subtop];
      }
      /* envelope coding */
      ntt_fwpred(nfr, n_crb, bark_tbl, ndiv,
		 cb_size, length, codev, len_max, prcpt,
		 env_memory, pdot,
		 pwt+subtop, bark_env+subtop, tc+subtop,
		 &index_fw[(i_ch*nsf+isf)*ndiv],
		 &ind_fw_alf[isf+i_ch*nsf], i_ch, pred_sw);
      
      pred_sw = 1;
    }
  }
  
  *p_w_type = current_block;
  
  
}

void ntt_enc_gaim(/* Input */
		  double power,      /* Power to be encoded */
		  /* Output */
		  int    *index_pow, /* Power code index */
		  double *gain,      /* Gain */
		  double *norm)      /* Power normalize factor */
{
  double mu_power, dmu_power, dec_power;
  
  /* encoding */
  mu_power = ntt_mulaw(power, ntt_SUB_AMP_MAX, ntt_MU);  /* mu-Law power */
  *index_pow = (int)((mu_power)/ ntt_SUB_STEP); /* quantization */

  /* local decoding */
  dmu_power = *index_pow * ntt_SUB_STEP +ntt_SUB_STEP/2.;
  dec_power = ntt_mulawinv(dmu_power, ntt_SUB_AMP_MAX, ntt_MU);
  *gain= dec_power/ ntt_SUB_AMP_NM;                       /* calculate gain */
  *norm = ntt_SUB_AMP_NM/(dec_power+0.1);                 /* calculate norm. */
}

void ntt_enc_gain(/* Input */
		  double power,      /* Power to be encoded */
		  /* Output */
		  int    *index_pow, /* Power code index */
		  double *gain,      /* Gain */
		  double *norm)      /* Power normalize factor */
{
    /*--- Variables --*/
    double mu_power, dmu_power, dec_power;

    mu_power = ntt_mulaw(power, ntt_AMP_MAX, ntt_MU);           /* mu-Law power */

    *index_pow = (int)((mu_power)/ ntt_STEP);  /* quantization */

    dmu_power = *index_pow * ntt_STEP + ntt_STEP/2.;        /* decoded mu-Law power */
    dec_power = ntt_mulawinv(dmu_power, ntt_AMP_MAX, ntt_MU);   /* decoded power */

    *gain= dec_power * ntt_I_AMP_NM;                    /* calculate gain */
    *norm = ntt_AMP_NM/(dec_power+0.1);                 /* calculate norm. */
}

void ntt_enc_gain_t(/* Parameters */
		    int    nfr,          /* block length */
		    int    nsf,          /* number of sub frames */
		    int    n_ch,
		    /* Input */
		    double bark_env[],   /* Bark-scale envelope */
                    /* In/Out */
		    double tc[],         /* flattened spectrum */
		    /* Output */ 
		    int    index_pow[],  /* gain code indices */
		    double gain[])       /* gain factor */
{
  int    ismp, top, subtop, isf, iptop, gtop, i_ch, block_size;
  double norm, pwr;
  double sub_pwr_tmp, sub_pwr[ntt_N_SHRT_MAX];
  double g_gain, g_norm;

  block_size = nfr * nsf;
  
  /*--- Encoding process ---*/
  for (i_ch=0; i_ch<n_ch; i_ch++){
    top = i_ch * block_size;
    /*--- Gain calculation ---*/
    pwr = 0.1;
    for(isf=0; isf<nsf; isf++){
      subtop = top + isf*nfr;
      for ( ismp=0; ismp<nfr; ismp++ ){
	tc[ismp+subtop] /= bark_env[ismp+subtop];
      }
      sub_pwr_tmp
	=(ntt_dotdd(nfr, tc+subtop, tc+subtop)+0.1)/(double)nfr;
      pwr += sub_pwr_tmp;
      sub_pwr[isf] =sqrt( sub_pwr_tmp );
    }
    pwr = sqrt(pwr/(double)nsf);

    /*--- Quantization ---*/
    if (isf == 1){
      /* global gain */
      ntt_enc_gain(pwr,&index_pow[i_ch],&gain[i_ch],&g_norm);
    }
    else{
      /* global gain */
      iptop = (nsf+1)*i_ch;
      gtop  = nsf*i_ch;
      ntt_enc_gain(pwr,&index_pow[iptop],&g_gain,&g_norm);
      gain[gtop] = g_gain;

      /* subband gain */
      for(isf=0; isf<nsf; isf++){
	subtop = top + isf*nfr;
	ntt_enc_gaim(sub_pwr[isf]*g_norm, &index_pow[iptop+isf+1],
		     &gain[gtop+isf], &norm);
	gain[gtop+isf] *= g_gain;
	norm *= g_norm;
      }
    }
  }
}

void ntt_enc_gair_p(int  *index_pgain, /* Output: Power code index */
	      double powG,        /* Input : power of the weighted target */
	      double gain2,       /* Input : squared gain of the target */
	      double *g_opt,      /* In/Out: optimum gain */                
	      double nume,/*Input: cross power or the orig. and quant. resid.*/
	      double denom)       /* Input : power of the orig. regid */
{
    double norm;
    double acc2_2, g_opt_2, acc2;
    int index_tmp;
    
    /*--- gain re-quantization ---*/
    ntt_enc_pgain(*g_opt, &index_tmp, g_opt, &norm);
    *index_pgain = index_tmp;    
    acc2= powG*gain2 -2.* *g_opt*nume + *g_opt* *g_opt*denom;
    if(index_tmp != 0){
	g_opt_2= ntt_mulawinv((index_tmp-1)*ntt_PGAIN_STEP+ntt_PGAIN_STEP/2., ntt_PGAIN_MAX, ntt_PGAIN_MU);
	acc2_2= powG*gain2 -2.*g_opt_2*nume+g_opt_2*g_opt_2*denom;
	if(acc2_2 < acc2){
	    acc2= acc2_2;
	    *index_pgain = ntt_max(index_tmp -1, 0);
	    *g_opt= g_opt_2;
	    return; 
	}
    }
}

void ntt_enc_lpc_spectrum
  (/* Parameters */
   int    nfr,           /* block length */
   int    nsf,           /* number of sub frames */
   int    n_ch,
   int    n_pr,
   double *lsp_code,
   double *lsp_fgcode,
   int    *lsp_csize,
   int    *lsp_cdim,
   double prev_buf[ntt_N_SUP_MAX][ntt_MA_NP][ntt_N_PR_MAX+1],
   int    ma_np,
   /* Input */
   double sig[],         /* input signal */
   int    w_type,        /* block type */
   int    current_block, /* block length type */
   /* Output */
   int    index_lsp[ntt_N_SUP_MAX][ntt_LSP_NIDX_MAX], /* code indices for LSP quantization */
   double lpc_spectrum[]) /* LPC spectrum */
{
  /*--- Variables ---*/
  double resid, alf[ntt_N_SUP_MAX][ntt_N_PR_MAX+1], 
 lsp[ntt_N_PR_MAX+1], lspq[ntt_N_SUP_MAX*(ntt_N_PR_MAX+1)];
  double yylpc[ntt_T_WDW_MAX];
  int    i_sup, top, subtop, w_type_t, isf, lsptop;
  int    block_size;

  block_size = nfr * nsf;

  /*--- encode LSP coefficients ---*/
  if (current_block == ntt_BLOCK_LONG) w_type_t = w_type;
  else                                 w_type_t = ONLY_LONG_WINDOW;
  for ( i_sup=0; i_sup<n_ch; i_sup++ ){
    lsptop = i_sup * n_pr;
    top    = i_sup*block_size;
    /* calculate LSP coefficients */
    ntt_mdctwd(sig-block_size*n_ch+top, sig+top, yylpc+top*2, w_type_t);
    ntt_getalf(yylpc+top*2,alf[i_sup],&resid);
    ntt_alflsp(n_pr, alf[i_sup], lsp);
    /* quantize LSP coefficients */
    ntt_lsp_encw(n_pr, (double (*)[ntt_N_PR_MAX])lsp_code,
                 (double (*)[ntt_MA_NP][ntt_N_PR_MAX])lsp_fgcode,
                 lsp_csize, lsp_cdim, prev_buf[i_sup], ma_np,
                 i_sup, lsp, lspq+i_sup*n_pr, index_lsp[i_sup], ntt_LSP_SPLIT);
  }

  /*--- reconstruct LPC spectrum ---*/
  for (i_sup=0; i_sup<n_ch; i_sup++){
    top = i_sup * block_size;
    lsptop = i_sup * n_pr;
    ntt_lsptowt(nfr, n_pr, lspq+lsptop, lpc_spectrum+top);
    for (isf=1; isf<nsf; isf++){
      subtop = top + isf*nfr;
      ntt_movdd(nfr, lpc_spectrum+top, lpc_spectrum+subtop); 
    }
  }
}

void ntt_enc_pgain(/* Input */
		   double power,      /* Power to be encoded */
		   /* Output */
		   int    *index, /* Power code index */
		   double *pgain,
		   double *norm)      /* Gain */
{
    /*--- Variables --*/
    double mu_power;
    int itmp;

    mu_power = ntt_mulaw(power, ntt_PGAIN_MAX, ntt_PGAIN_MU);           /* mu-Law power */
    itmp = (int)((mu_power)/ ntt_PGAIN_STEP);  /* quantization */
    *index = itmp;  /* quantization */
    
    ntt_dec_pgain( *index, pgain);
    *norm = 1./(*pgain+1.e-3);

}


void ntt_enc_pitch(/* Input */
	       double spectrum[],         /* spectrum */
	       double lpc_spectrum[],     /* LPC spectrum */
	       int    w_type,             /* block type */
	       /* Output */
	       int    index_pit[],        /* indices for periodic peak components coding */
	       int    index_pls[],        
	       int    index_pgain[],
	       double pitch_sequence[])   /* periodic peak components */


{
    /*--- Variables ---*/
    double tc[ntt_T_FR_MAX], pwt[ntt_T_FR_MAX];
    double pit_seq[ntt_T_FR_MAX];
    double pit_pack[ntt_N_FR_P_MAX*ntt_N_SUP_MAX];
    double tc_pack[ntt_N_FR_P_MAX*ntt_N_SUP_MAX];
    double wtbuf[ntt_T_FR_MAX];
    double pwtbuf[ntt_T_FR_MAX];
    double norm[ntt_N_SUP_MAX], dtmp, dpow; 
    int    ismp, i_sup, top, ptop;
    double pgain[ntt_N_SUP_MAX];
    double pgainq[ntt_N_SUP_MAX];

    switch(w_type){
    case ONLY_LONG_WINDOW:
    case LONG_SHORT_WINDOW:
    case SHORT_LONG_WINDOW:
    case LONG_MEDIUM_WINDOW:
    case MEDIUM_LONG_WINDOW:
	/* LPC flattening */
	for (i_sup=0; i_sup<ntt_N_SUP; i_sup++){
	    top = i_sup * ntt_N_FR;
	    for (ismp=0; ismp<ntt_N_FR; ismp++){
		tc[ismp+top] = spectrum[ismp+top] * lpc_spectrum[ismp+top];
	    }
	}
	/* pitch components extraction */
	for (i_sup=0; i_sup<ntt_N_SUP; i_sup++){
	    top = i_sup * ntt_N_FR;
	    ptop = i_sup * ntt_N_FR_P;
            ntt_sear_pitch(tc+top, lpc_spectrum+top,
		       &index_pit[i_sup]);
            ntt_extract_pitch(index_pit[i_sup], tc+top, tc_pack+ptop);
            ntt_extract_pitch(index_pit[i_sup], lpc_spectrum+top, wtbuf+ptop);
	    dtmp = 1.e-3+ntt_dotdd(ntt_N_FR_P, tc_pack+ptop, tc_pack+ptop);
	    dpow = sqrt(dtmp/ntt_N_FR_P);
	    ntt_enc_pgain( dpow, &index_pgain[i_sup], &pgain[i_sup], &norm[i_sup]);
	    ntt_dec_pgain(index_pgain[i_sup], &pgainq[i_sup]);
	    for (ismp=0; ismp<ntt_N_FR; ismp++){
		pwt[ismp+top] = 1. / pow(lpc_spectrum[ismp+top], 0.5);
            }
	    ntt_extract_pitch(index_pit[i_sup], pwt+top, pwtbuf+ptop);
            ntt_extract_pitch(index_pit[i_sup], spectrum+top, pit_pack+ptop);
	    dtmp = 1./(pgainq[i_sup]+1.e-5);
	    for (ismp=0; ismp<ntt_N_FR_P; ismp++){
	      pit_pack[ptop+ismp] *= dtmp;
	    }
	}

	/*--- Quantization of the pitch value ---*/
	ntt_wvq_pitch(pit_pack, wtbuf, pwtbuf, pgain,
		  index_pls, pgainq, index_pgain);
	/*--- Making the pitch sequence ---*/
	ntt_dec_pit_seq(index_pit, index_pls, pit_seq);
	for (i_sup=0; i_sup<ntt_N_SUP; i_sup++){
	    top = i_sup * ntt_N_FR;
	    for(ismp=0; ismp<ntt_N_FR; ismp++){
		pitch_sequence[ismp+top] = pgainq[i_sup] * pit_seq[ismp+top];
	    }
	}
	break;
    case ONLY_MEDIUM_WINDOW:
    case MEDIUM_SHORT_WINDOW:
    case SHORT_MEDIUM_WINDOW:
	ntt_zerod(ntt_N_FR*ntt_N_SUP, pitch_sequence);
	break;
    case ONLY_SHORT_WINDOW:
	ntt_zerod(ntt_N_FR*ntt_N_SUP, pitch_sequence);
	break;
    }


}

void     ntt_extract_pitch(
	      /* Input */
	      int     index_pit, 
	      double  pit_seq[],
	      /* Output */
	      double  pit_pack[]) 
{
    /*--- Variables ---*/
    int	   i_smp;
    static int InitFlag = 1;
    double dtmp, pitch;
    int npcount, iscount, top, ptop;
    int i_sup, ii,jj;
    static double fcmin, fcmax;
    double bandwidth;
    fcmin = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*100))/log(2.);
    fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*600))/log(2.);
    if(ntt_ISAMPF==8) {
    fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*1200))/log(2.);
    }
    if(ntt_ISAMPF==16) {
    fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*1200))/log(2.);
    }
    InitFlag = 0;
    bandwidth=4.0;
    if(ntt_ISAMPF==8) bandwidth=1.5;
    if(ntt_ISAMPF==11) bandwidth=2.;
    if(ntt_ISAMPF==16) bandwidth=2.;
    if(ntt_ISAMPF==22) bandwidth=4.;
    if(ntt_ISAMPF>=44) bandwidth=8.;
	
        dtmp = (double)index_pit / (double) ntt_BASF_STEP;
	dtmp = dtmp * (fcmax-fcmin) + fcmin;
	pitch = pow(2., dtmp);
	npcount = (int)(ntt_N_FR_P*bandwidth/(ntt_N_FR/pitch));
        iscount=0;

        for (jj=0; jj<ntt_N_FR_P; jj++){
              pit_pack[jj] = 0.0;
        }

        for (jj=0; jj<npcount/2; jj++){
              pit_pack[iscount++] = pit_seq[jj];
        }

        for (ii=0; (ii<ntt_N_FR_P) && (iscount<ntt_N_FR_P); ii++){
           i_smp = (int)(pitch*(ii+1)+0.5);
           if(i_smp+(npcount-1)/2+1 < ntt_N_FR) {
             for (jj=-npcount/2; (jj<(npcount-1)/2+1) && (iscount < ntt_N_FR_P);
 jj++, iscount++){
                pit_pack[iscount] = pit_seq[jj+i_smp];
             }
           }
        }

}

void ntt_freq_domain_pre_process(/* Parameters */
				 int    nfr,              /* block length */
				 int    nsf,              /* number of sub frames */
				 double band_lower,
				 double band_upper,
				 /* Input */
				 double spectrum[],       /* spectrum */
				 double lpc_spectrum[],   /* LPC spectrum */
				 ntt_PARAM param_ntt,     /* encoding parameters */
				 /* Output */
				 double spectrum_out[],   /* spectrum */
				 double lpc_spectrum_out[]) /* LPC spectrum */
{
  /*--- Variables ---*/
  int isf, subtop, start, stop, ismp;

  /*--- Band limit ---*/
  start = (int)(nfr * band_lower);
  stop  = (int)(nfr * band_upper);
  for (isf=0; isf<nsf; isf++){
    subtop = isf * nfr;
    /* lower cut */
    for (ismp=0; ismp<start; ismp++){
      spectrum_out[ismp+subtop] = 0.;
      lpc_spectrum_out[ismp+subtop] = 1.e5;
    }
    /* signal band */
    for (ismp=start; ismp<stop; ismp++){
      spectrum_out[ismp+subtop] = spectrum[ismp+subtop];
      lpc_spectrum_out[ismp+subtop] = lpc_spectrum[ismp+subtop];
    }
    /* upper cut */
    for (ismp=stop; ismp<nfr; ismp++){
      spectrum_out[ismp+subtop] = 0.;
      lpc_spectrum_out[ismp+subtop] = 1.e5;
    }
  }
}


void ntt_fw_div(int    ndiv,    /* Param. : number of interleave division */
		int    length,  /* Param. : codebook length */
		double prcpt,   /* Param. : perceptual weight */
		double env[],   /* Input  : envelope vector */
		double denv[],  /* Output : envelope subvector */
		double wt[],    /* Input  : weighting factor vector */
		double dwt[],   /* Output : weighting factor subvector */
		int    idiv)    /* Param. : division number */
{
  int ismp, ismp2;

  for ( ismp=0; ismp<length; ismp++ ){
    ismp2 = idiv + ismp * ndiv;
    denv[ismp] = env[ismp2];
    dwt[ismp] = pow(wt[ismp2], prcpt);
  }
}


void ntt_fw_sear(int    cb_size, /* Param  : codebook size */
		 int    length,  /* Param  : codevector length */
		 double *codev,  /* Param  : codebook */
		 int    len_max, /* Param  : codevector memory length */
		 double denv[],  /* Input  : envelope subvector */
		 double dwt[],   /* Input  : weight subvector */
		 int    *index,  /* Output : quantization index */
		 double *dmin)   /* Output : quant. weighted distortion */
{
  /*--- Variables ---*/
  double dtemp, ldmin;
  int    ismp, icb;
  double dist_buf;
  
  ldmin = 1.e50;
  for (icb=0; icb<cb_size; icb++){
    /*--- Calculate the weighted distortion measure ---*/
    dist_buf = 0.;
    for (ismp=0; ismp<length; ismp++){
      dtemp = denv[ismp] - codev[icb*len_max+ismp];
      dist_buf += dwt[ismp] * dtemp * dtemp;
    }
    
    /*--- Search for the optimum code vector ---*/
    if ( dist_buf < (ldmin) ){
      ldmin = dist_buf;
      *index = icb;
    }
  }
  *dmin = ldmin;
}


void ntt_fwalfenc(double alf,    /* Input  : AR prediction coefficients */
	      double *alfq,  /* Output : quantized AR pred. coefficients */
	      int *ind)      /* Output : the index */
{
    /*--- Variables ---*/
    double expand;
    
    /*--- Main operation ---*/
    expand = alf / (double) ntt_FW_ALF_STEP+0.5;
    *ind = ntt_min( (int)expand, ntt_FW_ARQ_NSTEP-1 );
    *ind = ntt_max(*ind, 0);
    *alfq = (double)*ind*ntt_FW_ALF_STEP;
}

void ntt_fwpred(int    nfr,  /* Param:  block size */
		int    n_crb,       /* Param:  number of Bark-scale band */
		int    *bark_tbl,   /* Param:  Bark-scale table */
		int    ndiv,        /* Param:  number of interleave division */
		int    cb_size,     /* Param:  codebook size */
		int    length,      /* Param:  codevector length */
		double *codev,      /* Param:  codebook */
		int    len_max,     /* Param:  codevector memory length */
		double prcpt,
		double *penv_tmp,   /* Param:  memory for Bark-scale envelope*/
		double *pdot_tmp,   /* Param:  memory for env. calculation */
		double iwt[],       /* Input:  LPC envelope */
		double pred[],      /* Output : Prediction factor */
		double tc[],        /* Input:  Residual signal */
		int    index_fw[],  /* Output: Envelope VQ indices */
		int    *ind_fw_alf, /* Output: AR prediction coefficient index */
		int    i_sup,       /* Input:  Channel number */
		int    pred_sw)     /* Input:  prediction switch */
{
    /*--- Variables ---*/
    double        bwt[ntt_N_CRB_MAX], env[ntt_N_CRB_MAX];
    double        *pdot, fwgain, alf, alfq;
    double        *penv;
    register double acc, cdot, acc2, col0, col1, dtmp;
    int           top, top2, ismp, iblow, ibhigh, ib;

    /*--- Initialization ---*/
    top  = i_sup*nfr;
    top2 = i_sup*n_crb;
    pdot = pdot_tmp + top;
    penv = penv_tmp + top2;

    /*--- Calculate envelope ---*/
    iblow=0; fwgain=0.; ib=0;
    for (ib=0; ib<n_crb; ib++){
	ibhigh = bark_tbl[ib];
	/* reset the accumulations */
	acc  = 0.0;
	acc2 = 0.0;
	/* bandle the input coefficient lines into the bark-scale band */
	for(ismp=iblow; ismp<ibhigh; ismp++){
	    cdot =  tc[ismp]*tc[ismp];/* calc. power */
	    acc += pdot[ismp] + cdot; /* acc. the current and previous power */
	    acc2 = acc2 + iwt[ismp];  /* accumulate the weighting factor */
	    pdot[ismp] = cdot;        /* store the power */
	}
	env[ib] = sqrt(acc/(double)(ibhigh-iblow)) + 0.1; /* envelope in bark*/
	bwt[ib] = acc2; 	/* weighting factor in bark scale */
	fwgain += env[ib];	/* accumulate the envelope power */

	iblow = ibhigh;
    }
    /* gain to normalize the bark-scale envelope */
    fwgain = (double) n_crb / fwgain;

    /*--- Normalize the envelope, and remove the offset ---*/
    for (ib=0; ib<n_crb; ib++){
	env[ib] = env[ib]*fwgain - 1.0;
    }

    /*--- Calculate the AR prediction coefficient and quantize it ---*/
    col0 = 0.1;
    col1 = 0.;
    if (pred_sw == 1){
      /* calculate auto correlation and cross correlation */
      for (ib=0; ib<n_crb; ib++){
	col0 += penv[ib]*penv[ib];
	col1 += penv[ib]*env[ib];
      }
      alf = col1/col0;   /* normalize the cross correlation coefficient */
      ntt_fwalfenc( alf, &alfq, ind_fw_alf ); /* quantize the cor. coefficient */
      /* AR prediction (cancellation using cor. coeff.) */
      for ( ib=0; ib<n_crb; ib++ ){
	env[ib] -= alfq*penv[ib];
      }
    }
    else{ /* in stop frame */
      alf = 0.;
      ntt_fwalfenc( alf, &alfq, ind_fw_alf );
    }
    
    /*--- Quantization of the envelope ---*/
    ntt_fwvq(ndiv, cb_size, length, codev, len_max, prcpt,
	     env, bwt, index_fw);
    /*--- Local decoding ---*/
    ntt_fwex( index_fw, ndiv, length, codev, len_max, env );
    for (ib=ndiv*length; ib<n_crb; ib++) env[ib] = 0.;
    for (ib=0, ismp=0; ib<n_crb; ib++){
	ibhigh = bark_tbl[ib];
	dtmp = ntt_max(env[ib]+alfq*penv[ib]+1., ntt_FW_LLIM);
	while(ismp<ibhigh){
	    pred[ismp] = dtmp;
	    ismp++;
	}
    }
    /*--- Store the current envelope ---*/
    ntt_movdd(n_crb, env, penv);
}


void ntt_fwvq(int    ndiv,     /* Param  : number of interleave division */
	      int    cb_size,  /* Param  : codebook size */
	      int    length,   /* Param  : codevector length */
	      double *codev,   /* Param  : codebook */
	      int    len_max,  /* Param  : codevector memory length */
	      double prcpt,    /* Param  : perceptual control factor */
	      double env[],    /* Input  : the envelope */
	      double wt[],     /* Input  : the weighting factor */
	      int    index[])  /* Output : indexes */
{
    /*--- Variables ---*/
    int    idiv;
    double denv[ntt_FW_CB_LEN_MX], dwt[ntt_FW_CB_LEN_MX], dmin;

    /*--- Initialization ---*/

    /*--- Main operation ---*/
    for ( idiv=0; idiv<ndiv; idiv++ ){
	/*--- Divide the input frame into subframe ---*/
	ntt_fw_div(ndiv, length, prcpt,
		   env, denv, wt, dwt, idiv);
	/*--- search ---*/
	ntt_fw_sear(cb_size, length,
		    codev, len_max,
		    denv, dwt, &index[idiv], &dmin );
    }
}

void ntt_get_wegt(/* Parameters */
		  int n_pr,
                  /* Input */
		  double flsp[],
		  /* Output */
		  double wegt[])
{
    int    i;
    double tmp;
    double llimit, ulimit;
    
    llimit = 0.4/(double)n_pr;
    ulimit = 1.-0.4/(double)n_pr;

    tmp     = ( ( flsp[2]-PI*llimit )-1.0);
    wegt[1] = tmp * tmp * 10.+1.0;
    if (tmp > 0.0 ) wegt[1] = 1.0;

    for ( i=2; i<=n_pr-1; i++ ) {
	tmp     = -flsp[i-1]+flsp[i+1]- 1.0;
        wegt[i] = tmp * tmp * 10.+1.0;
        if(tmp > 0.0 ) wegt[i] = 1.0;
    }
    tmp = -flsp[n_pr-1]+PI*ulimit- 1.0;
    wegt[n_pr] = tmp* tmp * 10.+1.0;
    if (tmp > 0.0 ) wegt[n_pr] = 1.0;
}


#define ntt_GAMMA  0.95

void ntt_getalf(double *in,          /* input : input sound data */
	    double *alf,         /* output: alpha parameter */
	    double *resid)       /* output: power of the residual */
{
    double wlag[ntt_N_PR_MAX + 1];		/* lag window */
    int unstable;
    int    ip;
    double ref[ntt_N_PR_MAX+1];         
    double cep[(ntt_N_PR_MAX+1)*2];        
    double refb[ntt_N_PR_MAX+1];      
    double alfb[ntt_N_PR_MAX+1];     
    double gamma; 			   
    double          
	wvpowfr,
	cor[ntt_N_PR_MAX+1];

    /*--- Initialization ---*/
    /* set the lag window */
    ntt_lagwdw( wlag, ntt_N_PR, ntt_BAND_EXP / ntt_SAMPF );

    /*--- LPC analysis --*/
    ntt_sigcor(in, ntt_N_FR*2, &wvpowfr, cor, ntt_N_PR); cor[0] = 1.;
    ntt_mulddd(ntt_N_PR + 1, cor, wlag, cor);
    ntt_corref(ntt_N_PR, cor, alfb ,refb, resid); alfb[0] = 1.;

    /*--- LPC parameters to cepstrum parameters ---*/
    ntt_alfcep(ntt_N_PR, alfb, cep, (ntt_N_PR)*2);
   
    /*--- Divide cepstrum parameters by 2 (sqrt in the spectrum domain) ---*/
    ntt_mulcdd((ntt_N_PR)*2, 0.5, cep+1, cep+1);

    /*--- Cepstrum parameters to LPC alpha parameters ---*/
    ntt_cep2alf((ntt_N_PR)*2, ntt_N_PR, cep, alf);

    /*--- Stability check ---*/
    alf[0]=1.0;
    do{
       ntt_alfref(ntt_N_PR, alf, ref, resid);
       unstable =0;
       for(ip=1; ip<=ntt_N_PR; ip++){
          if(ref[ip] > 0.999 || ref[ip] < -0.999) unstable =1;
          if(ref[ip] > 0.999 || ref[ip] < -0.999)
	       fprintf(stderr,"%5d %7.4f\n", ip, ref[ip]);
       }
       if(unstable) {
         gamma= ntt_GAMMA;
         for(ip=1; ip<=ntt_N_PR; ip++){
           alf[ip] *= gamma;
           gamma *= ntt_GAMMA;
         }
       }
    }while(unstable);

}


void ntt_lsp_encw(int    n_pr,
                  double code[][ntt_N_PR_MAX],
                  double fgcode[][ntt_MA_NP][ntt_N_PR_MAX],
                  int    *csize,
                  int    *cdim,
                  double buf_prev[ntt_MA_NP][ntt_N_PR_MAX+1],
                  int    ma_np,
                  int i_sup,         /* Input  : number of channels */
                  double freq[],     /* Input  : LSP parameters */
                  double freqout[],  /* Output : quantized LSP parameters */
                  int index[],       /* Output : the optimum LSP code index */
                  int  nsp)
{
  /*--- Variables ---*/
  int    j, vqword;
  double wegt[ntt_N_PR_MAX+1];
  double flsp[ntt_N_PR_MAX+1];
  double target_buf[ntt_N_MODE_MAX][ntt_N_PR_MAX];
  double fg_sum[ntt_N_MODE_MAX][ntt_N_PR_MAX];
  double amp_cur;
  double cmpe[ntt_N_MODE_MAX][ntt_N_PR_MAX];
  double out_vec[ntt_N_PR_MAX];
  int    i_mode, i_ma;
/*
  int ntt_isp[ntt_NSP_MAX];
*/
  int ntt_isp[ntt_NSP_MAX+1];

  /*--- Initialization ---*/
  /* set the band-split table */
  ntt_set_isp(nsp, n_pr, ntt_isp);

  /*--- Make the codebook with the prediction ---*/
  for(i_mode=0; i_mode<ntt_N_MODE; i_mode++){
    for(j=0; j<n_pr; j++){
      fg_sum[i_mode][j] =1.0;
      for(i_ma=0; i_ma<ma_np; i_ma++){
        fg_sum[i_mode][j] -= fgcode[i_mode][i_ma][j];
    }
  }
}

  ntt_movdd( n_pr, freq+1, flsp+1 );
  amp_cur =  1.0;
  ntt_get_wegt(n_pr, flsp, wegt );
  for(j=1; j<nsp; j++) {
    wegt[ntt_isp[j]] *= 1.2;
    wegt[ntt_isp[j]+1] *= 1.2;
}

  for (i_mode=0; i_mode< ntt_N_MODE; i_mode++){
    for(j=0; j<n_pr; j++) target_buf[i_mode][j] = flsp[j+1];
    for(i_ma=0; i_ma<ma_np; i_ma++){
      for(j=0; j<n_pr; j++){
        target_buf[i_mode][j] -=
          fgcode[i_mode][i_ma][j]*buf_prev[i_ma][j];
    }
  }
    for(j=0; j<n_pr; j++)
      target_buf[i_mode][j] /= fg_sum[i_mode][j];
}
  ntt_relspwed(n_pr, flsp, wegt, freqout, ntt_LSP_NSTAGE,
               csize, cdim, code, fg_sum,
               amp_cur, cmpe, target_buf, out_vec, &vqword , index, nsp );
  for (i_ma=ntt_MA_NP-1; i_ma> 0; i_ma--){
    ntt_movdd(n_pr, buf_prev[i_ma-1], buf_prev[i_ma]);
}
  for (j=0; j<n_pr; j++){
    buf_prev[0][j] = out_vec[j] * amp_cur;
}
}


void ntt_lsptowt(/* Parameters */
		 int nfr,        /* block length */
		 int n_pr,
		 /* Input */
		 double lsp[],
		 /* Output */
		 double wt[])
{
    register double  a,b,c,d,cosz2;
    double sa, sb,sc,sd;
    double coslsp[ntt_N_PR_MAX];
    int i, mag;
    double *lspp, *wp1, *wp2, *cp;

    mag =2*ntt_N_FR/nfr;
    for(i=0; i<n_pr; i++) coslsp[i] =  2.* cos(lsp[i+1]);

    wp1= wt;
    wp2= wt+nfr-1;
    cp = ntt_cos_TT+mag;
    switch(n_pr){
    case 20 :
	 for(i=0;i<nfr/2;i++) { 
           lspp = coslsp;
	   cosz2=2. * *cp;
	   a = (cosz2 - *lspp);
	   c = (cosz2 + *(lspp++));
	   b = (cosz2 - *lspp);
	   d = (cosz2 + *(lspp++));
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 sa=a*a; sb=b*b; sc=c*c; sd=d*d;
	 *(wp1++) = sa+sb +  (sa-sb)* *cp;
	 *(wp2--) = sc+sd + (-sc+sd)* *cp;
	 cp += mag*2;
      }
    break;
    case 16 :
	 for(i=0;i<nfr/2;i++) { 
           lspp = coslsp;
	   cosz2=2. * *cp;
	   a = (cosz2 - *lspp);
	   c = (cosz2 + *(lspp++));
	   b = (cosz2 - *lspp);
	   d = (cosz2 + *(lspp++));
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 { a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++)); }
	 sa=a*a; sb=b*b; sc=c*c; sd=d*d;
	 *(wp1++) = sa+sb +  (sa-sb)* *cp;
	 *(wp2--) = sc+sd + (-sc+sd)* *cp;
	 cp += mag*2;
      }
    break;
    default:
	 for(i=0;i<nfr/2;i++) { 
           lspp = coslsp;
	   cosz2=2. * *cp;
	   a = (cosz2 - *lspp);
	   c = (cosz2 + *(lspp++));
	   b = (cosz2 - *lspp);
	   d = (cosz2 + *(lspp++));
         while(lspp<coslsp+n_pr)     /* n_pr should be even */ 
	 {
	   a *= (cosz2 - *lspp);
	   c *= (cosz2 + *(lspp++));
	   b *= (cosz2 - *lspp);
	   d *= (cosz2 + *(lspp++));
	 }
	 sa=a*a; sb=b*b; sc=c*c; sd=d*d;
	 *(wp1++) = sa+sb +  (sa-sb)* *cp;
	 *(wp2--) = sc+sd + (-sc+sd)* *cp;
	 cp += mag*2;
      }
    }
}


void ntt_mdctwd(double prev[],   /* Input  --- Previous input frame */
	    double sig[],    /* Input  --- Current input frame */
	    double y[],      /* Output --- Windowed input */
	    int	 w_type)     /* Input  --- Window type */
{
    /*--- Variables ---*/
    int mm, nn, kk, ll, oo, pp;

    /*--- Initialization ---*/
    nn = ntt_N_FR   >> 1;
    mm = ntt_N_FR_S >> 1;
    oo = ntt_N_FR_M >> 1;
    kk = ntt_N_FR_WDW >> 1;
    ll = ntt_N_FR_S_WDW >> 1;
    pp = ntt_N_FR_M_WDW >> 1;

    /*--- Main operation ---*/
    switch( w_type ){
    case ONLY_LONG_WINDOW:	        /* Normal */
	ntt_zerod(nn-kk, y);
	ntt_sinwinl(&prev[nn-kk], &y[nn-kk], 0 );
	ntt_movdd(nn-kk, &prev[nn+kk], &y[nn+kk] );
	ntt_movdd(nn-kk, sig, &y[ntt_N_FR]);
	ntt_sinwinl(&sig[nn-kk], &y[nn*3-kk], 1);
	ntt_zerod(nn-kk, &y[nn*3+kk]);
	break;
    case LONG_SHORT_WINDOW:		/* Start */
	ntt_zerod(nn-kk, y);
	ntt_sinwinl(&prev[nn-kk], &y[nn-kk], 0 );
	ntt_movdd(nn-kk, &prev[nn+kk], &y[nn+kk] );
	ntt_movdd(nn-ll, sig, &y[ntt_N_FR]);
	ntt_sinwins(&sig[nn-ll], &y[nn*3-ll], 1);
	ntt_zerod(nn-ll, &y[nn*3+ll]);
	break;
    case LONG_MEDIUM_WINDOW:		/* Long-medium */
	ntt_zerod(nn-kk, y);
	ntt_sinwinl(&prev[nn-kk], &y[nn-kk], 0 );
	ntt_movdd(nn-kk, &prev[nn+kk], &y[nn+kk] );
	ntt_movdd(nn-pp, sig, &y[ntt_N_FR]);
	ntt_sinwinm(&sig[nn-pp], &y[nn*3-pp], 1);
	ntt_zerod(nn-pp, &y[nn*3+pp]);
	break;
    case SHORT_LONG_WINDOW:		/* Stop */
	ntt_zerod(nn-ll, y);
	ntt_sinwins(&prev[nn-ll], &y[nn-ll], 0 );
	ntt_movdd(nn-ll, &prev[nn+ll], &y[nn+ll] );
	ntt_movdd(nn-kk, sig, &y[ntt_N_FR]);
	ntt_sinwinl(&sig[nn-kk], &y[nn*3-kk], 1);
	ntt_zerod(nn-kk, &y[nn*3+kk]);
	break;
    case MEDIUM_LONG_WINDOW:		/* Medium-long */
	ntt_zerod(nn-pp, y);
	ntt_sinwinm(&prev[nn-pp], &y[nn-pp], 0 );
	ntt_movdd(nn-pp, &prev[nn+pp], &y[nn+pp] );
	ntt_movdd(nn-kk, sig, &y[ntt_N_FR]);
	ntt_sinwinl(&sig[nn-kk], &y[nn*3-kk], 1);
	ntt_zerod(nn-kk, &y[nn*3+kk]);
	break;
    case ONLY_SHORT_WINDOW:		/* Short */
	ntt_zerod(mm-ll, y);
	ntt_sinwins(&prev[mm-ll], &y[mm-ll], 0 );
	ntt_movdd(mm-ll, &prev[mm+ll], &y[mm+ll] );
	ntt_movdd(mm-ll, sig, &y[ntt_N_FR_S]);
	ntt_sinwins(&sig[mm-ll], &y[mm*3-ll], 1);
	ntt_zerod(mm-ll, &y[mm*3+ll]);
	break;
    case ONLY_MEDIUM_WINDOW:		/* Medium */
	ntt_zerod(oo-pp, y);
	ntt_sinwinm(&prev[oo-pp], &y[oo-pp], 0 );
	ntt_movdd(oo-pp, &prev[oo+pp], &y[oo+pp] );
	ntt_movdd(oo-pp, sig, &y[ntt_N_FR_M]);
	ntt_sinwinm(&sig[oo-pp], &y[oo*3-pp], 1);
	ntt_zerod(oo-pp, &y[oo*3+pp]);
	break;
    case MEDIUM_SHORT_WINDOW:		/* Medium-short */
	ntt_zerod(oo-pp, y);
	ntt_sinwinm(&prev[oo-pp], &y[oo-pp], 0 );
	ntt_movdd(oo-pp, &prev[oo+pp], &y[oo+pp] );
	ntt_movdd(oo-ll, sig, &y[ntt_N_FR_M]);
	ntt_sinwins(&sig[oo-ll], &y[oo*3-ll], 1);
	ntt_zerod(oo-ll, &y[oo*3+ll]);
	break;
    case SHORT_MEDIUM_WINDOW:		/* short-medium */
	ntt_zerod(oo-ll, y);
	ntt_sinwins(&prev[oo-ll], &y[oo-ll], 0 );
	ntt_movdd(oo-ll, &prev[oo+ll], &y[oo+ll] );
	ntt_movdd(oo-pp, sig, &y[ntt_N_FR_M]);
	ntt_sinwinm(&sig[oo-pp], &y[oo*3-pp], 1);
	ntt_zerod(oo-pp, &y[oo*3+pp]);
	break;
    default:
	fprintf
	    (stderr, "MDCT: Fatal error! %d: Unknown window type\n", w_type );
	exit(1);
    }
}


/***************************************/
/* quantization in ntt_mulaw-scale         */
/* coded by K. Mano    28/Jul/1988     */
/***************************************/

#define DISP_OVF 0

double ntt_mulaw(double x, double xmax,double mu) /* Input */
{
   double  y;
   if (x>xmax){
#if (DISP_OVF)
       fprintf(stderr, "ntt_mulaw(): %lf, %lf: Input overflow.\n", x, xmax);
#endif
       x=xmax;
   }
   else if (x< -xmax){
#if (DISP_OVF)
       fprintf(stderr, "ntt_mulaw(): %lf, %lf: Input underflow.\n", x, -xmax);
#endif
       x= -xmax;
   }
   y = xmax*log10(1.+mu*fabs(x)/xmax)/log10(1.+mu); 
   if (x<0.) y= -y;
   return(y);
}


void ntt_opt_gain_p(
	      int    i_div,    /* Input : division number */
	      int    cb_len,   /* Param. : codebook length */
	      double gt[],     /* Input : gain */
	      double d_targetv[], /* Input : target vector */
	      double sig_l[],  /* Input : decoded residual */
	      double d_wt[],   /* Input : weight */
	      double nume[],   /* Output: cross power (total)*/
	      double gain[],   /* Input : gain of the residual */
	      double denom[],  /* Output: decoded resid. power without gain */
	      double nume0[],  /* Output: cross power (divided) */
	      double denom0[]) /* Output: decoded resid. power without gain */
{
    double fact[ntt_N_SUP_MAX], acc;
    int i_smp, point, points, serial;
    
    serial = ntt_SMP_ACCp[i_div]; 
    if( ntt_N_SUP ==1){
	points = 0;
	for(i_smp=0; i_smp<cb_len; i_smp++){
	    acc =  gain[points]*d_targetv[i_smp]*sig_l[i_smp] ;
	    nume[points] +=  acc;
	    nume0[i_div] +=  acc;
	    acc = sig_l[i_smp]*sig_l[i_smp]*d_wt[i_smp];
	    denom[points] += acc;
	    denom0[i_div] += acc;
	}
    }
    else{
	for(points=0; points<ntt_N_SUP; points++)
	    fact[points] = 1./(gt[points])/(gt[points]);
	for(i_smp=0; i_smp<cb_len; i_smp++){
	    point = ntt_BIT_REVp[serial++];
	    points = (point)/ntt_N_FR_P;
	    acc =  gain[points]*d_targetv[i_smp]*sig_l[i_smp]*fact[points] ;
	    nume[points] +=  acc;
	    nume0[i_div] +=  acc;
	    acc = sig_l[i_smp]*sig_l[i_smp]*d_wt[i_smp]*fact[points];
	    denom[points] += acc;
	    denom0[i_div] += acc;
	}
    }
}


void ntt_pre_dot_p(int    cb_len,      /* Param. : codebook length */
	       int    i_div,       /* Input : division number */
	       double targetv[],   /* Input : target vector */
	       double d_targetv[], /* Output: target subvector (weighted) */
	       double wt[],        /* Input : weighting vector */
	       double mwt[],       /* Input : perceptual controlled weight */
	       double gt[],        /* Input : gain */
	       double powG[],      /* Output: power of the weighted target */
	       double d_wt[])      /* Output: weighting subvector */
{
    int   i_smp, points, point, serial;
    register double acc, accb;
    
    /* Make divided target and weighting vector */
    serial = ntt_SMP_ACCp[i_div];
    if(ntt_N_SUP==1){
	points = 0;
	for ( i_smp=0; i_smp<cb_len; i_smp++ ) {
	    point = ntt_BIT_REVp[serial++];
	    accb = mwt[point];
	    acc = targetv[point]* (wt[point] * accb);
	    accb *= gt[points];
	    d_targetv[i_smp] = acc *gt[points]*accb;
	    d_wt[i_smp] = accb*accb;
	    powG[points] += acc* acc;
	}
    }
    else{
	for ( i_smp=0; i_smp<cb_len; i_smp++ ) {
	    point = ntt_BIT_REVp[serial++];
	    points = (point) / ntt_N_FR_P;
	    accb = mwt[point];
	    acc = targetv[point]* (wt[point] * accb);
	    accb *= gt[points];
	    d_targetv[i_smp] = acc *gt[points]*accb;
	    d_wt[i_smp] = accb*accb;
	    powG[points] += acc* acc;
	}
    }
}


void ntt_relspwed(int    n_pr,
                  double lsp[ntt_N_PR_MAX+1],
                  double wegt[ntt_N_PR_MAX+1],
                  double lspq[ntt_N_PR_MAX+1],
                  int    nstage,
                  int    csize[],
                  int    cdim[],
                  double code[][ntt_N_PR_MAX],
                  double fg_sum[ntt_N_MODE_MAX][ntt_N_PR_MAX],
                  double amp_cur,
                  double cmpe[ntt_N_MODE_MAX][ntt_N_PR_MAX],
                  double target_buf[ntt_N_MODE_MAX][ntt_N_PR_MAX],
                  double out_vec[ntt_N_PR_MAX],
                  int    *vqword,
                  int    index_lsp[],
                  int    nsp)
{
  int      i, j, k, off_code, off_dim, off, code1, code2;
  double   dist, dmin, diff;
  int   kst, kend, index[ntt_N_MODE_MAX][NCD], index0;
  int   nbit0, nbit, k1;
  double dmin1, dmin2, tdist[NCD*ntt_N_MODE_MAX];
  int  tindex[NCD*ntt_N_MODE_MAX], mode_index, mode;
  double bufsave, rbuf[ntt_N_MODE_MAX][ntt_N_PR_MAX];
  double buf[ntt_N_PR_MAX], d[ntt_NC0_MAX];
  double lspbuf[ntt_N_PR_MAX+1];
  int i_mode, idim;
  int index_sp[ntt_NSP_MAX];
  register double acc, acc1;
  double *p_code, *p_rbuf;
/*
  int ntt_isp[ntt_NSP_MAX];
*/
  int ntt_isp[ntt_NSP_MAX+1];

  ntt_set_isp(nsp, n_pr, ntt_isp);
  for(i_mode=0; i_mode<ntt_N_MODE; i_mode++)
    ntt_movdd(n_pr, target_buf[i_mode], rbuf[i_mode]);
  off_code = 0;
  kst = 0;
  kend = nstage;
  off_dim = 0;
  off = csize[kst];
  nbit0 = (int)(log((double)csize[kst])/log(2.0));
  nbit  = (int)(log((double)csize[kend-1])/log(2.0) + 0.00001);
  for(mode = 0; mode<ntt_N_MODE; mode++){
    for(i=off_code; i<csize[kst]+off_code; i++){
      acc =0.0;
      acc1 =0.0;
      p_code = code[i];
      p_rbuf = rbuf[mode];
      for(j=off_dim; j<n_pr;j++){
        acc += *(p_rbuf++) * *(p_code);
        acc1+= *(p_code) * *(p_code++);
    }
      d[i-off_code] =  -acc*2.0 + acc1;

  }
    for(j=0; j<NCD; j++){
      for(i=1, index[mode][j]=0, dmin= d[0]; i<csize[kst]; i++){
        if(d[i]<dmin){
          dmin=d[i];
          index[mode][j]=i;
      }
    }
      d[index[mode][j]]=1.e38;
  }
    for(k=0; k<NCD; k++){
      code1=off_code+index[mode][k];
      for(dmin1=1.e38, k1 = 0; k1<csize[kend-1]; k1++){
        code2=off_code+k1+off;
        for(j=ntt_isp[0]; j<ntt_isp[1]; j++){
          buf[j]=(code[code1][j]+code[code2][j]);
      }
        ntt_dist_lsp(ntt_isp[1], rbuf[mode], buf, wegt, &dist);
        if(dist<dmin1) { dmin1 = dist; index_sp[0] = k1; }
        for(j=ntt_isp[0]; j<ntt_isp[1]; j++){
          buf[j]=(code[code1][j]+code[off_code+index_sp[0]+off][j]);
      }
    }
      bufsave = buf[ntt_isp[1]-1];
      for(idim=1; idim<nsp-1; idim++){

        for(dmin2=1.e38, k1 = 0; k1<csize[kend-1]; k1++){
          code2=off_code+k1+off;
          buf[ntt_isp[idim]-1] =bufsave;

          for(j=ntt_isp[idim]; j<ntt_isp[idim+1]; j++){
            buf[j]=(code[code1][j]+code[code2][j]);
	}
          ntt_dist_lsp(ntt_isp[idim+1]-ntt_isp[idim],rbuf[mode]+ntt_isp[idim],
                       buf+ntt_isp[idim],wegt+ntt_isp[idim],&dist);
          if(dist<dmin2) { dmin2 = dist; index_sp[idim] = k1; }
      }
        for(j=ntt_isp[idim]; j<ntt_isp[idim+1]; j++){
          buf[j]=(code[code1][j]+code[off_code+index_sp[idim]+off][j]);
      }
        bufsave = buf[ntt_isp[idim+1]-1];
    }

      for(dmin2=1.e38, k1 = 0; k1<csize[kend-1]; k1++){
        code2=off_code+k1+off;
        buf[ntt_isp[nsp-1]-1] =bufsave;
        for(j=ntt_isp[nsp-1]; j<ntt_isp[nsp]; j++){
          buf[j]=(code[code1][j]+code[code2][j]);
      }
        ntt_dist_lsp(ntt_isp[nsp]-ntt_isp[nsp-1],rbuf[mode]+ntt_isp[nsp-1],
                     buf+ntt_isp[nsp-1],wegt+ntt_isp[nsp-1],&dist);
        if(dist<dmin2) { dmin2 = dist; index_sp[nsp-1] = k1; }
    }
      for(j=ntt_isp[nsp-1]; j<ntt_isp[nsp]; j++){
        buf[j]=(code[code1][j]+code[off_code+index_sp[nsp-1]+off][j]);
    }
      if(buf[0] < L_LIMIT) {
        diff = L_LIMIT - buf[0];
        buf[0] += diff*1.2;
    }
      if(buf[n_pr-1] > M_LIMIT ){
        diff = buf[n_pr-1]-M_LIMIT;
        buf[n_pr-1] -= diff*1.2;
    }

      ntt_check_lsp(n_pr-1, buf+1, MIN_GAP);

      lspbuf[0] = 0.0;
      for(j=0; j<n_pr; j++){
        lspbuf[j+1] = lsp[j+1] +
          (buf[j] - rbuf[mode][j] ) * fg_sum[mode][j] ;
    }
      if(lspbuf[1] < L_LIMIT) {
        diff = L_LIMIT - lspbuf[1];
        lspbuf[1] += diff*1.2;
    }
      if(lspbuf[n_pr] > M_LIMIT ){
        diff = lspbuf[n_pr]-M_LIMIT;
        lspbuf[n_pr] -= diff*1.2;
    }
      ntt_check_lsp(n_pr-1, lspbuf+2, MIN_GAP);
      ntt_check_lsp(n_pr-1, lspbuf+2, MIN_GAP*0.95);
      ntt_check_lsp_sort(n_pr-1, lspbuf+2);
      ntt_dist_lsp(n_pr, lsp+1, lspbuf+1, wegt, &dist);

      tdist[k+mode*NCD] = dist;
      tindex[k+mode*NCD] =  0;
      for(idim=0; idim<nsp; idim++){
        tindex[k+mode*NCD] +=(index_sp[idim]<<(nbit*(nsp-idim-1)));
    }
  }
}
  for(dmin= 1.e38, mode=0; mode<ntt_N_MODE ; mode ++){
    for(k=0; k<NCD; k++){
      if(tdist[k+mode*NCD]<dmin) {
        dmin = tdist[k+mode*NCD];
        index0 = k;
        mode_index = mode;
    }
  }
}
  *vqword = (mode_index<<(nbit*nsp+nbit0))
    | (index[mode_index][index0]<<(nbit*nsp))
      | tindex[index0+mode_index*NCD];
  index_lsp[0] = mode_index;
  index_lsp[1] = index[mode_index][index0];
  for(idim=0; idim<nsp; idim++){
    index_lsp[idim+2] =
      (tindex[index0+mode_index*NCD]>>(nbit*(nsp-idim-1)))&(csize[kend-1]-1) ;
}

  code1=off_code+index[mode_index][index0];
  for(idim=0; idim<nsp; idim++){
    for(j=ntt_isp[idim]; j<ntt_isp[idim+1]; j++){
      lspq[j+1] =
        (code[code1][j] +code[off_code+off+index_lsp[2+idim]][j]);
  /*
  fprintf(stderr, "YYYYY lspq%5d %8.3f \n", j, lspq[j+1]);
  */
  }
}
  /*
  fprintf(stderr, "YYYYY %5d %8.3f %8.3f \n", code1,
  code[code1][1], code[off_code+off+index_lsp[2]][1]);
  */
  if(lspq[1] < L_LIMIT) {
    diff = L_LIMIT - lspq[1];
    lspq[1] += diff*1.2;
}
  if(lspq[n_pr] > M_LIMIT ){
    diff = lspq[n_pr]-M_LIMIT;
    lspq[n_pr] -= diff*1.2;
}

  ntt_check_lsp(n_pr-1, lspq+2, MIN_GAP);

  for(j=off_dim; j<n_pr; j++) buf[j] = lspq[j+1];
  for(j=off_dim; j<n_pr; j++){
    lspq[j+1] = lsp[j+1] +
      (lspq[j+1] - rbuf[mode_index][j] ) *
        fg_sum[mode_index][j] ;
    out_vec[j] = buf[j];
}
  if(lspq[1] < L_LIMIT) {
    diff = L_LIMIT - lspq[1];
    lspq[1] += diff*1.2;
}
  if(lspq[n_pr] > M_LIMIT ){
    diff = lspq[n_pr]-M_LIMIT;
    lspq[n_pr] -= diff*1.2;
}
  for(i=1; i<n_pr; i++){
    if(lspq[i] > lspq[i+1] - MIN_GAP){
      diff = lspq[i] - lspq[i+1];
      lspq[i]   -= (diff+MIN_GAP)/2.;
      lspq[i+1] += (diff+MIN_GAP)/2.;
  }
}
  for(i=1; i<n_pr; i++){
    if(lspq[i] > lspq[i+1] - MIN_GAP*0.95){
      diff = lspq[i] - lspq[i+1];
      /**/        fprintf(stderr,"%12.5f %5d %12.5f PERMUTATION \n",
                          diff, i, lsp[i+1]-lsp[i]);
      /**/
      lspq[i]   -= (diff+MIN_GAP*0.95)/2.;
      lspq[i+1] += (diff+MIN_GAP*0.95)/2.;
  }
}
  ntt_check_lsp_sort(n_pr-1, lspq+2);
}






void ntt_sear_ch_p(/* Parameters */
             int    cb_len,      /* codebook length */
	     int    pol_bits0,   /* number of polarity bits */
	     int    cb_size0,    /* codebook size */
	     int    n_can,       /* number of candidates */
             /* Input */
	     double d_targetv[], /* target subvector (weighted) */
	     double codevv[][ntt_CB_LEN_P_MAX],
                                 /* codebook */
	     double d_wt[],      /* divided weight */
	     /* Output */
	     double can_code_targ[ntt_POLBITS_P][ntt_N_CAN_MAX],
	     double can_code_sign[ntt_POLBITS_P][ntt_N_CAN_MAX],
	     int    can_ind[])
{
    /*--- Variables ---*/
    int i_cb, i_pol, i_can, j_can, ismp, tb_top, spl_pnt, t_ind;
    double cros_max_t[ntt_N_CAN_MAX], dtmp;
    double code_targ[ntt_POLBITS][ntt_PIT_CB_SIZE_MAX], 
    code_targ_tmp[ntt_PIT_CB_SIZE_MAX];
    register double accb, accc;



    for (i_cb=0; i_cb<cb_size0; i_cb++){
       accc = 0.;
       accb = 0.;
      {
       double *p_code, *p_targ, *p_wt;
       p_code=codevv[i_cb];
       p_targ=d_targetv;
       p_wt = d_wt;
       for (ismp=0; ismp<cb_len; ismp++){
           accb += *(p_targ++) * (*p_code);
           accc += *(p_wt++)  * *(p_code) * *(p_code++);
       }
      }
      code_targ[0][i_cb] = accb;
      if((pol_bits0 == 1)&&(accb<=0.0)){
           code_targ_tmp[i_cb] = -4.0*accb-accc;
      }
      else{
           code_targ_tmp[i_cb] =  4.0*accb-accc;
      }
    }

    /*--- pre-selection search ---*/
    if (n_can == ntt_PIT_CB_SIZE){ /* full search */
	i_pol=0;
	for( i_can=0; i_can<n_can; i_can++){
	    can_ind[i_can] = i_can;
	    can_code_targ[i_pol][i_can] = code_targ_tmp[i_can];
	    can_code_sign[i_pol][i_can] = 
		code_targ[i_pol][i_can] > 0. ? 1.0 : -1.0;
	}/* end 1st-ch preselection */
    }
    else{
	cros_max_t[0] = -1.e30;
	can_ind[0] = 0;
	tb_top=0;
	/*--- search for the insertion point ---*/
	for (i_cb=0; i_cb<cb_size0; i_cb++){
	    dtmp = code_targ_tmp[i_cb];
	    i_can=tb_top; j_can=0;
	    if (dtmp>cros_max_t[tb_top]){
		i_can=tb_top; j_can=0;
		while(i_can>j_can){
		    spl_pnt = (i_can-j_can)/2 + j_can;
		    if (cros_max_t[spl_pnt]>dtmp){
			j_can = spl_pnt+1;
		    }
		    else{
			i_can = spl_pnt;
		    }
		}
		tb_top = ntt_min(tb_top+1, n_can-1);
		for (j_can=tb_top; j_can>i_can; j_can--){
		    cros_max_t[j_can] = cros_max_t[j_can-1];
		    can_ind[j_can] = can_ind[j_can-1];
		}
		cros_max_t[i_can] = dtmp;
		can_ind[i_can] = i_cb;
	    }
	} /* end 1st-ch preselection */

	
	/*--- Make output ---*/
	i_pol = 0;
	for (i_can=0; i_can<n_can; i_can++){
	    t_ind = can_ind[i_can];
	    can_code_targ[i_pol][i_can] = code_targ_tmp[t_ind];
	    can_code_sign[i_pol][i_can] = 
		code_targ[i_pol][t_ind] > 0. ? 1.0 : -1.0;
	}
    }
}


#define ntt_GAMMA_P  0.05 

#define Pntt_IT_FR_DIV_EX 2
#define Pntt_IT_FR_DIV (1<<Pntt_IT_FR_DIV_EX)
#define ntt_PIT_N_FR_DIV (ntt_N_FR/Pntt_IT_FR_DIV)
#define SEAR_START 6
#define SEAR_STOP ((int)((ntt_PIT_N_FR_DIV/2)))

void ntt_sear_pitch(
		    /* Input */
		    double tc[],
		    double lpc_spectrum[],  /* LPC spectrum */
		    /* Output */
		    int    *index_pit)
{
  /*--- Variables ---*/
  int ismp, ii, jj;
  int npcount, ifc, itp;
  int  iscount;
  double pmax,  pitch;
  double dtmp, fcmax, fcmin;
  double tcbuf[ntt_N_FR_MAX];
  double bandwidth;
    
  /*--- Calculate the cepstrum ---*/
  bandwidth =4;
  if(ntt_ISAMPF==8) bandwidth=1.5;
  if(ntt_ISAMPF==11) bandwidth=2;
  if(ntt_ISAMPF==16) bandwidth=2;
  if(ntt_ISAMPF==22) bandwidth=4;
  if(ntt_ISAMPF>=44) bandwidth=8;
  fcmin = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*100))/log(2.);
  fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*600))/log(2.);
  if(ntt_ISAMPF==8) {
  fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*1200))/log(2.);
  }
  if(ntt_ISAMPF==16) {
  fcmax = log((double)((ntt_N_FR*2/(double)ntt_ISAMPF/1000.)*1200))/log(2.);
  }
  for(ii=0; ii<ntt_N_FR; ii++) 
    tcbuf[ii] = tc[ii]*tc[ii]*pow((lpc_spectrum[ii]+0.001), -ntt_GAMMA_P*2.0);

  pmax= -1.0e30;
  for (ifc=0; ifc<(1<<ntt_BASF_BIT); ifc++){
    pitch = (double)ifc / (double) ntt_BASF_STEP;
    pitch = pitch * (fcmax-fcmin) + fcmin;
    pitch = pow(2., pitch);
    dtmp=0.;
    npcount = (int)(ntt_N_FR_P*bandwidth/(ntt_N_FR/pitch));
    iscount=0;
    for (jj=0; jj<npcount/2; jj++){
      iscount ++;
      dtmp += tcbuf[jj];
    }
    for (ii=0; ii<(ntt_N_FR_P) && ( iscount<ntt_N_FR_P) ; ii++){
      ismp = (int)(pitch*(ii+1)+0.5);
      if(ismp+(npcount-1)/2+1<ntt_N_FR){
	for (jj=-npcount/2; (jj<(npcount-1)/2+1) && (iscount<ntt_N_FR_P);
	     jj++, iscount++){
	  dtmp += tcbuf[ismp+jj];
	}
      }
    }	
    if(pmax<dtmp){
      pmax=dtmp;
      *index_pit = ifc;
    }
  }
}


void ntt_sear_x_p(/* Parameters */
	    int    i_div,      /* division number */
	    int    cb_len,     /* codebook length */
	    int    pol_bits0,  /* polarity bits (0 ch) */
	    int    pol_bits1,  /* polarity bits (1 ch) */
	    int    can_ind0[], /* candidate indexes (0 ch) */
	    int    n_can0,     /* number of candidates (0 ch) */
	    int    can_ind1[], /* candidate indexes (1 ch) */
	    int    n_can1,     /* number of candidates (1 ch) */
            /* Output */
	    int    index[],    /* quantization index */
            /* Input */
	    double can_code_targ0[ntt_POLBITS_P][ntt_N_CAN_MAX], 
	    double can_code_targ1[ntt_POLBITS_P][ntt_N_CAN_MAX], 
	    double can_code_sign0[ntt_POLBITS_P][ntt_N_CAN_MAX], 
	    double can_code_sign1[ntt_POLBITS_P][ntt_N_CAN_MAX], 
	    double d_wt[],     /* weight subvector */
            /* Output */
	    double sig_l[],    /* decoded residual */
	    double *dist_min)  /* quantization distortion */
{    
    /*--- Variables ---*/
    int i_pol, i_can, j_can, i_smp, index0, index1, i_can0, i_can1;
    double pol0[ntt_POLBITS_P], pol1[ntt_POLBITS_P];
    double cross, dist;
    double *pt_i, *pt_j;
    double weightbuf[ntt_CB_LEN_P_MAX];
    int n_can0_act, n_can1_act;
    double ttmp;

		i_pol = 0;
    if (pol_bits1 == 1){
	*dist_min = 1.e50;
        n_can0_act = n_can0;
        n_can1_act = n_can1;
#if 0
        if(n_can0> 8){
	  i_can=0;
          while( (can_code_targ0[0][n_can0-1] >
                  can_code_targ1[0][n_can1-1-i_can]) &&(n_can1_act>8) ){
            i_can++;
            n_can1_act --;
          }
          while( (can_code_targ0[0][n_can0-1-i_can] <
                  can_code_targ1[0][n_can1-1]) && (n_can0_act>8) ){
            i_can++;
            n_can0_act --;
          }
        }
#endif
	for(i_can=0; i_can<n_can0_act; i_can++){
            ttmp = -can_code_targ0[i_pol][i_can];
	    pt_i = ntt_codevp0[can_ind0[i_can]];
	    for(i_smp=0; i_smp<cb_len; i_smp++){
	        weightbuf[i_smp] = 2. * *(pt_i++) * d_wt[i_smp]
		                 * can_code_sign0[i_pol][i_can];
	    }
	    for(j_can=0; j_can<n_can1_act; j_can++){
		/*--- Calculate the distortion measure ---*/
	        pt_j = ntt_codevp0[can_ind1[j_can]+ntt_PIT_CB_SIZE];
		cross =0.0;
	        for(i_smp=0; i_smp<cb_len; i_smp++){
	            cross += weightbuf[i_smp]* *(pt_j++);
	        }
		cross *= can_code_sign1[i_pol][j_can];

        	dist = cross + ttmp - can_code_targ1[i_pol][j_can];

		/*--- Compare the distortion with the minimum ---*/
		if ( dist < *dist_min ){
		    i_can0 = i_can;
		    i_can1 = j_can;
		    *dist_min = dist;
		}
	    } /* j_can */
	}  /* i_can */
	
	/*--- Make output indexes ---*/
	index[i_div] = index0 = can_ind0[i_can0];
	index[i_div+ntt_N_DIV_P] = index1 = can_ind1[i_can1];
	if(can_code_sign0[0][i_can0] <= 0) 
	    index[i_div] += ((0x1)<<(ntt_MAXBIT_SHAPE_P));
	if(can_code_sign1[0][i_can1] <= 0) 
	    index[i_div+ntt_N_DIV_P] +=  ((0x1)<<(ntt_MAXBIT_SHAPE_P));
	
    }
    /**/
    else {
	*dist_min = 1.e50;
        n_can0_act = n_can0;
        n_can1_act = n_can1;
        if(n_can0> 8){
	  i_can=0;
          while( (can_code_targ0[0][n_can0-1] >
                  can_code_targ1[0][n_can1-1-i_can]) &&(n_can1_act>8) ){
            i_can++;
            n_can1_act --;
          }
          while( (can_code_targ0[0][n_can0-1-i_can] <
                  can_code_targ1[0][n_can1-1]) && (n_can0_act>8) ){
            i_can++;
            n_can0_act --;
          }
        }
        for(i_can=0; i_can<n_can0_act; i_can++){
            ttmp = -can_code_targ0[i_pol][i_can];
	    pt_i = ntt_codevp0[can_ind0[i_can]];
	    for(i_smp=0; i_smp<cb_len; i_smp++){
	        weightbuf[i_smp] = 2. * *(pt_i++) * d_wt[i_smp]
		                 * can_code_sign0[i_pol][i_can];
	    }
	    for(j_can=0; j_can<n_can1_act; j_can++){
		
		/*--- Calculate the distortion measure ---*/
	        pt_j = ntt_codevp0[can_ind1[j_can]+ntt_PIT_CB_SIZE];
		cross =0.0;
	        for(i_smp=0; i_smp<cb_len; i_smp++){
	            cross += weightbuf[i_smp]* *(pt_j++);
	        }
        	dist = cross + ttmp - can_code_targ1[i_pol][j_can];

		/*--- Compare the distortion with the minimum ---*/
		if ( dist < *dist_min ){
		    i_can0 = i_can;
		    i_can1 = j_can;
		    *dist_min = dist;
		}
	    } /* j_can */
	}  /* i_can */
	/*--- Make output indexes ---*/
	index[i_div] = index0 = can_ind0[i_can0];
	index[i_div+ntt_N_DIV_P] = index1 = can_ind1[i_can1];
	if(pol_bits0 ==1){
	    if(can_code_sign0[0][i_can0] <= 0) 
	    index[i_div] += ((0x1)<<(ntt_MAXBIT_SHAPE_P));
        }
    }
    
    
    /*--- Make the polarity indexes ---*/
    for(i_pol=0; i_pol<ntt_POLBITS_P; i_pol++){
	pol0[i_pol] =1- 2*((index[i_div] >> (i_pol+ntt_MAXBIT_SHAPE_P)) & 0x1);
	pol1[i_pol] =1- 2*((index[i_div+ntt_N_DIV_P]>>(i_pol+ntt_MAXBIT_SHAPE_P)) & 0x1);
    }

    /*--- Local decoding ---*/
    for(i_pol=0; i_pol<ntt_POLBITS_P; i_pol++){
	for ( i_smp=i_pol; i_smp<cb_len; i_smp +=ntt_POLBITS_P ){
	    sig_l[i_smp] = 
		(pol0[i_pol]*ntt_codevp0[index0][i_smp] 
		 +pol1[i_pol]*ntt_codevp0[index1+ntt_PIT_CB_SIZE][i_smp])*0.5;
	}
    }
}


#define EPS  1.e-10

void ntt_wvq_pitch(
	   double targetv[],     /* Input : target vector */
	   double wt[],          /* Input : weighting vector */
	   double pwt[],         /* Input : perceptual controlled weight */
	   double pgain[],       /* Input : gain */
	   int    index_pls[],   /* Output: quantization indexes */
	   double pgainq[],      /* In/Out : gain */
	   int    index_pgain[]) /* Output: gain index */
{
    /*--- Variables ---*/
    int		i_div;
    double	d_targetv[ntt_CB_LEN_P_MAX], d_wt[ntt_CB_LEN_P_MAX];
    double	dist_min;
    int         can_ind0[ntt_N_CAN_MAX], can_ind1[ntt_N_CAN_MAX];
    double      can_code_targ0[ntt_POLBITS_P][ntt_N_CAN_MAX], 
		can_code_targ1[ntt_POLBITS_P][ntt_N_CAN_MAX];
    double      can_code_sign0[ntt_POLBITS_P][ntt_N_CAN_MAX];
    double      can_code_sign1[ntt_POLBITS_P][ntt_N_CAN_MAX];
    static int	InitFlag = 1;
    static double      gain2[ntt_N_SUP_MAX];
    static int bits_p[ntt_N_DIV_P_MAX], length_p[ntt_N_DIV_P_MAX];
    int         cb_len, cb_size0, cb_size1;
    double   sig_l[ntt_CB_LEN_P_MAX];
    double   nume[ntt_N_SUP_MAX], denom[ntt_N_SUP_MAX];
    double   g_opt[ntt_N_SUP_MAX];
    int      pol_bits0, pol_bits1;
    double   nume0[ntt_N_DIV_P_MAX], denom0[ntt_N_DIV_P_MAX];
    double   powG[ntt_N_SUP_MAX];
    int      i_sup;
    double   acc_tmp;
    static double ntt_codevp1[ntt_PIT_CB_SIZE_MAX][ntt_CB_LEN_P_MAX];
    double   *ptr;
    int index_pgain0;

    /*--- Initialization ---*/
    if (InitFlag){
	/* get codebook */
	ptr = (double *)ntt_codevp0;
	ntt_get_cdbk( ntt_PIT_CB_NAME, ptr, ntt_PIT_CB_SIZE*2, ntt_CB_LEN_P, ntt_CB_LEN_P_MAX );
        {int i,j;
	  for(i=0;i<ntt_PIT_CB_SIZE; i++){
	    for(j=0; j<ntt_CB_LEN_P; j++){
	      ntt_codevp1[i][j] = ntt_codevp0[i+ntt_PIT_CB_SIZE][j];
	    }
          }
        }
    }
    InitFlag = 0;
    ntt_vec_lenp(bits_p, length_p);
    for(i_sup=0; i_sup<ntt_N_SUP; i_sup++){ 
	nume[i_sup] = denom[i_sup] = 0.;
	gain2[i_sup] = pgain[i_sup]*pgain[i_sup];
	powG[i_sup] = 0.0;
    }

    /*--- Main operation ---*/
    acc_tmp=0.0;
    for ( i_div=0; i_div<ntt_N_DIV_P; i_div++ ){
	nume0[i_div]= denom0[i_div] =0.0;
	/*--- set codebook lengths and sizes ---*/
	cb_len = length_p[i_div];
	cb_size0 = 0x1 << ntt_MAXBIT_SHAPE_P;
	cb_size1 = 0x1 << ntt_MAXBIT_SHAPE_P;
	pol_bits0 = ((bits_p[i_div]+1)/2)-ntt_MAXBIT_SHAPE_P;
	pol_bits1 = ((bits_p[i_div])/2)-ntt_MAXBIT_SHAPE_P;

	/*--- divide vectors into subvectors ---*/
	ntt_pre_dot_p(cb_len, i_div, targetv, d_targetv,
		wt, pwt, pgain, powG, d_wt);

	/*--- Best codebook search ---*/
	/* pre-selection 0 */
        ntt_sear_ch_p(cb_len,pol_bits0, cb_size0, ntt_N_CAN_P, d_targetv, ntt_codevp0, d_wt,
	       can_code_targ0, can_code_sign0,
	       can_ind0);
	/* pre-selection 1 */
        ntt_sear_ch_p(cb_len,pol_bits1, cb_size1, ntt_N_CAN_P, d_targetv, ntt_codevp1, d_wt,
	       can_code_targ1, can_code_sign1,
	       can_ind1);
	/* main selection */
	ntt_sear_x_p(i_div, cb_len, pol_bits0, pol_bits1,
	       can_ind0, ntt_N_CAN_P, can_ind1, ntt_N_CAN_P, index_pls,
	       can_code_targ0, can_code_targ1,
	       can_code_sign0, can_code_sign1, 
	       d_wt, sig_l, &dist_min);
	acc_tmp += dist_min;
	/* Prepair for calculating the optimum gain */
        ntt_opt_gain_p(i_div,cb_len,pgain,d_targetv,sig_l,d_wt,nume,
                 pgainq, denom, nume0, denom0);
    }

    /*--- gain re-quantization ---*/
    for(i_sup=0; i_sup<ntt_N_SUP; i_sup++){
	g_opt[i_sup] = nume[i_sup]/(denom[i_sup]+EPS); /* calc. opt. gain */
	/* re-quantization */
	ntt_enc_gair_p(&index_pgain0,
		 powG[i_sup], gain2[i_sup], &g_opt[i_sup],
		 nume[i_sup], denom[i_sup]);
	index_pgain[i_sup] = index_pgain0;
        ntt_dec_pgain(index_pgain[i_sup], &pgainq[i_sup]); 
    } /* end i_sup */
}
