/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include "options.h" #include "cnst.h" #include "prot.h" #include "rom_com.h" /*---------------------------------------------------------------------* * Local functions *---------------------------------------------------------------------*/ static void find_cn( const float xn[], const float Ap[], const float *p_Aq, float cn[] ); /*-----------------------------------------------------------------* * Transform domain contribution encoding *-----------------------------------------------------------------*/ void transf_cdbk_enc( Encoder_State *st, /* i/o: encoder state structure */ const long core_brate, /* i : core bitrate */ const short extl, /* i : extension layer */ const short coder_type, /* i : coding type */ const short harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ const short i_subfr, /* i : subframe index */ const short tc_subfr, /* i : TC subframe index */ float cn[], /* i/o: target vector in residual domain */ float exc[], /* i/o: pointer to excitation signal frame */ const float *p_Aq, /* i : 12k8 Lp coefficient */ const float Ap[], /* i : weighted LP filter coefficients */ const float h1[], /* i : weighted filter input response */ float xn[], /* i/o: target vector */ float xn2[], /* i/o: target vector for innovation search */ float y1[], /* i/o: zero-memory filtered adaptive excitation */ const float y2[], /* i : zero-memory filtered innovative excitation */ const float Es_pred, /* i : predicited scaled innovation energy */ float *gain_pit, /* i/o: adaptive excitation gain */ const float gain_code, /* i : innovative excitation gain */ float g_corr[], /* o : ACELP correlation values */ const short clip_gain, /* i : adaptive gain clipping flag */ float *mem_deemp, /* i/o: prequantizer deemhasis memory */ float *mem_preemp, /* i/o: prequantizer preemhasis memory */ float *gain_preQ, /* o : prequantizer excitation gain */ float code_preQ[], /* o : prequantizer excitation */ short *unbits /* o : number of AVQ unused bits */ ) { short i, index, nBits, Nsv; float x_in[L_SUBFR], x_tran[L_SUBFR], temp; int x_norm[L_SUBFR+L_SUBFR/WIDTH_BAND]; float corr, ener; short nq[L_SUBFR/WIDTH_BAND]; /*--------------------------------------------------------------* * Set bit-allocation *--------------------------------------------------------------*/ Nsv = 8; nBits = AVQ_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ(tc_subfr))]; /* increase # of AVQ allocated bits by unused bits from the previous subframe */ nBits += (*unbits); /*--------------------------------------------------------------* * Compute/Update target * For inactive frame, find target in residual domain * Deemphasis *--------------------------------------------------------------*/ if ( coder_type == INACTIVE ) { for( i=0; i ACELP_24k40 && core_brate <= ACELP_32k && !harm_flag_acelp ) { mvr2r( x_in, x_tran, L_SUBFR ); } else { edct2( L_SUBFR, -1, x_in, x_tran, ip_edct2_64, w_edct2_64 ); } /*--------------------------------------------------------------* * Split algebraic vector quantizer based on RE8 lattice *--------------------------------------------------------------*/ AVQ_cod( x_tran, x_norm, nBits, Nsv ); /*--------------------------------------------------------------* * Find prequantizer excitation gain * Quantize the gain *--------------------------------------------------------------*/ corr = 0; ener = 1e-6f; for (i = 0; i < Nsv*8; i++) { corr += x_tran[i]*(float)x_norm[i]; ener += (float)x_norm[i]*(float)x_norm[i]; } *gain_preQ = corr/ener; if ( coder_type == INACTIVE ) { *gain_preQ /= gain_code; if( core_brate == ACELP_64k ) { index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT_64k, G_AVQ_DELTA_INACT_64k, (1 << G_AVQ_BITS) ); } else if( core_brate == ACELP_48k ) { index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT_48k, G_AVQ_DELTA_INACT_48k, (1 << G_AVQ_BITS) ); } else { index = usquant( *gain_preQ, gain_preQ, G_AVQ_MIN_INACT, G_AVQ_DELTA_INACT, (1 << G_AVQ_BITS) ); } *gain_preQ *= gain_code; } else { if( Es_pred < 0 ) { temp = 0.25f * fabs(Es_pred); } else { temp = Es_pred; } *gain_preQ /= temp; if( core_brate > ACELP_24k40 && core_brate <= ACELP_32k ) { index = gain_quant( gain_preQ, 0.1f*G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); } else { index = gain_quant( gain_preQ, G_AVQ_MIN, G_AVQ_MAX, G_AVQ_BITS ); } *gain_preQ *= temp; } push_indice( st, IND_AVQ_GAIN, index, G_AVQ_BITS ); /*--------------------------------------------------------------* * Encode and multiplex subvectors into bit-stream *--------------------------------------------------------------*/ AVQ_encmux( st, -1, x_norm, &nBits, Nsv, nq ); /* save # of AVQ unused bits for next subframe */ *unbits = nBits; /* at the last subframe, write AVQ unused bits */ if( i_subfr == 4*L_SUBFR && extl != SWB_BWE_HIGHRATE && extl != FB_BWE_HIGHRATE ) { while( *unbits > 0 ) { i = min(*unbits, 16); push_indice( st, IND_UNUSED, 0, i ); *unbits -= i; } } /*--------------------------------------------------------------* * DCT transform *--------------------------------------------------------------*/ for( i=0; i ACELP_24k40 && core_brate <= ACELP_32k && !harm_flag_acelp ) { mvr2r( x_tran, code_preQ, L_SUBFR ); } else { edct2( L_SUBFR, 1, x_tran, code_preQ, ip_edct2_64, w_edct2_64 ); } /*--------------------------------------------------------------* * Preemphasise *--------------------------------------------------------------*/ /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */ if( (nq[7] != 0) && (st->last_nq_preQ - nq[0] > 7) ) { *mem_preemp /= 16; } st->last_nq_preQ = nq[7]; preemph( code_preQ, FAC_PRE_AVQ, L_SUBFR, mem_preemp ); /*--------------------------------------------------------------* * For inactive segments * - Zero-memory filtered pre-filter excitation * - Update of targets and gain_pit * For active segments * - Update xn[L_subfr-1] for updating the memory of the weighting filter *--------------------------------------------------------------*/ if ( coder_type == INACTIVE ) { temp = code_preQ[0] * h1[L_SUBFR-1]; for( i=1; i 0.95f ) { *gain_pit = 0.95f; } updt_tar( xn, xn2, y1, *gain_pit, L_SUBFR ); } st->use_acelp_preq = 1; return; } /*-------------------------------------------------------------------* * Find target in residual domain - cn[] *-------------------------------------------------------------------*/ static void find_cn( const float xn[], /* i : target signal */ const float Ap[], /* i : weighted LP filter coefficients */ const float *p_Aq, /* i : 12k8 LP coefficients */ float cn[] /* o : target signal in residual domain */ ) { float tmp, tmp_fl[L_SUBFR+M]; set_f( tmp_fl, 0, M ); mvr2r( xn, tmp_fl+M, L_SUBFR ); tmp = 0.0f; preemph( tmp_fl+M, PREEMPH_FAC_16k, L_SUBFR, &tmp ); syn_filt( Ap, M, tmp_fl+M, tmp_fl+M, L_SUBFR, tmp_fl, 0 ); residu( p_Aq, M, tmp_fl+M, cn, L_SUBFR ); return; } /*---------------------------------------------------------------* * gain_quant() * * Quantization of gains between the specified range * using the specified number of levels. *---------------------------------------------------------------*/ short gain_quant( /* o: quantization index */ float *gain, /* i/o: quantized gain */ const float min, /* i: value of lower limit */ const float max, /* i: value of upper limit */ const short bits /* i: number of bits to quantize */ ) { short index, levels; float tmp, c_min, c_mult; levels = 1< levels-1 ) { index = levels-1; } *gain = (float)pow( 10.0, (((float)index)/c_mult) + c_min ); return(index); }