diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 41a718269ce9ce639ead16003a992dcaa4c0eec4..af5c81594118d6dd2a9a31de23fba71496532805 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -1979,11 +1979,10 @@ typedef enum _DCTTYPE #define INV_PREECHO_SMOOTH_LENP1 ( 1 / ( PREECHO_SMOOTH_LEN + 1.0 ) ); #define EPSILON 0.000000000000001f -#define EPSILON_FX 0 #define EPSILON_FX_SMALL 1 -#ifdef IVAS_FLOAT_FIXED #define EPSILON_FIX (1) -#endif +#define EPSILON_FX (Word32)1 + #define MAX_SEGMENT_LENGTH 480 #define NUM_TIME_SWITCHING_BLOCKS 4 diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index cc848c7f6c02e9d9390b64688258980713f46456..3aa2073c5dfa9c858ced7759503448b289bb8a44 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -70,8 +70,8 @@ #define INV_SQRT2_FX 1518500224 /* 1/sqrt(2) */ #ifdef IVAS_FLOAT_FIXED -#define INV_SQRT2_FX_Q15 23170 /* 1/sqrt(2) Q15*/ - +#define INV_SQRT2_FX_Q15 23170 /* 1/sqrt(2) Q15*/ +#define INV_SQRT3_FX 18918 /* 1/sqrt(3) Q15*/ #endif #define LOG_10 2.30258509299f diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index a965ac7a0d349af9b4aeee1dff9ecf99fd034a81..d7b41adbe9f4e314f0f9c91f6270b3b439fde21f 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3042,6 +3042,25 @@ void mvr2r_inc( const int16_t n /* i : vector size */ ); +#ifdef IVAS_FLOAT_FIXED +void mvr2r_inc_fixed_one( + const Word32 x_fx[], /* i : input vector */ + const Word16 x_inc, /* i : increment for vector x[] */ + Word32 y_fx[], /* o : output vector */ + const Word16 y_inc, /* i : increment for vector y[] */ + const Word16 n /* i : vector size */ +); + +void mvr2r_inc_fixed( + const float x[], /* i : input vector */ + const Word32 x_fx[], /* i : input vector */ + const int16_t x_inc, /* i : increment for vector x[] */ + float y[], /* o : output vector */ + Word32 y_fx[], /* o : output vector */ + const int16_t y_inc, /* i : increment for vector y[] */ + const int16_t n /* i : vector size */ +); +#endif void v_add_inc( const float x1[], /* i : Input vector 1 */ const int16_t x_inc, /* i : Increment for input vector 1 */ @@ -3085,6 +3104,13 @@ void v_addc_fx( const Word16 N /* i : Vector length */ ); #endif + +void v_addc_fixed( + const Word32 x[], /* i : Input vector */ + const Word32 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains c*x */ + const Word16 N /* i : Vector length */ +); void v_addc( const float x[], /* i : Input vector */ const float c, /* i : Constant */ @@ -4162,6 +4188,13 @@ void ivas_dirac_dec_get_response_fixed( const Word16 elevation, Word32 *response, const Word16 ambisonics_order ); + +void ivas_dirac_dec_get_response_fixed_Q( + const Word16 azimuth, + const Word16 elevation, + Word32 *response, + const Word16 ambisonics_order, + Word16 Q); #endif void calculate_hodirac_sector_parameters( diff --git a/lib_com/ivas_spar_com.c b/lib_com/ivas_spar_com.c index a8132a4341e84d5a2d2c7537bd3ce5593535e88b..be9eb075def19a56eb62e496d4a853b5519f8715 100644 --- a/lib_com/ivas_spar_com.c +++ b/lib_com/ivas_spar_com.c @@ -1998,6 +1998,123 @@ void ivas_dirac_dec_get_response_fixed( return; } + +void ivas_dirac_dec_get_response_fixed_Q( + const Word16 azimuth, + const Word16 elevation, + Word32 *response, + const Word16 ambisonics_order, + Word16 Q_out) +{ + Word16 index_azimuth, index_elevation; + Word16 el, e, az; + Word32 cos_1, cos_2, sin_1, cos_az[3]; + Word32 sin_az[3]; + Word32 f, c; + Word16 l, m; + Word16 b, b1, b_2, b1_2, a; + + index_azimuth = (azimuth + 180) % 360; + index_elevation = elevation + 90; + e = index_elevation > 90 ? -1 : 1; + el = index_elevation > 90 ? 180 - index_elevation : index_elevation; + + az = index_azimuth > 180 ? 360 - index_azimuth : index_azimuth; + f = index_azimuth > 180 ? -(1 << Q29) : (1 << Q29); + + cos_1 = dirac_gains_trg_term_int[az][0] >> 1; // Q29 + cos_2 = Mpy_32_32(cos_1, cos_1); // Q27 + sin_1 = Mpy_32_32(f, dirac_gains_trg_term_int[az][1] >> 1); // Q27 + cos_az[0] = cos_1; // Q29 + cos_az[1] = L_sub(Mpy_32_32((1 << Q30), cos_2), (1 << Q25)) << 4; // Q29 + cos_az[2] = L_sub(Mpy_32_32(Mpy_32_32((1 << Q30), cos_1), cos_az[1]) << 4, cos_az[0]); // Q29 + sin_az[0] = sin_1 << 2; // Q29 + sin_az[1] = Mpy_32_32(Mpy_32_32(sin_1, (1 << Q30)), cos_1) << 6; // Q29 + sin_az[2] = Mpy_32_32(sin_1, L_sub(L_shl_sat(Mpy_32_32((1 << Q30), cos_2), 5), (1 << 29))) << 4; + + response[0] = L_shl(1, Q_out); + /* Un-optimized code - for reference */ + /* for( l = 1; l<= ambisonics_order; l++ ) */ + /* { */ + /* int16_t b, b1, a; */ + /* float c; */ + /* for( m = 0; m < l; m++ ) */ + /* { */ + /* b = l*l+m; */ + /* a = dirac_gains_P_idx[b]; */ + /* c = SQRT2 * dirac_gains_norm_term[a] * dirac_gains_Pnm[el][a]; */ + + /* if( m%2 == 1 ) */ + /* { */ + /* c = c*e; */ + /* } */ + + /* response[b] = c * sin_az[l-m-1]; */ + + /* b1 = l*l+2*l-m; */ + /* response[b1] = c * cos_az[l-m-1]; */ + + /* } */ + + /* b = l*l+l; */ + /* a = dirac_gains_P_idx[b]; */ + /* c = dirac_gains_norm_term[a] * dirac_gains_Pnm[el][a]; */ + /* if( l%2 == 1) */ + /* { */ + /* c = c*e; */ + /* } */ + + /* response[b] = c; */ + /* } */ + + FOR(l = 1; l <= ambisonics_order; l++) + { + b_2 = l * l; + b1_2 = l * l + 2 * l; + FOR(m = 0; m < l; m += 2) + { + b = b_2 + m; + a = dirac_gains_P_idx[b]; + c = Mpy_32_32(Mpy_32_32(SQRT2_FIXED, dirac_gains_norm_term_int[a]), dirac_gains_Pnm_int[el][a]); // Q25 + + response[b] = L_shl(Mpy_32_32(c, sin_az[l - m - 1]), Q_out - Q23); // Q_out + + b1 = b1_2 - m; + response[b1] = L_shl(Mpy_32_32(c, cos_az[l - m - 1]), Q_out - Q23); // Q_out + } + + FOR(m = 1; m < l; m += 2) + { + b = b_2 + m; + a = dirac_gains_P_idx[b]; + c = Mpy_32_32(Mpy_32_32(SQRT2_FIXED, dirac_gains_norm_term_int[a]), dirac_gains_Pnm_int[el][a]); // Q25 + IF(e == -1) + { + c = -c; + } + + response[b] = L_shl(Mpy_32_32(c, sin_az[l - m - 1]), Q_out - Q23); // Q29 + + b1 = b1_2 - m; + response[b1] = L_shl(Mpy_32_32(c, cos_az[l - m - 1]), Q_out - Q23); // Q29 + } + + b = b_2 + l; + a = dirac_gains_P_idx[b]; + c = Mpy_32_32(dirac_gains_norm_term_int[a], dirac_gains_Pnm_int[el][a]); //Q26 + IF(l % 2 == 1) + { + IF(e == -1) + { + c = -c; + } + } + + response[b] = L_shl(c, Q_out - Q26); // Q29 + } + + return; +} #endif /*-----------------------------------------------------------------------------------------* diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index 42e34e7df1a93ae562c150a4e46d736e34ccc042..6985cbc4ea56ccb90010ca37a90d17899aed1f40 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -187,6 +187,103 @@ void ivas_syn_output_f( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void mvr2r_inc_fixed_one( + const Word32 x_fx[], /* i : input vector */ + const Word16 x_inc, /* i : increment for vector x[] */ + Word32 y_fx[], /* o : output vector */ + const Word16 y_inc, /* i : increment for vector y[] */ + const Word16 n /* i : vector size */ +) +{ + Word16 i; + Word16 ix; + Word16 iy; + + IF(n <= 0) + { + /* cannot transfer vectors with size 0 */ + return; + } + + IF(y_fx < x_fx) + { + ix = 0; + iy = 0; + FOR(i = 0; i < n; i++) + { + y_fx[iy] = x_fx[ix]; + + ix += x_inc; + iy += y_inc; + } + } + ELSE + { + ix = (n - 1) * x_inc; + iy = (n - 1) * y_inc; + FOR(i = n - 1; i >= 0; i--) + { + y_fx[iy] = x_fx[ix]; + + ix -= x_inc; + iy -= y_inc; + } + } + + return; +} + +void mvr2r_inc_fixed( + const float x[], /* i : input vector */ + const Word32 x_fx[], /* i : input vector */ + const Word16 x_inc, /* i : increment for vector x[] */ + float y[], /* o : output vector */ + Word32 y_fx[], /* o : output vector */ + const Word16 y_inc, /* i : increment for vector y[] */ + const Word16 n /* i : vector size */ +) +{ + Word16 i; + Word16 ix; + Word16 iy; + + IF (n <= 0) + { + /* cannot transfer vectors with size 0 */ + return; + } + + IF (y_fx < x_fx) + { + ix = 0; + iy = 0; + FOR (i = 0; i < n; i++) + { + y_fx[iy] = x_fx[ix]; + y[iy] = x[ix]; + + ix += x_inc; + iy += y_inc; + } + } + ELSE + { + ix = (n - 1) * x_inc; + iy = (n - 1) * y_inc; + FOR (i = n - 1; i >= 0; i--) + { + y_fx[iy] = x_fx[ix]; + y[iy] = x[ix]; + + ix -= x_inc; + iy -= y_inc; + } + } + + return; +} +#endif void mvr2r_inc( const float x[], /* i : input vector */ @@ -402,6 +499,24 @@ void v_addc_fx( * * Addition of constant to vector *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void v_addc_fixed( + const Word32 x[], /* i : Input vector */ + const Word32 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains c*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR(i = 0; i < N; i++) + { + y[i] = L_add(c, x[i]); + } + + return; +} +#endif void v_addc( const float x[], /* i : Input vector */ @@ -2279,4 +2394,4 @@ Word64 var_32_fx( var = var / len; return var; -} \ No newline at end of file +} diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index 2d65bebd0b70b54ece8ca152fdbed04b3e4c5fa4..e0634bdc7859936c56dd2a3495cd68f792cca8eb 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -45,6 +45,7 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #include "prot_fx1.h" +#include "prot_fx2.h" #endif /*-------------------------------------------------------------------* @@ -2254,22 +2255,6 @@ void msvq_dec_float( } #ifdef IVAS_FLOAT_FIXED -static Word16 find_guarded_bits_fx( Word32 n ); - -static Word16 find_guarded_bits_fx( Word32 n ) -{ - return n <= 1 ? 0 : n <= 2 ? 1 - : n <= 4 ? 2 - : n <= 8 ? 3 - : n <= 16 ? 4 - : n <= 32 ? 5 - : n <= 64 ? 6 - : n <= 128 ? 7 - : n <= 256 ? 8 - : n <= 512 ? 9 - : n <= 1024 ? 10 - : 11; -} void msvq_dec_fx( const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ diff --git a/lib_com/prot.h b/lib_com/prot.h index d01005cc47e23a9947c67cac1d94d396c773adca..6a0639df9b61b653f8a9b8557966d69daf528c27 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -166,6 +166,14 @@ float sum2_f( const int16_t lvec /* i : length of input vector */ ); +#ifdef IVAS_FLOAT_FIXED +Word32 sum2_f_32_fx( + const Word32 *vec, /* i : input vector */ + const int16_t lvec, /* i : length of input vector */ + Word16 gb +); +#endif + void set_c( int8_t y[], /* i/o: Vector to set */ const int8_t a, /* i : Value to set the vector to */ @@ -322,6 +330,15 @@ void v_sub( const int16_t N /* i : Vector length */ ); +#ifdef IVAS_FLOAT_FIXED +void v_mult_fixed( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +); +#endif + void v_mult( const float x1[], /* i : Input vector 1 */ const float x2[], /* i : Input vector 2 */ diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 354cf5cf989118c9310c30a335e587c694f1d607..87b29ccf3db965ef6ffe4183158304f51dcad883 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -5444,6 +5444,14 @@ Word32 dotp_fixed_o( const Word16 n, /* i : vector length */ const Word16 log_len, /* i : max factor added to result q after dot product (equal to log2(n)) */ Word16 *res_q ); +#ifdef IVAS_FLOAT_FIXED +Word32 dotp_fixed_guarded( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n /* i : vector length */ +); +#endif + void lsf_end_dec_fx( Decoder_State* st, /* i/o: decoder state structure */ Word16 mode2_flag, diff --git a/lib_com/tools.c b/lib_com/tools.c index 7486a24b3619abfac01fda5996b11d264dd5fcbf..ed46d2cf1e89bd735623947c36c268b4d4d61d75 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -195,6 +195,28 @@ float sum2_f( return tmp; } +#ifdef IVAS_FLOAT_FIXED +Word32 sum2_f_32_fx( + const Word32 *vec, /* i : input vector */ + const int16_t lvec, /* i : length of input vector */ + Word16 gb +) +{ + int16_t i; + Word32 tmp; + + tmp = 0; + Word32 var_a = 0; + for (i = 0; i < lvec; i++) + { + var_a = Mpy_32_32(vec[i], vec[i]);//2x-31 + tmp = L_add(tmp, L_shr(var_a, gb));//2x-31-gb + } + + return tmp; +} +#endif + /*-------------------------------------------------------------------* * set_c() * set_s() @@ -852,16 +874,36 @@ Word32 dotp_fixed( Word16 i; Word32 suma; - suma = Mpy_32_32( x[0], y[0] ); + suma = Mpy_32_32(x[0], y[0]); - FOR ( i = 1; i < n; i++ ) + FOR(i = 1; i < n; i++) { - suma = L_add( suma, Mpy_32_32( x[i], y[i] ) ); + suma = L_add(suma, Mpy_32_32(x[i], y[i])); } return suma; } +#ifdef IVAS_FLOAT_FIXED +Word32 dotp_fixed_guarded( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n /* i : vector length */ +) +{ + Word16 i; + Word32 suma; + Word16 guarded_bits = find_guarded_bits_fx(n); + suma = L_shr(Mpy_32_32( x[0], y[0] ), guarded_bits); + + FOR ( i = 1; i < n; i++ ) + { + suma = L_add( suma, L_shr(Mpy_32_32( x[i], y[i] ), guarded_bits)); + } + + return suma; +} +#endif /*To calculate dot product of two 32 bit arrays in case of overflow*/ Word32 dotp_fixed_o( @@ -1111,6 +1153,24 @@ void v_sub_fixed( * * Multiplication of two vectors *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void v_mult_fixed( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR(i = 0; i < N; i++) + { + y[i] = Mpy_32_32(x1[i], x2[i]); + } + + return; +} +#endif void v_mult( const float x1[], /* i : Input vector 1 */ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 007c4520a08f3ed051e5479ce4b6f863fd0fbb2e..1c90efff4c139615687ddc62e5135248db221715 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -3350,6 +3350,9 @@ void ivas_dirac_dec_render_sf( float dirEne; float surCohEner; float surCohRatio[CLDFB_NO_CHANNELS_MAX]; +#ifdef IVAS_FLOAT_FIXED + set_zero( surCohRatio, CLDFB_NO_CHANNELS_MAX ); +#endif int16_t subframe_idx; int16_t slot_idx, index_slot; int16_t hodirac_flag; @@ -3369,6 +3372,9 @@ void ivas_dirac_dec_render_sf( int16_t azimuth[CLDFB_NO_CHANNELS_MAX]; int16_t elevation[CLDFB_NO_CHANNELS_MAX]; float diffuseness_vector[CLDFB_NO_CHANNELS_MAX]; +#ifdef IVAS_FLOAT_FIXED + Word32 diffuseness_vector_fx[CLDFB_NO_CHANNELS_MAX]; +#endif DIRAC_DEC_STACK_MEM DirAC_mem; float *reference_power, *reference_power_smooth; @@ -3421,10 +3427,16 @@ void ivas_dirac_dec_render_sf( mvs2s( hSpatParamRendCom->azimuth[hSpatParamRendCom->render_to_md_map[subframe_idx]], azimuth, hSpatParamRendCom->num_freq_bands ); mvs2s( hSpatParamRendCom->elevation[hSpatParamRendCom->render_to_md_map[subframe_idx]], elevation, hSpatParamRendCom->num_freq_bands ); mvr2r( hSpatParamRendCom->diffuseness_vector[hSpatParamRendCom->render_to_md_map[subframe_idx]], diffuseness_vector, hSpatParamRendCom->num_freq_bands ); +#ifdef IVAS_FLOAT_FIXED + Copy32(hSpatParamRendCom->diffuseness_vector_fx[hSpatParamRendCom->render_to_md_map[subframe_idx]], diffuseness_vector_fx, hSpatParamRendCom->num_freq_bands); +#endif } else { set_zero( diffuseness_vector, hSpatParamRendCom->num_freq_bands ); +#ifdef IVAS_FLOAT_FIXED + set32_fx(diffuseness_vector_fx, 0, hSpatParamRendCom->num_freq_bands); +#endif } if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) @@ -3458,11 +3470,30 @@ void ivas_dirac_dec_render_sf( /* compute response */ if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { +#ifdef IVAS_FLOAT_FIXED + for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + diffuseness_vector_fx[i] = float_to_fix( diffuseness_vector[i], Q30 ); + } + + ivas_dirac_dec_compute_power_factors_fx( hSpatParamRendCom->num_freq_bands, + diffuseness_vector_fx, + hDirACRend->h_output_synthesis_psd_params.max_band_decorr, + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx ); + + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] = fix_to_float( hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], Q29 ); + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] = fix_to_float( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], Q29 ); + } +#else ivas_dirac_dec_compute_power_factors( hSpatParamRendCom->num_freq_bands, diffuseness_vector, hDirACRend->h_output_synthesis_psd_params.max_band_decorr, hDirACRend->h_output_synthesis_psd_state.direct_power_factor, hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); +#endif if ( coherence_flag ) { @@ -3483,11 +3514,27 @@ void ivas_dirac_dec_render_sf( } else { +#ifdef IVAS_FLOAT_FIXED + Word16 max_exp_direct = 0, max_exp_diffusion = 0; + ivas_dirac_dec_compute_gain_factors_fx( hSpatParamRendCom->num_freq_bands, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx, + &max_exp_direct, &max_exp_diffusion ); + + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], max_exp_direct ); + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], max_exp_diffusion ); + } + +#else ivas_dirac_dec_compute_gain_factors( hSpatParamRendCom->num_freq_bands, hSpatParamRendCom->diffuseness_vector[md_idx], hDirACRend->h_output_synthesis_psd_params.max_band_decorr, hDirACRend->h_output_synthesis_psd_state.direct_power_factor, hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); +#endif if ( coherence_flag ) { @@ -3504,6 +3551,41 @@ void ivas_dirac_dec_render_sf( if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order == 1 ) { +#ifdef IVAS_FLOAT_FIXED + Word32 surCohRatio_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 Q_surCohRatio = Q31; + IF( surCohRatio != NULL ) + { + float max_val = 0.0f; + for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + max_val = max( max_val, surCohRatio[i] ); + } + Word16 a = norm_l( (Word32) max_val ); + if ( a != 0 ) + { + Q_surCohRatio = a; + } + for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + surCohRatio_fx[i] = float_to_fix( surCohRatio[i], Q_surCohRatio ); + } + } + + ivas_dirac_dec_compute_directional_responses_fx( hSpatParamRendCom, + hDirACRend, + st_ivas->hVBAPdata, + st_ivas->hMasa == NULL ? NULL : st_ivas->hMasa->data.band_mapping, + st_ivas->hMasaIsmData, + azimuth, + elevation, + md_idx, + surCohRatio_fx, + Q_surCohRatio, + st_ivas->hCombinedOrientationData->shd_rot_max_order, + p_Rmat, + hodirac_flag ); +#else ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, hDirACRend, st_ivas->hVBAPdata, @@ -3516,9 +3598,45 @@ void ivas_dirac_dec_render_sf( st_ivas->hCombinedOrientationData->shd_rot_max_order, p_Rmat, hodirac_flag ); +#endif } else { +#ifdef IVAS_FLOAT_FIXED + Word32 surCohRatio_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 Q_surCohRatio = Q31; + IF( surCohRatio != NULL ) + { + float max_val = 0.0f; + for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + max_val = max( max_val, surCohRatio[i] ); + } + Word16 a = norm_l( (Word32) max_val ); + if ( a != 0 ) + { + Q_surCohRatio = a; + } + for ( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + surCohRatio_fx[i] = float_to_fix( surCohRatio[i], Q_surCohRatio ); + } + } + + ivas_dirac_dec_compute_directional_responses_fx( hSpatParamRendCom, + hDirACRend, + st_ivas->hVBAPdata, + st_ivas->hMasa == NULL ? NULL : st_ivas->hMasa->data.band_mapping, + st_ivas->hMasaIsmData, + azimuth, + elevation, + md_idx, + surCohRatio_fx, + Q_surCohRatio, + 0, + NULL, + hodirac_flag ); +#else ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, hDirACRend, st_ivas->hVBAPdata, @@ -3531,6 +3649,7 @@ void ivas_dirac_dec_render_sf( 0, NULL, hodirac_flag ); +#endif } } diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c index e0a79fd577d35d3e2897ffef1f2c007923765e5e..e8b76a64f15448e88fadfeaea07cf559c085464c 100644 --- a/lib_dec/ivas_out_setup_conversion.c +++ b/lib_dec/ivas_out_setup_conversion.c @@ -62,7 +62,6 @@ #define LS_OUT_CONV_CLIP_FACTOR_MAX_SQ_Q28 1073741824 #define LS_OUT_CONV_CLIP_FACTOR_MIN_Q29 161061274 #define LS_OUT_CONV_CLIP_FACTOR_MIN_SQ_Q28 24159191 -#define EPSILON_FX 1 #endif diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_rend/ivas_dirac_output_synthesis_dec.c index 356215c5db54e6561b3fb158a78665f560b64b86..92a60a28ac55de786d169b424fd6978a2df13a6b 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec.c @@ -77,7 +77,13 @@ static void computeTargetPSDs_diffuse_with_onsets( const int16_t num_channels, c static void computeAlphaSynthesis( float *alpha_synthesis, const int16_t averaging_length_ms, const float maxAlpha, int16_t *numAlphas, const int16_t slot_size, const int16_t num_freq_bands, const float *frequency_axis, const int32_t output_Fs ); #ifdef IVAS_FLOAT_FIXED -static void computeAlphaSynthesis_fx( Word16 *alpha_synthesis_fx, const int16_t averaging_length_ms, const Word16 maxAlpha_fx, int16_t *numAlphas, const int16_t slot_size, const int16_t num_freq_bands, Word16 *frequency_axis_fx, const int32_t output_Fs); +static void computeAlphaSynthesis_fx( Word16 *alpha_synthesis_fx, const int16_t averaging_length_ms, const Word16 maxAlpha_fx, int16_t *numAlphas, const int16_t slot_size, const int16_t num_freq_bands, Word16 *frequency_axis_fx, const int32_t output_Fs ); + +static void spreadCoherencePanningHoa_fx( const Word16 azimuth, const Word16 elevation, const Word16 spreadCoh_fx, Word32 *direct_response_fx, Word16 *Q_direct_response_hoa, const Word16 num_channels_dir, const Word16 ambisonics_order ); + +static void spreadCoherencePanningVbap_fx( const int16_t azimuth, const int16_t elevation, const float spreadCoh, const Word16 spreadCoh_fx, float *direct_response, Word32 *direct_response_fx, Word16 *Q_direct_response, const int16_t num_channels_dir, const VBAP_HANDLE hVBAPdata ); + +static void normalizePanningGains_fx( Word32 *direct_response_fx, Word16 *q_direct_res, const Word16 num_channels_dir ); #endif static void spreadCoherencePanningHoa( const int16_t azimuth, const int16_t elevation, const float spreadCoh, float *direct_response, const int16_t num_channels_dir, const int16_t ambisonics_order ); @@ -2465,6 +2471,712 @@ static void ivas_dirac_dec_get_response_split_order( * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_compute_directional_responses_fx( + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const Word16 *masa_band_mapping, /* i : Band mapping for MASA, NULL assumes not using MASA in any form */ + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ + const Word16 *azimuth, + const Word16 *elevation, + const Word16 md_idx, + const Word32 *surCohRatio_fx, + Word16 Q_surCohRatio, + const Word16 shd_rot_max_order, /* i : split-order rotation method */ + const float *p_Rmat, /* i : rotation matrix */ + const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ +) +{ + Word16 k, l, i; + Word16 num_channels_dir; + const Word16 *azimuth2, *elevation2; + float direct_response_hoa[MAX_OUTPUT_CHANNELS]; /* number of output channels (HOA 3rd order) -> 16 */ + float direct_response_ls[MAX_OUTPUT_CHANNELS]; + float direct_response_square[MAX_OUTPUT_CHANNELS]; + float *direct_response; + float direct_response_dir2[MAX_OUTPUT_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_surCohRatio = 31 - Q_surCohRatio; + Word32 direct_response_ls_fx[MAX_OUTPUT_CHANNELS]; + Word16 Q_direct_response_ls = Q31, exp_direct_response_ls = 0; + Word32 direct_response_dir2_fx[MAX_OUTPUT_CHANNELS]; + Word16 Q_direct_response_dir2 = Q31, exp_direct_response_dir2 = 0; + Word32 direct_response_hoa_fx[MAX_OUTPUT_CHANNELS]; + Word16 Q_direct_response_hoa = Q31, exp_direct_response_hoa = 0; + Word32 totalDirect_fx; + Word32 directRatio_fx[MASA_MAXIMUM_DIRECTIONS]; +#endif + + Word16 codingBand; + Word16 dipole_freq_range[2]; + MASA_TRANSPORT_SIGNAL_TYPE transport_signal_type; + + azimuth2 = NULL; + elevation2 = NULL; + transport_signal_type = MASA_STEREO_NOT_DEFINED; + move16(); + + IF( hDirACRend->masa_stereo_type_detect != NULL ) + { + dipole_freq_range[0] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[0]; + move16(); + dipole_freq_range[1] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[1]; + move16(); + transport_signal_type = hDirACRend->masa_stereo_type_detect->masa_stereo_type; + move16(); + } + + num_channels_dir = hDirACRend->num_outputs_dir; + move16(); + IF( EQ_16( hSpatParamRendCom->numParametricDirections, 2 ) ) + { + azimuth2 = hSpatParamRendCom->azimuth2[md_idx]; + move16(); + elevation2 = hSpatParamRendCom->elevation2[md_idx]; + move16(); + } + + codingBand = negate(1); + + assert( num_channels_dir <= MAX_OUTPUT_CHANNELS && "Number of channels is too high" ); + + FOR( k = 0; k < hSpatParamRendCom->num_freq_bands; ++k ) + { + IF( masa_band_mapping != NULL && EQ_16( k, MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] ) ) + { + codingBand = add( codingBand, 1 ); + } + + IF( masa_band_mapping != NULL && GT_16( k, MASA_band_grouping_24[masa_band_mapping[codingBand]] ) && + LT_16( k, MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] ) && + NE_16( k, hDirACRend->h_output_synthesis_psd_params.max_band_decorr ) ) + { + /* Panning gains have to be computed only for the first bin of the coding band in MASA, for other bins the previous values can be used */ + IF( NE_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) + { + mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k - 1], + hSpatParamRendCom->num_freq_bands, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], + hSpatParamRendCom->num_freq_bands, num_channels_dir ); + } + mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses[k - 1], + hSpatParamRendCom->num_freq_bands, + &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], + hSpatParamRendCom->num_freq_bands, num_channels_dir ); + } + ELSE + { + /* HOA3 PANNING */ + IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_HOA3 ) ) + { + /*TODO : Clean up*/ + set_f( direct_response_hoa, 1.0f, MAX_OUTPUT_CHANNELS ); + set_f( direct_response_dir2, 1.0f, MAX_OUTPUT_CHANNELS ); + + set32_fx( direct_response_hoa_fx, ONE_IN_Q29, MAX_OUTPUT_CHANNELS ); + set32_fx( direct_response_dir2_fx, ONE_IN_Q29, MAX_OUTPUT_CHANNELS ); + + Q_direct_response_hoa = Q29; + move16(); + Q_direct_response_dir2 = Q29; + move16(); + exp_direct_response_hoa = 0; + move16(); + exp_direct_response_dir2 = 0; + move16(); + + IF( p_Rmat != 0 ) + { + ivas_dirac_dec_get_response_split_order( azimuth[k], elevation[k], direct_response_hoa, shd_rot_max_order, p_Rmat ); + + IF( hodirac_flag ) + { + ivas_dirac_dec_get_response_split_order( azimuth2[k], elevation2[k], direct_response_dir2, shd_rot_max_order, p_Rmat ); + } + } + ELSE + { + ivas_dirac_dec_get_response_fixed_Q( azimuth[k], elevation[k], direct_response_hoa_fx, hDirACRend->hOutSetup.ambisonics_order, Q_direct_response_hoa ); + + IF( hodirac_flag ) + { + ivas_dirac_dec_get_response_fixed_Q( azimuth2[k], elevation2[k], direct_response_dir2_fx, hDirACRend->hOutSetup.ambisonics_order, Q_direct_response_dir2 ); + } + } + + IF( masa_band_mapping == NULL && EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) + { + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_hoa[i] = fix_to_float( direct_response_hoa_fx[i], Q_direct_response_hoa ); + } + mvr2r_inc( direct_response_hoa, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + + IF( hodirac_flag ) + { + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_dir2[i] = fix_to_float( direct_response_dir2_fx[i], Q_direct_response_dir2 ); + } + mvr2r_inc( direct_response_dir2, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k + hSpatParamRendCom->num_freq_bands * num_channels_dir], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + } + } + ELSE IF( ( ( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) && ( masa_band_mapping != NULL ) ) || + EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD ) || EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) ) + { + /* Synthesize the first direction */ + IF( GT_16( Q_direct_response_hoa, Q29 ) ) + { + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_hoa_fx[i] = L_shr( direct_response_hoa_fx[i], abs_s( Q_direct_response_hoa - Q29 ) ); + } + Q_direct_response_hoa = Q29; + move16(); + exp_direct_response_hoa = sub( 31, Q_direct_response_hoa ); + move16(); + } + spreadCoherencePanningHoa_fx( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence_fx[md_idx][k], + direct_response_hoa_fx, &Q_direct_response_hoa, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + + exp_direct_response_hoa = sub( 31, Q_direct_response_hoa ); + move16(); + /* Synthesize the second direction and combine the gains */ + IF( EQ_16( hSpatParamRendCom->numParametricDirections, 2 ) ) + { + IF( GT_16( Q_direct_response_dir2, Q29 ) ) + { + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_dir2_fx[i] = L_shr( direct_response_dir2_fx[i], abs_s( Q_direct_response_dir2 - Q29 ) ); + } + Q_direct_response_dir2 = Q29; + move16(); + exp_direct_response_dir2 = sub( 31, Q_direct_response_dir2 ); + move16(); + } + spreadCoherencePanningHoa_fx( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2_fx[md_idx][k], + direct_response_dir2_fx, &Q_direct_response_dir2, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + + exp_direct_response_hoa = sub( 31, Q_direct_response_hoa ); + move16(); + /* Combine gains from the two directions */ + totalDirect_fx = L_add( hSpatParamRendCom->energy_ratio1_fx[md_idx][k], hSpatParamRendCom->energy_ratio2_fx[md_idx][k] ); + IF( totalDirect_fx == 0 ) + { + totalDirect_fx = EPSILON_FIX; + move32(); + } + + Word16 var_a = 0, var_b = 0, exp_1 = 0, exp_2 = 0; + var_a = BASOP_Util_Divide3232_Scale( hSpatParamRendCom->energy_ratio1_fx[md_idx][k], totalDirect_fx, &exp_1 ); + var_b = BASOP_Util_Divide3232_Scale( hSpatParamRendCom->energy_ratio2_fx[md_idx][k], totalDirect_fx, &exp_2 ); + + directRatio_fx[0] = L_deposit_h( var_a ); + move32(); + directRatio_fx[1] = L_deposit_h( var_b ); + move32(); + + Word32 temp_a = 0; + Word16 exp_arr[MAX_OUTPUT_CHANNELS], exp_temp_a = 0, final_exp = 0; + set16_fx( exp_arr, exp_direct_response_hoa, MAX_OUTPUT_CHANNELS ); + exp_direct_response_hoa = sub( 31, Q_direct_response_hoa ); + move16(); + + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_hoa_fx[l] = Mpy_32_32( direct_response_hoa_fx[l], directRatio_fx[0] ); + move32(); + exp_arr[l] = add( exp_1, sub( 31, Q_direct_response_hoa ) ); + move16(); + temp_a = Mpy_32_32( directRatio_fx[1], direct_response_dir2_fx[l] ); + move32(); + exp_temp_a = add( exp_2, sub( 31, Q_direct_response_dir2 ) ); + move16(); + direct_response_hoa_fx[l] = BASOP_Util_Add_Mant32Exp( direct_response_hoa_fx[l], exp_arr[l], temp_a, exp_temp_a, &final_exp ); + move32(); + exp_arr[l] = final_exp; + move16(); + } + + Word16 max_exp = MIN16B; + move16(); + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + direct_response_hoa_fx[l] = L_shr( direct_response_hoa_fx[l], max_exp - exp_arr[l] ); + move32(); + } + exp_direct_response_hoa = max_exp; + move16(); + Q_direct_response_hoa = sub( 31, max_exp ); + move16(); + } + + IF( GT_16( hSpatParamRendCom->numIsmDirections, 0 ) ) + { + Word16 dir; + Word32 direct_response_temp_fx[MAX_OUTPUT_CHANNELS]; + Word32 direct_response_ism_fx[MAX_OUTPUT_CHANNELS]; + Word16 exp_direct_response_ism = 0, exp_direct_response_temp = 0; + Word32 masaDirect_fx; + Word32 ismDirect_fx; + + set32_fx( direct_response_ism_fx, 0, num_channels_dir ); + + FOR( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + { + IF( hMasaIsm->ism_is_edited[dir] ) + { + ivas_dirac_dec_get_response_fixed( hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order ); + } + ELSE + { + ivas_dirac_dec_get_response_fixed( hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order ); + } + exp_direct_response_temp = 2; + move16(); + + Word32 temp_1 = 0; + Word16 exp_temp = 0, exp_arr[MAX_OUTPUT_CHANNELS]; + set16_fx( exp_arr, 0, MAX_OUTPUT_CHANNELS); + FOR( l = 0; l < num_channels_dir; l++ ) + { + temp_1 = Mpy_32_32( direct_response_temp_fx[l], hMasaIsm->energy_ratio_ism_fx[dir][md_idx][k] ); // Q28 + direct_response_ism_fx[l] = BASOP_Util_Add_Mant32Exp( direct_response_ism_fx[l], exp_direct_response_ism, temp_1, exp_direct_response_temp + 1, &exp_temp ); + move32(); + exp_arr[l] = exp_temp; + move16(); + } + Word16 max_exp = MIN16B; + FOR( l = 0; l < num_channels_dir; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ism_fx[l] = L_shr( direct_response_ism_fx[l], max_exp - exp_arr[l] ); + move32(); + } + exp_direct_response_ism = max_exp; + move16(); + } + Word16 exp_1 = 0, exp_2 = 0; + masaDirect_fx = hSpatParamRendCom->energy_ratio1_fx[md_idx][k]; + move32(); + IF( masaDirect_fx == 0 ) + { + masaDirect_fx = L_add( masaDirect_fx, EPSILLON_FX ); + } + IF( hSpatParamRendCom->numParametricDirections == 2 ) + { + masaDirect_fx = L_add( masaDirect_fx, hSpatParamRendCom->energy_ratio2_fx[md_idx][k] ); + } + + ismDirect_fx = hMasaIsm->energy_ratio_ism_fx[0][md_idx][k]; + move32(); + FOR( dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + { + ismDirect_fx = L_add( ismDirect_fx, hMasaIsm->energy_ratio_ism_fx[dir][md_idx][k] ); + } + + totalDirect_fx = L_add( masaDirect_fx, ismDirect_fx ); + Word16 var_a = 0, var_b = 0; + var_a = BASOP_Util_Divide3232_Scale( masaDirect_fx, totalDirect_fx, &exp_1 ); + var_b = BASOP_Util_Divide3232_Scale( ismDirect_fx, totalDirect_fx, &exp_2 ); + directRatio_fx[0] = L_deposit_h( var_a ); + move32(); + directRatio_fx[1] = L_deposit_h( var_b ); + move32(); + + Word32 temp_2 = 0, temp_3 = 0; + Word16 exp_arr[MAX_OUTPUT_CHANNELS], exp_temp_3 = 0; + set16_fx( exp_arr, exp_direct_response_hoa, MAX_OUTPUT_CHANNELS ); + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_hoa_fx[l] = Mpy_32_32( direct_response_hoa_fx[l], directRatio_fx[0] ); + move32(); + exp_arr[l] = exp_direct_response_hoa + exp_1; + move16(); + temp_2 = Mpy_32_32( directRatio_fx[1], direct_response_ism_fx[l] ); + temp_3 = BASOP_Util_Add_Mant32Exp( direct_response_hoa_fx[l], exp_arr[l], temp_2, exp_2 + exp_direct_response_ism, &exp_temp_3 ); + + direct_response_hoa_fx[l] = temp_3; + move32(); + exp_arr[l] = exp_temp_3; + move16(); + } + + Word16 max_exp = MIN16B; + move16(); + FOR( l = 0; l < num_channels_dir; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_hoa_fx[l] = L_shr( direct_response_hoa_fx[l], max_exp - exp_arr[l] ); + move32(); + } + Q_direct_response_hoa = sub(31 , max_exp); + exp_direct_response_hoa = max_exp; + move16(); + } + + /* Synthesize surrounding coherence */ + IF( surCohRatio_fx != NULL && GT_32( surCohRatio_fx[k], 0 ) ) + { + Word32 var_a = 0, var_b = 0; + Word16 exp_arr[MAX_OUTPUT_CHANNELS], exp = 0; + set16_fx( exp_arr, exp_direct_response_hoa, MAX_OUTPUT_CHANNELS ); + + FOR( l = 1; l < num_channels_dir; l++ ) + { + exp = 0; + var_a = BASOP_Util_Add_Mant32Exp( ONE_IN_Q30, 1, L_negate( surCohRatio_fx[k] ), 31 - Q_surCohRatio, &exp ); + var_b = Sqrt32( var_a, &exp ); + direct_response_hoa_fx[l] = Mpy_32_32( direct_response_hoa_fx[l], var_b ); + move32(); + exp_arr[l] = 31 - Q_direct_response_hoa + exp; + move16(); + } + Word16 max_exp = MIN_16; + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + direct_response_hoa_fx[l] = L_shr( direct_response_hoa_fx[l], max_exp - exp_arr[l] ); + move32(); + } + Q_direct_response_hoa = sub(31 , max_exp); + exp_direct_response_hoa = max_exp; + move16(); + } + + /* Set computed gains */ + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_hoa[i] = me2f( direct_response_hoa_fx[i], exp_direct_response_hoa ); + } + + direct_response = direct_response_hoa; + IF( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); + mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + + IF( transport_signal_type == MASA_STEREO_SPACED_MICS ) + { + direct_response[0] = 1.0f; + IF( k >= dipole_freq_range[0] && k < dipole_freq_range[1] ) + { + direct_response[1] = 1.0f; + } + } + ELSE + { + set_f( direct_response, 1.0f, hDirACRend->num_protos_ambi ); + } + } + + mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + } + ELSE + { + assert( 0 && "Not supported synthesis method!" ); + } + } + + ELSE IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_VBAP ) ) /*VBAP*/ + { + /* Synthesize the first direction */ + spreadCoherencePanningVbap_fx( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], hSpatParamRendCom->spreadCoherence_fx[md_idx][k], + direct_response_ls, direct_response_ls_fx, &Q_direct_response_ls, num_channels_dir, hVBAPdata ); + normalizePanningGains_fx( direct_response_ls_fx, &Q_direct_response_ls, num_channels_dir ); + exp_direct_response_ls = sub( 31, Q_direct_response_ls ); + + /* Synthesize the second direction and combine the gains */ + IF( EQ_16( hSpatParamRendCom->numParametricDirections, 2 ) ) + { + spreadCoherencePanningVbap_fx( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], hSpatParamRendCom->spreadCoherence2_fx[md_idx][k], direct_response_dir2, direct_response_dir2_fx, &Q_direct_response_dir2, num_channels_dir, hVBAPdata ); + normalizePanningGains_fx( direct_response_dir2_fx, &Q_direct_response_dir2, num_channels_dir ); + + /* Combine gains from the two directions */ + /*TODO: Remove float code*/ + hSpatParamRendCom->energy_ratio1_fx[md_idx][k] = float_to_fix( hSpatParamRendCom->energy_ratio1[md_idx][k], Q30 ); + hSpatParamRendCom->energy_ratio2_fx[md_idx][k] = float_to_fix( hSpatParamRendCom->energy_ratio2[md_idx][k], Q30 ); + Word32 test = L_add( hSpatParamRendCom->energy_ratio1_fx[md_idx][k], hSpatParamRendCom->energy_ratio2_fx[md_idx][k] ); + + IF( EQ_32( test, 0 ) ) + { + totalDirect_fx = L_add( test, EPSILON_FIX ); // Q30 + } + ELSE + { + totalDirect_fx = test; + move32(); + } + Word16 exp_1 = 0, exp_2 = 0; + move16(); + move16(); + Word16 var_1 = 0, var_2 = 0; + move16(); + move16(); + var_1 = BASOP_Util_Divide3232_Scale( hSpatParamRendCom->energy_ratio1_fx[md_idx][k], totalDirect_fx, &exp_1 ); + var_2 = BASOP_Util_Divide3232_Scale( hSpatParamRendCom->energy_ratio2_fx[md_idx][k], totalDirect_fx, &exp_2 ); + + directRatio_fx[0] = L_deposit_h( var_1 ); + move32(); + directRatio_fx[1] = L_deposit_h( var_2 ); + move32(); + + Word32 var_a = 0; + Word16 exp_tmp = 0; + Word16 exp_max = MIN16B, exp_table[MAX_OUTPUT_CHANNELS]; + set16_fx( exp_table, exp_direct_response_ls, MAX_OUTPUT_CHANNELS ); + + exp_direct_response_ls = sub( 31, Q_direct_response_ls ); + exp_direct_response_dir2 = sub( 31, Q_direct_response_dir2 ); + + Word32 temp = 0; + FOR( l = 0; l < num_channels_dir; l++ ) + { + temp = Mpy_32_32( direct_response_ls_fx[l], directRatio_fx[0] ); // exp_direct_response_ls + exp_1 + var_a = Mpy_32_32( directRatio_fx[1], direct_response_dir2_fx[l] ); // exp_direct_response_dir2 + exp_2 + exp_tmp = 0; + direct_response_ls_fx[l] = BASOP_Util_Add_Mant32Exp( temp, exp_direct_response_ls + exp_1, var_a, exp_direct_response_dir2 + exp_2, &exp_tmp ); + move32(); + exp_table[l] = exp_tmp; + move16(); + } + + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + exp_max = s_max( exp_max, exp_table[i] ); + } + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_ls_fx[i] = L_shr( direct_response_ls_fx[i], exp_max - exp_table[i] ); + move32(); + } + Q_direct_response_ls = sub( 31, exp_max ); + exp_direct_response_ls = exp_max; + move16(); + + normalizePanningGains_fx( direct_response_ls_fx, &Q_direct_response_ls, num_channels_dir ); + exp_direct_response_ls = sub( 31, Q_direct_response_ls ); + } + + IF( GT_16( hSpatParamRendCom->numIsmDirections, 0 ) ) + { + Word16 dir; + + Word32 direct_response_temp_fx[MAX_OUTPUT_CHANNELS]; + set32_fx( direct_response_temp_fx, 0, MAX_OUTPUT_CHANNELS ); + Word16 Q_direct_response_temp = Q31; + Word32 direct_response_ism_fx[MAX_OUTPUT_CHANNELS]; + set32_fx( direct_response_ism_fx, 0, num_channels_dir ); + Word32 masaDirect_fx; + Word32 ismDirect_fx; + + FOR( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + { + IF( hMasaIsm->ism_is_edited[dir] ) + { + vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1 ); + } + ELSE + { + vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1 ); + } + Word32 tmp = 0; + move32(); + Word16 Q_arr[MAX_OUTPUT_CHANNELS], exp_tmp = 0; + move16(); + FOR( l = 0; l < num_channels_dir; l++ ) + { + tmp = Mpy_32_32( direct_response_temp_fx[l], hMasaIsm->energy_ratio_ism_fx[dir][md_idx][k] ); // Q30 * 2 - 31 + direct_response_ism_fx[l] = BASOP_Util_Add_Mant32Exp( direct_response_ism_fx[l], 0, tmp, 31 - ( 60 - 31 ), &exp_tmp ); + move32(); + Q_arr[l] = sub(31 , exp_tmp); + move16(); + } + Word16 Q_min = MAX16B; + FOR( i = 0; i < num_channels_dir; i++ ) + { + Q_min = s_min( Q_min, Q_arr[i] ); + } + FOR( i = 0; i < num_channels_dir; i++ ) + { + direct_response_ism_fx[i] = L_shr( direct_response_ism_fx[i], sub(Q_arr[i] , Q_min) ); + move32(); + } + Q_direct_response_temp = Q_min; + move16(); + normalizePanningGains_fx( direct_response_ism_fx, &Q_direct_response_temp, num_channels_dir ); + } + + Word16 exp_1 = 0, exp_2 = 0; + move16(); + masaDirect_fx = hSpatParamRendCom->energy_ratio1_fx[md_idx][k]; + move32(); + IF( EQ_32(masaDirect_fx , 0 )) + { + masaDirect_fx = L_add( masaDirect_fx, EPSILLON_FX ); + } + IF( EQ_32(hSpatParamRendCom->numParametricDirections , 2 )) + { + masaDirect_fx = L_add( masaDirect_fx, hSpatParamRendCom->energy_ratio2_fx[md_idx][k] ); + } + + ismDirect_fx = hMasaIsm->energy_ratio_ism_fx[0][md_idx][k]; + move32(); + FOR( dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + { + ismDirect_fx = L_add( ismDirect_fx, hMasaIsm->energy_ratio_ism_fx[dir][md_idx][k] ); + } + + totalDirect_fx = L_add( masaDirect_fx, ismDirect_fx ); + Word16 var_a = 0, var_b = 0; + move16(); + var_a = BASOP_Util_Divide3232_Scale( masaDirect_fx, totalDirect_fx, &exp_1 ); + var_b = BASOP_Util_Divide3232_Scale( ismDirect_fx, totalDirect_fx, &exp_2 ); + directRatio_fx[0] = L_deposit_h( var_a ); + move32(); + directRatio_fx[1] = L_deposit_h( var_b ); + move32(); + + Word32 temp_2 = 0, temp_3 = 0; + move16(); + move16(); + Word16 exp_arr[MAX_OUTPUT_CHANNELS], exp_temp_3 = 0; + move16(); + //set16_fx( exp_arr, 0, MAX_OUTPUT_CHANNELS); + set16_fx(exp_arr, exp_direct_response_ls, MAX_OUTPUT_CHANNELS); + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ls_fx[l] = Mpy_32_32( direct_response_ls_fx[l], directRatio_fx[0] ); + move32(); + exp_arr[l] = add(exp_direct_response_ls , exp_1); + move16(); + temp_2 = Mpy_32_32( directRatio_fx[1], direct_response_ism_fx[l] ); + temp_3 = BASOP_Util_Add_Mant32Exp( direct_response_ls_fx[l], exp_arr[l], temp_2, exp_2 + 31 - Q_direct_response_temp, &exp_temp_3 ); + + direct_response_ls_fx[l] = temp_3; + move32(); + exp_arr[l] = exp_temp_3; + move16(); + } + + Word16 max_exp = MIN16B; + FOR( l = 0; l < num_channels_dir; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < num_channels_dir; l++ ) + { + direct_response_ls_fx[l] = L_shr( direct_response_ls_fx[l], max_exp - exp_arr[l] ); + move16(); + } + Q_direct_response_ls = sub( 31, max_exp ); + exp_direct_response_ls = max_exp; + move16(); + + normalizePanningGains_fx( direct_response_ls_fx, &Q_direct_response_ls, num_channels_dir ); + exp_direct_response_ls = sub( 31, Q_direct_response_ls ); + } + + /* Synthesize surrounding coherence */ + IF( surCohRatio_fx != NULL && GT_32( surCohRatio_fx[k], 0 ) ) + { + Word16 num_channels_surrCoh; + + num_channels_surrCoh = num_channels_dir; + move16(); + num_channels_surrCoh = sub(num_channels_surrCoh , hDirACRend->num_ele_spk_no_diffuse_rendering); + + Word32 temp = 0, final = 0; + move32(); + move32(); + Word16 exp_temp = 0, exp_temp_a = 0, temp_a = 0, final_exp = 0; + move16(); + move16(); + move16(); + move16(); + Word16 exp_arr[MAX_OUTPUT_CHANNELS], max_exp = MIN16B; + move16(); + set16_fx( exp_arr, exp_direct_response_ls, MAX_OUTPUT_CHANNELS ); + FOR( l = 0; l < num_channels_dir; l++ ) + { + exp_temp = 0; + temp = BASOP_Util_Add_Mant32Exp( ONE_IN_Q30, 1, L_negate( surCohRatio_fx[k] ), exp_surCohRatio, &exp_temp ); + temp = Sqrt32( temp, &exp_temp ); + direct_response_ls_fx[l] = Mpy_32_32( direct_response_ls_fx[l], temp ); // exp_direct_response_ls + exp_temp + move32(); + + exp_arr[l] = add(exp_direct_response_ls , exp_temp); + move16(); + IF( hDirACRend->diffuse_response_function[l] > 0.f ) //TODO: clean up + { + exp_temp_a = 0; + temp_a = BASOP_Util_Divide3216_Scale( surCohRatio_fx[k], num_channels_surrCoh, &exp_temp_a ); + exp_temp_a = add(exp_temp_a , sub( exp_surCohRatio , 15 )); + temp_a = Sqrt16( temp_a, &exp_temp_a ); + final_exp = 0; + final = BASOP_Util_Add_Mant32Exp( direct_response_ls_fx[l], exp_arr[l], L_deposit_h( temp_a ), exp_temp_a, &final_exp ); + direct_response_ls_fx[l] = final; + move32(); + exp_arr[l] = final_exp; + move16(); + } + } + + max_exp = MIN16B; + move16(); + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + max_exp = s_max( max_exp, exp_arr[l] ); + } + FOR( l = 0; l < MAX_OUTPUT_CHANNELS; l++ ) + { + direct_response_ls_fx[l] = L_shr( direct_response_ls_fx[l], max_exp - exp_arr[l] ); + move32(); + } + + Q_direct_response_ls = sub( 31, max_exp ); + exp_direct_response_ls = max_exp; + move16(); + } + + normalizePanningGains_fx( direct_response_ls_fx, &Q_direct_response_ls, num_channels_dir ); + exp_direct_response_ls = sub( 31, Q_direct_response_ls ); + + /* Set computed gains */ + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + direct_response_ls[i] = fix_to_float( direct_response_ls_fx[i], Q_direct_response_ls ); + } + direct_response = direct_response_ls; + v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); + + mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + } + ELSE + { + assert( 0 && "Not supported panning method!" ); + } + } + } + + return; +} +#endif void ivas_dirac_dec_compute_directional_responses( SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ @@ -2499,7 +3211,7 @@ void ivas_dirac_dec_compute_directional_responses( elevation2 = NULL; transport_signal_type = MASA_STEREO_NOT_DEFINED; - if ( hDirACRend->masa_stereo_type_detect != NULL ) + if (hDirACRend->masa_stereo_type_detect != NULL) { dipole_freq_range[0] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[0]; dipole_freq_range[1] = hDirACRend->masa_stereo_type_detect->dipole_freq_range[1]; @@ -2507,7 +3219,7 @@ void ivas_dirac_dec_compute_directional_responses( } num_channels_dir = hDirACRend->num_outputs_dir; - if ( hSpatParamRendCom->numParametricDirections == 2 ) + if (hSpatParamRendCom->numParametricDirections == 2) { azimuth2 = hSpatParamRendCom->azimuth2[md_idx]; elevation2 = hSpatParamRendCom->elevation2[md_idx]; @@ -2515,89 +3227,89 @@ void ivas_dirac_dec_compute_directional_responses( codingBand = -1; - assert( num_channels_dir <= MAX_OUTPUT_CHANNELS && "Number of channels is too high" ); + assert(num_channels_dir <= MAX_OUTPUT_CHANNELS && "Number of channels is too high"); - for ( k = 0; k < hSpatParamRendCom->num_freq_bands; ++k ) + for (k = 0; k < hSpatParamRendCom->num_freq_bands; ++k) { - if ( masa_band_mapping != NULL && k == MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] ) + if (masa_band_mapping != NULL && k == MASA_band_grouping_24[masa_band_mapping[codingBand + 1]]) { codingBand++; } - if ( masa_band_mapping != NULL && k > MASA_band_grouping_24[masa_band_mapping[codingBand]] && - k < MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] && - k != hDirACRend->h_output_synthesis_psd_params.max_band_decorr ) + if (masa_band_mapping != NULL && k > MASA_band_grouping_24[masa_band_mapping[codingBand]] && + k < MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] && + k != hDirACRend->h_output_synthesis_psd_params.max_band_decorr) { /* Panning gains have to be computed only for the first bin of the coding band in MASA, for other bins the previous values can be used */ - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if (hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD) { - mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k - 1], - hSpatParamRendCom->num_freq_bands, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], - hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc(&hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k - 1], + hSpatParamRendCom->num_freq_bands, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], + hSpatParamRendCom->num_freq_bands, num_channels_dir); } - mvr2r_inc( &hDirACRend->h_output_synthesis_psd_state.direct_responses[k - 1], - hSpatParamRendCom->num_freq_bands, - &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], - hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc(&hDirACRend->h_output_synthesis_psd_state.direct_responses[k - 1], + hSpatParamRendCom->num_freq_bands, + &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], + hSpatParamRendCom->num_freq_bands, num_channels_dir); } else { /* HOA3 PANNING */ - if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 ) + if (hDirACRend->panningConf == DIRAC_PANNING_HOA3) { - set_f( direct_response_hoa, 1.0f, MAX_OUTPUT_CHANNELS ); - set_f( direct_response_dir2, 1.0f, MAX_OUTPUT_CHANNELS ); + set_f(direct_response_hoa, 1.0f, MAX_OUTPUT_CHANNELS); + set_f(direct_response_dir2, 1.0f, MAX_OUTPUT_CHANNELS); - if ( p_Rmat != 0 ) + if (p_Rmat != 0) { - ivas_dirac_dec_get_response_split_order( azimuth[k], elevation[k], direct_response_hoa, shd_rot_max_order, p_Rmat ); + ivas_dirac_dec_get_response_split_order(azimuth[k], elevation[k], direct_response_hoa, shd_rot_max_order, p_Rmat); - if ( hodirac_flag ) + if (hodirac_flag) { - ivas_dirac_dec_get_response_split_order( azimuth2[k], elevation2[k], direct_response_dir2, shd_rot_max_order, p_Rmat ); + ivas_dirac_dec_get_response_split_order(azimuth2[k], elevation2[k], direct_response_dir2, shd_rot_max_order, p_Rmat); } } else { - ivas_dirac_dec_get_response( azimuth[k], elevation[k], direct_response_hoa, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response(azimuth[k], elevation[k], direct_response_hoa, hDirACRend->hOutSetup.ambisonics_order); - if ( hodirac_flag ) + if (hodirac_flag) { - ivas_dirac_dec_get_response( azimuth2[k], elevation2[k], direct_response_dir2, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response(azimuth2[k], elevation2[k], direct_response_dir2, hDirACRend->hOutSetup.ambisonics_order); } } - if ( masa_band_mapping == NULL && hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + if (masa_band_mapping == NULL && hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD) { - mvr2r_inc( direct_response_hoa, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc(direct_response_hoa, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir); - if ( hodirac_flag ) + if (hodirac_flag) { - mvr2r_inc( direct_response_dir2, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k + hSpatParamRendCom->num_freq_bands * num_channels_dir], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc(direct_response_dir2, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k + hSpatParamRendCom->num_freq_bands * num_channels_dir], hSpatParamRendCom->num_freq_bands, num_channels_dir); } } - else if ( ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) && ( masa_band_mapping != NULL ) ) || - hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + else if (((hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD) && (masa_band_mapping != NULL)) || + hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO) { /* Synthesize the first direction */ - spreadCoherencePanningHoa( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + spreadCoherencePanningHoa(azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order); /* Synthesize the second direction and combine the gains */ - if ( hSpatParamRendCom->numParametricDirections == 2 ) + if (hSpatParamRendCom->numParametricDirections == 2) { - spreadCoherencePanningHoa( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); + spreadCoherencePanningHoa(azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order); /* Combine gains from the two directions */ totalDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + hSpatParamRendCom->energy_ratio2[md_idx][k] + EPSILON; directRatio[0] = hSpatParamRendCom->energy_ratio1[md_idx][k] / totalDirect; directRatio[1] = hSpatParamRendCom->energy_ratio2[md_idx][k] / totalDirect; - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_hoa[l] *= directRatio[0]; direct_response_hoa[l] += directRatio[1] * direct_response_dir2[l]; } } - if ( hSpatParamRendCom->numIsmDirections > 0 ) + if (hSpatParamRendCom->numIsmDirections > 0) { int16_t dir; float direct_response_temp[MAX_OUTPUT_CHANNELS]; @@ -2605,33 +3317,33 @@ void ivas_dirac_dec_compute_directional_responses( float masaDirect; float ismDirect; - set_zero( direct_response_ism, num_channels_dir ); + set_zero(direct_response_ism, num_channels_dir); - for ( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + for (dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++) { - if ( hMasaIsm->ism_is_edited[dir] ) + if (hMasaIsm->ism_is_edited[dir]) { - ivas_dirac_dec_get_response( hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], direct_response_temp, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response(hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], direct_response_temp, hDirACRend->hOutSetup.ambisonics_order); } else { - ivas_dirac_dec_get_response( hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], direct_response_temp, hDirACRend->hOutSetup.ambisonics_order ); + ivas_dirac_dec_get_response(hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], direct_response_temp, hDirACRend->hOutSetup.ambisonics_order); } - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_ism[l] += direct_response_temp[l] * hMasaIsm->energy_ratio_ism[dir][md_idx][k]; } } masaDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + EPSILON; - if ( hSpatParamRendCom->numParametricDirections == 2 ) + if (hSpatParamRendCom->numParametricDirections == 2) { masaDirect += hSpatParamRendCom->energy_ratio2[md_idx][k]; } ismDirect = hMasaIsm->energy_ratio_ism[0][md_idx][k]; - for ( dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + for (dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++) { ismDirect += hMasaIsm->energy_ratio_ism[dir][md_idx][k]; } @@ -2639,7 +3351,7 @@ void ivas_dirac_dec_compute_directional_responses( totalDirect = masaDirect + ismDirect; directRatio[0] = masaDirect / totalDirect; directRatio[1] = ismDirect / totalDirect; - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_hoa[l] *= directRatio[0]; direct_response_hoa[l] += directRatio[1] * direct_response_ism[l]; @@ -2647,67 +3359,67 @@ void ivas_dirac_dec_compute_directional_responses( } /* Synthesize surrounding coherence */ - if ( surCohRatio != NULL && surCohRatio[k] > 0.f ) + if (surCohRatio != NULL && surCohRatio[k] > 0.f) { - for ( l = 1; l < num_channels_dir; l++ ) + for (l = 1; l < num_channels_dir; l++) { - direct_response_hoa[l] *= sqrtf( 1.0f - surCohRatio[k] ); + direct_response_hoa[l] *= sqrtf(1.0f - surCohRatio[k]); } } /* Set computed gains */ direct_response = direct_response_hoa; - if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + if (hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD) { - v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); - mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + v_mult(direct_response, direct_response, direct_response_square, num_channels_dir); + mvr2r_inc(direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir); - if ( transport_signal_type == MASA_STEREO_SPACED_MICS ) + if (transport_signal_type == MASA_STEREO_SPACED_MICS) { direct_response[0] = 1.0f; - if ( k >= dipole_freq_range[0] && k < dipole_freq_range[1] ) + if (k >= dipole_freq_range[0] && k < dipole_freq_range[1]) { direct_response[1] = 1.0f; } } else { - set_f( direct_response, 1.0f, hDirACRend->num_protos_ambi ); + set_f(direct_response, 1.0f, hDirACRend->num_protos_ambi); } } - mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + mvr2r_inc(direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir); } else { - assert( 0 && "Not supported synthesis method!" ); + assert(0 && "Not supported synthesis method!"); } } - else if ( hDirACRend->panningConf == DIRAC_PANNING_VBAP ) /*VBAP*/ + else if (hDirACRend->panningConf == DIRAC_PANNING_VBAP) /*VBAP*/ { /* Synthesize the first direction */ - spreadCoherencePanningVbap( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_ls, num_channels_dir, hVBAPdata ); - normalizePanningGains( direct_response_ls, num_channels_dir ); + spreadCoherencePanningVbap(azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_ls, num_channels_dir, hVBAPdata); + normalizePanningGains(direct_response_ls, num_channels_dir); /* Synthesize the second direction and combine the gains */ - if ( hSpatParamRendCom->numParametricDirections == 2 ) + if (hSpatParamRendCom->numParametricDirections == 2) { - spreadCoherencePanningVbap( azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata ); - normalizePanningGains( direct_response_dir2, num_channels_dir ); + spreadCoherencePanningVbap(azimuth2[k], elevation2[k], hSpatParamRendCom->spreadCoherence2[md_idx][k], direct_response_dir2, num_channels_dir, hVBAPdata); + normalizePanningGains(direct_response_dir2, num_channels_dir); /* Combine gains from the two directions */ totalDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + hSpatParamRendCom->energy_ratio2[md_idx][k] + EPSILON; directRatio[0] = hSpatParamRendCom->energy_ratio1[md_idx][k] / totalDirect; directRatio[1] = hSpatParamRendCom->energy_ratio2[md_idx][k] / totalDirect; - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_ls[l] *= directRatio[0]; direct_response_ls[l] += directRatio[1] * direct_response_dir2[l]; } - normalizePanningGains( direct_response_ls, num_channels_dir ); + normalizePanningGains(direct_response_ls, num_channels_dir); } - if ( hSpatParamRendCom->numIsmDirections > 0 ) + if (hSpatParamRendCom->numIsmDirections > 0) { int16_t dir; float direct_response_temp[MAX_OUTPUT_CHANNELS]; @@ -2719,50 +3431,50 @@ void ivas_dirac_dec_compute_directional_responses( float masaDirect; float ismDirect; - set_zero( direct_response_ism, num_channels_dir ); + set_zero(direct_response_ism, num_channels_dir); - for ( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + for (dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++) { - if ( hMasaIsm->ism_is_edited[dir] ) + if (hMasaIsm->ism_is_edited[dir]) { #ifdef IVAS_FLOAT_FIXED - vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1 ); - FOR( int i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + vbap_determine_gains_fx(hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1); + FOR(int i = 0; i < MAX_OUTPUT_CHANNELS; i++) { - direct_response_temp[i] = fix_to_float( direct_response_temp_fx[i], Q29 ); + direct_response_temp[i] = fix_to_float(direct_response_temp_fx[i], Q29); } #else - vbap_determine_gains( hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1 ); + vbap_determine_gains(hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1); #endif } else { #ifdef IVAS_FLOAT_FIXED - vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1 ); - FOR( int i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + vbap_determine_gains_fx(hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1); + FOR(int i = 0; i < MAX_OUTPUT_CHANNELS; i++) { - direct_response_temp[i] = fix_to_float( direct_response_temp_fx[i], Q29 ); + direct_response_temp[i] = fix_to_float(direct_response_temp_fx[i], Q29); } #else - vbap_determine_gains( hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1 ); + vbap_determine_gains(hVBAPdata, direct_response_temp, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1); #endif } - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_ism[l] += direct_response_temp[l] * hMasaIsm->energy_ratio_ism[dir][md_idx][k]; } } - normalizePanningGains( direct_response_ism, num_channels_dir ); + normalizePanningGains(direct_response_ism, num_channels_dir); masaDirect = hSpatParamRendCom->energy_ratio1[md_idx][k] + EPSILON; - if ( hSpatParamRendCom->numParametricDirections == 2 ) + if (hSpatParamRendCom->numParametricDirections == 2) { masaDirect += hSpatParamRendCom->energy_ratio2[md_idx][k]; } ismDirect = hMasaIsm->energy_ratio_ism[0][md_idx][k]; - for ( dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++ ) + for (dir = 1; dir < hSpatParamRendCom->numIsmDirections; dir++) { ismDirect += hMasaIsm->energy_ratio_ism[dir][md_idx][k]; } @@ -2770,43 +3482,43 @@ void ivas_dirac_dec_compute_directional_responses( totalDirect = masaDirect + ismDirect; directRatio[0] = masaDirect / totalDirect; directRatio[1] = ismDirect / totalDirect; - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { direct_response_ls[l] *= directRatio[0]; direct_response_ls[l] += directRatio[1] * direct_response_ism[l]; } - normalizePanningGains( direct_response_ls, num_channels_dir ); + normalizePanningGains(direct_response_ls, num_channels_dir); } /* Synthesize surrounding coherence */ - if ( surCohRatio != NULL && surCohRatio[k] > 0.f ) + if (surCohRatio != NULL && surCohRatio[k] > 0.f) { int16_t num_channels_surrCoh; num_channels_surrCoh = num_channels_dir; num_channels_surrCoh -= hDirACRend->num_ele_spk_no_diffuse_rendering; - for ( l = 0; l < num_channels_dir; l++ ) + for (l = 0; l < num_channels_dir; l++) { - direct_response_ls[l] *= sqrtf( 1.0f - surCohRatio[k] ); - if ( hDirACRend->diffuse_response_function[l] > 0.f ) + direct_response_ls[l] *= sqrtf(1.0f - surCohRatio[k]); + if (hDirACRend->diffuse_response_function[l] > 0.f) { - direct_response_ls[l] += sqrtf( surCohRatio[k] / (float) num_channels_surrCoh ); + direct_response_ls[l] += sqrtf(surCohRatio[k] / (float)num_channels_surrCoh); } } } - normalizePanningGains( direct_response_ls, num_channels_dir ); + normalizePanningGains(direct_response_ls, num_channels_dir); /* Set computed gains */ direct_response = direct_response_ls; - v_mult( direct_response, direct_response, direct_response_square, num_channels_dir ); - mvr2r_inc( direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); - mvr2r_inc( direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); + v_mult(direct_response, direct_response, direct_response_square, num_channels_dir); + mvr2r_inc(direct_response_square, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses_square[k], hSpatParamRendCom->num_freq_bands, num_channels_dir); + mvr2r_inc(direct_response, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir); } else { - assert( 0 && "Not supported panning method!" ); + assert(0 && "Not supported panning method!"); } } } @@ -2814,13 +3526,66 @@ void ivas_dirac_dec_compute_directional_responses( return; } - /*------------------------------------------------------------------------- * ivas_dirac_dec_compute_gain_factors() * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_compute_gain_factors_fx( + const Word16 num_freq_bands, + const Word32 *diffuseness_fx, + Word32 *direct_gain_factor, + Word32 *diffuse_gain_factor, + Word16 *max_exp_direct_fx, + Word16 *max_exp_diffusion ) +{ + Word16 i; + Word16 exp1, exp2; + Word16 exp_diffuse_gain_factor[60], exp_direct_gain_factor[60]; /*exp buffers*/ + + FOR( i = 0; i < num_freq_bands; i++ ) + { + exp1 = 1; + exp2 = 1; + direct_gain_factor[i] = Sqrt32( L_sub( ONE_IN_Q30, diffuseness_fx[i] ), &exp1 ); + move32(); + diffuse_gain_factor[i] = Sqrt32( diffuseness_fx[i], &exp2 ); + move32(); + exp_direct_gain_factor[i] = exp1; + move16(); + exp_diffuse_gain_factor[i] = exp2; + move16(); + } + + /*make common exp for both buffers*/ + Word16 max_exp_direct = MIN16B; + move16(); + Word16 max_exp_diffuse = MIN16B; + move16(); + FOR( i = 0; i < num_freq_bands; i++ ) + { + max_exp_direct = s_max( max_exp_direct, exp_direct_gain_factor[i] ); + max_exp_diffuse = s_max( max_exp_diffuse, exp_diffuse_gain_factor[i] ); + } + + *max_exp_direct_fx = max_exp_direct; + move16(); + *max_exp_diffusion = max_exp_diffuse; + move16(); + + FOR( i = 0; i < num_freq_bands; i++ ) + { + direct_gain_factor[i] = L_shr( direct_gain_factor[i], max_exp_direct - exp_direct_gain_factor[i] ); + diffuse_gain_factor[i] = L_shr( diffuse_gain_factor[i], max_exp_diffuse - exp_diffuse_gain_factor[i] ); + } + + + return; +} +#endif + void ivas_dirac_dec_compute_gain_factors( const int16_t num_freq_bands, const float *diffuseness, @@ -2871,7 +3636,34 @@ void ivas_dirac_dec_compute_power_factors( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_compute_power_factors_fx( + const Word16 num_freq_bands, + const Word32 *diffuseness_fx, // Q3O + const Word16 max_band_decorr, + Word32 *direct_power_factor, + Word32 *diffuse_power_factor +) +{ + v_multc_fixed( diffuseness_fx, L_negate( ( ONE_IN_Q31 ) ), direct_power_factor, num_freq_bands ); // Q30 + + v_addc_fixed( direct_power_factor, ONE_IN_Q30, direct_power_factor, num_freq_bands ); // Q30 + Copy32( diffuseness_fx, diffuse_power_factor, num_freq_bands ); // Q30 + + v_mult_fixed( &direct_power_factor[max_band_decorr], &direct_power_factor[max_band_decorr], &direct_power_factor[max_band_decorr], num_freq_bands - max_band_decorr ); // Q29 + + v_mult_fixed( &diffuse_power_factor[max_band_decorr], &diffuse_power_factor[max_band_decorr], &diffuse_power_factor[max_band_decorr], num_freq_bands - max_band_decorr ); // Q29 + + + FOR( int i = 0; i < max_band_decorr; i++ ) + { + direct_power_factor[i] = L_shr( direct_power_factor[i], 1 ); // Q29 + diffuse_power_factor[i] = L_shr( diffuse_power_factor[i], 1 ); // Q29 + } + return; +} +#endif /*------------------------------------------------------------------------- * ivas_lfe_synth_with_filters() * @@ -3255,6 +4047,85 @@ static void computeAlphaSynthesis( return; } +#ifdef IVAS_FLOAT_FIXED +static void spreadCoherencePanningHoa_fx( + const Word16 azimuth, + const Word16 elevation, + const Word16 spreadCoh_fx, /*Q15*/ + Word32 *direct_response_fx, /*Q29*/ + Word16 *Q_direct_response, /*Q29*/ + const Word16 num_channels_dir, + const Word16 ambisonics_order ) +{ + Word16 i; + + Word32 direct_response_left_fx[MAX_OUTPUT_CHANNELS]; + Word32 direct_response_right_fx[MAX_OUTPUT_CHANNELS]; + Word32 gainCenter_fx; + Word32 gainSide_fx; + + ivas_dirac_dec_get_response_fixed_Q( azimuth, elevation, direct_response_fx, ambisonics_order, *Q_direct_response ); + + Word16 exp_Gain_side = 0, exp_Gain_center = 0; + IF( GT_32( spreadCoh_fx, 0 ) ) + { + ivas_dirac_dec_get_response_fixed_Q( azimuth + 30, elevation, direct_response_left_fx, ambisonics_order, *Q_direct_response ); + ivas_dirac_dec_get_response_fixed_Q( azimuth + 330, elevation, direct_response_right_fx, ambisonics_order, *Q_direct_response ); + + + Word16 var_a, var_b, exp_a = 0; + + IF( LT_16( spreadCoh_fx, ONE_IN_Q14 ) ) + { + /*gainCenter = (3 - 4*spreadCoh )/3*/ + var_a = sub( 24576 /*3 in Q13*/, spreadCoh_fx ); // Q13 + var_a = mult( var_a, float_to_fix16( 0.33333333f, Q15 ) ); // Q13 + + gainCenter_fx = L_deposit_h( shr( var_a, 2 ) ); // Q11 + 16 = Q27 + gainSide_fx = L_deposit_h( mult( spreadCoh_fx, float_to_fix16( 0.33333333f, Q15 ) ) ); // Q14 + 16 (reduce Q by 1 to *2) = Q30 + exp_Gain_side = 31 - Q30; + exp_Gain_center = 31 - Q27; + } + ELSE + { + var_a = shl( sub( 16384 /*2 in Q13*/, shr( spreadCoh_fx, 2 ) ), 1 ); + exp_a = 15 - Q13; + var_a = Inv16( var_a, &exp_a ); + gainSide_fx = L_deposit_h( var_a ); // Q14 + 16 = Q30 //exp_a + exp_Gain_side = exp_a; + + var_b = sub( 8192 /*2 in Q12*/, shr( spreadCoh_fx, 2 ) /*Q14*/ ); // exp => 3 + gainCenter_fx = L_deposit_h( mult( var_b, var_a ) ); // Q13 + 16 = Q29 // 3 + exp_a + exp_Gain_center = 3 + exp_a; + } + + + Word32 mpy1, mpy2; + Word16 exp_arr[16], exp = 0; + set16_fx( exp_arr, 31 - *Q_direct_response, 16 ); + FOR( i = 0; i < num_channels_dir; i++ ) + { + mpy1 = Mpy_32_32( L_add( direct_response_left_fx[i], direct_response_right_fx[i] ), gainSide_fx ); // 31 - Q_direct_response + exp_Gain_Side + mpy2 = Mpy_32_32( direct_response_fx[i], gainCenter_fx ); // 31 - Q_direct_response + exp_Gain_Center + exp = 0; + direct_response_fx[i] = BASOP_Util_Add_Mant32Exp( mpy1, 31 - *Q_direct_response + exp_Gain_side, mpy2, 31 - *Q_direct_response + exp_Gain_center, &exp ); + exp_arr[i] = exp; + } + Word16 max_val = MIN_16; + FOR( i = 0; i < 16; i++ ) + { + max_val = max( max_val, exp_arr[i] ); + } + FOR( i = 0; i < 16; i++ ) + { + direct_response_fx[i] = L_shr( direct_response_fx[i], max_val - exp_arr[i] ); + } + *Q_direct_response = 31 - max_val; + } + + return; +} +#endif static void spreadCoherencePanningHoa( const int16_t azimuth, @@ -3298,6 +4169,120 @@ static void spreadCoherencePanningHoa( return; } +#ifdef IVAS_FLOAT_FIXED +static void spreadCoherencePanningVbap_fx( + const int16_t azimuth, + const int16_t elevation, + const float spreadCoh, + const Word16 spreadCoh_fx, + float *direct_response, + Word32 *direct_response_fx, + Word16 *Q_direct_response, + const int16_t num_channels_dir, + const VBAP_HANDLE hVBAPdata) +{ + int16_t i; + float direct_response_left[MAX_OUTPUT_CHANNELS]; + float direct_response_right[MAX_OUTPUT_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word32 direct_response_left_fx[MAX_OUTPUT_CHANNELS]; + Word32 direct_response_right_fx[MAX_OUTPUT_CHANNELS]; + set32_fx(direct_response_left_fx, 0, MAX_OUTPUT_CHANNELS); + set32_fx(direct_response_right_fx, 0, MAX_OUTPUT_CHANNELS); + Word32 gainCenter_fx; + Word32 gainSide_fx; +#endif + float gainCenter; + float gainSide; + + if (hVBAPdata == NULL) + { + /* Distribute signal to all channels if VBAP is not properly initialized. */ + Word16 exp_tmp = 0; + Word16 var_temp = ISqrt16(num_channels_dir, &exp_tmp); + set32_fx(direct_response_fx, var_temp, num_channels_dir); + *Q_direct_response = 31 - exp_tmp; + + set_f(direct_response, inv_sqrt(num_channels_dir), num_channels_dir); + + return; + } +#ifdef IVAS_FLOAT_FIXED + set32_fx(direct_response_fx, 0, MAX_OUTPUT_CHANNELS); + vbap_determine_gains_fx(hVBAPdata, direct_response_fx, azimuth, elevation, 0); + *Q_direct_response = Q29; +#else + vbap_determine_gains(hVBAPdata, direct_response, azimuth, elevation, 0); +#endif + + if (spreadCoh > 0.f) + { +#ifdef IVAS_FLOAT_FIXED + vbap_determine_gains_fx(hVBAPdata, direct_response_left_fx, azimuth + 30, elevation, 0); + FOR(i = 0; i < MAX_OUTPUT_CHANNELS; i++) + { + direct_response_left[i] = fix_to_float(direct_response_left_fx[i], Q29); + } + vbap_determine_gains_fx(hVBAPdata, direct_response_right_fx, azimuth - 30, elevation, 0); + FOR(i = 0; i < MAX_OUTPUT_CHANNELS; i++) + { + direct_response_right[i] = fix_to_float(direct_response_right_fx[i], Q29); + } +#else + vbap_determine_gains(hVBAPdata, direct_response_left, azimuth + 30, elevation, 0); + vbap_determine_gains(hVBAPdata, direct_response_right, azimuth - 30, elevation, 0); +#endif + Word32 var1 = 0, var2 = 0; + Word16 var_a = 0, var_b = 0; + if (spreadCoh < 0.5f) + { +#ifdef IVAS_FLOAT_FIXED + var_a = mult(spreadCoh_fx, INV_SQRT3_FX); //Q14 + var_b = sub(ONE_IN_Q14, spreadCoh_fx);//Q14 + gainCenter_fx = L_deposit_h(add(var_a, var_b)); //Q30 + gainSide_fx = L_deposit_h(var_a);//Q30 + + gainCenter = fix_to_float(gainCenter_fx, Q30); + gainSide = fix_to_float(gainSide_fx, Q30); +#else + gainCenter = (1.0f - 2.0f * spreadCoh) + 2.0f * spreadCoh * INV_SQRT3; + gainSide = 2.0f * spreadCoh * INV_SQRT3; +#endif + } + else + { +#ifdef IVAS_FLOAT_FIXED + var_a = sub(ONE_IN_Q14, shr(spreadCoh_fx,1)); //Q13 + gainCenter_fx = L_shl(L_deposit_h(var_a), 1);//Q30 + gainSide_fx = ONE_IN_Q30; + + gainCenter = fix_to_float(gainCenter_fx, Q30); + gainSide = fix_to_float(gainSide_fx, Q30); +#else + gainCenter = 2.0f - 2.0f * spreadCoh; + gainSide = 1.0f; +#endif + } + + Word32 var3 = 0; + *Q_direct_response = Q28; + for (i = 0; i < num_channels_dir; i++) + { +#ifdef IVAS_FLOAT_FIXED + var1 = L_add(direct_response_left_fx[i], direct_response_right_fx[i]); // Q29 + var2 = Mpy_32_32(var1, gainSide_fx); // Q28 + var3 = Mpy_32_32(direct_response_fx[i], gainCenter_fx); // Q28 + direct_response_fx[i] = L_add(var3, var2); // Q28 +#else + direct_response[i] = direct_response[i] * gainCenter + (direct_response_left[i] + direct_response_right[i]) * gainSide; +#endif + } + } + + return; +} +#endif + static void spreadCoherencePanningVbap( const int16_t azimuth, const int16_t elevation, @@ -3375,6 +4360,45 @@ static void spreadCoherencePanningVbap( return; } +#ifdef IVAS_FLOAT_FIXED +static void normalizePanningGains_fx( + Word32 *direct_response_fx, + Word16 *q_direct_res, + const int16_t num_channels_dir ) +{ + Word32 energySum_fx; + Word16 exp_energySum = 0; + Word32 normVal_fx; + int16_t i; + + Word16 gb = find_guarded_bits_fx( num_channels_dir ); + energySum_fx = sum2_f_32_fx( direct_response_fx, num_channels_dir, gb ); + if ( *q_direct_res > 31 ) + { + exp_energySum = ( 31 - *q_direct_res ) * 2 + gb; + } + exp_energySum = 31 - ( ( 2 * ( *q_direct_res ) - 31 ) - gb ); + + IF( GT_32( energySum_fx, 0 ) ) + { + normVal_fx = ISqrt32( energySum_fx, &exp_energySum ); + } + ELSE + { + energySum_fx = BASOP_Util_Add_Mant32Exp( energySum_fx, exp_energySum, ONE_IN_Q30, 1, &exp_energySum ); + normVal_fx = ISqrt32( energySum_fx, &exp_energySum ); + } + + FOR( i = 0; i < num_channels_dir; i++ ) + { + direct_response_fx[i] = Mpy_32_32( direct_response_fx[i], normVal_fx ); + } + Word16 exp = 31 - *q_direct_res + exp_energySum; + *q_direct_res = 31 - exp; + + return; +} +#endif static void normalizePanningGains( float *direct_response, diff --git a/lib_rend/ivas_dirac_rend.c b/lib_rend/ivas_dirac_rend.c index 596897439c0af2838272e6aa12a040b1887e182f..1fb5d050913215e7b8a45ab5752fa2ea70f47ff9 100644 --- a/lib_rend/ivas_dirac_rend.c +++ b/lib_rend/ivas_dirac_rend.c @@ -1434,6 +1434,9 @@ ivas_error ivas_dirac_alloc_mem( hDirAC_mem->proto_power_smooth = NULL; hDirAC_mem->proto_power_diff_smooth = NULL; hDirAC_mem->direct_responses_square = NULL; +#ifdef IVAS_FLOAT_FIXED + hDirAC_mem->direct_responses_square_fx = NULL; +#endif hDirAC_mem->frame_dec_f = NULL; if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) { @@ -1460,6 +1463,14 @@ ivas_error ivas_dirac_alloc_mem( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } set_zero( hDirAC_mem->direct_responses_square, size ); + +#ifdef IVAS_FLOAT_FIXED + if ((hDirAC_mem->direct_responses_square_fx = (Word32 *)malloc(sizeof(Word32) * size)) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n")); + } + set32_fx(hDirAC_mem->direct_responses_square_fx, 0, size); +#endif if ( hDirACRend->proto_signal_decorr_on && ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) ) { if ( ( hDirAC_mem->frame_dec_f = (float *) malloc( sizeof( float ) * 2 * num_outputs_diff * num_freq_bands ) ) == NULL ) @@ -1472,6 +1483,9 @@ ivas_error ivas_dirac_alloc_mem( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth = hDirAC_mem->proto_power_diff_smooth; hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth = hDirAC_mem->cy_auto_dir_smooth; hDirACRend->h_output_synthesis_psd_state.direct_responses_square = hDirAC_mem->direct_responses_square; +#ifdef IVAS_FLOAT_FIXED + hDirACRend->h_output_synthesis_psd_state.direct_responses_square_fx = hDirAC_mem->direct_responses_square_fx; +#endif /* Target and smoothed nrg factors/gains */ if ( ( hDirAC_mem->cy_cross_dir_smooth = (float *) malloc( sizeof( float ) * size_ho ) ) == NULL ) @@ -1509,6 +1523,18 @@ ivas_error ivas_dirac_alloc_mem( hDirACRend->h_output_synthesis_psd_state.direct_responses = hDirAC_mem->direct_responses; +#ifdef IVAS_FLOAT_FIXED + /*Responses (gains/factors)*/ + if ((hDirAC_mem->direct_responses_fx = (Word32 *)malloc(sizeof(Word32) * size_ho)) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n")); + } + set32_fx(hDirAC_mem->direct_responses_fx, 0, size); + + + hDirACRend->h_output_synthesis_psd_state.direct_responses_fx = hDirAC_mem->direct_responses_fx; +#endif + /* Prototypes */ hDirAC_mem->proto_direct_buffer_f = NULL; hDirAC_mem->proto_diffuse_buffer_f = NULL; @@ -1544,6 +1570,11 @@ ivas_error ivas_dirac_alloc_mem( hDirAC_mem->direct_power_factor = NULL; hDirAC_mem->diffuse_power_factor = NULL; +#ifdef IVAS_FLOAT_FIXED + hDirAC_mem->direct_power_factor_fx = NULL; + hDirAC_mem->diffuse_power_factor_fx = NULL; +#endif + if ( renderer_type != RENDERER_BINAURAL_PARAMETRIC && renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && renderer_type != RENDERER_STEREO_PARAMETRIC ) { if ( ( hDirAC_mem->direct_power_factor = (float *) malloc( sizeof( float ) * size_pf ) ) == NULL ) @@ -1554,10 +1585,26 @@ ivas_error ivas_dirac_alloc_mem( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } +#ifdef IVAS_FLOAT_FIXED + IF((hDirAC_mem->direct_power_factor_fx = (Word32 *)malloc(sizeof(Word32) * size_pf)) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n")); + } + IF((hDirAC_mem->diffuse_power_factor_fx = (Word32 *)malloc(sizeof(Word32) * size_pf)) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n")); + } +#endif } hDirACRend->h_output_synthesis_psd_state.direct_power_factor = hDirAC_mem->direct_power_factor; hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor = hDirAC_mem->diffuse_power_factor; +#ifdef IVAS_FLOAT_FIXED + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx = hDirAC_mem->direct_power_factor_fx; + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx = hDirAC_mem->diffuse_power_factor_fx; + set_zero(hDirACRend->h_output_synthesis_psd_state.direct_power_factor , size_pf); + set_zero(hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor, size_pf); +#endif hDirAC_mem->reference_power = NULL; hDirAC_mem->onset_filter = NULL; @@ -1626,6 +1673,10 @@ void ivas_dirac_free_mem_fx( { free(hDirAC_mem->direct_responses_square); } + IF(hDirAC_mem->direct_responses_square_fx != NULL) + { + free(hDirAC_mem->direct_responses_square_fx); + } IF (hDirAC_mem->frame_dec_f != NULL) { free(hDirAC_mem->frame_dec_f); @@ -1658,6 +1709,14 @@ void ivas_dirac_free_mem_fx( { free(hDirAC_mem->diffuse_power_factor); } + IF(hDirAC_mem->direct_power_factor_fx != NULL) + { + free(hDirAC_mem->direct_power_factor_fx); + } + IF(hDirAC_mem->diffuse_power_factor_fx != NULL) + { + free(hDirAC_mem->diffuse_power_factor_fx); + } IF (hDirAC_mem->reference_power != NULL) { free(hDirAC_mem->reference_power); diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 7acd0d9ac54a391c613ef2d153b34b923ec6c469..5e32b5be25a0a2a73cc76aadcd31cefea4c0600b 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -651,6 +651,23 @@ void compute_hoa_encoder_mtx_fx( Word32 *response_fx, const Word16 num_responses, const Word16 ambisonics_order); + +void ivas_dirac_dec_compute_power_factors_fx( + const int16_t num_freq_bands, + const Word32 *diffuseness_fx, + const Word16 max_band_decorr, + Word32 *direct_power_factor, + Word32 *diffuse_power_factor +); + +void ivas_dirac_dec_compute_gain_factors_fx( + const Word16 num_freq_bands, + const Word32 *diffuseness_fx, + Word32 *direct_gain_factor, + Word32 *diffuse_gain_factor, + Word16 *max_exp_direct_fx, + Word16 *max_exp_diffusion +); #endif void ivas_dirac_dec_compute_gain_factors( @@ -684,6 +701,24 @@ void ivas_dirac_dec_compute_directional_responses( const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_compute_directional_responses_fx( + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const Word16 *masa_band_mapping, /* i : Band mapping for MASA, NULL assumes not using MASA in any form */ + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ + const Word16 *azimuth, + const Word16 *elevation, + const Word16 md_idx, + const Word32 *surCohRatio_fx, + Word16 Q_surCohRatio, + const Word16 shd_rot_max_order, /* i : split-order rotation method */ + const float *p_Rmat, /* i : rotation matrix */ + const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); +#endif + void ivas_dirac_dec_get_frequency_axis( float *frequency_axis, /* o : array of center frequencies of a real filter bank */ const int32_t output_Fs, /* i : sampling frequency */ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 2475124853c247cf6a54fedcbc726cc05fba352e..a623f93b253ad5e2b81d8e94a178d559fd0b39b6 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -247,10 +247,18 @@ typedef struct dirac_dec_stack_mem float *direct_power_factor; float *diffuse_power_factor; +#ifdef IVAS_FLOAT_FIXED + Word32 *direct_power_factor_fx; + Word32 *diffuse_power_factor_fx; +#endif + /*Directional responses (gains & Nrg)*/ float *direct_responses; float *direct_responses_square; - +#ifdef IVAS_FLOAT_FIXED + Word32 *direct_responses_fx; + Word32 *direct_responses_square_fx; +#endif /* Target co-variance mtx */ float *cy_auto_dir_smooth; float *cy_cross_dir_smooth; @@ -333,14 +341,17 @@ typedef struct dirac_output_synthesis_state_structure #ifdef IVAS_FLOAT_FIXED /* only pointer to local buffers */ - Word16 *direct_responses_fx; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ - Word16 *direct_responses_square_fx; + Word32 *direct_responses_fx; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ + Word32 *direct_responses_square_fx; Word16 *diffuse_responses_square_fx; /* squared diffuse responses. Size: num_channels. */ /* only pointer to local buffers */ - Word16 *direct_power_factor_fx; - Word16 *diffuse_power_factor_fx; + Word32 *direct_power_factor_fx; + Word32 *diffuse_power_factor_fx; + Word16 Q_direct_power_factor; + Word16 Q_diffuse_power_factor; + Word16 *proto_power_smooth_fx; /* Smoothed power of the prototype signals. Size: num_freq_bands*num_channels. */ Word16 *proto_power_smooth_prev_fx; /* Smoothed power of the prototype signals of the previous synthesis block. Size: num_freq_bands*num_channels. */