/*****************************************************************************/
/* This software module was originally developed by                          */
/*   Akio Jin (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)1997.                                                        */
/*****************************************************************************/

#include "ntt_conf.h"
#include "ntt_scale_conf.h"

void ntt_scale_tf_proc_spectrum_d(/* Input */
				  ntt_INDEX  *indexp,
				  double flat_spectrum[],
				  /* Output */
				  double spectrum[],
				  /* scalable layer ID */
				  int iscl)
{
  /*--- Variables ---*/
  double inv_lpc_spec[ntt_T_FR_MAX],inv_lpc_spec_nall[ntt_T_FR_MAX];
  double bark_env[ntt_T_FR_MAX];
  double gain[ntt_T_SHRT_MAX];
  double pit_seq[ntt_T_FR_MAX];
  double pgain[ntt_T_SHRT_MAX];
  static int InitFlag = 1;
  int    i_ch, ii, jj;
  int    ifr, fw_nbit;
  /*--- Parameters ---*/
  int    nfr, nsf;
  double *fw_codebook;
  int    fw_ndiv, fw_cv_len, fw_cv_len_max;
  int    *fw_bark_tbl, fw_n_crb;
  double fw_alf_step, *fw_penv_tmp;
  double *lsp_code;
  double *lsp_fgcode;
  int    n_pr, *lsp_csize, *lsp_cdim, isf, ismp, top, subtop, nfr_l, nfr_lu;
  double band_lower, band_upper;
  /*--- Memories ---*/
  /* Bark-scale envelope quantization */
  static double
    env_memory_long[ntt_NSclLay_MAX][ntt_N_CRB_MAX*ntt_N_SUP_MAX];
  static double
    env_memory_medium[ntt_NSclLay_MAX][ntt_N_CRB_M_MAX*ntt_N_SUP_MAX];
  static double
    env_memory_short[ntt_NSclLay_MAX][ntt_N_CRB_S_MAX*ntt_N_SUP_MAX];
  /* LSP quantization */
  static double
    prev_buf[ntt_NSclLay_MAX][ntt_N_SUP_MAX][ntt_MA_NP][ntt_N_PR_MAX+1];
  static int    ma_np[ntt_NSclLay_MAX];
  int i_sup, iptop;
  double g_gain;

  /*--- Initialization ---*/
  if (InitFlag==1){
    for (ii=0; ii<ntt_NSclLay; ii++){
      /* Bark-scale envelope */
      ntt_zerod(ntt_N_CRB_SCL[ii]  *ntt_N_SUP, env_memory_long[ii]);
      ntt_zerod(ntt_N_CRB_M_SCL[ii]*ntt_N_SUP, env_memory_medium[ii]);
      ntt_zerod(ntt_N_CRB_S_SCL[ii]*ntt_N_SUP, env_memory_short[ii]);

      /* LPC spectrum */
      for (i_ch=0; i_ch<ntt_N_SUP; i_ch++){
	for (jj=0; jj<ntt_MA_NP; jj++){
	  ntt_zerod(ntt_N_PR+1, prev_buf[ii][i_ch][jj]);
	}
      }
      ma_np[ii] = 0;
    }
  }
  InitFlag = 0;
  
  /*--- Parameter settings ---*/
  switch (indexp->w_type){
  case ONLY_LONG_WINDOW:  /* long */
  case LONG_SHORT_WINDOW:
  case SHORT_LONG_WINDOW:
  case LONG_MEDIUM_WINDOW:
  case MEDIUM_LONG_WINDOW:
    /* subframes */
    nfr = ntt_N_FR;
    nsf = 1;
    /* quantization (Bark-scale envelope) */
    fw_codebook = (double *)ntt_fwcodev_scl[iscl];
    fw_ndiv       = ntt_FW_N_DIV_SCL[iscl];
    fw_cv_len     = ntt_FW_CB_LEN_SCL[iscl];
    fw_cv_len_max = ntt_FW_CB_LEN_SCL[iscl];
    /* Bark-scale table (Bark-scale envelope) */
    fw_bark_tbl = ntt_crb_tbl_scl[iscl];
    fw_n_crb    = ntt_N_CRB_SCL[iscl];
    /* Reconstruction (Bark-scale envelope) */
    fw_alf_step = ntt_FW_ALF_STEP;
    fw_penv_tmp = env_memory_long[iscl];
    fw_nbit = ntt_FW_N_BIT_SCL[iscl];
    break;
  case ONLY_MEDIUM_WINDOW:
  case MEDIUM_SHORT_WINDOW:
  case SHORT_MEDIUM_WINDOW:
    /* subframes */
    nfr = ntt_N_FR_M;
    nsf = ntt_N_MID;
    /* quantization (Bark-scale envelope) */
    fw_codebook = (double *)ntt_fwcodevm_scl[iscl];
    fw_ndiv       = ntt_FW_N_DIV_M_SCL[iscl];
    fw_cv_len     = ntt_FW_CB_LEN_M_SCL[iscl];
    fw_cv_len_max = ntt_FW_CB_LEN_M_SCL[iscl];
    /* Bark-scale table (Bark-scale envelope) */
    fw_bark_tbl = ntt_crb_tbl_m_scl[iscl];
    fw_n_crb    = ntt_N_CRB_M_SCL[iscl];
    /* Reconstruction (Bark-scale envelope) */
    fw_alf_step = ntt_FW_ALF_STEP;
    fw_penv_tmp = env_memory_medium[iscl];
    fw_nbit = ntt_FW_N_BIT_M_SCL[iscl];
    break;
  case ONLY_SHORT_WINDOW:
    /* subframes */
    nfr = ntt_N_FR_S;
    nsf = ntt_N_SHRT;
    /* quantization (Bark-scale envelope) */
    fw_codebook = (double *)ntt_fwcodevs_scl[iscl];
    fw_ndiv       = ntt_FW_N_DIV_S_SCL[iscl];
    fw_cv_len     = ntt_FW_CB_LEN_S_SCL[iscl];
    fw_cv_len_max = ntt_FW_CB_LEN_S_SCL[iscl];
    /* Bark-scale table (Bark-scale envelope) */
    fw_bark_tbl = ntt_crb_tbl_s_scl[iscl];
    fw_n_crb    = ntt_N_CRB_S_SCL[iscl];
    /* Reconstruction (Bark-scale envelope) */
    fw_alf_step = ntt_FW_ALF_STEP;
    fw_penv_tmp = env_memory_short[iscl];
    fw_nbit = ntt_FW_N_BIT_S_SCL[iscl];
    break;
  }
  /* LSP quantization */
  n_pr       = ntt_N_PR_SCL[iscl];                  /* prediction order */
  lsp_code   = (double *)lsp_code_scl[iscl];   /* code tables */
  lsp_fgcode = (double *)lsp_fgcode_scl[iscl];
  lsp_csize  = ntt_lsp_csize_scl[iscl];        /* codebook size */
  lsp_cdim   = ntt_lsp_cdim_scl[iscl];         /* codevector length */
  /* Post process (band limitation) */
  band_lower = ntt_BAND_LOWER_SCL[iscl];
  band_upper = ntt_BAND_UPPER_SCL[iscl];

  /*--- Decoding tools ---*/
  
  /* Periodic pitch components */
#if 0
  if( ntt_TBIT_P2 > 0){
    ntt_dec_pitch(indexp->pit, indexp->pls, indexp->pgain, indexp->w_type, 
		  pit_seq, pgain);
  }
  else{
    ntt_zerod(ntt_N_FR*ntt_N_SUP, pit_seq); 
    ntt_zerod(ntt_N_SHRT*ntt_N_SUP, pgain);
  }
#endif
  ntt_zerod(ntt_N_FR*ntt_N_SUP, pit_seq); 
  ntt_zerod(ntt_N_SHRT*ntt_N_SUP, pgain);
  /* Bark-scale envelope */
  if(fw_nbit>0){
    ntt_scale_dec_bark_env(nfr, nsf, ntt_N_SUP,
		   fw_codebook, fw_ndiv, fw_cv_len, fw_cv_len_max,
		   fw_bark_tbl, fw_n_crb, fw_alf_step, fw_penv_tmp,
		   indexp->fw, indexp->fw_alf, indexp->pf, bark_env, 
		   band_lower);
  }
  else{
     for(ifr=0; ifr<nsf*nfr*ntt_N_SUP; ifr++){
	bark_env[ifr] = 1.0;
     }
  }
  /* Gain */
  if(nsf==1) {
     for(i_sup=0; i_sup<ntt_N_SUP; i_sup++){
        ntt_dec_sq_gain(indexp->pow[i_sup],
                ntt_AMP_MAX_SCL[iscl], ntt_MU_SCL[iscl], 
		ntt_STEP_SCL[iscl],
		ntt_AMP_NM, &gain[i_sup]);
     g_gain= gain[i_sup];
     }
  }
  else{
    for(i_sup=0; i_sup<ntt_N_SUP; i_sup++){
         iptop = i_sup * (nsf + 1);
        ntt_dec_sq_gain(indexp->pow[iptop],
                ntt_AMP_MAX_SCL[iscl], ntt_MU_SCL[iscl], 
		ntt_STEP_SCL[iscl], ntt_AMP_NM, &g_gain);
         for(isf=0; isf<nsf; isf++){
            ntt_dec_sq_gain(indexp->pow[iptop+1+isf],
                  ntt_SUB_AMP_MAX_SCL[iscl], ntt_MU_SCL[iscl], 
		  ntt_SUB_STEP_SCL[iscl],
                  ntt_SUB_AMP_NM, &gain[isf+i_sup*nsf]);
            gain[isf+i_sup*nsf] *=g_gain;
        }
    }
  }
  /* LPC spectrum */
  ntt_dec_lpc_spectrum_inv(nfr, nsf, ntt_N_SUP, ntt_N_PR_SCL[iscl],
			   ntt_LSP_SPLIT_SCL[iscl],
			   lsp_code, lsp_fgcode,
			   lsp_csize, lsp_cdim, prev_buf[iscl], ma_np[iscl],
			   indexp->lsp, inv_lpc_spec);

  /*--- band re-extension for nallow band lpc (by A.Jin 1997.6.9) ---*/
  nfr_l = nfr*band_lower;
  nfr_lu = nfr*(band_upper-band_lower);

  for( i_ch=0; i_ch<ntt_N_SUP; i_ch++ ){
    top    = i_ch*nfr*nsf;
    ntt_zerod(nfr*nsf, inv_lpc_spec_nall+top);

      for(isf=0; isf<nsf; isf++){
        subtop = top + isf*nfr;
        for(ismp=0; ismp<nfr_lu; ismp++){
          inv_lpc_spec_nall[ismp+subtop+nfr_l] =
          inv_lpc_spec[(int)(ismp/(band_upper-band_lower))+subtop];
        }
      }
  }
  /* De-normalization */
  ntt_denormalizer_spectrum(nfr, nsf, ntt_N_SUP,
			    flat_spectrum, gain, 
			    pit_seq, pgain, bark_env, inv_lpc_spec_nall,
			    spectrum);

  /*--- Post processing ---*/
  ntt_post_process(nfr, nsf, band_lower, band_upper,
		   spectrum, spectrum);

  /*--- Memory operation ---*/
  ma_np[iscl] ++;
  if(ma_np[iscl] > ntt_MA_NP) ma_np[iscl] = ntt_MA_NP;

}

