/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include "options.h" #include "prot.h" #include "rom_com.h" /*-------------------------------------------------------------------* * en_band_quant() * * Quantize the band envelop *-------------------------------------------------------------------*/ static short en_band_quant( /* o : quantization index */ float *en_band, /* i/o: (un)quantized envelope value */ const float *env_code, /* i : envelope codebook */ const short N /* i : codebook dimension */ ) { float maxerr, err; short i, j, ind; maxerr = FLT_MAX; ind = 0; for( i = 0; i < N; i++ ) { err = FLT_MIN; for (j = 0; j < 2; j++) { err += (en_band[j] - env_code[i*2+j]) * (en_band[j] - env_code[i*2+j]); } if (err < maxerr) { maxerr = err; ind = i; } } en_band[0] = env_code[2*ind]; en_band[1] = env_code[2*ind+1]; return( ind ); } /*-------------------------------------------------------------------* * swb_bwe_enc_hr() * * HR SWB BWE encoder *-------------------------------------------------------------------*/ void swb_bwe_enc_hr( Encoder_State *st, /* i/o: encoder state structure */ const float *new_input, /* i : input signal */ const short input_frame, /* i : frame length */ const short coder_type, /* i : coding type */ const short unbits /* i : number of core unused bits */ ) { short i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; short is_transient, pos; int x_norm[NSV_MAX*(WIDTH_BAND+1)], x_norm1[NSV_MAX*(WIDTH_BAND+1)]; float t_audio[L_FRAME48k], t_audio_tmp[L_FRAME48k]; float gain, gain2, en_band[N_BANDS_BWE_HR]; short ind1, ind2; short nq[NSV_MAX], nq2[NSV_MAX]; float tmpF, min_env; float en_noncoded; /*---------------------------------------------------------------------* * initializations *---------------------------------------------------------------------*/ ind2 = 0; /* only to suppress warnings */ Nsv2 = 0; /* only to suppress warnings */ gain2 = 0 ; /* only to suppress warnings */ en_noncoded = 0;/* only to suppress warnings */ /* reset memories in case that last frame was a different technology */ if( st->last_core == HQ_CORE || st->last_extl != st->extl ) { set_f( st->old_wtda_swb, 0, L_FRAME48k ); } /* calculate SWB BWE bit-budget (extension layer bit-rate + AVQ unused bits from the core layer) */ nBits = (short)(st->extl_brate) / 50 + unbits; nBits_total = nBits; /*---------------------------------------------------------------------* * detect transient frames *---------------------------------------------------------------------*/ is_transient = detect_transient( new_input, st, input_frame, coder_type ); push_indice( st, IND_HR_IS_TRANSIENT, is_transient, 1 ); /*---------------------------------------------------------------------* * OLA and MDCT *---------------------------------------------------------------------*/ wtda( new_input, t_audio_tmp, st->old_wtda_swb, ALDO_WINDOW, ALDO_WINDOW, input_frame ); direct_transform( t_audio_tmp, t_audio, is_transient, input_frame ); if( is_transient ) { nBits = -1; /* is_transient flag */ nBits_block = nBits_total / NUM_TIME_SWITCHING_BLOCKS; nBits += nBits_total % NUM_TIME_SWITCHING_BLOCKS; /* set width of noncoded (blind estimated) spectrum */ if( st->extl == SWB_BWE_HIGHRATE ) { width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; } else /* st->extl == FB_BWE_HIGHRATE */ { width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; } /*---------------------------------------------------------------------* * transient frames: processing in blocks (subframes) *---------------------------------------------------------------------*/ for( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) { nBits += nBits_block; /* compute energy of noncoded (14.4-20kHz) spectrum */ if( st->extl == FB_BWE_HIGHRATE ) { en_noncoded = sum2_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_END_FREQ_COEF, width_noncoded ) + 0.001f; en_noncoded = (float)sqrt( en_noncoded / width_noncoded ); } /* keep only frequencies in interest */ set_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS, 0, NUM_TRANS_START_FREQ_COEF ); set_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS, 0, (input_frame-L_FRAME32k)/NUM_TIME_SWITCHING_BLOCKS ); /*---------------------------------------------------------------------* * global gain coding *---------------------------------------------------------------------*/ /* compute and quantize global energy */ gain = sum2_f( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_START_FREQ_COEF, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR ) + 0.001f; gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR); ind1 = gain_quant( &gain, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); nBits -= NBITS_GLOB_GAIN_BWE_HR; /* normalization with global gain */ tmpF = 1/gain; for( i=0; iextl == SWB_BWE_HIGHRATE ) { en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; } else /* st->extl == FB_BWE_HIGHRATE */ { en_noncoded /= (gain * en_band[N_BANDS_TRANS_BWE_HR-1]); ind1 = 0; if( en_noncoded < BWE_HR_TRANS_EN_LIMIT1 ) { ind1 = 1; en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT1; } else if( en_noncoded < BWE_HR_TRANS_EN_LIMIT2 ) { ind1 = 2; en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT2; } else if( en_noncoded < BWE_HR_TRANS_EN_LIMIT3 ) { ind1 = 3; en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1] * BWE_HR_TRANS_EN_LIMIT3; } else { en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; } push_indice( st, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); nBits -= NBITS_HF_GAIN_BWE_HR; } /*---------------------------------------------------------------------* * AVQ coding (quantize normalized spectrum) *---------------------------------------------------------------------*/ Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; AVQ_cod( t_audio + k*input_frame/NUM_TIME_SWITCHING_BLOCKS + NUM_TRANS_START_FREQ_COEF, x_norm, nBits, Nsv ); AVQ_encmux( st, st->extl, x_norm, &nBits, Nsv, nq ); } } else /* !is_transient */ { nBits--; /* is_transient flag */ /*---------------------------------------------------------------------* * processing of normal (non-transient) frames *---------------------------------------------------------------------*/ /* set width of noncoded (blind estimated) spectrum */ if( st->extl == SWB_BWE_HIGHRATE ) { width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; } else /* st->extl == FB_BWE_HIGHRATE */ { width_noncoded = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_END_FREQ_COEF; } /* compute energy of noncoded (14.4-20kHz) spectrum */ if( st->extl == FB_BWE_HIGHRATE ) { en_noncoded = sum2_f( t_audio + NUM_NONTRANS_END_FREQ_COEF, width_noncoded ) + 0.001f; en_noncoded = (float)sqrt( en_noncoded / width_noncoded ); } /* keep only frequencies in interest */ set_f( t_audio, 0, NUM_NONTRANS_START_FREQ_COEF ); set_f( t_audio + NUM_NONTRANS_END_FREQ_COEF, 0, input_frame-NUM_NONTRANS_END_FREQ_COEF ); /*---------------------------------------------------------------------* * global gain coding *---------------------------------------------------------------------*/ /* compute and quantize global gain */ gain = sum2_f( t_audio + NUM_NONTRANS_START_FREQ_COEF, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR ) + 0.001f; gain = (float)sqrt(gain) / (WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR); ind1 = gain_quant( &gain, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); nBits -= NBITS_GLOB_GAIN_BWE_HR; /* normalization with global gain */ tmpF = 1/gain; for( i=0; i NBITS_THRESH_BWE_HR ) { i = NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF; mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, t_audio_tmp, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF ); } else { /* reorder the spectrum */ ind1 = (pos*64 + pos/2 * WIDTH_BAND); mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF, t_audio_tmp, ind1 ); ind2 = ((pos+1)*64 + (pos+1)/2 * WIDTH_BAND); mvr2r( t_audio + NUM_NONTRANS_START_FREQ_COEF + ind2, t_audio_tmp + ind1, NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - ind2 ); i = ind1 + NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF - ind2; } /*---------------------------------------------------------------------* * estimate energy of noncoded spectrum (14.4-20kHz) *---------------------------------------------------------------------*/ if( st->extl == SWB_BWE_HIGHRATE ) { en_noncoded = 0.5f * min_env; } else /* st->extl == FB_BWE_HIGHRATE */ { en_noncoded /= (gain * min_env); ind1 = 0; if( en_noncoded < BWE_HR_NONTRANS_EN_LIMIT1 ) { ind1 = 1; en_noncoded = 0.5f * min_env * BWE_HR_NONTRANS_EN_LIMIT1; } else if( en_noncoded > BWE_HR_NONTRANS_EN_LIMIT2 ) { ind1 = 2; en_noncoded = min_env * BWE_HR_NONTRANS_EN_LIMIT2; } else if( en_noncoded > BWE_HR_NONTRANS_EN_LIMIT3 ) { ind1 = 3; en_noncoded = min_env * BWE_HR_NONTRANS_EN_LIMIT3; } else { en_noncoded = 0.5f * min_env; } push_indice( st, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); nBits -= NBITS_HF_GAIN_BWE_HR; } /*---------------------------------------------------------------------* * AVQ coding (quantize normalized spectrum) *---------------------------------------------------------------------*/ Nsv = i / WIDTH_BAND; AVQ_cod( t_audio_tmp, x_norm, nBits, Nsv ); AVQ_encmux( st, st->extl, x_norm, &nBits, Nsv, nq ); /*---------------------------------------------------------------------* * second stage coding *---------------------------------------------------------------------*/ if( nBits >= 9 + NBITS_GLOB_GAIN_BWE_HR && sum_s( nq, Nsv) > 0 ) { /* select spectrum of the second stage coding */ k = 0; for( i=0; i 396 ) { Nsv2 = 33; } else { Nsv2 = nBits/12; } /* second stage global gain estimation and coding */ gain2 = sum2_f( t_audio, Nsv2*WIDTH_BAND ) + 0.001f; gain2 = (float)(16*sqrt( gain2 / (Nsv2*WIDTH_BAND) )); ind1 = gain_quant( &gain2, MIN_GLOB_GAIN_BWE_HR, MAX_GLOB_GAIN_BWE_HR, NBITS_GLOB_GAIN_BWE_HR ); push_indice( st, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); nBits -= NBITS_GLOB_GAIN_BWE_HR; /* normalize with global gain */ gain2 *= 0.0625f; /* 1/16 */ tmpF = 1/gain2; for( i=0; iextl, x_norm1, &nBits, Nsv2, nq2 ); } } /* write unused bits */ while( nBits > 0 ) { i = min( nBits, 16 ); push_indice( st, IND_UNUSED, 0, i ); nBits -= i; } return; }