diff --git a/lib_com/options.h b/lib_com/options.h index 7794c5d10eb35eb157a4a4622bec762336da2f03..1dc4b8192374db8a3a96c5c081be0cc7a48eb5ea 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -151,8 +151,6 @@ #define SIMPLIFY_SBA_RENDERING_LOGIC /* SBA rendering maintenance related to ticket #45 */ #define SBA_CLEANING /* SBA maintenance related to ticket #45 */ -#define REFACTOR_REVERB_INIT_ADD_CFG_CHECKS /* Simplify and improve reverb initialization + add range checks on config parameter values */ - #define DIRAC_DRCT_GAIN_TUNING #define FIX_34 /* Nokia: Fix bug in MASA format EXT output spherical indexing */ diff --git a/lib_dec/ivas_reverb.c b/lib_dec/ivas_reverb.c index 4affe6a8dc5d4ab793241f8d874251abad982b2e..e89725d6608b01a2a4d73b1ff812f0102ba7f7d0 100644 --- a/lib_dec/ivas_reverb.c +++ b/lib_dec/ivas_reverb.c @@ -43,1477 +43,6 @@ #include #include "wmops.h" -#ifndef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS - -/*------------------------------------------------------------------------------------------* - * Local constants - *------------------------------------------------------------------------------------------*/ - -#define INNER_BLK_SIZE 80 /* size of data blocks used for more efficient delay line and IIR filter processing */ - /* should be a divisor of the frame length at any sampling rate and an even number*/ -#define USE_SR_INDEPENDENT_FIT_FOR_T60_FILTERS /* use sample-rate independent ref. frequency ranges for T60 filters */ -#define FFT_FILTER_WND_FLAT_REGION ( 0.40f ) /* flat section (==1) length of FFT filter window, in proportion to overlap */ -#define FFT_FILTER_WND_TRANS_REGION ( 0.15f ) /* transition (1->0) length of FFT filter window, in proportion to overlap */ -#ifdef USE_SR_INDEPENDENT_FIT_FOR_T60_FILTERS -#define REF_LF_MIN ( 100.0f ) -#define REF_LF_MAX ( 250.0f ) -#define REF_HF_MIN ( 5000.0f ) -#define REF_HF_MAX ( 7950.0f ) -#define LF_BIAS ( 0.5f ) -#else /* settings for previous version of improved 1st order filter design, somewhat dependent on the sampling rate */ -#define REF_LF_MIN ( 0.0f ) -#define REF_LF_MAX ( 200.0f ) -#define REF_HF_MIN ( 6000.0f ) -#define REF_HF_MAX ( 48000.0f ) -#define LF_BIAS ( 0.75f ) -#endif - -#define DEFAULT_SRC_DIST ( 1.5f ) /* default source distance [m] for reverb dmx factor computing */ - -#define IVAS_REVERB_FFT_SIZE_48K ( 512 ) -#define IVAS_REVERB_FFT_SIZE_32K ( 512 ) -#define IVAS_REVERB_FFT_SIZE_16K ( 256 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_48K ( 1 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_32K ( 1 ) -#define IVAS_REVERB_FFT_N_SUBBLOCKS_16K ( 1 ) - -const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 }; -const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 }; -const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 }; -const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 }; - -#define MAX_NR_OUTPUTS 2 -#define MAX_T60_FILTER_ORDER 12 - - -/*------------------------------------------------------------------------------------------* - * Local Struct definition - *------------------------------------------------------------------------------------------*/ - -typedef struct ivas_reverb_params_t -{ - float dmx_gain; /* (for now, fullband) gain to apply at input to realize diffuse-to-source energy ratio */ - int16_t pre_delay; /* Delay of the FDC reverb, first peak after pre_delay samples. Note that */ - /* there may be non-zero samples earlier due to the filters being */ - /* linear-phase. */ - int16_t nr_loops; /* Number of feedback loops (= L) */ - int16_t pLoop_delays[IVAS_REV_MAX_NR_BRANCHES]; /* Delay for each feedback loop in samples. */ - float pLoop_feedback_matrix[IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_NR_BRANCHES]; /* Feedback [L][L] matrix that mixes the signals of the loops. */ - int16_t nr_outputs; /* Nr of signals extracted from the loops (= S). */ - /* Currently this is fixed to 2. */ - float pLoop_extract_matrix[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES]; /* Mix [S][L] matrix from feedback loops to outputs. */ - /* In Matlab: [S x L] - Currently S=2, later may be more than 2 for speaker playback. */ - int16_t t60_is_iir; /* Flag indicates whether T60 filters are IIR. */ - int16_t t60_filter_order; /* Filter order (length of vector) */ - float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * ( MAX_T60_FILTER_ORDER + 1 )]; /* Filters [][] in feedback loops, controlling T60. */ - /* In Matlab: IIR: [(2 * L) x ( + 1)] (odd: b-vector, even: a-vector) */ - /* In Matlab: FIR: [L x ] */ - float *pFc; /* Center frequencies for FFT filter design */ - float *pRt60; /* RT60 values at these frequencies */ - float *pDsr; /* DSR values at these frequencies */ - int16_t do_corr_filter; /* Flag indicating whether correlation filters should be used. */ - /* Correlation only supported and needed for binaural playback (i.e. */ - /* when nr_outputs != 2 correlation filtering is never supported). */ - -} ivas_reverb_params_t; - -typedef struct ivas_reverb_sizes_t -{ - int16_t max_nr_loops; /* 4, 6, 8 or 16 */ - int16_t max_nr_outputs; /* 2, ... */ - int16_t max_t60_filter_order; /* 1..128 */ - -} ivas_reverb_sizes_t; - - -/*------------------------------------------------------------------------------------------* - * Static functions declarations - *------------------------------------------------------------------------------------------*/ - -static ivas_error design_iir2_1st_order( ivas_reverb_params_t *pParams, const uint16_t nrLoop, const uint16_t nrFrequencies, float frequencies[], float amplitudes[], const int32_t output_Fs ); - - -/*-----------------------------------------------------------------------------------------* - * Function set_max_sizes() - * - * - *-----------------------------------------------------------------------------------------*/ - -static void set_max_sizes( - ivas_reverb_sizes_t *pRevSizes ) -{ - pRevSizes->max_nr_loops = IVAS_REV_MAX_NR_BRANCHES; - pRevSizes->max_nr_outputs = MAX_NR_OUTPUTS; - pRevSizes->max_t60_filter_order = MAX_T60_FILTER_ORDER; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_feedback_matrix() - * - * Compute the N x N matrix for the mixing the N feedback loop outputs into the N inputs again - *-----------------------------------------------------------------------------------------*/ - -static ivas_error compute_feedback_matrix( - float *pFeedbackMatrix, - const int16_t n ) -{ - float u, v; - int16_t i, j, x; - - if ( n == 6 ) - { - /* special case (there is no 6 x 6 Hadamard matrix in set R) */ - u = -1.0f / 3; - v = 1.0f + u; - for ( i = 0; i < n; i++ ) - { - for ( j = 0; j < n; j++ ) - { - if ( i == j ) - { - pFeedbackMatrix[i * n + j] = v; - } - else - { - pFeedbackMatrix[i * n + j] = u; - } - } - } - } - else - { - if ( !( n == 4 || n == 8 || n == 16 ) ) - { - return IVAS_ERR_INTERNAL; /* n must be 4, 6, 8 or 16, else ERROR */ - } - u = 1.0f / sqrtf( n ); - if ( n == 4 ) - { - u = -u; - } - - pFeedbackMatrix[0] = u; - for ( x = 1; x < n; x += x ) - { - for ( i = 0; i < x; i++ ) - { - for ( j = 0; j < x; j++ ) - { - pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j]; - pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j]; - pFeedbackMatrix[( i + x ) * n + j + x] = -pFeedbackMatrix[i * n + j]; - } - } - } - - if ( n == 4 ) - { - /* special case */ - for ( j = 12; j < 16; j++ ) - { - pFeedbackMatrix[j] = -pFeedbackMatrix[j]; - } - } - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_2_out_extract_matrix() - * - * Compute the N x 2 matrix for mixing the N Jot feedback loops to 2 outputs - *-----------------------------------------------------------------------------------------*/ - -static void compute_2_out_extract_matrix( - float *pExtractMatrix, - const int16_t n ) -{ - float ff; - int16_t i; - - ff = 1.0; - for ( i = 0; i < n; i++ ) - { - pExtractMatrix[i] = 1.0; - pExtractMatrix[i + n] = ff; - ff = -ff; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_base_config() - * - * Set all jot reverb parameters that are independent of the input reverb configuration - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_base_config( - ivas_reverb_params_t *pParams, - const int32_t output_Fs, - ivas_reverb_sizes_t *pRevSizes ) -{ - ivas_error error; - int16_t loop; - const int16_t *selected_loop_delay = NULL; - - if ( pParams == NULL ) - { - return IVAS_ERR_INTERNAL; - } - - if ( pRevSizes == NULL ) - { - return IVAS_ERR_INTERNAL; - } - - /* TODO: values below could be reconsidered, and/or be made variable */ - pParams->pre_delay = 0; - pParams->nr_outputs = 2; - - if ( pParams->nr_outputs > pRevSizes->max_nr_outputs ) - { - return IVAS_ERR_INTERNAL; - } - - pParams->nr_loops = IVAS_REV_MAX_NR_BRANCHES; - - if ( pParams->nr_loops > pRevSizes->max_nr_loops ) - { - return IVAS_ERR_INTERNAL; - } - - /* set loop delays to default */ - if ( output_Fs == 48000 ) - { - selected_loop_delay = default_loop_delay_48k; - } - else if ( output_Fs == 32000 ) - { - selected_loop_delay = default_loop_delay_32k; - } - else if ( output_Fs == 16000 ) - { - selected_loop_delay = default_loop_delay_16k; - } - - for ( loop = 0; loop < pParams->nr_loops; loop++ ) - { - pParams->pLoop_delays[loop] = selected_loop_delay[loop]; - } - - /* set feedback and output matrices */ - if ( ( error = compute_feedback_matrix( pParams->pLoop_feedback_matrix, pParams->nr_loops ) ) != IVAS_ERR_OK ) - { - return error; - } - - compute_2_out_extract_matrix( pParams->pLoop_extract_matrix, pParams->nr_loops ); - - /* pre-set the various filters; they will be set later based on reverb configuration */ - pParams->t60_is_iir = TRUE; - pParams->t60_filter_order = 1; /* set to 1 in base config. */ - - if ( pParams->t60_filter_order > pRevSizes->max_t60_filter_order ) - { - return IVAS_ERR_INTERNAL; - } - - if ( pParams->nr_outputs == 2 ) - { - pParams->do_corr_filter = 1; - } - else - { - pParams->do_corr_filter = 0; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_dmx_gain() - * - * Computes and sets the downmix gain - *-----------------------------------------------------------------------------------------*/ - -static void calc_dmx_gain( - ivas_reverb_params_t *pParams ) -{ - const float dist = DEFAULT_SRC_DIST; - - pParams->dmx_gain = sqrtf( 4.0f * EVS_PI * dist * dist / 0.001f ); - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_predelay() - * - * Calculate the predelay, taking shortest jot loop delay into account - *-----------------------------------------------------------------------------------------*/ - -static void calc_predelay( - ivas_reverb_params_t *pParams, - float acoustic_predelay_sec, - const int32_t output_Fs ) -{ - int16_t i, predelay; - int16_t fbdelay; - int16_t output_frame; - - fbdelay = pParams->pLoop_delays[0]; - predelay = (int16_t) round( acoustic_predelay_sec * output_Fs ); - output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); - - fbdelay = pParams->pLoop_delays[0]; - for ( i = 1; i < pParams->nr_loops; i++ ) - { - if ( fbdelay > pParams->pLoop_delays[i] ) - { - fbdelay = pParams->pLoop_delays[i]; - } - } - predelay -= fbdelay; - - if ( predelay < 0 ) - { - predelay = 0; - } - - if ( output_frame < predelay ) - { - predelay = output_frame; - } - - pParams->pre_delay = predelay; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function compute_t60_coeffs() - * - * Calculate Jot reverb's T60 filter coefficients - *-----------------------------------------------------------------------------------------*/ - -static ivas_error compute_t60_coeffs( - ivas_reverb_params_t *pParams, - int16_t nr_fc_fft_filter, - const int32_t output_Fs ) -{ - int16_t i, j, tf_T60_len; - int16_t len; - float c, d; - float H_b[RV_LENGTH_NR_FC]; - float norm_f[RV_LENGTH_NR_FC]; - float inv_hfs; - float *targetT60 = pParams->pRt60; - float *freqT60 = pParams->pFc; - ivas_error error; - - error = IVAS_ERR_OK; - tf_T60_len = nr_fc_fft_filter; - - if ( pParams->t60_is_iir == FALSE ) - { - return IVAS_ERR_INTERNAL; /* only IIR supported */ - } - - /* normalize pFrequencies: 0 .. 1/2 output_Fs --> 0.0 .. 1.0 */ - inv_hfs = 2.0f / (float) output_Fs; - for ( i = 0; i < tf_T60_len; i++ ) - { - norm_f[i] = freqT60[i] * inv_hfs; - } - - c = -3.0f * LOG_10 / (float) output_Fs; /* 10^(x) == exp(LOG_10 * x) */ - - for ( j = 0; j < pParams->nr_loops; j++ ) - { - d = c * pParams->pLoop_delays[j]; - for ( i = 0; i < tf_T60_len; i++ ) - { - H_b[i] = expf( d / targetT60[i] ); /* using EXP(x) instead of 10^x */ - } - - if ( ( error = design_iir2_1st_order( pParams, j, tf_T60_len, norm_f, H_b, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - len = pParams->t60_filter_order + 1; - for ( i = 0; i < pParams->nr_loops; i++ ) - { - if ( pParams->pT60_filter_coeff[( i + i ) * len] < 0.0f ) - { - for ( j = 0; j < len; j++ ) - { - pParams->pT60_filter_coeff[( i + i ) * len + j] *= ( -1.0f ); - } - } - } - - // TODO: Compute proper (group) Delay from IIR filter - len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */ - for ( i = 0; i < pParams->nr_loops; i++ ) - { - pParams->pLoop_delays[i] -= len; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_low_shelf_first_order_filter() - * - * Calculate 1st order low shelf filter - *-----------------------------------------------------------------------------------------*/ - -static void calc_low_shelf_first_order_filter( - float *pNum, - float *pDen, - const float f0, - const float g ) -{ - float w0; - - w0 = tanf( EVS_PI * f0 / 2.0f ); - - if ( g < 1.0f ) - { - pNum[0] = 1 + w0 * g; - pNum[1] = w0 * g - 1; - pDen[0] = 1 + w0; - pDen[1] = w0 - 1; - } - else - { - pNum[0] = 1 + w0; - pNum[1] = w0 - 1; - pDen[0] = 1 + w0 / g; - pDen[1] = w0 / g - 1; - } - - pNum[0] = pNum[0] / pDen[0]; - pNum[1] = pNum[1] / pDen[0]; - pDen[1] = pDen[1] / pDen[0]; - pDen[0] = 1.0f; - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function calc_jot_t60_coeffs() - * - * Calculate Jot reverb's T60 filters - *-----------------------------------------------------------------------------------------*/ - -static ivas_error calc_jot_t60_coeffs( - float *pAmplitudes, - const uint16_t nrFrequencies, - float *pFrequencies, - float *pCoeffA, - float *pCoeffB, - float fNyquist ) -{ - const float ref_lf_min_norm = REF_LF_MIN / fNyquist; - const float ref_lf_max_norm = REF_LF_MAX / fNyquist; - const float ref_hf_min_norm = REF_HF_MIN / fNyquist; - const float ref_hf_max_norm = REF_HF_MAX / fNyquist; - int16_t f_idx; - int16_t minidx = nrFrequencies - 1; - float f0, gain, tmp; - float minval = 1000000.0f; - float lf_target_gain_dB = 0.0f; - float hf_target_gain_dB = 0.0f; - float mid_crossing_gain_dB; - uint16_t n_points_lf = 0; - uint16_t n_points_hf = 0; - float lin_gain_lf, lin_gain_hf; - float pH_dB[RV_LENGTH_NR_FC]; - - if ( pAmplitudes[0] < pAmplitudes[nrFrequencies - 1] ) - { - /* amplitude response has to have low-pass characteristic */ - return IVAS_ERR_INTERNAL; - } - - for ( f_idx = 0; f_idx < nrFrequencies; f_idx++ ) - { - pH_dB[f_idx] = 20.0f * log10f( pAmplitudes[f_idx] ); - if ( ( pFrequencies[f_idx] >= ref_lf_min_norm ) && ( pFrequencies[f_idx] <= ref_lf_max_norm ) ) - { - lf_target_gain_dB += pH_dB[f_idx]; - n_points_lf++; - } - if ( ( pFrequencies[f_idx] >= ref_hf_min_norm ) && ( pFrequencies[f_idx] <= ref_hf_max_norm ) ) - { - hf_target_gain_dB += pH_dB[f_idx]; - n_points_hf++; - } - } - - if ( ( n_points_lf == 0 ) || ( n_points_hf == 0 ) ) - { - return IVAS_ERR_INTERNAL; - } - - lf_target_gain_dB = lf_target_gain_dB / (float) n_points_lf; - hf_target_gain_dB = hf_target_gain_dB / (float) n_points_hf; - mid_crossing_gain_dB = hf_target_gain_dB + LF_BIAS * ( lf_target_gain_dB - hf_target_gain_dB ); - - for ( f_idx = 1; f_idx < nrFrequencies - 1; f_idx++ ) - { - tmp = fabsf( pH_dB[f_idx] - mid_crossing_gain_dB ); - if ( tmp < minval ) - { - minval = tmp; - minidx = f_idx; - } - } - - f0 = pFrequencies[minidx]; - lin_gain_lf = powf( 10.0f, lf_target_gain_dB * 0.05f ); - lin_gain_hf = powf( 10.0f, hf_target_gain_dB * 0.05f ); - - gain = lin_gain_lf / lin_gain_hf; - - /* call low-pass iir shelf */ - calc_low_shelf_first_order_filter( pCoeffB, pCoeffA, f0, gain ); - - /* adjust gain to match pAmplitudes */ - pCoeffB[0] = pCoeffB[0] * lin_gain_hf; - pCoeffB[1] = pCoeffB[1] * lin_gain_hf; - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function design_iir2_1st_order() - * - * Design 1st order IIR filter - *-----------------------------------------------------------------------------------------*/ - -static ivas_error design_iir2_1st_order( - ivas_reverb_params_t *pParams, - const uint16_t nrLoop, - const uint16_t nrFrequencies, - float frequencies[], - float amplitudes[], - const int32_t output_Fs ) -{ - int16_t len, n, j; - float coefA[2] = { 1.0f, 0.0f }; - float coefB[2] = { 1.0f, 0.0f }; - ivas_error error = IVAS_ERR_OK; - - /* Get numerator and denominator coefficients */ - error = calc_jot_t60_coeffs( amplitudes, nrFrequencies, frequencies, coefA, coefB, 0.5f * output_Fs ); - - if ( error != IVAS_ERR_OK ) - { - return error; - } - - len = 2; - n = nrLoop + nrLoop; - for ( j = 0; j < len; j++ ) - { - pParams->pT60_filter_coeff[(n) *len + j] = coefB[j]; - pParams->pT60_filter_coeff[( n + 1 ) * len + j] = coefA[j]; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function initialize_reverb() - * - * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data) - *-----------------------------------------------------------------------------------------*/ - -static ivas_error initialize_reverb( - REVERB_HANDLE pState ) -{ - ivas_error error; - - error = IVAS_ERR_OK; - - /* init correlation and coloration filters */ - if ( ( error = ivas_reverb_t2f_f2t_init( &pState->fft_filter_ols, pState->fft_size, pState->fft_subblock_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_correl_0, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_correl_1, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_color_0, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = ivas_reverb_fft_filter_init( &pState->fft_filter_color_1, pState->fft_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - return error; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_t60_filter() - * - * Sets t60 number of taps and coefficients A and B - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_t60_filter( - REVERB_HANDLE pState, - const uint16_t branch, - const uint16_t nr_taps, - float coefA[], - float coefB[] ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - if ( nr_taps > IVAS_REV_MAX_IIR_FILTER_LENGTH ) - { - return IVAS_ERR_INTERNAL; - } - - ivas_reverb_iir_filt_set( &( pState->t60[branch] ), nr_taps, coefA, coefB ); - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_feedback_delay() - * - * Sets Delay of feedback branch in number of samples - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_feedback_delay( - REVERB_HANDLE pState, - const uint16_t branch, - const int16_t fb_delay ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - pState->delay_line[branch].Delay = fb_delay; - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_feedback_gain() - * - * Sets nr_of_branches feedback gain values in feedback matrix - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_feedback_gain( - REVERB_HANDLE pState, - const uint16_t branch, - float *pGain ) -{ - if ( branch >= pState->nr_of_branches ) - { - return IVAS_ERR_INTERNAL; - } - - for ( uint16_t i = 0; i < pState->nr_of_branches; i++ ) - { - pState->gain_matrix[branch][i] = pGain[i]; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_correl_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_correl_fft_filter( - REVERB_HANDLE pState, - const uint16_t channel, - rv_fftwf_type_complex *pSpectrum ) -{ - if ( channel > 1 ) - { - return IVAS_ERR_INTERNAL; - } - - if ( channel == 0 ) - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_correl_0.fft_spectrum, pState->fft_filter_correl_0.fft_size ); - } - else - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_correl_1.fft_spectrum, pState->fft_filter_correl_1.fft_size ); - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_color_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_color_fft_filter( - REVERB_HANDLE pState, - const uint16_t channel, - rv_fftwf_type_complex *pSpectrum ) -{ - if ( channel > 1 ) - { - return IVAS_ERR_INTERNAL; - } - - if ( channel == 0 ) - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_color_0.fft_spectrum, pState->fft_filter_color_0.fft_size ); - } - else - { - ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR( pSpectrum, pState->fft_filter_color_1.fft_spectrum, pState->fft_filter_color_1.fft_size ); - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function post_fft_filter() - * - * - *-----------------------------------------------------------------------------------------*/ - -static void post_fft_filter( - REVERB_HANDLE pState, - float *p0, - float *p1, - float *pBuffer_0, - float *pBuffer_1 ) -{ - if ( pState->do_corr_filter ) - { - ivas_reverb_t2f_f2t_in( &pState->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_correl_0, pBuffer_0 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_correl_1, pBuffer_1 ); - ivas_reverb_fft_filter_CrossMix( pBuffer_0, pBuffer_1, pState->fft_filter_correl_0.fft_size ); - } - else - { - ivas_reverb_t2f_f2t_in( &pState->fft_filter_ols, p0, p1, pBuffer_0, pBuffer_1 ); - } - - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_color_0, pBuffer_0 ); - ivas_reverb_fft_filter_ComplexMul( &pState->fft_filter_color_1, pBuffer_1 ); - ivas_reverb_t2f_f2t_out( &pState->fft_filter_ols, pBuffer_0, pBuffer_1, p0, p1 ); - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function set_mixer_level() - * - * Sets Mixer level: to mix 2 output channels from 8 feedback branches - *-----------------------------------------------------------------------------------------*/ - -static ivas_error set_mixer_level( - REVERB_HANDLE pState, - const uint16_t channel, - float level[] ) -{ - if ( channel >= BINAURAL_CHANNELS ) - { - return IVAS_ERR_INTERNAL; - } - - for ( uint16_t i = 0; i < pState->nr_of_branches; i++ ) - { - pState->mixer[channel][i] = level[i]; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function reverb_block() - * - * Input a block (mono) and calculate the 2 output blocks. - *-----------------------------------------------------------------------------------------*/ - -static void reverb_block( - REVERB_HANDLE pState, - float *pInput, - float *pOut0, - float *pOut1 ) - -{ - uint16_t nr_branches = pState->nr_of_branches; - uint16_t bsize = pState->full_block_size; - uint16_t inner_bsize = INNER_BLK_SIZE; - uint16_t i, j, k, ns, branch_idx, blk_idx, start_sample_idx; - - float *pFFT_buf[2], FFT_buf_1[RV_FILTER_MAX_FFT_SIZE], FFT_buf_2[RV_FILTER_MAX_FFT_SIZE]; - float pFeedback_input[INNER_BLK_SIZE]; - float pTemp[INNER_BLK_SIZE]; - float *ppOutput[IVAS_REV_MAX_NR_BRANCHES]; - float Output[IVAS_REV_MAX_NR_BRANCHES][INNER_BLK_SIZE]; - - pFFT_buf[0] = &FFT_buf_1[0]; - pFFT_buf[1] = &FFT_buf_2[0]; - - for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ ) - { - ppOutput[branch_idx] = (float *) Output + branch_idx * inner_bsize; - } - for ( k = 0; k < bsize; k += inner_bsize ) - { - float *pO0 = &pOut0[k]; - float *pO1 = &pOut1[k]; - for ( i = 0; i < inner_bsize; i++ ) - { - pO0[i] = 0.0f; - pO1[i] = 0.0f; - } - - /* feedback network: */ - for ( i = 0; i < nr_branches; i++ ) - { - float *pOutput_i = &ppOutput[i][0]; - float mixer_0_i = pState->mixer[0][i]; - float mixer_1_i = pState->mixer[1][i]; - - /* output and feedback are same, get sample from delay line ... */ - ivas_rev_delay_line_get_sample_blk( &( pState->delay_line[i] ), inner_bsize, pTemp ); - ivas_reverb_iir_filt_2taps_feed_blk( &( pState->t60[i] ), inner_bsize, pTemp, ppOutput[i] ); - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pO0[ns] += pOutput_i[ns] * mixer_0_i; /* mixer ch 0 */ - pO1[ns] += pOutput_i[ns] * mixer_1_i; /* mixer ch 1 */ - } - } - - for ( i = 0; i < nr_branches; i++ ) - { - float *pIn = &pInput[k]; - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pFeedback_input[ns] = pIn[ns]; - } - for ( j = 0; j < nr_branches; j++ ) - { - float gain_matrix_j_i = pState->gain_matrix[j][i]; - float *pOutput = &ppOutput[j][0]; - for ( ns = 0; ns < inner_bsize; ns++ ) - { - pFeedback_input[ns] += gain_matrix_j_i * pOutput[ns]; - } - } - ivas_rev_delay_line_feed_sample_blk( &( pState->delay_line[i] ), inner_bsize, pFeedback_input ); - } - } - - /* Applying FFT filter to each sub-frame */ - for ( blk_idx = 0; blk_idx < pState->num_fft_subblocks; blk_idx++ ) - { - start_sample_idx = blk_idx * pState->fft_subblock_size; - post_fft_filter( pState, pOut0 + start_sample_idx, pOut1 + start_sample_idx, pFFT_buf[0], pFFT_buf[1] ); - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function downmix_input_block() - * - * Downmix input to mono, taking also DSR gain into account - *-----------------------------------------------------------------------------------------*/ - -static ivas_error downmix_input_block( - REVERB_HANDLE pState, - float pcm_in[][L_FRAME48k], - const AUDIO_CONFIG transport_config, - float *pPcm_out, - const int16_t input_offset ) -{ - int16_t i, s, nchan_transport; - float dmx_gain = pState->dmx_gain; - - switch ( transport_config ) - { - case AUDIO_CONFIG_STEREO: - case AUDIO_CONFIG_5_1: - case AUDIO_CONFIG_7_1: - case AUDIO_CONFIG_5_1_2: - case AUDIO_CONFIG_5_1_4: - case AUDIO_CONFIG_7_1_4: - case AUDIO_CONFIG_ISM1: - case AUDIO_CONFIG_ISM2: - case AUDIO_CONFIG_ISM3: - case AUDIO_CONFIG_ISM4: - { - nchan_transport = audioCfg2channels( transport_config ); - for ( s = 0; s < pState->full_block_size; s++ ) - { - float temp = pcm_in[0][input_offset + s]; - for ( i = 1; i < nchan_transport; i++ ) - { - temp += pcm_in[i][input_offset + s]; - } - pPcm_out[s] = dmx_gain * temp; - } - break; - } - case AUDIO_CONFIG_MONO: /* ~'ZOA_1' */ - case AUDIO_CONFIG_FOA: - case AUDIO_CONFIG_HOA2: - case AUDIO_CONFIG_HOA3: - { - for ( s = 0; s < pState->full_block_size; s++ ) - { - pPcm_out[s] = dmx_gain * pcm_in[0][input_offset + s]; - } - break; - } - default: - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" ); - break; - } - - return IVAS_ERR_OK; -} - - -/*-----------------------------------------------------------------------------------------* - * Function predelay_block() - * - * Perform a predelay - *-----------------------------------------------------------------------------------------*/ - -static void predelay_block( - REVERB_HANDLE pState, - float *pInput, - float *pOutput ) -{ - uint16_t i, idx, n_samples, blk_size; - uint16_t max_blk_size = (uint16_t) pState->predelay_line.Delay; - - if ( max_blk_size < 2 ) - { - if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */ - { - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutput[i] = pInput[i]; - } - } - else /* 1-sample length delay line: feed the data sample-by-sample */ - { - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutput[i] = ivas_rev_delay_line_get_sample( &( pState->predelay_line ) ); - ivas_rev_delay_line_feed_sample( &( pState->predelay_line ), pInput[i] ); - } - } - } - else /* multiple-sample length delay line: use block processing */ - { - idx = 0; - n_samples = pState->full_block_size; - while ( n_samples > 0 ) - { - blk_size = n_samples; - if ( blk_size > max_blk_size ) - { - blk_size = max_blk_size; - } - ivas_rev_delay_line_get_sample_blk( &( pState->predelay_line ), blk_size, &pOutput[idx] ); - ivas_rev_delay_line_feed_sample_blk( &( pState->predelay_line ), blk_size, &pInput[idx] ); - idx += blk_size; - n_samples -= blk_size; - } - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function mix_output_block() - * - * mix one block of *pInL and *pInR samples into *pOutL and *pOutL respectively - *-----------------------------------------------------------------------------------------*/ - -static void mix_output_block( - REVERB_HANDLE pState, - const float *pInL, - const float *pInR, - float *pOutL, - float *pOutR ) -{ - uint16_t i; - - for ( i = 0; i < pState->full_block_size; i++ ) - { - pOutL[i] += pInL[i]; - pOutR[i] += pInR[i]; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * Function clear_buffers() - * - * Clears buffers of delay lines and filters - *-----------------------------------------------------------------------------------------*/ - -static void clear_buffers( - REVERB_HANDLE pState ) -{ - int16_t i; - ivas_rev_iir_filter_t *iirFilter; - ivas_rev_delay_line_t *delay_line; - - for ( i = 0; i < IVAS_REV_MAX_NR_BRANCHES; i++ ) - { - delay_line = &( pState->delay_line[i] ); - set_f( delay_line->pBuffer, 0, delay_line->MaxDelay ); - delay_line->BufferPos = 0; - - iirFilter = &( pState->t60[i] ); - set_f( iirFilter->pBuffer, 0, iirFilter->MaxTaps ); - } - - ivas_reverb_t2f_f2t_ClearHistory( &pState->fft_filter_ols ); - - return; -} - - -/*------------------------------------------------------------------------- - * ivas_reverb_open() - * - * Allocate and initialize Crend reverberation handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_reverb_open( - REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ - const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ - RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */ - const int32_t output_Fs /* i : output sampling rate */ -) -{ - ivas_error error; - REVERB_HANDLE pState = NULL; - int16_t i, idx, hrtf_idx, subframe_len, output_frame, predelay_bf_len, nr_out_ch, m, channel; - ivas_reverb_sizes_t rev_sizes; - ivas_reverb_params_t params; - int16_t loop; - rv_fftwf_type_complex pFft_wf_filter_ch0[RV_LENGTH_NR_FC]; - rv_fftwf_type_complex pFft_wf_filter_ch1[RV_LENGTH_NR_FC]; - const float *pHrtf_avg_pwr_response_l_const; /* The HRTF set's average left ear power response */ - const float *pHrtf_avg_pwr_response_r_const; /* The HRTF set's average right ear power response */ - const float *pHrtf_inter_aural_coherence_const; /* The HRTF set's inter-aural coherence for diffuse sound */ - float *pHrtf_avg_pwr_response_l; /* The HRTF set's average left ear power response */ - float *pHrtf_avg_pwr_response_r; /* The HRTF set's average right ear power response */ - float *pHrtf_inter_aural_coherence; /* The HRTF set's inter-aural coherence for diffuse sound */ - float *pHrtf_set_l_re[IVAS_MAX_NUM_CH]; - float *pHrtf_set_l_im[IVAS_MAX_NUM_CH]; - float *pHrtf_set_r_re[IVAS_MAX_NUM_CH]; - float *pHrtf_set_r_im[IVAS_MAX_NUM_CH]; - float coef_a[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float coef_b[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float pColor_target_l[RV_LENGTH_NR_FC]; - float pColor_target_r[RV_LENGTH_NR_FC]; - float pTime_window[RV_FILTER_MAX_FFT_SIZE]; - float freq_step; - float delay_diff; - float ln_1e6_inverted; - int16_t offset; - int16_t fft_hist_size; - int16_t transitionStart; - int16_t transitionLength; - int16_t nrcoefs; - int16_t nr_fc_input, nr_fc_fft_filter; - - error = IVAS_ERR_OK; - output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); - subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; - predelay_bf_len = output_frame; - - /* Allocate main reverb. handle */ - if ( ( pState = (REVERB_HANDLE) count_malloc( sizeof( REVERB_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " ); - } - - nr_fc_input = hRenderConfig->roomAcoustics.nBands; - set_max_sizes( &rev_sizes ); - - if ( ( error = set_base_config( ¶ms, output_Fs, &rev_sizes ) ) != IVAS_ERR_OK ) - { - return error; - } - - for ( loop = 0; loop < IVAS_REV_MAX_NR_BRANCHES; loop++ ) - { - if ( ( pState->loop_delay_buffer[loop] = (float *) count_malloc( params.pLoop_delays[loop] * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); - } - } - - if ( ( pState->pPredelay_buffer = (float *) count_malloc( output_frame * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CREND Reverberator" ); - } - pState->full_block_size = subframe_len; - pState->nr_of_branches = rev_sizes.max_nr_loops; - - if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_48K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K; - } - else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_32K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K; - } - else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES ) - { - pState->fft_size = IVAS_REVERB_FFT_SIZE_16K; - pState->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K; - } - else - { - assert( 0 ); /* unsupported block size */ - } - pState->fft_subblock_size = subframe_len / pState->num_fft_subblocks; - nr_fc_fft_filter = ( pState->fft_size >> 1 ) + 1; - - /* === 'Control logic': compute the reverb processing parameters from the === */ - /* === room, source and listener acoustic information provided in the reverb config === */ - /* Setting up shared temporary buffers for fc, RT60, DSR, etc. */ - pHrtf_avg_pwr_response_l = &pFft_wf_filter_ch0[0][0]; - pHrtf_avg_pwr_response_r = pHrtf_avg_pwr_response_l + nr_fc_fft_filter; - params.pRt60 = &pFft_wf_filter_ch1[0][0]; - params.pDsr = params.pRt60 + nr_fc_fft_filter; - params.pFc = &pState->fft_filter_color_0.fft_spectrum[0]; - pHrtf_inter_aural_coherence = &pState->fft_filter_color_1.fft_spectrum[0]; - - /* Note: these temp buffers can only be used before the final step of the FFT filter design : */ - /* before calls to ivas_reverb_calc_correl_filters(...) or to ivas_reverb_calc_color_filters(...) */ - /* set the uniform frequency grid for FFT filtering */ - freq_step = 0.5f * output_Fs / ( nr_fc_fft_filter - 1 ); - for ( idx = 0; idx < nr_fc_fft_filter; idx++ ) - { - params.pFc[idx] = freq_step * idx; - } - - /* use crend hrtf filters */ - if ( hHrtf != NULL ) - { - /* Compute HRTF set properties: average left/right energies, IA coherence */ - /* First, find the offset of the frequency-domain data for the 1st frame and assign HRTF pointers */ - for ( nr_out_ch = 0; nr_out_ch < BINAURAL_CHANNELS; nr_out_ch++ ) - { - for ( hrtf_idx = 0; hrtf_idx < hHrtf->max_num_ir; hrtf_idx++ ) - { - offset = 0; - for ( m = 0; m < hHrtf->num_iterations[hrtf_idx][nr_out_ch] - 1; m++ ) - { - offset += hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][m]; - } - - if ( nr_out_ch == 0 ) - { - pHrtf_set_l_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][0][offset]; - pHrtf_set_l_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][0][offset]; - } - else - { - pHrtf_set_r_re[hrtf_idx] = &hHrtf->pOut_to_bin_re[hrtf_idx][1][offset]; - pHrtf_set_r_im[hrtf_idx] = &hHrtf->pOut_to_bin_im[hrtf_idx][1][offset]; - } - } - } - - /* Compute HRTF set properties using frequency-domain HRTF data */ - ivas_reverb_get_hrtf_set_properties( pHrtf_set_l_re, pHrtf_set_l_im, pHrtf_set_r_re, pHrtf_set_r_im, hHrtf->max_num_ir, subframe_len, - nr_fc_fft_filter, pHrtf_avg_pwr_response_l, pHrtf_avg_pwr_response_r, pHrtf_inter_aural_coherence ); - - pHrtf_avg_pwr_response_l_const = (const float *) pHrtf_avg_pwr_response_l; - pHrtf_avg_pwr_response_r_const = (const float *) pHrtf_avg_pwr_response_r; - pHrtf_inter_aural_coherence_const = (const float *) pHrtf_inter_aural_coherence; - } - else - { - pHrtf_avg_pwr_response_l_const = orange53_left_avg_power; - pHrtf_avg_pwr_response_r_const = orange53_right_avg_power; - pHrtf_inter_aural_coherence_const = orange53_coherence; - } - - /* interpolate input table data for T60 and DSR to the FFT filter grid */ - ivas_reverb_interpolate_acoustic_data( nr_fc_input, hRenderConfig->roomAcoustics.pFc_input, hRenderConfig->roomAcoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_dsr, - nr_fc_fft_filter, params.pFc, params.pRt60, params.pDsr ); - - /* adjust DSR for the delay difference */ - delay_diff = hRenderConfig->roomAcoustics.inputPreDelay - hRenderConfig->roomAcoustics.acousticPreDelay; - ln_1e6_inverted = 1.0f / logf( 1e06f ); - for ( idx = 0; idx < nr_fc_fft_filter; idx++ ) - { - const float tau = params.pRt60[idx] * ln_1e6_inverted; - params.pDsr[idx] *= expf( delay_diff / tau ); - } - - /* input downmix */ - calc_dmx_gain( ¶ms ); - - /* predelay - must be after set_base_config() and before compute_t60_coeffs() */ - calc_predelay( ¶ms, hRenderConfig->roomAcoustics.acousticPreDelay, output_Fs ); - /* jot reverb filters */ - if ( ( error = compute_t60_coeffs( ¶ms, nr_fc_fft_filter, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* === Now, copy parameters from ivas_reverb_params_t to REVERB_DATA === */ - /* === to be used for subsequent audio signal processing === */ - /* init input downmixer */ - pState->dmx_gain = params.dmx_gain; - - /* Defining appropriate windowing parameters for FFT filters to prevent aliasing */ - fft_hist_size = pState->fft_size - pState->fft_subblock_size; - - transitionStart = (int16_t) round( FFT_FILTER_WND_FLAT_REGION * fft_hist_size ); - transitionLength = (int16_t) round( FFT_FILTER_WND_TRANS_REGION * fft_hist_size ); - pState->do_corr_filter = params.do_corr_filter; - - /* Compute target levels (gains) for the coloration filters */ - ivas_reverb_calc_color_levels( output_Fs, nr_fc_fft_filter, params.nr_loops, params.pFc, params.pDsr, pHrtf_avg_pwr_response_l_const, pHrtf_avg_pwr_response_r_const, - params.pLoop_delays, params.pT60_filter_coeff, pColor_target_l, pColor_target_r ); - - /* Defining the window used for FFT filters */ - ivas_reverb_define_window_fft( pTime_window, transitionStart, transitionLength, nr_fc_fft_filter ); - - /* clear & init jot reverb (stored parameters, sample buffers etc) */ - if ( ( error = initialize_reverb( pState ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( pState->do_corr_filter ) - { - /* Computing correlation filters on the basis of target IA coherence */ - ivas_reverb_calc_correl_filters( pHrtf_inter_aural_coherence_const, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); - - /* Copying the computed FFT correlation filters to the fft_filter components */ - if ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - /* Computing coloration filters on the basis of target responses */ - ivas_reverb_calc_color_filters( pColor_target_l, pColor_target_r, pTime_window, pState->fft_size, 0.0f, pFft_wf_filter_ch0, pFft_wf_filter_ch1 ); - - /* Copying the computed FFT colorations filters to the fft_filter components */ - if ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1 ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* init predelay */ - ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer, params.pre_delay, predelay_bf_len ); - - /* initialize feedback branches */ - for ( i = 0; i < rev_sizes.max_nr_loops; i++ ) - { - ivas_rev_delay_line_init( &( pState->delay_line[i] ), pState->loop_delay_buffer[i], init_loop_delay[i], params.pLoop_delays[i] ); - ivas_reverb_iir_filt_init( &( pState->t60[i] ), IVAS_REV_MAX_IIR_FILTER_LENGTH ); - pState->mixer[0][i] = 0.0f; - pState->mixer[1][i] = 0.0f; - } - clear_buffers( pState ); - nrcoefs = params.t60_filter_order + 1; - - if ( IVAS_REV_MAX_IIR_FILTER_LENGTH < nrcoefs ) - { - return IVAS_ERR_INTERNAL; - } - else - { - for ( loop = 0; loop < params.nr_loops; loop++ ) - { - for ( i = 0; i < nrcoefs; i++ ) - { - coef_a[i] = params.pT60_filter_coeff[2 * nrcoefs * loop + i + nrcoefs]; - coef_b[i] = params.pT60_filter_coeff[2 * nrcoefs * loop + i]; - } - - if ( ( error = set_t60_filter( pState, loop, nrcoefs, coef_a, coef_b ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_feedback_delay( pState, loop, params.pLoop_delays[loop] ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( ( error = set_feedback_gain( pState, loop, &( params.pLoop_feedback_matrix[loop * params.nr_loops] ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - - for ( channel = 0; channel < params.nr_outputs; channel++ ) - { - if ( ( error = set_mixer_level( pState, channel, &( params.pLoop_extract_matrix[channel * params.nr_loops] ) ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - *hReverb = pState; - - return error; -} - - -/*------------------------------------------------------------------------- - * ivas_reverb_close() - * - * Deallocate Crend reverberation handle - *------------------------------------------------------------------------*/ - -void ivas_reverb_close( - REVERB_HANDLE *hReverb_in /* i/o: Reverberator handle */ -) -{ - REVERB_HANDLE hReverb; - int16_t loop; - - hReverb = *hReverb_in; - - if ( hReverb != NULL ) - { - for ( loop = 0; loop < IVAS_REV_MAX_NR_BRANCHES; loop++ ) - { - if ( hReverb->loop_delay_buffer[loop] != NULL ) - { - count_free( hReverb->loop_delay_buffer[loop] ); - hReverb->loop_delay_buffer[loop] = NULL; - } - } - - count_free( hReverb->pPredelay_buffer ); - hReverb->pPredelay_buffer = NULL; - - count_free( hReverb ); - hReverb = NULL; - } - - return; -} - - -/*-----------------------------------------------------------------------------------------* - * ivas_reverb_process() - * - * Process the input PCM audio into output PCM audio, applying reverb - *-----------------------------------------------------------------------------------------*/ - -ivas_error ivas_reverb_process( - REVERB_HANDLE hReverb, /* i/o: reverb state */ - const AUDIO_CONFIG transport_config, /* i : reverb. input audio configuration */ - const int16_t mix_signals, /* i : add reverb to output signal */ - float pcm_in[][L_FRAME48k], /* i : the PCM audio to apply reverb on */ - float pcm_out[][L_FRAME48k], /* o : the PCM audio with reverb applied */ - const int16_t i_ts ) -{ - float tmp0[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - ivas_error error; - - if ( ( error = downmix_input_block( hReverb, pcm_in, transport_config, tmp1, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK ) - { - return error; - } - - predelay_block( hReverb, tmp1, tmp0 ); - - reverb_block( hReverb, tmp0, tmp1, tmp2 ); - - if ( mix_signals ) - { - mix_output_block( hReverb, tmp1, tmp2, &pcm_out[0][i_ts * hReverb->full_block_size], &pcm_out[1][i_ts * hReverb->full_block_size] ); - } - else - { - mvr2r( tmp1, &pcm_out[0][i_ts * hReverb->full_block_size], hReverb->full_block_size ); - mvr2r( tmp2, &pcm_out[1][i_ts * hReverb->full_block_size], hReverb->full_block_size ); - } - - return IVAS_ERR_OK; -} - -#else /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ /*------------------------------------------------------------------------------------------* * Local constants @@ -2886,4 +1415,3 @@ ivas_error ivas_reverb_process( return IVAS_ERR_OK; } -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ diff --git a/lib_dec/ivas_reverb_filter_design.c b/lib_dec/ivas_reverb_filter_design.c index 3adfaa8a7d0cbd1c84431fc0ecaa1e688b99de74..daa3bc2525c60644e9dc49dd0c791d7bdf3d44b6 100644 --- a/lib_dec/ivas_reverb_filter_design.c +++ b/lib_dec/ivas_reverb_filter_design.c @@ -540,15 +540,9 @@ void ivas_reverb_calc_color_levels( const float alpha = -log__0_001 / t60[freq_idx]; const float revPredNormEnergy = ( A0_square_est / ( 2.0f * alpha ) ) * output_Fs / ( 0.8776f * minDelayDiff + 26.7741f ); -#ifndef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS - pTarget_color_L[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_L[freq_idx] ) / sqrtf( revPredNormEnergy ); - - pTarget_color_R[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_R[freq_idx] ) / sqrtf( revPredNormEnergy ); -#else /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ pTarget_color_L[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_L[freq_idx] ) / max( sqrtf( revPredNormEnergy ), EPS ); pTarget_color_R[freq_idx] = sqrtf( pAcoustic_dsr[freq_idx] * revEnergyFactor * pHrtf_avg_pwr_R[freq_idx] ) / max( sqrtf( revPredNormEnergy ), EPS ); -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ } /* Limiting the frequency response gradients diff --git a/lib_dec/ivas_reverb_utils.c b/lib_dec/ivas_reverb_utils.c index 760ddc199f6cfa9386da7c45aeeb7840a8ffa33a..c038c75203401f62b53c3d80113be01ff18cf3d2 100644 --- a/lib_dec/ivas_reverb_utils.c +++ b/lib_dec/ivas_reverb_utils.c @@ -94,12 +94,7 @@ void ivas_reverb_prepare_cldfb_params( float avg_pwr_left[CLDFB_NO_CHANNELS_MAX]; float avg_pwr_right[CLDFB_NO_CHANNELS_MAX]; -#ifndef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS - float delay_diff; - float ln_1e6_inverted; -#else /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ float delay_diff, ln_1e6_inverted, exp_argument; -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ const float dist = DEFAULT_SRC_DIST; const float dmx_gain_2 = 4.0f * EVS_PI * dist * dist / 0.001f; @@ -115,16 +110,11 @@ void ivas_reverb_prepare_cldfb_params( ln_1e6_inverted = 1.0f / logf( 1e06f ); for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { -#ifndef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS - const float tau = pOutput_t60[idx] * ln_1e6_inverted; - pOutput_ene[idx] *= expf( delay_diff / tau ); -#else /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ exp_argument = delay_diff / ( pOutput_t60[idx] * ln_1e6_inverted ); /* Limit exponent to approx +/-100 dB in case of incoherent value of delay_diff, to prevent overflow */ exp_argument = min( exp_argument, 23.0f ); exp_argument = max( exp_argument, -23.0f ); pOutput_ene[idx] *= expf( exp_argument ); -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ } ivas_reverb_get_fastconv_hrtf_set_energies( renderer_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ); diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 8f963664fb2e19519c483cd6a3fab7c4ff1aa8d4..f77b98442eb5c940c5a0e7547d3f1ba9c2452b47 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -256,12 +256,10 @@ void IVAS_DEC_Close( ( *phIvasDec )->st_ivas->hHeadTrackData = NULL; } -#ifdef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS if ( ( *phIvasDec )->st_ivas->hRenderConfig != NULL ) { ivas_render_config_close( &( ( *phIvasDec )->st_ivas->hRenderConfig ) ); } -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ ivas_HRTF_binary_close( &( *phIvasDec )->st_ivas->hHrtfTD ); diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 25195f890c736b6a3561525086b9fc96f6973e1b..383b305c0f9c2e0a38920df2a426d3ca0eba9818 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -48,7 +48,6 @@ #define MAX_ITEM_LENGTH ( 64 ) #define N_REVERB_VECTORS ( 3 ) -#ifdef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS #define SHORTEST_REV_DEL_LINE ( 0.015f ) #define N_BANDS_MIN ( 2 ) #define N_BANDS_MAX ( 60 ) @@ -65,7 +64,6 @@ #define ACOUSTICPREDELAY_FDREV_MAX ( (float) ( REVERB_PREDELAY_MAX ) / (float) ( 16 * FRAMES_PER_SEC ) ) #define INPUTPREDELAY_MIN ( 0.0f ) #define INPUTPREDELAY_MAX ( 1.0e+2f ) -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ /*------------------------------------------------------------------------------------------* * Type definitions @@ -223,7 +221,6 @@ static int32_t errorHandler( return numErrors; } -#ifdef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS /*------------------------------------------------------------------------------------------* * RenderConfigReader_checkValues() * @@ -314,7 +311,6 @@ static ivas_error RenderConfigReader_checkValues( return IVAS_ERR_OK; } -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ /*------------------------------------------------------------------------------------------* * RenderConfigReader_open() @@ -562,11 +558,7 @@ ivas_error RenderConfigReader_read( return IVAS_ERR_FAILED_FILE_PARSE; } -#ifndef REFACTOR_REVERB_INIT_ADD_CFG_CHECKS - return IVAS_ERR_OK; -#else /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ return RenderConfigReader_checkValues( hRenderConfig ); -#endif /* REFACTOR_REVERB_INIT_ADD_CFG_CHECKS */ }