/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include #include "options.h" #include "cnst.h" #include "prot.h" #include "rom_com.h" #include "rom_enc.h" #include "basop_util.h" #include "basop_proto_func.h" /*---------------------------------------------------------------------* * Local functions *---------------------------------------------------------------------*/ static short SWB_BWE_encoding( Encoder_State *st, const float *insig, const float *insig_lp, const float *insig_hp, const float *synth, const float *yos, float *SWB_fenv, const float tilt_nb, const short st_offset, const short coder_type ); static void MSVQ_Interpol_Tran( float *SWB_env_energy, short *indice ); static void calculate_tonality( const float *org, const float *gen, float *SFM_org, float *SFM_gen, const short length ); static short WB_BWE_encoding( const short coder_type, const float *yos, float *WB_fenv, Encoder_State *st ); static void energy_control( Encoder_State *st, const short core, const short mode, const short coder_type, const float *org, const short offset, float *energy_factor ); static short decision_hq_generic_class (const float *coefs, const short hq_generic_offset ); /*-------------------------------------------------------------------* * wb_bwe_enc() * * WB BWE encoder *-------------------------------------------------------------------*/ void wb_bwe_enc( Encoder_State *st, /* i/o: encoder state structure */ const float *new_wb_speech, /* i : original input signal at 16kHz */ short coder_type /* i : coding type */ ) { float old_input[NS2SA(16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k]; float *new_input; /* pointer to original input signal */ float yorig[L_FRAME16k]; /* MDCT spectrum of weighted original */ short mode = 0; float wtda_old_input[2*L_FRAME16k]; float WB_fenv[SWB_FENV]; short Sample_Delay_WB_BWE; if( st->total_brate == ACELP_13k20 ) { /*---------------------------------------------------------------------* * Delay the original input signal to be synchronized with ACELP core synthesis *---------------------------------------------------------------------*/ set_f( old_input, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); new_input = old_input + Sample_Delay_WB_BWE; mvr2r( st->old_input_wb, old_input, Sample_Delay_WB_BWE ); mvr2r( new_wb_speech, new_input, L_FRAME16k ); mvr2r( old_input + L_FRAME16k, st->old_input_wb, Sample_Delay_WB_BWE ); /*---------------------------------------------------------------------* * WB BWE encoding *---------------------------------------------------------------------*/ /* MDCT of the original signal */ wtda( old_input, wtda_old_input, st->old_wtda_swb, ALDO_WINDOW, ALDO_WINDOW, L_FRAME16k ); direct_transform( wtda_old_input, yorig, 0, L_FRAME16k ); mode = WB_BWE_encoding( coder_type, yorig, WB_fenv, st ); push_indice( st, IND_WB_CLASS, mode - 2, 1 ); } st->prev_mode = mode; return; } /*-------------------------------------------------------------------* * get_normalize_spec() * *-------------------------------------------------------------------*/ static void get_normalize_spec( const short core, /* i : core selected */ const short extl, /* i : extension layer selected */ const short mode, /* i : SHB BWE class */ const short core_type, /* i : coding type */ const float *org, /* i : input spectrum */ float *SWB_signal, /* o : output spectrum */ short *prev_L_swb_norm, /* i : previous norm. len */ const short offset /* i : frequency offset */ ) { short n_freq, L_swb_norm; float envelope[L_FRAME32k]; short frq_end; set_f( SWB_signal, 0, HQ_GENERIC_HIGH0+offset ); calc_normal_length(core, org, mode, extl, &L_swb_norm, prev_L_swb_norm); if( extl == SWB_BWE || extl == FB_BWE ) { if( mode == HARMONIC ) { mvr2r( org, &SWB_signal[240+offset], 240 ); mvr2r( &org[128], &SWB_signal[480+offset], 80 ); } else { mvr2r( &org[112], &SWB_signal[240+offset], 128 ); mvr2r( &org[112], &SWB_signal[368+offset], 128 ); mvr2r( &org[176], &SWB_signal[496+offset], 64 ); } frq_end = 560+offset; } else if (extl == WB_BWE) { if( core_type == 0 ) { mvr2r(&org[160], &SWB_signal[240], 80); } else { mvr2r(&org[80], &SWB_signal[240], 80); } frq_end = L_FRAME16k; } else { mvr2r( org+HQ_GENERIC_OFFSET, SWB_signal+HQ_GENERIC_HIGH0+offset, HQ_GENERIC_LEN0 ); mvr2r( org+HQ_GENERIC_OFFSET, SWB_signal+HQ_GENERIC_HIGH1+offset, HQ_GENERIC_LEN0 ); if ( offset == HQ_GENERIC_FOFFSET_24K4 ) { mvr2r( org+HQ_GENERIC_LOW0, SWB_signal+HQ_GENERIC_HIGH2+offset, HQ_GENERIC_END_FREQ-HQ_GENERIC_HIGH2 ); } frq_end = L_FRAME32k; } /* calculate envelope */ calc_norm_envelop( SWB_signal, envelope, L_swb_norm, frq_end - offset, offset ); /* Normalize with envelope */ for( n_freq = swb_bwe_subband[0]+offset; n_freqextl == SWB_BWE || st->extl == FB_BWE ) { input_hi = &fSpectrum[256]; numsharp = NUM_SHARP; if ( ( st->last_extl == SWB_BWE && st->extl == SWB_BWE ) || ( st->last_extl == FB_BWE && st->extl == FB_BWE ) ) { gain_tmp = fGain / (st->prev_global_gain + EPSILON); if (st->prev_mode == TRANSIENT) { numharmonic = numharmonic * 2; } else if (st->prev_mode == NORMAL || st->prev_mode == NOISE) { numharmonic = 3 * numharmonic / 2; } } else { gain_tmp = 1; if (st->prev_mode == HARMONIC) { numharmonic = numharmonic / 2; sharplimit = sharplimit / 2; } else { numharmonic = numharmonic * 2; sharplimit = sharplimit * 2; } } } else if (st->extl == WB_BWE) { input_hi = &fSpectrum[224]; numsharp = NUM_SHARP / 3; if (st->prev_mode == HARMONIC) { numharmonic = numharmonic / 4; } else { numharmonic = numharmonic / 2; } if (st->last_extl != WB_BWE) { if (st->prev_mode == HARMONIC) { sharplimit = sharplimit / 2; } else { sharplimit = sharplimit * 2; } } } meanH = EPSILON; for(i = 0; i < numsharp; i ++) { peak = 0.0f; mean[i] = 0; for(j = 0; j < SHARP_WIDTH; j ++) { mag = (float) fabs(*input_hi); if (mag > peak) { peak = mag; } mean[i] += mag; input_hi ++; } meanH += mean[i]; if(mean[i] != peak) { sharp = (float) (peak * (SHARP_WIDTH - 1) / (mean[i] - peak)); } else { sharp = 0.0f; } if (sharp > 4.5 && peak > 8) { k += 1; } else if (sharp < 3.0) { noise += 1; } if (sharp > sharpPeak) { sharpPeak = sharp; } } if ( st->extl == SWB_BWE || st->extl == FB_BWE ) { if(k >= numharmonic && gain_tmp > 0.5f && gain_tmp < 1.8f && sharpPeak > sharplimit) { sharpMod = 1; } else { sharpMod = 0; } meanH /= 288; mean_d = 0.0f; for(i=0; iextl == WB_BWE) { if (k >= numharmonic && sharpPeak > sharplimit) { sharpMod = 1; } else { sharpMod = 0; } } if (sharpMod && st->modeCount < 12) { st->modeCount++; } else if (sharpMod == 0 && st->modeCount > 0) { st->modeCount--; } if (st->modeCount >= 2) { sharpMod = 1; } if (sharpMod) { mode = HARMONIC; } else if ( st->extl == SWB_BWE || st->extl == FB_BWE ) { if (noise > 4 && mean_d < 4.8f*meanH && tilt_nb < 5) { mode = NOISE; } } return mode; } /*-------------------------------------------------------------------* * WB_BWE_encoding() * * WB BWE main encoder *-------------------------------------------------------------------*/ static short WB_BWE_encoding( /* o : classification of wb signal */ const short coder_type, const float *yos, /* i : MDCT coefficients of weighted original */ float *WB_fenv, /* i/o: energy of WB envelope */ Encoder_State *st /* i/o: Encoder structure */ ) { short mode; float global_gain; float energy; short i, n_coeff, n_band; short index; float energy_factor[4]; /* Energy for the different bands and global energies */ global_gain = EPSILON; for (i = 0, n_band = 0; i < 2; i++) { energy = EPSILON; for (n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band+2]; n_coeff++) { energy += yos[n_coeff] * yos[n_coeff]; } WB_fenv[i] = energy; n_band += 2; global_gain += energy; } mode = FD_BWE_class(yos, global_gain, 0, st); energy_control( st, ACELP_CORE, mode, coder_type, yos, 0, energy_factor ); for (i = 0; i < 2; i++) { WB_fenv[i] = (float)(log10( WB_fenv[i]*energy_factor[i<<1]/40 )*FAC_LOG2); } index = WB_BWE_fenv_q( WB_fenv, F_2_5, 32, 2 ); push_indice( st, IND_WB_FENV, index, 5 ); return (mode); } /*-------------------------------------------------------------------* * swb_bwe_enc() * * SWB BWE encoder (only for 32kHz signals) *-------------------------------------------------------------------*/ void swb_bwe_enc( Encoder_State *st, /* i/o: encoder state structure */ const float *old_input_12k8, /* i : input signal @12.8kHz for SWB BWE */ const float *old_input_16k, /* i : input signal @16kHz for SWB BWE */ const float *old_syn_12k8_16k, /* i : ACELP core synthesis at 12.8kHz or 16kHz*/ const float *new_swb_speech, /* i : original input signal at 32kHz */ const float *shb_speech, /* i : SHB target signal (6-14kHz) at 16kHz */ const short coder_type /* i : coding type */ ) { short i, inner_frame, idxGain; float *new_input; long inner_Fs; float old_input[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; float old_input_lp[L_FRAME16k], new_input_hp[L_FRAME16k]; float yorig[L_FRAME48k]; float wtda_old_input[2*L_FRAME48k]; float SWB_fenv[SWB_FENV]; float tilt_nb; short Sample_Delay_SWB_BWE, Sample_Delay_HP, Sample_Delay_LP; float ener_low, energy_fbe_fb, fb_ener_adjust, ener_adjust_quan; ener_adjust_quan = 0.0f; idxGain = 0; /*---------------------------------------------------------------------* * Delay the original input signal to be synchronized with ACELP core synthesis *---------------------------------------------------------------------*/ if( st->extl == FB_BWE ) { inner_frame = L_FRAME48k; inner_Fs = 48000; } else { inner_frame = L_FRAME32k; inner_Fs = 32000; } set_f( old_input, 0.0f, NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + inner_frame ); if( st->L_frame == L_FRAME ) { Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS); Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS); Sample_Delay_LP = NS2SA(12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS); mvr2r( st->old_input_lp, old_input_lp, Sample_Delay_LP ); mvr2r( old_input_12k8 + L_INP_MEM, &old_input_lp[Sample_Delay_LP], L_FRAME-Sample_Delay_LP ); mvr2r( old_input_12k8 + L_INP_MEM + L_FRAME - Sample_Delay_LP, st->old_input_lp, Sample_Delay_LP ); } else { Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS); Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS); Sample_Delay_LP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS); mvr2r( st->old_input_lp, old_input_lp, Sample_Delay_LP ); mvr2r( old_input_16k + L_INP_MEM, &old_input_lp[Sample_Delay_LP], L_FRAME16k-Sample_Delay_LP ); mvr2r( old_input_16k + L_INP_MEM + L_FRAME16k - Sample_Delay_LP, st->old_input_lp, Sample_Delay_LP ); } mvr2r( st->new_input_hp, new_input_hp, Sample_Delay_HP ); mvr2r( shb_speech, new_input_hp + Sample_Delay_HP, L_FRAME16k - Sample_Delay_HP ); mvr2r( shb_speech + L_FRAME16k - Sample_Delay_HP, st->new_input_hp, Sample_Delay_HP ); new_input = old_input + Sample_Delay_SWB_BWE; mvr2r( st->old_input, old_input, Sample_Delay_SWB_BWE ); mvr2r( new_swb_speech, new_input, inner_frame ); mvr2r( old_input + inner_frame, st->old_input, Sample_Delay_SWB_BWE ); /*----------------------------------------------------------------------* * Calculate tilt of the input signal and the ACELP core synthesis *----------------------------------------------------------------------*/ calc_tilt_bwe( old_input_lp, &tilt_nb, L_FRAME ); /*---------------------------------------------------------------------* * SWB BWE encoding * FB BWE encoding *---------------------------------------------------------------------*/ /* windowing of the original input signal */ wtda( old_input, wtda_old_input, st->old_wtda_swb, ALDO_WINDOW,ALDO_WINDOW,inner_frame ); /* DCT of the original input signal */ direct_transform( wtda_old_input, yorig, 0, inner_frame ); /* FB BWE encoding */ if ( st->extl == FB_BWE ) { energy_fbe_fb = sum2_f( yorig + FB_BAND_BEGIN, FB_BAND_WIDTH ) + EPSILON; ener_low = EPSILON; for( i=FB_BAND_BEGIN - FB_BAND_WIDTH; iL_frame == L_FRAME16k) { SWB_BWE_encoding( st, old_input, old_input_lp, new_input_hp, old_syn_12k8_16k, yorig, SWB_fenv, tilt_nb, 80, coder_type ); } else { SWB_BWE_encoding( st, old_input, old_input_lp, new_input_hp, old_syn_12k8_16k, yorig, SWB_fenv, tilt_nb, 6, coder_type ); } /* write FB BWE frame gain to the bitstream */ if( st->extl == FB_BWE ) { push_indice( st, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); } return; } /*-------------------------------------------------------------------* * Freq_weights() * *-------------------------------------------------------------------*/ static void freq_weights( const float Band_Ener[], /* i : Band energy */ const float f_weighting[], /* i : weigting coefs. */ float w[], /* o : Freq. weighting */ const short Nb /* i : Number of bands */ ) { short i; float tmp, w1[SWB_FENV], w2[SWB_FENV]; float min_b, max_b; /* Find Max band energy */ min_b = Band_Ener[0]; max_b = Band_Ener[0]; for( i=1; i max_b ) { max_b = Band_Ener[i]; } } /* Find weighting function */ tmp = 1.f/(max_b-min_b); for( i=0; i k; l-- ) { dist_min[l] = dist_min[l - 1]; index[l] = index[l - 1]; } dist_min[k] = dist; index[k] = i; break; } } } } else { set_f( dist_min, 3.402823466e+38F, surv ); /* FLT_MAX */ for (i = 0; i < surv; i++) { index[i] = i; } p_E_ROM_dico = E_ROM_dico; for( i = 0; i < E_ROM_dico_size; i++ ) { dist = x[0] - *p_E_ROM_dico++; dist *= dist; for( j = 1; j < dim; j++ ) { temp1 = x[j] - *p_E_ROM_dico++; dist += temp1 * temp1; } for( k = 0; k < surv; k++ ) { if( dist < dist_min[k] ) { for( l = surv - 1; l > k; l-- ) { dist_min[l] = dist_min[l-1]; index[l] = index[l-1]; } dist_min[k] = dist; index[k] = i; break; } } } } return; } /*-------------------------------------------------------------------* * vqSimple_w() * *-------------------------------------------------------------------*/ static short vqSimple_w( const float *x, /* i : input for quantizer */ float *y, /* i : quantized value */ const float *cb, /* i : codebooks */ const float *w, /* i : weight */ const short dim, /* i : dimension */ const short l, /* i : number of candidates */ const short flag /* i : flag indicationg weighted distortion metric */ ) { short i, j, index; const float *cbP; float dist_min, dist, temp; index = 0; dist_min = FLT_MAX; cbP = cb; if( flag ) { for( i = 0; i < l; i++ ) { dist = x[0] - *cbP++; dist *= (dist * w[0]); for( j = 1; j < dim; j++ ) { temp = x[j] - *cbP++; dist += temp * temp * w[j]; } if( dist < dist_min ) { dist_min = dist; index = i; } } } else { for( i = 0; i < l; i++ ) { dist = x[0] - *cbP++; dist *= dist; for( j = 1; j < dim; j++ ) { temp = x[j] - *cbP++; dist += temp * temp; } if( dist < dist_min ) { dist_min = dist; index = i; } } } /* Reading the selected vector */ mvr2r( &cb[index * dim], y, dim ); return(index); } /*-------------------------------------------------------------------* * MSVQ_Interpol_Tran() * *-------------------------------------------------------------------*/ static void MSVQ_Interpol_Tran( float *SWB_env_energy, /* i/o : (original/quantized) energy */ short *indice /* o : quantized index */ ) { short k, n_band, candInd[N_CAND_TR], ind_tmp[2]; float env_temp11[SWB_FENV_TRANS/2], env_temp12[SWB_FENV_TRANS/2]; float dist, minDist, tmp_q; float quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; float distCand[N_CAND_TR], quant_select[SWB_FENV_TRANS]; /* Extract target vector */ for( n_band = 0; n_band < DIM_TR1; n_band++ ) { env_temp11[n_band] = SWB_env_energy[2*n_band]; env_temp12[n_band] = SWB_env_energy[2*n_band+1]; } vqWithCand_w( env_temp11, Env_TR_Cdbk1, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); minDist = FLT_MAX; for( k=0; ktotal_brate <= ACELP_8k00 ) { core_type = 0; } else { core_type = 1; } get_normalize_spec( core, st->extl, mode, core_type, org, SWB_signal, &(st->prev_L_swb_norm1), offset ); if ( st->extl == WB_BWE) { max_band = 4; band_step = 2; } } else /* HQ core */ { gamma = 0.55f; get_normalize_spec( core, -1, mode, -1, org, SWB_signal, &(st->prev_L_swb_norm1), offset ); if ( offset == HQ_GENERIC_FOFFSET_32K ) { max_band = 12; } } for( n_band=0; n_bandL_frame == L_FRAME ) { L = L_SUBFR; } else { L = L_SUBFR16k; } /* HF transient detect */ IsTransient = detect_transient( insig_hp, st, L_FRAME16k, coder_type ); /* LF transient detect */ IsTransient_LF = 0; for ( n_band = 0; n_band < 4; n_band++ ) { energy = EPSILON; for ( i = 0; i < L; i++ ) { energy += insig_lp[i + n_band*L] * insig_lp[i + n_band*L]; } if( energy > 5.5f * st->EnergyLF ) { IsTransient_LF = 1; } st->EnergyLF = energy; } calc_tilt_bwe(insig, &tilt, L_FRAME32k); if( IsTransient == 1 && (tilt > 8.0 || st->clas > 1) ) { IsTransient = 0; st->TransientHangOver = 0; } if( IsTransient == 1 ) { mode = IsTransient; push_indice( st, IND_SWB_CLASS, mode, 2 ); /* Energy for the different bands and global energies */ global_gain = 0; for (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) { energy = EPSILON; for (n_coeff = swb_bwe_trans_subband[n_band]+st_offset; n_coeff < swb_bwe_trans_subband[n_band+1]+st_offset; n_coeff++) { energy += yos[n_coeff] * yos[n_coeff]; } global_gain += energy; SWB_fenv[n_band] = energy; } global_gain *= 0.5f; for (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) { SWB_fenv[n_band] = 10.0f * (float)log10( SWB_fenv[n_band]/swb_bwe_trans_subband_width[n_band] ) - Mean_env_tr[n_band]; } WB_tenv_orig = EPSILON; WB_tenv_syn = EPSILON; for(n_band = 0; n_band < SWB_TENV; n_band++) { SWB_tenv[n_band] = EPSILON; for(i = 0; i < L_SUBFR16k; i++) { SWB_tenv[n_band] += insig_hp[i + n_band*L_SUBFR16k] * insig_hp[i + n_band*L_SUBFR16k]; } for(i=0; i 1) { Rat_tenv = 1.0f; } for(n_band = 0; n_band < SWB_TENV; n_band++) { SWB_tenv[n_band] *= Rat_tenv; } max = SWB_tenv[0]; pos = 0; for(n_band = 1; n_band < SWB_TENV; n_band++) { if(SWB_tenv[n_band] > max) { max = SWB_tenv[n_band]; pos = n_band; } } max = SWB_tenv[0]; for(n_band = 1; n_band < SWB_TENV; n_band++) { if(SWB_tenv[n_band] > 5.0f*SWB_tenv[n_band-1]) { break; } } if(n_band < SWB_TENV) { energy = 0.0f; for(n_band = (pos+1); n_band < SWB_TENV; n_band++) { energy += SWB_tenv[n_band]; } if(pos == SWB_TENV-1) { energy = 0.0f; } else { energy /= (SWB_TENV-pos-1); } for(n_band = 0; n_band < pos; n_band++) { SWB_tenv[n_band] *= 0.5f; } SWB_tenv[pos] *= 1.005f; if(energy < SWB_tenv[pos]) { for(n_band = pos+1; n_band < SWB_TENV; n_band++) { SWB_tenv[n_band] *= 0.9f; } } } else { for(n_band = 1; n_band < SWB_TENV; n_band++) { if(SWB_tenv[n_band-1] > SWB_tenv[n_band]) { SWB_tenv[n_band-1] = 0.5f*(SWB_tenv[n_band-1]+SWB_tenv[n_band]); } else { SWB_tenv[n_band] = 0.5f*(SWB_tenv[n_band-1]+SWB_tenv[n_band]); } } for(n_band = 0; n_band < SWB_TENV; n_band++) { SWB_tenv[n_band] *= 0.9f; } } if(IsTransient_LF == 0 && coder_type == INACTIVE && st->TransientHangOver == 1) { for(n_band = 0; n_band < SWB_TENV; n_band++) { SWB_tenv[n_band] *= 0.5f; } for(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) { SWB_fenv[n_band] *= 0.05f; } } else { SWB_fenv[2] *= 0.1f; SWB_fenv[3] *= 0.05f; } for(n_band = 0; n_band < SWB_TENV; n_band++) { SWB_tenv_tmp[n_band] = (float) log10( SWB_tenv[n_band] + EPSILON ) * FAC_LOG2; if (SWB_tenv_tmp[n_band] > 15) { index = 15; } else if (SWB_tenv_tmp[n_band] < 0) { index = 0; } else { index = (short)(SWB_tenv_tmp[n_band]+0.5f); } push_indice( st, IND_SWB_TENV, index, 4 ); } MSVQ_Interpol_Tran(SWB_fenv, indice); push_indice( st, IND_SWB_FENV, indice[0], 7 ); push_indice( st, IND_SWB_FENV, indice[1], 6 ); } else { /* Energy for the different bands and global energies */ global_gain = 0; for (n_band = 0; n_band < SWB_FENV; n_band++) { energy = EPSILON; for (n_coeff = swb_bwe_subband[n_band]+st_offset; n_coeff < swb_bwe_subband[n_band+1]+st_offset; n_coeff++) { energy += yos[n_coeff] * yos[n_coeff]; } if (n_bandprev_mode = mode; st->prev_global_gain = global_gain; return mode; } static short decision_hq_generic_class ( const float *coefs, /* i: original MDCT spectrum */ const short hq_generic_offset /* i: frequency offset of high frequency spectrum */ ) { short i, k; float p, a, e; float p2a; float avgp2a; short nband; if ( hq_generic_offset == HQ_GENERIC_FOFFSET_24K4 ) { nband = 10; } else { nband = 8; } avgp2a = 0.f; for (k = 0; k < nband; k++) { a = 0.0f; p = 0.0f; for (i = swb_bwe_subband[k]+hq_generic_offset; i p) { p = e; } a += e; } if (a > 0.0f) { a *= swb_inv_bwe_subband_width[k]; p2a = 10.0f * (float) log10 (p / a); avgp2a += p2a; } } avgp2a /= (float)(nband); if ( avgp2a > 8.6f ) { return HQ_GENERIC_EXC1; } else { return HQ_GENERIC_EXC0; } } /*-------------------------------------------------------------------* * hq_generic_hf_encoding() * *-------------------------------------------------------------------*/ void hq_generic_hf_encoding( const float *coefs, /* i : MDCT coefficients of weighted original */ float *hq_generic_fenv, /* i/o: energy of SWB envelope */ const short hq_generic_offset, /* i : frequency offset for extracting energy */ Encoder_State *st, /* i/o: encoder state structure */ short *hq_generic_exc_clas /* o : HF excitation class */ ) { short n_coeff, n_band; float energy; float energy_factor[SWB_FENV], w_env[SWB_FENV]; short indice[HQ_GENERIC_NVQIDX]; short nenv; if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) { nenv = SWB_FENV; } else { nenv = SWB_FENV-2; } for( n_band = 0; n_band < nenv; n_band++ ) { energy = EPSILON; for( n_coeff = swb_bwe_subband[n_band]+hq_generic_offset; n_coeff < swb_bwe_subband[n_band+1] + hq_generic_offset; n_coeff++ ) { energy += coefs[n_coeff] * coefs[n_coeff]; } hq_generic_fenv[n_band] = energy; } if ( st->bwidth == FB ) { for( n_band = 0; n_band < DIM_FB; n_band++ ) { energy = EPSILON; for( n_coeff = fb_bwe_subband[n_band]; n_coeff < fb_bwe_subband[n_band+1]; n_coeff++ ) { energy += coefs[n_coeff] * coefs[n_coeff]; } hq_generic_fenv[n_band+nenv] = energy; } } energy_control( st, HQ_CORE, -1, -1, coefs, hq_generic_offset, energy_factor ); if ( st->hq_generic_speech_class == 1 ) { push_indice( st, IND_HQ_SWB_EXC_SP_CLAS, 1, 1 ); *hq_generic_exc_clas = HQ_GENERIC_SP_EXC; } else { *hq_generic_exc_clas = decision_hq_generic_class(coefs, hq_generic_offset); push_indice( st, IND_HQ_SWB_EXC_SP_CLAS, 0, 1 ); push_indice( st, IND_HQ_SWB_EXC_CLAS, *hq_generic_exc_clas, 1 ); } for( n_band = 0; n_band < nenv; n_band++ ) { hq_generic_fenv[n_band] *= energy_factor[n_band]; hq_generic_fenv[n_band] = 10.0f * (float)log10( hq_generic_fenv[n_band]*swb_inv_bwe_subband_width[n_band] ); } if ( st->bwidth == FB ) { for( n_band = 0; n_band < DIM_FB; n_band++ ) { hq_generic_fenv[n_band+nenv] = 10.0f * (float)log10( hq_generic_fenv[n_band+nenv]*fb_inv_bwe_subband_width[n_band] ); } } freq_weights( hq_generic_fenv, w_NOR, w_env, nenv ); for( n_band = 0; n_band < nenv; n_band++ ) { hq_generic_fenv[n_band] -= Mean_env[n_band]; } if ( st->bwidth == FB ) { for( n_band = 0; n_band < DIM_FB; n_band++ ) { hq_generic_fenv[n_band+nenv] -= Mean_env_fb[n_band]; } } /* Energy VQ */ if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) { msvq_interpol( hq_generic_fenv, w_env, indice ); } else { msvq_interpol_2( hq_generic_fenv, w_env, indice, nenv ); } if ( st->bwidth == FB ) { indice[5] = vqSimple_w( hq_generic_fenv+nenv, hq_generic_fenv+nenv, EnvCdbkFB, NULL, DIM_FB, N_CB_FB, 0 ); } push_indice( st, IND_SWB_FENV_HQ, indice[0], 5 ); push_indice( st, IND_SWB_FENV_HQ, indice[1], 7 ); push_indice( st, IND_SWB_FENV_HQ, indice[2], 6 ); push_indice( st, IND_SWB_FENV_HQ, indice[3], 5 ); if ( hq_generic_offset <= HQ_GENERIC_FOFFSET_24K4 ) { push_indice( st, IND_SWB_FENV_HQ, indice[4], 6 ); } else { push_indice( st, IND_SWB_FENV_HQ, indice[4], 5 ); } if ( st->bwidth == FB ) { push_indice( st, IND_FB_FENV_HQ, indice[5], 5 ); } for( n_band = 0; n_band < nenv; n_band++ ) { Word16 tmp,frac,exp; Word32 L_tmp; tmp = add((short)(hq_generic_fenv[n_band]*256),(short)(Mean_env[n_band]*256)); /*Q8 */ L_tmp = L_mult(tmp, 21771); /* 0.166096 in Q17 -> Q26 */ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ tmp = extract_l(Pow2(13, frac));/* Put 13 as exponent so that */ /* output of Pow2() will be: */ /* 16384 < Pow2() <= 32767 */ exp = sub(exp, 13); tmp = shl(tmp, add(exp,1)); /*Q1 */ hq_generic_fenv[n_band] = (float)tmp*0.5f;; /*Q1 */ } if ( st->bwidth == FB ) { for( n_band = 0; n_band < DIM_FB; n_band++ ) { Word16 tmp,frac,exp; Word32 L_tmp; tmp = add((short)(hq_generic_fenv[n_band + nenv]*128),(short)(Mean_env_fb[n_band]*128)); /*Q7 */ L_tmp = L_mult(tmp, 21771); /* 0.166096 in Q17 -> Q25 */ L_tmp = L_shr(L_tmp, 9); /* From Q25 to Q16 */ frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ tmp = extract_l(Pow2(13, frac));/* Put 13 as exponent so that */ /* output of Pow2() will be: */ /* 16384 < Pow2() <= 32767 */ exp = sub(exp, 13); tmp = shl(tmp, add(exp, 1));/*Q1 */ hq_generic_fenv[add(n_band,nenv)] = (float)tmp*0.5f; } } return; }