/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include "options.h" #include "prot.h" #include "rom_com.h" /*---------------------------------------------------------------------* * bass_pf_enc() * * Low-frequency postfiltering, decoder parammeter estimation *---------------------------------------------------------------------*/ float bass_pf_enc( const float *orig, /* (i) : 12.8kHz original signal */ const float *syn, /* (i) : 12.8kHz synthesis to postfilter */ const float pitch_buf[], /* (i) : Pitch gain for all subframes (gainT_sf[16]) */ const float gainT_sf[], /* (i) : Pitch gain for all subframes (gainT_sf[16]) */ const short l_frame, /* (i) : frame length (should be multiple of l_subfr)*/ const short l_subfr_in, /* (i) : sub-frame length (80/64) */ float mem_bpf[], /* i/o : memory state [2*L_FILT16k] */ float mem_error_bpf[], /* i/o : memory state [2*L_FILT16k] */ int *gain_factor_param, /* (o) : quantized gain factor */ const short mode, /* (i) : coding mode of adapt bpf */ float *mem_deemph_err, /* o : Error deemphasis memory */ float *lp_ener /* o : long_term error signal energy */ ) { int i, j, sf, i_subfr, T, lg, l_subfr, l_filt; float d,n, snr, nrg1,nrg2, gain,nrg,tmp; float noise_buf[L_FILT16k+(2*L_SUBFR)], *noise, *noise_in; float error_buf[L_FILT16k+(2*L_SUBFR)], *error, *error_in; float cross_n_d, nrg_n; const float *pFilt; float ener2; if ( l_frame!=L_FRAME16k ) { pFilt = filt_lp; l_filt = L_FILT; } else { pFilt = filt_lp_16kHz; l_filt = L_FILT16k; } noise = noise_buf + l_filt; noise_in = noise_buf + 2*l_filt; error = error_buf + l_filt; error_in = error_buf + 2*l_filt; sf = 0; snr=0.f; nrg_n=1e-6f; cross_n_d = 0.f; l_subfr = l_subfr_in; for (i_subfr=0; i_subfr<l_frame; i_subfr+=l_subfr, sf++) { T = (int)pitch_buf[sf]; gain = gainT_sf[sf]; if (gain > 1.0f) gain = 1.0f; if (gain < 0.0f) gain = 0.0f; lg = l_frame - T - i_subfr; if (lg < 0) lg = 0; if (lg > l_subfr) lg = l_subfr; if (gain > 0) { tmp = 0.01f; nrg=0.01f; for (i=0; i<lg; i++) { tmp += syn[i+i_subfr] * (0.5f*syn[i+i_subfr-T] + 0.5f*syn[i+i_subfr+T]); nrg += (0.5f*syn[i+i_subfr-T] + 0.5f*syn[i+i_subfr+T])*(0.5f*syn[i+i_subfr-T] + 0.5f*syn[i+i_subfr+T]); } for (i=lg; i<l_subfr; i++) { tmp += syn[i+i_subfr]*syn[i+i_subfr-T]; nrg += syn[i+i_subfr-T]*syn[i+i_subfr-T]; } gain=tmp/nrg; if(gain>1.0f) { gain=1.0f; } else if(gain<0.f) { gain=0.f; } ener2=0.01f; for (i=0; i<lg; i++) { error[i] = gain * (syn[i+i_subfr] - 0.5f*syn[i+i_subfr-T] - 0.5f*syn[i+i_subfr+T]); error[i] = error[i] + 0.9f* *mem_deemph_err; *mem_deemph_err = error[i]; ener2 +=error[i]*error[i]; } for (i=lg; i<l_subfr; i++) { error[i] = 0.5f*gain * (syn[i+i_subfr] - syn[i+i_subfr-T]); error[i] = error[i] + 0.9f* *mem_deemph_err; *mem_deemph_err = error[i]; ener2 +=error[i]*error[i]; } ener2=(float) (10.f*log10(ener2)); *lp_ener = (float)(0.99f* *lp_ener + 0.01f*ener2); ener2=(float)pow(10.f,0.1f* *lp_ener); tmp=0.5f*tmp/(nrg+ener2); if(tmp>0.5f) { tmp=0.5f; } else if(tmp<0.f) { tmp=0.0f; } for (i=0; i<lg; i++) { noise_in[i] = tmp * (syn[i+i_subfr] - 0.5f*syn[i+i_subfr-T] - 0.5f*syn[i+i_subfr+T]); error_in[i] =(orig[i+i_subfr]-syn[i+i_subfr]); } for (i=lg; i<l_subfr; i++) { noise_in[i] = tmp * (syn[i+i_subfr] - syn[i+i_subfr-T]); noise_in[i] *= 0.5f; error_in[i] =(orig[i+i_subfr]-syn[i+i_subfr]); } } else { set_zero(noise_in, l_subfr); set_zero(error_in, l_subfr); } mvr2r(mem_bpf, noise_buf, 2*l_filt); mvr2r(noise_buf+l_subfr, mem_bpf, 2*l_filt); mvr2r(mem_error_bpf, error_buf, 2*l_filt); mvr2r(error_buf+l_subfr, mem_error_bpf, 2*l_filt); nrg1=1e-6f; nrg2=1e-6f; /* substract from voiced speech low-pass filtered noise */ for (i=0; i<l_subfr; i++) { n = pFilt[0] * noise[i]; d = error[i]; for(j=1; j<=l_filt; j++) { n += pFilt[j] * (noise[i-j] + noise[i+j]); } /*for optimal g*/ nrg_n += n*n; cross_n_d += n*d; /*for evaluating SNR*/ nrg1 += (d+n)*(d+n); nrg2 += d*d; } /*SegSNR*/ snr += (float)log10( nrg2/nrg1 ); } /*Compute and quantize optimal gain*/ /* optimal gain = -<n,d>/<n,n> */ if(mode==2) { *gain_factor_param = (int)(-2.f*(cross_n_d/nrg_n)+0.5f); if(*gain_factor_param>3) { *gain_factor_param=3; } else if(*gain_factor_param<0) { *gain_factor_param=0; } /*If optimal gain negatif or zero but snr still positif->gain=0.5f*/ if(snr>0.f && *gain_factor_param==0) { *gain_factor_param=1; } } else { *gain_factor_param=2; } return(snr); }