Loading lib_com/ivas_cnst.h +20 −0 Original line number Diff line number Diff line Loading @@ -1677,6 +1677,26 @@ typedef enum #define IVAS_LIMITER_THRESHOLD 32729 /* -0.01 dBFS */ #define IVAS_LIMITER_ATTACK_SECONDS 0.005f #ifdef ENHANCED_STEREO_DMX /*----------------------------------------------------------------------------------* * Stereo downmix EVS constants *----------------------------------------------------------------------------------*/ typedef enum { STEREO_DMX_EVS_PHA_IPD, STEREO_DMX_EVS_PHA_IPD2, STEREO_DMX_EVS_NO_PHA } STEREO_DMX_EVS_PHA; typedef enum { STEREO_DMX_EVS_PRC_POC, STEREO_DMX_EVS_PRC_PHA, } STEREO_DMX_EVS_PRC; #endif #endif /* clang-format on */ Loading lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,7 @@ #define ISSUE_24_CLEANUP_MCT_LFE /* Issue 24: Cleanup LFE path withing MCT */ #define ENHANCED_STEREO_DMX /* Orange : Contribution 48 - Enhanced stereo downmix. */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ Loading lib_enc/ivas_stat_enc.h +34 −0 Original line number Diff line number Diff line Loading @@ -982,9 +982,43 @@ typedef struct stereo_dmx_evs_phase_only_correlation_structure } STEREO_DMX_EVS_POC_DATA, *STEREO_DMX_EVS_POC_HANDLE; #ifdef ENHANCED_STEREO_DMX typedef struct stereo_dmx_evs_correlation_filter_structure { float ipd_ff[L_FRAME48k / 2 + 1]; float Pr[L_FRAME48k / 2 + 1]; float Pi[L_FRAME48k / 2 + 1]; int32_t pha_len; int32_t fad_len; float win[L_FRAME48k]; float fad_g[L_FRAME48k]; float *p_prev_taps[CPE_CHANNELS], prev_taps[CPE_CHANNELS][L_FRAME48k]; float *p_curr_taps[CPE_CHANNELS], curr_taps[CPE_CHANNELS][L_FRAME48k]; float data_mem[CPE_CHANNELS][L_FRAME48k*2]; STEREO_DMX_EVS_PHA curr_pha; STEREO_DMX_EVS_PHA prev_pha; int16_t pha_hys_cnt; int16_t prc_thres; STEREO_DMX_EVS_PRC curr_prc; STEREO_DMX_EVS_PRC prev_prc; int16_t prc_hys_cnt; float fad_g_prc[L_FRAME48k]; int32_t fad_len_prc; } STEREO_DMX_EVS_PHA_DATA, *STEREO_DMX_EVS_PHA_HANDLE; #endif typedef struct stereo_dmx_evs_enc_data_structure { STEREO_DMX_EVS_POC_HANDLE hPOC; #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA; #endif float itd; Loading lib_enc/ivas_stereo_dmx_evs.c +526 −0 Original line number Diff line number Diff line Loading @@ -65,13 +65,37 @@ #define Q_BAND 0.25f #ifdef ENHANCED_STEREO_DMX #define STEREO_DMX_EVS_PHA_LEN_16 20.0f #define STEREO_DMX_EVS_FAD_LEN_16 20.0f #define STEREO_DMX_EVS_PHA_LEN_32 10.0f #define STEREO_DMX_EVS_FAD_LEN_32 10.0f #define STEREO_DMX_EVS_PHA_LEN_48 5.0f #define STEREO_DMX_EVS_FAD_LEN_48 5.0f #define STEREO_DMX_EVS_ISD_THRES 1.3f #define STEREO_DMX_EVS_ISD_DIST_THRES 0.42f #define STEREO_DMX_EVS_SWTCH_HYS_THRES 1 #define STEREO_DMX_EVS_SWTCH_PRC_THRES 0.6f #define STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES 1 #define STEREO_DMX_EVS_FADE_LEN_PRC 20.0f #endif /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ static void estimate_itd_wnd_fft( const float *input, float *specr, float *speci, const float *rfft_coef, const float *wnd, const int16_t input_frame ); #ifdef ENHANCED_STEREO_DMX static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE hPHA, const float wnd[], const float rfft_coef[], const float specLr[], const float specLi[], const float specRr[], const float specRi[], const int16_t input_frame ); static ivas_error estimate_itd( float *corr, STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE hPHA, const float srcL[], const float srcR[], float itd[], const int16_t input_frame ); # else static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, const float wnd[], const float rfft_coef[], const float specLr[], const float specLi[], const float specRr[], const float specRi[], const int16_t input_frame ); static ivas_error estimate_itd( float *corr, STEREO_DMX_EVS_POC_HANDLE hPOC, const float srcL[], const float srcR[], float itd[], const int16_t input_frame ); #endif static void weighted_ave( const float src1[], const float src2[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); static void adapt_gain( const float src[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); static void create_M_signal( const float srcL[], const float srcR[], float dmx[], const float w_curr, const int16_t input_frame, const float wnd[], float *w_prev, float *dmx_energy, float *src_energy ); Loading Loading @@ -141,6 +165,9 @@ void estimate_itd_wnd_fft( static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, /* i/o: phase only correlation structure */ #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA, /* i/o : correlation filter structure */ #endif const float wnd[], /* i : window coef */ const float rfft_coef[], /* i : RFFT coef */ const float specLr[], /* i : Lch real-part spectra */ Loading @@ -167,9 +194,23 @@ static void calc_poc( int16_t cos_step, cos_max; float eps_cos, eps_sin, EPS; #ifdef ENHANCED_STEREO_DMX float Nr, Ni, Dr, Di, ISD, isd_rate; int16_t isd_cnt, n, end8; float *Pr, *Pi, *ipd_ff; float tPr, tPi, Pn; float *p_curr_taps, *p_curr_taps_l2r; double energy; #endif /* Initialization */ iN = 1.0f / (float) input_frame; #ifdef ENHANCED_STEREO_DMX Pr = hPHA->Pr; Pi = hPHA->Pi; #endif s = hPOC->sin; P = hPOC->P; n0 = input_frame / 2; Loading Loading @@ -337,6 +378,183 @@ static void calc_poc( } specPOr[n0] = sign( specLr[n0] * specRr[n0] ) * wnd[i * step + bias] * gamma; #ifdef ENHANCED_STEREO_DMX end8 = 160; // Memorize the filters N-1 for ( n = 0; n < CPE_CHANNELS; n++ ) { if (hPHA->p_curr_taps[n]) { hPHA->p_prev_taps[n] = hPHA->prev_taps[n]; mvr2r( hPHA->p_curr_taps[n], hPHA->p_prev_taps[n], hPHA->pha_len ); } else { hPHA->p_prev_taps[n] = NULL; } hPHA->p_curr_taps[n] = NULL; } // ISD isd_cnt = 0; for ( int i = 1; i <= end8 ; i++ ) { Nr = ( specLr[i] - specRr[i] ); Ni = ( specLi[i] - specRi[i] ); Dr = ( specLr[i] + specRr[i] ); Di = ( specLi[i] + specRi[i] ); ISD = sqrt( (Nr*Nr + Ni*Ni) / (Dr*Dr + Di*Di) ); if (ISD > STEREO_DMX_EVS_ISD_THRES) { isd_cnt++; } } isd_rate = (float)isd_cnt / (float)end8; if (isd_rate > STEREO_DMX_EVS_ISD_DIST_THRES) { if ( hPHA->curr_pha != STEREO_DMX_EVS_PHA_IPD ) { if (hPHA->prev_pha == STEREO_DMX_EVS_PHA_IPD) { hPHA->pha_hys_cnt += 1; } else { hPHA->pha_hys_cnt = 0; } if (hPHA->pha_hys_cnt >= STEREO_DMX_EVS_SWTCH_HYS_THRES) { hPHA->curr_pha = STEREO_DMX_EVS_PHA_IPD; } } hPHA->prev_pha = STEREO_DMX_EVS_PHA_IPD; } else { if (hPHA->curr_pha != STEREO_DMX_EVS_PHA_IPD2) { if (hPHA->prev_pha == STEREO_DMX_EVS_PHA_IPD2) { hPHA->pha_hys_cnt += 1; } else { hPHA->pha_hys_cnt = 0; } if (hPHA->pha_hys_cnt >= STEREO_DMX_EVS_SWTCH_HYS_THRES) { hPHA->curr_pha = STEREO_DMX_EVS_PHA_IPD2; } } hPHA->prev_pha = STEREO_DMX_EVS_PHA_IPD2; } if (hPHA->curr_pha != STEREO_DMX_EVS_NO_PHA) { ipd_ff = hPHA->ipd_ff; for ( i = 0; i < ( end8 + 1 ); i++ ) { tPr = ( specLr[i] * specRr[i] + specLi[i] * specRi[i] ); tPi = ( specLi[i] * specRr[i] - specLr[i] * specRi[i] ); Pn = sqrt( tPr * tPr + tPi * tPi ); tPr /= (Pn+EPSILON); tPi /= (Pn+EPSILON); if (fabs(tPr*tPi) < EPSILON) { tPr = 1.; tPi = 0.; } Pr[i] = ipd_ff[i]*Pr[i] + (1.0 - ipd_ff[i])*tPr; Pi[i] = ipd_ff[i]*Pi[i] + (1.0 - ipd_ff[i])*tPi; } for ( i = end8+1; i < n0; i++ ) { Pr[i] = 1.0; Pi[i] = 0.0; } if (hPHA->curr_pha == STEREO_DMX_EVS_PHA_IPD) { // PHA R2L hPHA->p_curr_taps[1] = hPHA->curr_taps[1]; p_curr_taps = hPHA->p_curr_taps[1]; p_curr_taps[0] = Pr[0]; p_curr_taps[1] = Pr[n0]; for ( i = 1; i < n0; i++ ) { p_curr_taps[i * 2] = Pr[i]; p_curr_taps[i * 2 + 1] = Pi[i]; } rfft( p_curr_taps, rfft_coef, input_frame, +1 ); } else { // PHA R2L hPHA->p_curr_taps[1] = hPHA->curr_taps[1]; p_curr_taps = hPHA->p_curr_taps[1]; for ( i = 1; i < n0; i++ ) { Pn = sqrt( Pr[i] * Pr[i] + Pi[i] * Pi[i] ); tPr = Pr[i]/(Pn+EPSILON); p_curr_taps[i * 2] = sqrt((1.+tPr)/2.); p_curr_taps[i * 2 + 1] = sqrt((1.-tPr)/2.)*sign(Pi[i]); } p_curr_taps[0] = 1; p_curr_taps[1] = 1; rfft( p_curr_taps, rfft_coef, input_frame, +1 ); // PHA L2R hPHA->p_curr_taps[0] = hPHA->curr_taps[0]; p_curr_taps_l2r = hPHA->p_curr_taps[0]; p_curr_taps_l2r[0] = p_curr_taps[0]; for ( i = 1; i < input_frame; i++ ) { p_curr_taps_l2r[i] = p_curr_taps[input_frame-i]; } } } for ( n = 0; n < CPE_CHANNELS; n++ ) { if (hPHA->p_curr_taps[n]) { for ( i = 0; i < hPHA->pha_len; i++ ) { hPHA->p_curr_taps[n][i] *= hPHA->win[i]; } energy = 0; for ( i = 0; i < hPHA->pha_len; i++ ) { energy += hPHA->p_curr_taps[n][i] * hPHA->p_curr_taps[n][i]; } energy = sqrtf( energy ); for ( i = 0; i < hPHA->pha_len; i++ ) { hPHA->p_curr_taps[n][i] /= energy; } } } #endif rfft_buf[0] = specPOr[0]; rfft_buf[1] = specPOr[n0]; Loading Loading @@ -550,6 +768,9 @@ static float find_poc_peak( static ivas_error estimate_itd( float *corr, /* o : correlation */ STEREO_DMX_EVS_POC_HANDLE hPOC, /* i/o: phase only correlation structure */ #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA, /* i/o : correlation filter structure */ #endif const float srcL[], /* i : Lch input signal */ const float srcR[], /* i : Rch input signal */ float itd[], /* o : estimated itd */ Loading Loading @@ -598,7 +819,11 @@ static ivas_error estimate_itd( estimate_itd_wnd_fft( srcL, specLr, specLi, rfft_coef, hPOC->wnd, input_frame ); estimate_itd_wnd_fft( srcR, specRr, specRi, rfft_coef, hPOC->wnd, input_frame ); #ifdef ENHANCED_STEREO_DMX calc_poc( hPOC, hPHA, hPOC->wnd, rfft_coef, specLr, specLi, specRr, specRi, input_frame ); #else calc_poc( hPOC, hPOC->wnd, rfft_coef, specLr, specLi, specRr, specRi, input_frame ); #endif *corr = find_poc_peak( hPOC, itd, input_frame, STEREO_DMX_EVS_POC_W_FORGETTING ); return error; Loading Loading @@ -794,7 +1019,18 @@ void stereo_dmx_evs_enc( int16_t n; float dmx_weight, corr; float data_f[CPE_CHANNELS][L_FRAME48k]; #ifdef ENHANCED_STEREO_DMX int16_t k, m; int32_t pha_len, fad_len; float mem_out_curr[CPE_CHANNELS][L_FRAME48k], mem_out_last[L_FRAME48k]; float *p_data_mem, *p_prev_taps, *p_curr_taps, *fad_g, *p_mem_out_curr, *p_data_f; float dmx_itd_data[L_FRAME48k], dmx_ipd_data[L_FRAME48k], *p_dmx_data; STEREO_DMX_EVS_PRC curr_prc; #else float dmx_data[L_FRAME48k]; #endif int16_t input_frame; input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); Loading @@ -810,6 +1046,186 @@ void stereo_dmx_evs_enc( set_f( data_f[1] + n_samples, 0.0f, input_frame - n_samples ); } #ifdef ENHANCED_STEREO_DMX estimate_itd( &corr, hStereoDmxEVS->hPOC, hStereoDmxEVS->hPHA, data_f[0], data_f[1], &hStereoDmxEVS->itd, input_frame ); pha_len = hStereoDmxEVS->hPHA->pha_len; fad_len = hStereoDmxEVS->hPHA->fad_len; fad_g = hStereoDmxEVS->hPHA->fad_g; for ( k = 0; k < CPE_CHANNELS; k++ ) { p_prev_taps = hStereoDmxEVS->hPHA->p_prev_taps[k]; p_curr_taps = hStereoDmxEVS->hPHA->p_curr_taps[k]; p_mem_out_curr = mem_out_curr[k]; p_data_f = data_f[k]; p_data_mem = hStereoDmxEVS->hPHA->data_mem[k]; mvr2r( &( p_data_mem[input_frame] ), p_data_mem, pha_len ); p_data_mem = &( p_data_mem[pha_len] ); mvr2r( p_data_f, p_data_mem, input_frame ); if (p_prev_taps) { for (n = 0; n < fad_len; n++) { mem_out_last[n] = 0; for ( m = 0; m < pha_len; m++ ) { mem_out_last[n] += p_data_mem[n - m] * p_prev_taps[m]; } mem_out_last[n] *= fad_g[fad_len - (1+n)]; } } if (p_curr_taps) { if (p_prev_taps == NULL) { for (n = 0; n < fad_len; n++) { mem_out_last[n] = fad_g[fad_len - (1+n)] * p_data_f[n]; } } for (n = 0; n < fad_len; n++) { p_mem_out_curr[n] = 0; for ( m = 0; m < pha_len; m++ ) { p_mem_out_curr[n] += p_data_mem[n - m] * p_curr_taps[m]; } p_mem_out_curr[n] = fad_g[n] * p_mem_out_curr[n] + mem_out_last[n]; } for (; n < input_frame; n++) { p_mem_out_curr[n] = 0; for (m = 0; m < pha_len; m++) { p_mem_out_curr[n] += p_data_mem[n - m] * p_curr_taps[m]; } } } else { if (p_prev_taps) { for (n = 0; n < fad_len; n++) { p_mem_out_curr[n] = fad_g[n] * p_data_f[n] + mem_out_last[n]; } mvr2r( &(p_data_f[fad_len]), &(p_mem_out_curr[fad_len]), input_frame-fad_len ); } else { mvr2r( p_data_f, p_mem_out_curr, input_frame ); } } } // poc if ( hStereoDmxEVS->itd ) { dmx_weight = ( ( hStereoDmxEVS->itd > 0 ) ? ( -1 ) : 1 ) * 0.5f * corr + 0.5f; } else { dmx_weight = 0.5f; } create_M_signal( data_f[0], data_f[1], dmx_itd_data, dmx_weight, input_frame, hStereoDmxEVS->s_wnd, hStereoDmxEVS->dmx_weight, hStereoDmxEVS->pre_dmx_energy, hStereoDmxEVS->aux_dmx_energy ); // pha for ( n=0; n < input_frame; n++ ) { dmx_ipd_data[n] = (mem_out_curr[0][n] + mem_out_curr[1][n])*0.5; } // prc switch curr_prc = hStereoDmxEVS->hPHA->curr_prc; if (abs((int16_t)hStereoDmxEVS->itd) > hStereoDmxEVS->hPHA->prc_thres) { if ( hStereoDmxEVS->hPHA->curr_prc != STEREO_DMX_EVS_PRC_POC ) { if (hStereoDmxEVS->hPHA->prev_prc == STEREO_DMX_EVS_PRC_POC) { hStereoDmxEVS->hPHA->prc_hys_cnt += 1; } else { hStereoDmxEVS->hPHA->prc_hys_cnt = 0; } if (hStereoDmxEVS->hPHA->prc_hys_cnt >= STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES) { hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_POC; } } hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_POC; } else { if ( hStereoDmxEVS->hPHA->curr_prc != STEREO_DMX_EVS_PRC_PHA ) { if (hStereoDmxEVS->hPHA->prev_prc == STEREO_DMX_EVS_PRC_PHA) { hStereoDmxEVS->hPHA->prc_hys_cnt += 1; } else { hStereoDmxEVS->hPHA->prc_hys_cnt = 0; } if (hStereoDmxEVS->hPHA->prc_hys_cnt >= STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES) { hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_PHA; } } hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_PHA; } if ( hStereoDmxEVS->hPHA->curr_prc == STEREO_DMX_EVS_PRC_POC ) { p_dmx_data = dmx_itd_data; if (curr_prc != hStereoDmxEVS->hPHA->curr_prc) { fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for (n = 0; n < fad_len; n++) { p_dmx_data[n] *= fad_g[n]; p_dmx_data[n] += (1.-fad_g[n]) * dmx_ipd_data[n]; } } } else { p_dmx_data = dmx_ipd_data; if (curr_prc != hStereoDmxEVS->hPHA->curr_prc) { fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for (n = 0; n < fad_len; n++) { p_dmx_data[n] *= fad_g[n]; p_dmx_data[n] += (1.-fad_g[n]) * dmx_itd_data[n]; } } } mvr2s( p_dmx_data, data, n_samples ); #else estimate_itd( &corr, hStereoDmxEVS->hPOC, data_f[0], data_f[1], &hStereoDmxEVS->itd, input_frame ); if ( hStereoDmxEVS->itd ) Loading @@ -826,6 +1242,8 @@ void stereo_dmx_evs_enc( mvr2s( dmx_data, data, n_samples ); #endif return; } Loading @@ -844,6 +1262,15 @@ ivas_error stereo_dmx_evs_init_encoder( STEREO_DMX_EVS_ENC_HANDLE hStereoDmxEVS; int16_t n, input_frame; #ifdef ENHANCED_STEREO_DMX int32_t f_len, pha_len, fad_len; float *win, *fad_g; float a_min, a_max, a_step, n0, itrh; float *ipd_ff; #endif input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); hStereoDmxEVS = NULL; Loading Loading @@ -933,6 +1360,97 @@ ivas_error stereo_dmx_evs_init_encoder( hStereoDmxEVS->hPOC->confidence = 0.0f; #ifdef ENHANCED_STEREO_DMX hStereoDmxEVS->hPHA = NULL; if ( ( hStereoDmxEVS->hPHA = (STEREO_DMX_EVS_PHA_HANDLE) malloc( sizeof( STEREO_DMX_EVS_PHA_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for STEREO_DMX_EVS_CORFILT_DATA\n" ) ); } for ( n = 0; n < CPE_CHANNELS; n++ ) { hStereoDmxEVS->hPHA->p_curr_taps[n] = NULL; hStereoDmxEVS->hPHA->p_prev_taps[n] = NULL; set_zero( hStereoDmxEVS->hPHA->data_mem[n], L_FRAME48k * 2 ); set_zero( hStereoDmxEVS->hPHA->curr_taps[n], L_FRAME48k ); } if ( input_Fs == 16000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_16 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_16 * input_Fs / 1000; } else if ( input_Fs == 32000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_32 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_32 * input_Fs / 1000; } else if ( input_Fs == 48000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_48 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_48 * input_Fs / 1000; } else { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid sampling frequency\n" ); } hStereoDmxEVS->hPHA->pha_len = f_len/2; pha_len = hStereoDmxEVS->hPHA->pha_len; fad_len = hStereoDmxEVS->hPHA->fad_len; win = hStereoDmxEVS->hPHA->win; set_zero( win, L_FRAME48k ); for ( n = 0; n < pha_len; n++ ) { win[n] = 0.5f * (1.0f + cosf( ( PI2 * ( n + 1 ) ) / ( ( f_len ) + 1 ) ) ); } fad_g = hStereoDmxEVS->hPHA->fad_g; for ( n = 0; n < fad_len; n++ ) { fad_g[n] = (float) n / (float)fad_len; } hStereoDmxEVS->hPHA->curr_pha = STEREO_DMX_EVS_NO_PHA; hStereoDmxEVS->hPHA->prev_pha = STEREO_DMX_EVS_NO_PHA; hStereoDmxEVS->hPHA->pha_hys_cnt = 0; // Compute the forgetting factor a_min = 0.8576958985908941; a_max = 0.9440608762859234; itrh = 60; n0 = input_frame / 2; a_step = ( a_min - a_max ) / (n0+1-itrh); ipd_ff = hStereoDmxEVS->hPHA->ipd_ff; for ( n = 0; n < itrh; n++ ) { ipd_ff[n] = a_max; } for ( ; n < ( n0 + 1 ); n++ ) { ipd_ff[n] = a_max + (n-itrh) * a_step; } hStereoDmxEVS->hPHA->prc_thres = STEREO_DMX_EVS_SWTCH_PRC_THRES * input_Fs / 1000; hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_POC; hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_POC; hStereoDmxEVS->hPHA->prc_hys_cnt = 0; hStereoDmxEVS->hPHA->fad_len_prc = STEREO_DMX_EVS_FADE_LEN_PRC * input_Fs / 1000; fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for ( n = 0; n < fad_len; n++ ) { fad_g[n] = (float) n / (float)fad_len; } #endif *hStereoDmxEVS_out = hStereoDmxEVS; return IVAS_ERR_OK; Loading Loading @@ -960,6 +1478,14 @@ void stereo_dmx_evs_close_encoder( ( *hStereoDmxEVS )->hPOC = NULL; } #ifdef ENHANCED_STEREO_DMX if ( ( *hStereoDmxEVS )->hPHA != NULL ) { free( ( *hStereoDmxEVS )->hPHA ); ( *hStereoDmxEVS )->hPHA = NULL; } #endif free( ( *hStereoDmxEVS ) ); ( *hStereoDmxEVS ) = NULL; Loading Loading
lib_com/ivas_cnst.h +20 −0 Original line number Diff line number Diff line Loading @@ -1677,6 +1677,26 @@ typedef enum #define IVAS_LIMITER_THRESHOLD 32729 /* -0.01 dBFS */ #define IVAS_LIMITER_ATTACK_SECONDS 0.005f #ifdef ENHANCED_STEREO_DMX /*----------------------------------------------------------------------------------* * Stereo downmix EVS constants *----------------------------------------------------------------------------------*/ typedef enum { STEREO_DMX_EVS_PHA_IPD, STEREO_DMX_EVS_PHA_IPD2, STEREO_DMX_EVS_NO_PHA } STEREO_DMX_EVS_PHA; typedef enum { STEREO_DMX_EVS_PRC_POC, STEREO_DMX_EVS_PRC_PHA, } STEREO_DMX_EVS_PRC; #endif #endif /* clang-format on */ Loading
lib_com/options.h +1 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,7 @@ #define ISSUE_24_CLEANUP_MCT_LFE /* Issue 24: Cleanup LFE path withing MCT */ #define ENHANCED_STEREO_DMX /* Orange : Contribution 48 - Enhanced stereo downmix. */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ Loading
lib_enc/ivas_stat_enc.h +34 −0 Original line number Diff line number Diff line Loading @@ -982,9 +982,43 @@ typedef struct stereo_dmx_evs_phase_only_correlation_structure } STEREO_DMX_EVS_POC_DATA, *STEREO_DMX_EVS_POC_HANDLE; #ifdef ENHANCED_STEREO_DMX typedef struct stereo_dmx_evs_correlation_filter_structure { float ipd_ff[L_FRAME48k / 2 + 1]; float Pr[L_FRAME48k / 2 + 1]; float Pi[L_FRAME48k / 2 + 1]; int32_t pha_len; int32_t fad_len; float win[L_FRAME48k]; float fad_g[L_FRAME48k]; float *p_prev_taps[CPE_CHANNELS], prev_taps[CPE_CHANNELS][L_FRAME48k]; float *p_curr_taps[CPE_CHANNELS], curr_taps[CPE_CHANNELS][L_FRAME48k]; float data_mem[CPE_CHANNELS][L_FRAME48k*2]; STEREO_DMX_EVS_PHA curr_pha; STEREO_DMX_EVS_PHA prev_pha; int16_t pha_hys_cnt; int16_t prc_thres; STEREO_DMX_EVS_PRC curr_prc; STEREO_DMX_EVS_PRC prev_prc; int16_t prc_hys_cnt; float fad_g_prc[L_FRAME48k]; int32_t fad_len_prc; } STEREO_DMX_EVS_PHA_DATA, *STEREO_DMX_EVS_PHA_HANDLE; #endif typedef struct stereo_dmx_evs_enc_data_structure { STEREO_DMX_EVS_POC_HANDLE hPOC; #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA; #endif float itd; Loading
lib_enc/ivas_stereo_dmx_evs.c +526 −0 Original line number Diff line number Diff line Loading @@ -65,13 +65,37 @@ #define Q_BAND 0.25f #ifdef ENHANCED_STEREO_DMX #define STEREO_DMX_EVS_PHA_LEN_16 20.0f #define STEREO_DMX_EVS_FAD_LEN_16 20.0f #define STEREO_DMX_EVS_PHA_LEN_32 10.0f #define STEREO_DMX_EVS_FAD_LEN_32 10.0f #define STEREO_DMX_EVS_PHA_LEN_48 5.0f #define STEREO_DMX_EVS_FAD_LEN_48 5.0f #define STEREO_DMX_EVS_ISD_THRES 1.3f #define STEREO_DMX_EVS_ISD_DIST_THRES 0.42f #define STEREO_DMX_EVS_SWTCH_HYS_THRES 1 #define STEREO_DMX_EVS_SWTCH_PRC_THRES 0.6f #define STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES 1 #define STEREO_DMX_EVS_FADE_LEN_PRC 20.0f #endif /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ static void estimate_itd_wnd_fft( const float *input, float *specr, float *speci, const float *rfft_coef, const float *wnd, const int16_t input_frame ); #ifdef ENHANCED_STEREO_DMX static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE hPHA, const float wnd[], const float rfft_coef[], const float specLr[], const float specLi[], const float specRr[], const float specRi[], const int16_t input_frame ); static ivas_error estimate_itd( float *corr, STEREO_DMX_EVS_POC_HANDLE hPOC, STEREO_DMX_EVS_PHA_HANDLE hPHA, const float srcL[], const float srcR[], float itd[], const int16_t input_frame ); # else static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, const float wnd[], const float rfft_coef[], const float specLr[], const float specLi[], const float specRr[], const float specRi[], const int16_t input_frame ); static ivas_error estimate_itd( float *corr, STEREO_DMX_EVS_POC_HANDLE hPOC, const float srcL[], const float srcR[], float itd[], const int16_t input_frame ); #endif static void weighted_ave( const float src1[], const float src2[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); static void adapt_gain( const float src[], float dst[], const float gain, const float old_gain, const int16_t input_frame, const float wnd[] ); static void create_M_signal( const float srcL[], const float srcR[], float dmx[], const float w_curr, const int16_t input_frame, const float wnd[], float *w_prev, float *dmx_energy, float *src_energy ); Loading Loading @@ -141,6 +165,9 @@ void estimate_itd_wnd_fft( static void calc_poc( STEREO_DMX_EVS_POC_HANDLE hPOC, /* i/o: phase only correlation structure */ #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA, /* i/o : correlation filter structure */ #endif const float wnd[], /* i : window coef */ const float rfft_coef[], /* i : RFFT coef */ const float specLr[], /* i : Lch real-part spectra */ Loading @@ -167,9 +194,23 @@ static void calc_poc( int16_t cos_step, cos_max; float eps_cos, eps_sin, EPS; #ifdef ENHANCED_STEREO_DMX float Nr, Ni, Dr, Di, ISD, isd_rate; int16_t isd_cnt, n, end8; float *Pr, *Pi, *ipd_ff; float tPr, tPi, Pn; float *p_curr_taps, *p_curr_taps_l2r; double energy; #endif /* Initialization */ iN = 1.0f / (float) input_frame; #ifdef ENHANCED_STEREO_DMX Pr = hPHA->Pr; Pi = hPHA->Pi; #endif s = hPOC->sin; P = hPOC->P; n0 = input_frame / 2; Loading Loading @@ -337,6 +378,183 @@ static void calc_poc( } specPOr[n0] = sign( specLr[n0] * specRr[n0] ) * wnd[i * step + bias] * gamma; #ifdef ENHANCED_STEREO_DMX end8 = 160; // Memorize the filters N-1 for ( n = 0; n < CPE_CHANNELS; n++ ) { if (hPHA->p_curr_taps[n]) { hPHA->p_prev_taps[n] = hPHA->prev_taps[n]; mvr2r( hPHA->p_curr_taps[n], hPHA->p_prev_taps[n], hPHA->pha_len ); } else { hPHA->p_prev_taps[n] = NULL; } hPHA->p_curr_taps[n] = NULL; } // ISD isd_cnt = 0; for ( int i = 1; i <= end8 ; i++ ) { Nr = ( specLr[i] - specRr[i] ); Ni = ( specLi[i] - specRi[i] ); Dr = ( specLr[i] + specRr[i] ); Di = ( specLi[i] + specRi[i] ); ISD = sqrt( (Nr*Nr + Ni*Ni) / (Dr*Dr + Di*Di) ); if (ISD > STEREO_DMX_EVS_ISD_THRES) { isd_cnt++; } } isd_rate = (float)isd_cnt / (float)end8; if (isd_rate > STEREO_DMX_EVS_ISD_DIST_THRES) { if ( hPHA->curr_pha != STEREO_DMX_EVS_PHA_IPD ) { if (hPHA->prev_pha == STEREO_DMX_EVS_PHA_IPD) { hPHA->pha_hys_cnt += 1; } else { hPHA->pha_hys_cnt = 0; } if (hPHA->pha_hys_cnt >= STEREO_DMX_EVS_SWTCH_HYS_THRES) { hPHA->curr_pha = STEREO_DMX_EVS_PHA_IPD; } } hPHA->prev_pha = STEREO_DMX_EVS_PHA_IPD; } else { if (hPHA->curr_pha != STEREO_DMX_EVS_PHA_IPD2) { if (hPHA->prev_pha == STEREO_DMX_EVS_PHA_IPD2) { hPHA->pha_hys_cnt += 1; } else { hPHA->pha_hys_cnt = 0; } if (hPHA->pha_hys_cnt >= STEREO_DMX_EVS_SWTCH_HYS_THRES) { hPHA->curr_pha = STEREO_DMX_EVS_PHA_IPD2; } } hPHA->prev_pha = STEREO_DMX_EVS_PHA_IPD2; } if (hPHA->curr_pha != STEREO_DMX_EVS_NO_PHA) { ipd_ff = hPHA->ipd_ff; for ( i = 0; i < ( end8 + 1 ); i++ ) { tPr = ( specLr[i] * specRr[i] + specLi[i] * specRi[i] ); tPi = ( specLi[i] * specRr[i] - specLr[i] * specRi[i] ); Pn = sqrt( tPr * tPr + tPi * tPi ); tPr /= (Pn+EPSILON); tPi /= (Pn+EPSILON); if (fabs(tPr*tPi) < EPSILON) { tPr = 1.; tPi = 0.; } Pr[i] = ipd_ff[i]*Pr[i] + (1.0 - ipd_ff[i])*tPr; Pi[i] = ipd_ff[i]*Pi[i] + (1.0 - ipd_ff[i])*tPi; } for ( i = end8+1; i < n0; i++ ) { Pr[i] = 1.0; Pi[i] = 0.0; } if (hPHA->curr_pha == STEREO_DMX_EVS_PHA_IPD) { // PHA R2L hPHA->p_curr_taps[1] = hPHA->curr_taps[1]; p_curr_taps = hPHA->p_curr_taps[1]; p_curr_taps[0] = Pr[0]; p_curr_taps[1] = Pr[n0]; for ( i = 1; i < n0; i++ ) { p_curr_taps[i * 2] = Pr[i]; p_curr_taps[i * 2 + 1] = Pi[i]; } rfft( p_curr_taps, rfft_coef, input_frame, +1 ); } else { // PHA R2L hPHA->p_curr_taps[1] = hPHA->curr_taps[1]; p_curr_taps = hPHA->p_curr_taps[1]; for ( i = 1; i < n0; i++ ) { Pn = sqrt( Pr[i] * Pr[i] + Pi[i] * Pi[i] ); tPr = Pr[i]/(Pn+EPSILON); p_curr_taps[i * 2] = sqrt((1.+tPr)/2.); p_curr_taps[i * 2 + 1] = sqrt((1.-tPr)/2.)*sign(Pi[i]); } p_curr_taps[0] = 1; p_curr_taps[1] = 1; rfft( p_curr_taps, rfft_coef, input_frame, +1 ); // PHA L2R hPHA->p_curr_taps[0] = hPHA->curr_taps[0]; p_curr_taps_l2r = hPHA->p_curr_taps[0]; p_curr_taps_l2r[0] = p_curr_taps[0]; for ( i = 1; i < input_frame; i++ ) { p_curr_taps_l2r[i] = p_curr_taps[input_frame-i]; } } } for ( n = 0; n < CPE_CHANNELS; n++ ) { if (hPHA->p_curr_taps[n]) { for ( i = 0; i < hPHA->pha_len; i++ ) { hPHA->p_curr_taps[n][i] *= hPHA->win[i]; } energy = 0; for ( i = 0; i < hPHA->pha_len; i++ ) { energy += hPHA->p_curr_taps[n][i] * hPHA->p_curr_taps[n][i]; } energy = sqrtf( energy ); for ( i = 0; i < hPHA->pha_len; i++ ) { hPHA->p_curr_taps[n][i] /= energy; } } } #endif rfft_buf[0] = specPOr[0]; rfft_buf[1] = specPOr[n0]; Loading Loading @@ -550,6 +768,9 @@ static float find_poc_peak( static ivas_error estimate_itd( float *corr, /* o : correlation */ STEREO_DMX_EVS_POC_HANDLE hPOC, /* i/o: phase only correlation structure */ #ifdef ENHANCED_STEREO_DMX STEREO_DMX_EVS_PHA_HANDLE hPHA, /* i/o : correlation filter structure */ #endif const float srcL[], /* i : Lch input signal */ const float srcR[], /* i : Rch input signal */ float itd[], /* o : estimated itd */ Loading Loading @@ -598,7 +819,11 @@ static ivas_error estimate_itd( estimate_itd_wnd_fft( srcL, specLr, specLi, rfft_coef, hPOC->wnd, input_frame ); estimate_itd_wnd_fft( srcR, specRr, specRi, rfft_coef, hPOC->wnd, input_frame ); #ifdef ENHANCED_STEREO_DMX calc_poc( hPOC, hPHA, hPOC->wnd, rfft_coef, specLr, specLi, specRr, specRi, input_frame ); #else calc_poc( hPOC, hPOC->wnd, rfft_coef, specLr, specLi, specRr, specRi, input_frame ); #endif *corr = find_poc_peak( hPOC, itd, input_frame, STEREO_DMX_EVS_POC_W_FORGETTING ); return error; Loading Loading @@ -794,7 +1019,18 @@ void stereo_dmx_evs_enc( int16_t n; float dmx_weight, corr; float data_f[CPE_CHANNELS][L_FRAME48k]; #ifdef ENHANCED_STEREO_DMX int16_t k, m; int32_t pha_len, fad_len; float mem_out_curr[CPE_CHANNELS][L_FRAME48k], mem_out_last[L_FRAME48k]; float *p_data_mem, *p_prev_taps, *p_curr_taps, *fad_g, *p_mem_out_curr, *p_data_f; float dmx_itd_data[L_FRAME48k], dmx_ipd_data[L_FRAME48k], *p_dmx_data; STEREO_DMX_EVS_PRC curr_prc; #else float dmx_data[L_FRAME48k]; #endif int16_t input_frame; input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); Loading @@ -810,6 +1046,186 @@ void stereo_dmx_evs_enc( set_f( data_f[1] + n_samples, 0.0f, input_frame - n_samples ); } #ifdef ENHANCED_STEREO_DMX estimate_itd( &corr, hStereoDmxEVS->hPOC, hStereoDmxEVS->hPHA, data_f[0], data_f[1], &hStereoDmxEVS->itd, input_frame ); pha_len = hStereoDmxEVS->hPHA->pha_len; fad_len = hStereoDmxEVS->hPHA->fad_len; fad_g = hStereoDmxEVS->hPHA->fad_g; for ( k = 0; k < CPE_CHANNELS; k++ ) { p_prev_taps = hStereoDmxEVS->hPHA->p_prev_taps[k]; p_curr_taps = hStereoDmxEVS->hPHA->p_curr_taps[k]; p_mem_out_curr = mem_out_curr[k]; p_data_f = data_f[k]; p_data_mem = hStereoDmxEVS->hPHA->data_mem[k]; mvr2r( &( p_data_mem[input_frame] ), p_data_mem, pha_len ); p_data_mem = &( p_data_mem[pha_len] ); mvr2r( p_data_f, p_data_mem, input_frame ); if (p_prev_taps) { for (n = 0; n < fad_len; n++) { mem_out_last[n] = 0; for ( m = 0; m < pha_len; m++ ) { mem_out_last[n] += p_data_mem[n - m] * p_prev_taps[m]; } mem_out_last[n] *= fad_g[fad_len - (1+n)]; } } if (p_curr_taps) { if (p_prev_taps == NULL) { for (n = 0; n < fad_len; n++) { mem_out_last[n] = fad_g[fad_len - (1+n)] * p_data_f[n]; } } for (n = 0; n < fad_len; n++) { p_mem_out_curr[n] = 0; for ( m = 0; m < pha_len; m++ ) { p_mem_out_curr[n] += p_data_mem[n - m] * p_curr_taps[m]; } p_mem_out_curr[n] = fad_g[n] * p_mem_out_curr[n] + mem_out_last[n]; } for (; n < input_frame; n++) { p_mem_out_curr[n] = 0; for (m = 0; m < pha_len; m++) { p_mem_out_curr[n] += p_data_mem[n - m] * p_curr_taps[m]; } } } else { if (p_prev_taps) { for (n = 0; n < fad_len; n++) { p_mem_out_curr[n] = fad_g[n] * p_data_f[n] + mem_out_last[n]; } mvr2r( &(p_data_f[fad_len]), &(p_mem_out_curr[fad_len]), input_frame-fad_len ); } else { mvr2r( p_data_f, p_mem_out_curr, input_frame ); } } } // poc if ( hStereoDmxEVS->itd ) { dmx_weight = ( ( hStereoDmxEVS->itd > 0 ) ? ( -1 ) : 1 ) * 0.5f * corr + 0.5f; } else { dmx_weight = 0.5f; } create_M_signal( data_f[0], data_f[1], dmx_itd_data, dmx_weight, input_frame, hStereoDmxEVS->s_wnd, hStereoDmxEVS->dmx_weight, hStereoDmxEVS->pre_dmx_energy, hStereoDmxEVS->aux_dmx_energy ); // pha for ( n=0; n < input_frame; n++ ) { dmx_ipd_data[n] = (mem_out_curr[0][n] + mem_out_curr[1][n])*0.5; } // prc switch curr_prc = hStereoDmxEVS->hPHA->curr_prc; if (abs((int16_t)hStereoDmxEVS->itd) > hStereoDmxEVS->hPHA->prc_thres) { if ( hStereoDmxEVS->hPHA->curr_prc != STEREO_DMX_EVS_PRC_POC ) { if (hStereoDmxEVS->hPHA->prev_prc == STEREO_DMX_EVS_PRC_POC) { hStereoDmxEVS->hPHA->prc_hys_cnt += 1; } else { hStereoDmxEVS->hPHA->prc_hys_cnt = 0; } if (hStereoDmxEVS->hPHA->prc_hys_cnt >= STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES) { hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_POC; } } hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_POC; } else { if ( hStereoDmxEVS->hPHA->curr_prc != STEREO_DMX_EVS_PRC_PHA ) { if (hStereoDmxEVS->hPHA->prev_prc == STEREO_DMX_EVS_PRC_PHA) { hStereoDmxEVS->hPHA->prc_hys_cnt += 1; } else { hStereoDmxEVS->hPHA->prc_hys_cnt = 0; } if (hStereoDmxEVS->hPHA->prc_hys_cnt >= STEREO_DMX_EVS_SWTCH_PRC_HYS_THRES) { hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_PHA; } } hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_PHA; } if ( hStereoDmxEVS->hPHA->curr_prc == STEREO_DMX_EVS_PRC_POC ) { p_dmx_data = dmx_itd_data; if (curr_prc != hStereoDmxEVS->hPHA->curr_prc) { fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for (n = 0; n < fad_len; n++) { p_dmx_data[n] *= fad_g[n]; p_dmx_data[n] += (1.-fad_g[n]) * dmx_ipd_data[n]; } } } else { p_dmx_data = dmx_ipd_data; if (curr_prc != hStereoDmxEVS->hPHA->curr_prc) { fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for (n = 0; n < fad_len; n++) { p_dmx_data[n] *= fad_g[n]; p_dmx_data[n] += (1.-fad_g[n]) * dmx_itd_data[n]; } } } mvr2s( p_dmx_data, data, n_samples ); #else estimate_itd( &corr, hStereoDmxEVS->hPOC, data_f[0], data_f[1], &hStereoDmxEVS->itd, input_frame ); if ( hStereoDmxEVS->itd ) Loading @@ -826,6 +1242,8 @@ void stereo_dmx_evs_enc( mvr2s( dmx_data, data, n_samples ); #endif return; } Loading @@ -844,6 +1262,15 @@ ivas_error stereo_dmx_evs_init_encoder( STEREO_DMX_EVS_ENC_HANDLE hStereoDmxEVS; int16_t n, input_frame; #ifdef ENHANCED_STEREO_DMX int32_t f_len, pha_len, fad_len; float *win, *fad_g; float a_min, a_max, a_step, n0, itrh; float *ipd_ff; #endif input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); hStereoDmxEVS = NULL; Loading Loading @@ -933,6 +1360,97 @@ ivas_error stereo_dmx_evs_init_encoder( hStereoDmxEVS->hPOC->confidence = 0.0f; #ifdef ENHANCED_STEREO_DMX hStereoDmxEVS->hPHA = NULL; if ( ( hStereoDmxEVS->hPHA = (STEREO_DMX_EVS_PHA_HANDLE) malloc( sizeof( STEREO_DMX_EVS_PHA_DATA ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for STEREO_DMX_EVS_CORFILT_DATA\n" ) ); } for ( n = 0; n < CPE_CHANNELS; n++ ) { hStereoDmxEVS->hPHA->p_curr_taps[n] = NULL; hStereoDmxEVS->hPHA->p_prev_taps[n] = NULL; set_zero( hStereoDmxEVS->hPHA->data_mem[n], L_FRAME48k * 2 ); set_zero( hStereoDmxEVS->hPHA->curr_taps[n], L_FRAME48k ); } if ( input_Fs == 16000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_16 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_16 * input_Fs / 1000; } else if ( input_Fs == 32000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_32 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_32 * input_Fs / 1000; } else if ( input_Fs == 48000 ) { f_len = STEREO_DMX_EVS_PHA_LEN_48 * input_Fs / 1000; hStereoDmxEVS->hPHA->fad_len = STEREO_DMX_EVS_FAD_LEN_48 * input_Fs / 1000; } else { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid sampling frequency\n" ); } hStereoDmxEVS->hPHA->pha_len = f_len/2; pha_len = hStereoDmxEVS->hPHA->pha_len; fad_len = hStereoDmxEVS->hPHA->fad_len; win = hStereoDmxEVS->hPHA->win; set_zero( win, L_FRAME48k ); for ( n = 0; n < pha_len; n++ ) { win[n] = 0.5f * (1.0f + cosf( ( PI2 * ( n + 1 ) ) / ( ( f_len ) + 1 ) ) ); } fad_g = hStereoDmxEVS->hPHA->fad_g; for ( n = 0; n < fad_len; n++ ) { fad_g[n] = (float) n / (float)fad_len; } hStereoDmxEVS->hPHA->curr_pha = STEREO_DMX_EVS_NO_PHA; hStereoDmxEVS->hPHA->prev_pha = STEREO_DMX_EVS_NO_PHA; hStereoDmxEVS->hPHA->pha_hys_cnt = 0; // Compute the forgetting factor a_min = 0.8576958985908941; a_max = 0.9440608762859234; itrh = 60; n0 = input_frame / 2; a_step = ( a_min - a_max ) / (n0+1-itrh); ipd_ff = hStereoDmxEVS->hPHA->ipd_ff; for ( n = 0; n < itrh; n++ ) { ipd_ff[n] = a_max; } for ( ; n < ( n0 + 1 ); n++ ) { ipd_ff[n] = a_max + (n-itrh) * a_step; } hStereoDmxEVS->hPHA->prc_thres = STEREO_DMX_EVS_SWTCH_PRC_THRES * input_Fs / 1000; hStereoDmxEVS->hPHA->curr_prc = STEREO_DMX_EVS_PRC_POC; hStereoDmxEVS->hPHA->prev_prc = STEREO_DMX_EVS_PRC_POC; hStereoDmxEVS->hPHA->prc_hys_cnt = 0; hStereoDmxEVS->hPHA->fad_len_prc = STEREO_DMX_EVS_FADE_LEN_PRC * input_Fs / 1000; fad_len = hStereoDmxEVS->hPHA->fad_len_prc; fad_g = hStereoDmxEVS->hPHA->fad_g_prc; for ( n = 0; n < fad_len; n++ ) { fad_g[n] = (float) n / (float)fad_len; } #endif *hStereoDmxEVS_out = hStereoDmxEVS; return IVAS_ERR_OK; Loading Loading @@ -960,6 +1478,14 @@ void stereo_dmx_evs_close_encoder( ( *hStereoDmxEVS )->hPOC = NULL; } #ifdef ENHANCED_STEREO_DMX if ( ( *hStereoDmxEVS )->hPHA != NULL ) { free( ( *hStereoDmxEVS )->hPHA ); ( *hStereoDmxEVS )->hPHA = NULL; } #endif free( ( *hStereoDmxEVS ) ); ( *hStereoDmxEVS ) = NULL; Loading