diff --git a/lib_com/cnst.h b/lib_com/cnst.h index eec60bbd296fda785ba0814b0e587834536b489a..7816c19e023776840421edc9e49c17d54fedb372 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -2717,7 +2717,7 @@ enum #define LG10 24660 /* 10*log10(2) in Q13 */ #define LG10_s3_0 16440 /* 10*log10(2)/1.55 = 1.00343331 in Q14 */ #define LOG2_10 27213 /* log base 2 of 10 in Q12 */ -#define INV_LOG10_2_Q31 646456993 /* inverse log base 10 of 2 in Q31 */ +#define LOG10_2_Q31 646456993 /* inverse log base 10 of 2 in Q31 */ #define MU_MA_FX 10923 /* original prediction factor for the AMR WB tables (Q15) */ #define E_MIN_FXQ15 115 /* Q15*/ diff --git a/lib_com/float_to_fix_ops.c b/lib_com/float_to_fix_ops.c index 736b2f38afba2e54d029318a3b4107ebeee6fcc2..3de3c441a79e425e92e5d2531bb48b084b5827a4 100644 --- a/lib_com/float_to_fix_ops.c +++ b/lib_com/float_to_fix_ops.c @@ -248,6 +248,47 @@ Word16 L_get_q_buf( float *ptr_flt, Word16 length ) return sub( norm_l( (Word32) ftemp ), 0 ); } } + +Word16 L_get_q1( float f ) +{ + if ( fabsf( f ) >= 0.f && fabsf( f ) < 1.f ) + { + return Q31; + } + else if ( fabsf( f ) > (float) INT_MAX ) + { + return sub( sub( W_norm( (Word64) f ), 32 ), 0 ); + } + else + { + return sub( norm_l( (Word32) f ), 0 ); + } +} + +Word16 L_get_q_buf1( float *ptr_flt, Word16 length ) +{ + Word16 k; + float ftemp = 0.0; + + for ( k = 0; k < length; k++ ) + { + if ( fabsf( ptr_flt[k] ) > ftemp ) + ftemp = fabsf( ptr_flt[k] ); + } + + if ( ftemp >= 0.f && ftemp < 1.f ) + { + return Q31; + } + else if ( ftemp > (float) INT_MAX ) + { + return sub( sub( W_norm( (Word64) ftemp ), 32 ), 0 ); + } + else + { + return sub( norm_l( (Word32) ftemp ), 0 ); + } +} #endif #ifdef IVAS_FLOAT_FIXED diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 88ece4c551ddd6519acca7b2583fa14492ef2d5f..5ce69999b619834edaf8718fa29a504ef5238120 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -132,8 +132,10 @@ void fix2f(Word32 *var_fix, float *var_flt, Word32 expo); #ifdef IVAS_FLOAT_FIXED // Get max Q factor for a float value before sat in 32-bit Word16 L_get_q( float f ); +Word16 L_get_q1( float f ); // Get max Q factor for a float buffer before sat in 32-bit Word16 L_get_q_buf( float *ptr_flt, Word16 length ); +Word16 L_get_q_buf1( float *ptr_flt, Word16 length ); #endif Word32 Mult_32_16( diff --git a/lib_dec/dec_tcx_fx.c b/lib_dec/dec_tcx_fx.c index 45e907d8d8058284151e6c6778cc3119e0721b8f..2c596d0afa460fcd4baa1c5df810b37ecc70e57d 100644 --- a/lib_dec/dec_tcx_fx.c +++ b/lib_dec/dec_tcx_fx.c @@ -3662,8 +3662,8 @@ void decoder_tcx_ivas_fx( Scale_sig( st->hTcxDec->syn_Overl_TDACFB, 480, -( st->Q_syn + 2 ) ); // Scaling to Q-2 Scale_sig( st->hTcxDec->syn_OverlFB, 480, -( st->Q_syn + 2 ) ); // Scaling to Q-2 Scale_sig( st->hTcxDec->old_syn_Overl, 320, -( st->Q_syn + 1 + 0 ) ); // Scaling to Q-2 - Scale_sig( st->hHQ_core->old_out_LB_fx, 640, -( st->hHQ_core->Q_old_wtda + 2 ) ); // Scaling to Q-2 - Scale_sig( st->hHQ_core->old_out_fx, 960, -( st->hHQ_core->Q_old_wtda + 2 ) ); // Scaling to Q-2 + Scale_sig( st->hHQ_core->old_out_LB_fx, 640, -( st->Q_syn + 2 ) ); // Scaling to Q-2 + Scale_sig( st->hHQ_core->old_out_fx, 960, -( st->Q_syn + 2 ) ); // Scaling to Q-2 Copy_Scale_sig_16_32_no_sat( st->old_Aq_12_8_fx, st->old_Aq_12_8_fx_32, M + 1, ( 28 - ( 15 - norm_s( st->old_Aq_12_8_fx[0] - 1 ) ) ) ); diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 80c0d9d1acfa4393391590eb7382fcc6510f6d64..085e0fba2a293c3045901dea766ce4e40500238c 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1211,7 +1211,7 @@ ivas_error ivas_allocate_binaural_hrtf( * * *-------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED static ivas_error ivas_binaural_hrtf_open( HRTFS_FASTCONV_HANDLE *hHrtfFastConv, /* i : fastconv HRTF handle */ const AUDIO_CONFIG input_config, /* i : output configuration */ @@ -1326,7 +1326,122 @@ static ivas_error ivas_binaural_hrtf_open( return IVAS_ERR_OK; } +#else +static ivas_error ivas_binaural_hrtf_open( + HRTFS_FASTCONV_HANDLE *hHrtfFastConv, /* i : fastconv HRTF handle */ + const AUDIO_CONFIG input_config, /* i : output configuration */ + const RENDERER_TYPE renderer_type /* i : renderer type */ +) +{ + int16_t i, j; + ivas_error error; + + if ( hHrtfFastConv != NULL && *hHrtfFastConv != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_FASTCONV *HrtfFastConv; + + if ( ( HrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for FastConv HRTF tables" ); + } + + ivas_init_binaural_hrtf( HrtfFastConv ); + if ( input_config == IVAS_AUDIO_CONFIG_BINAURAL || renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + HrtfFastConv->FASTCONV_HRIR_latency_s = FASTCONV_HRIR_latency_s; + } + if ( input_config == IVAS_AUDIO_CONFIG_HOA2 ) + { + HrtfFastConv->FASTCONV_HOA2_latency_s = FASTCONV_HOA2_latency_s; + } + if ( input_config == IVAS_AUDIO_CONFIG_HOA3 ) + { + HrtfFastConv->FASTCONV_HOA3_latency_s = FASTCONV_HOA3_latency_s; + } + if ( input_config == IVAS_AUDIO_CONFIG_FOA ) + { + HrtfFastConv->FASTCONV_FOA_latency_s = FASTCONV_FOA_latency_s; + } + if ( input_config == IVAS_AUDIO_CONFIG_BINAURAL || renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + HrtfFastConv->FASTCONV_BRIR_latency_s = FASTCONV_BRIR_latency_s; + } + + HrtfFastConv->allocate_init_flag = 1; + + if ( ( error = ivas_allocate_binaural_hrtf( HrtfFastConv, input_config, BINAURAL_INPUT_AUDIO_CONFIG_INVALID, renderer_type, HrtfFastConv->allocate_init_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + if ( renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + HrtfFastConv->leftHRIRReal[i][j] = leftHRIRReal[i][j]; + HrtfFastConv->leftHRIRImag[i][j] = leftHRIRImag[i][j]; + HrtfFastConv->rightHRIRReal[i][j] = rightHRIRReal[i][j]; + HrtfFastConv->rightHRIRImag[i][j] = rightHRIRImag[i][j]; + } + } + else if ( renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + HrtfFastConv->leftBRIRReal[i][j] = leftBRIRReal[i][j]; + HrtfFastConv->leftBRIRImag[i][j] = leftBRIRImag[i][j]; + HrtfFastConv->rightBRIRReal[i][j] = rightBRIRReal[i][j]; + HrtfFastConv->rightBRIRImag[i][j] = rightBRIRImag[i][j]; + } + } + if ( input_config == IVAS_AUDIO_CONFIG_HOA3 ) + { + for ( j = 0; j < HOA3_CHANNELS; j++ ) + { + HrtfFastConv->leftHRIRReal_HOA3[i][j] = leftHRIRReal_HOA3[i][j]; + HrtfFastConv->leftHRIRImag_HOA3[i][j] = leftHRIRImag_HOA3[i][j]; + HrtfFastConv->rightHRIRReal_HOA3[i][j] = rightHRIRReal_HOA3[i][j]; + HrtfFastConv->rightHRIRImag_HOA3[i][j] = rightHRIRImag_HOA3[i][j]; + } + } + if ( input_config == IVAS_AUDIO_CONFIG_HOA2 ) + { + for ( j = 0; j < HOA2_CHANNELS; j++ ) + { + HrtfFastConv->leftHRIRReal_HOA2[i][j] = leftHRIRReal_HOA2[i][j]; + HrtfFastConv->leftHRIRImag_HOA2[i][j] = leftHRIRImag_HOA2[i][j]; + HrtfFastConv->rightHRIRReal_HOA2[i][j] = rightHRIRReal_HOA2[i][j]; + HrtfFastConv->rightHRIRImag_HOA2[i][j] = rightHRIRImag_HOA2[i][j]; + } + } + if ( input_config == IVAS_AUDIO_CONFIG_FOA ) + { + for ( j = 0; j < FOA_CHANNELS; j++ ) + { + HrtfFastConv->leftHRIRReal_FOA[i][j] = leftHRIRReal_FOA[i][j]; + HrtfFastConv->leftHRIRImag_FOA[i][j] = leftHRIRImag_FOA[i][j]; + HrtfFastConv->rightHRIRReal_FOA[i][j] = rightHRIRReal_FOA[i][j]; + HrtfFastConv->rightHRIRImag_FOA[i][j] = rightHRIRImag_FOA[i][j]; + } + } + } + mvr2r( fastconvReverberationTimes, HrtfFastConv->fastconvReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( fastconvReverberationEneCorrections, HrtfFastConv->fastconvReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfFastConv = HrtfFastConv; + } + + return IVAS_ERR_OK; +} +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * ivas_binaural_obtain_DMX() diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 18ca3e140b5dae30dff933a649f1fe2f6125ca80..1d6922e899581c0b0812a3baf35b557c2dfd276d 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -5547,7 +5547,28 @@ void ivas_dirac_dec_render_sf_fx( } else { +#ifdef IVAS_FLOAT_FIXED + Word16 q_reference_power_smooth; + Word16 size, size_ho, q_Cldfb; + size = hDirACRend->num_outputs_dir * hSpatParamRendCom->num_freq_bands; + size_ho = ( hodirac_flag ) ? size * DIRAC_HO_NUMSECTORS : size; +#endif /* Determine encoding quality based additional smoothing factor */ +#ifdef IVAS_FLOAT_FIXED + float qualityBasedSmFactor = 1.0f; + Word32 qualityBasedSmFactor_fx = ONE_IN_Q31; + move32(); + + IF( st_ivas->hMasa != NULL ) + { + st_ivas->hMasa->data.dir_decode_quality_fx = float_to_fix16( st_ivas->hMasa->data.dir_decode_quality, Q15 ); + + qualityBasedSmFactor_fx = L_deposit_h( st_ivas->hMasa->data.dir_decode_quality_fx ); // Q31 + qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); // (Q31, Q31) -> Q31 + } + + qualityBasedSmFactor = fixedToFloat( qualityBasedSmFactor_fx, Q31 ); +#else float qualityBasedSmFactor = 1.0f; if ( st_ivas->hMasa != NULL ) @@ -5555,7 +5576,133 @@ void ivas_dirac_dec_render_sf_fx( qualityBasedSmFactor = st_ivas->hMasa->data.dir_decode_quality; qualityBasedSmFactor *= qualityBasedSmFactor; } +#endif + +#ifdef IVAS_FLOAT_FIXED + FOR( ch = 0; ch < hDirACRend->hOutSetup.nchan_out_woLFE; ch++ ) + { + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + floatToFixed_arrL( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer_fx[ch][slot_idx], + Q6, + hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer_fx[ch][slot_idx], + Q6, + hSpatParamRendCom->num_freq_bands ); + } + } + + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_q = Q31; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.direct_power_factor, hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx, hDirACRend->h_output_synthesis_psd_state.direct_power_factor_q, hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.direct_responses_q = Q31; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses, hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses_q, hDirACRend->num_outputs_dir * hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.direct_responses_square_q = Q31; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_square, hDirACRend->h_output_synthesis_psd_state.direct_responses_square_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses_square_q, hDirACRend->num_outputs_dir * hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_q = Q31; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor, hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx, hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_q, hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.diffuse_responses_square_q = Q31; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.diffuse_responses_square, hDirACRend->h_output_synthesis_psd_state.diffuse_responses_square_fx, hDirACRend->h_output_synthesis_psd_state.diffuse_responses_square_q, hDirACRend->num_outputs_dir ); + + floatToFixed_arrL( diffuseness_vector, diffuseness_vector_fx, Q31, hSpatParamRendCom->num_freq_bands ); // Q31 + + q_reference_power_smooth = L_get_q_buf( reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + q_reference_power_smooth = s_min( q_reference_power_smooth, L_get_q_buf( hDirACRend->h_output_synthesis_psd_state.reference_power_smooth_prev, hSpatParamRendCom->num_freq_bands ) ); + floatToFixed_arrL( reference_power_smooth, reference_power_smooth_fx, q_reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.reference_power_smooth_prev, hDirACRend->h_output_synthesis_psd_state.reference_power_smooth_prev_fx, q_reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth, size_ho ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth, size_ho ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth, size_ho ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth, size_ho ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev, size_ho ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev, size_ho ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev, size_ho ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev, size_ho ); + + hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + + IF( hDirACRend->masa_stereo_type_detect != NULL ) + { + hDirACRend->masa_stereo_type_detect->q_target_power_y_smooth = L_get_q( hDirACRend->masa_stereo_type_detect->target_power_y_smooth ); + hDirACRend->masa_stereo_type_detect->target_power_y_smooth_fx = floatToFixed( hDirACRend->masa_stereo_type_detect->target_power_y_smooth, hDirACRend->masa_stereo_type_detect->q_target_power_y_smooth ); + + hDirACRend->masa_stereo_type_detect->q_subtract_power_y = s_min( L_get_q( hDirACRend->masa_stereo_type_detect->subtract_power_y ), + L_get_q( hDirACRend->masa_stereo_type_detect->subtract_power_y_smooth ) ); + hDirACRend->masa_stereo_type_detect->subtract_power_y_smooth_fx = floatToFixed( hDirACRend->masa_stereo_type_detect->subtract_power_y_smooth, hDirACRend->masa_stereo_type_detect->q_subtract_power_y ); + hDirACRend->masa_stereo_type_detect->subtract_power_y_fx = floatToFixed( hDirACRend->masa_stereo_type_detect->subtract_power_y, hDirACRend->masa_stereo_type_detect->q_subtract_power_y ); + } + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q = s_min( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, + L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ) ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + + hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q = L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ); + IF( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev != 0 ) + { + hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q = s_min( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, + L_get_q_buf1( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ) ); + } + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ); + IF( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev != 0 ) + { + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ); + } + + hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_q = Q26; + hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_q = Q26; + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.gains_dir_prev, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_q, size ); + floatToFixed_arrL( hDirACRend->h_output_synthesis_psd_state.gains_diff_prev, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_q, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + floatToFixed_arrL( &hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f[i_mult( i_mult( slot_idx, 2 ), + i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_protos_dir ) )], + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_fx + + i_mult( i_mult( slot_idx, 2 ), i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_protos_dir ) ), + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q, + 2 * hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + } + IF( hDirACRend->proto_signal_decorr_on ) + { + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q = hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q; + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + floatToFixed_arrL( &hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f[i_mult( i_mult( slot_idx, 2 ), + i_mult( hDirACRend->h_output_synthesis_psd_params.max_band_decorr, hDirACRend->hOutSetup.nchan_out_woLFE ) )], + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx + + i_mult( i_mult( slot_idx, 2 ), i_mult( hDirACRend->h_output_synthesis_psd_params.max_band_decorr, hDirACRend->hOutSetup.nchan_out_woLFE ) ), + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q, + 2 * hDirACRend->hOutSetup.nchan_out_woLFE * hDirACRend->h_output_synthesis_psd_params.max_band_decorr ); + } + } +#endif + +#ifdef IVAS_FLOAT_FIXED + ivas_dirac_dec_output_synthesis_process_subframe_psd_ls_fx( Cldfb_RealBuffer_fx, + Cldfb_ImagBuffer_fx, + hSpatParamRendCom, + hDirACRend, + hSpatParamRendCom->subframe_nbslots[subframe_idx], + diffuseness_vector_fx, + reference_power_smooth_fx, + &q_reference_power_smooth, + qualityBasedSmFactor_fx, + hDirAC->hConfig->enc_param_start_band, + &q_Cldfb ); +#else ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, Cldfb_ImagBuffer, hSpatParamRendCom, @@ -5565,6 +5712,51 @@ void ivas_dirac_dec_render_sf_fx( reference_power_smooth, qualityBasedSmFactor, hDirAC->hConfig->enc_param_start_band ); +#endif + +#ifdef IVAS_FLOAT_FIXED + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.reference_power_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.reference_power_smooth_prev, q_reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + + IF( hDirACRend->masa_stereo_type_detect != NULL ) + { + hDirACRend->masa_stereo_type_detect->subtract_target_ratio_db = fixedToFloat( hDirACRend->masa_stereo_type_detect->subtract_target_ratio_db_fx, Q21 ); + + hDirACRend->masa_stereo_type_detect->target_power_y_smooth = fixedToFloat( hDirACRend->masa_stereo_type_detect->target_power_y_smooth_fx, hDirACRend->masa_stereo_type_detect->q_target_power_y_smooth ); + hDirACRend->masa_stereo_type_detect->subtract_power_y_smooth = fixedToFloat( hDirACRend->masa_stereo_type_detect->subtract_power_y_smooth_fx, hDirACRend->masa_stereo_type_detect->q_subtract_power_y ); + hDirACRend->masa_stereo_type_detect->subtract_power_y = fixedToFloat( hDirACRend->masa_stereo_type_detect->subtract_power_y_fx, hDirACRend->masa_stereo_type_detect->q_subtract_power_y ); + } + + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth, size ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth, hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth, size_ho ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth, size ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev, size ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev, hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev, size_ho ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev, hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_q, size ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_q, hSpatParamRendCom->num_freq_bands * hDirACRend->hOutSetup.nchan_out_woLFE ); + + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q, hDirACRend->num_protos_dir * hSpatParamRendCom->num_freq_bands ); + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ); + IF( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev != 0 ) + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, hDirACRend->h_output_synthesis_psd_params.max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE ); + } + + FOR( ch = 0; ch < hDirACRend->hOutSetup.nchan_out_woLFE; ch++ ) + { + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + fixedToFloat_arrL( Cldfb_RealBuffer_fx[ch][slot_idx], Cldfb_RealBuffer[ch][slot_idx], + q_Cldfb, + hSpatParamRendCom->num_freq_bands ); + fixedToFloat_arrL( Cldfb_ImagBuffer_fx[ch][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], + q_Cldfb, + hSpatParamRendCom->num_freq_bands ); + } + } +#endif } /*-----------------------------------------------------------------* diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 80173b9fa36c912dbe9f308f74891d195b98931b..9e5afa24bf94d90d1c89b9e954fc5c07a0b999f9 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2318,7 +2318,7 @@ ivas_error ivas_init_decoder_fx( IF ( st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - IF ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL, st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_reverb_open_fx( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL, st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 2028e6cf8d45f709872d77e77e06ca81e57f53c3..d162c9366ea5cec51a4b600365c2f74898bedbc5 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -199,7 +199,7 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( } IF ( st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - IF ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL,st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_reverb_open_fx( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL,st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -690,7 +690,7 @@ static ivas_error ivas_ism_bitrate_switching_dec( if ( st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - if ( ( error = ivas_reverb_open( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL,st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_reverb_open_fx( &st_ivas->hReverb, st_ivas->hDecoderConfig->output_config, NULL,st_ivas->hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 91db00884f7f52ceb045ca1e0c671f19f9783905..69b758d40524416dae4c8dfe7ad7a51a7b5be5bc 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -2639,7 +2639,7 @@ ivas_error ivas_rend_openCrend( IF ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - IF ( ( error = ivas_reverb_open( &( hCrend->hReverb ), inConfig, ( *pCrend )->hHrtfCrend,NULL, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_reverb_open_fx( &( hCrend->hReverb ), inConfig, ( *pCrend )->hHrtfCrend,NULL, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 79ba4ba4d7972db991dd00e8cc054babc868dcb5..a7870d0752694bdb17deabb030bcebb362271032 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -625,6 +625,7 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx( } #endif // IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED ivas_error ivas_dirac_dec_binaural_copy_hrtfs( HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ ) @@ -654,6 +655,9 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( } } + mvl2l( parametricReverberationTimes_fx, hrtfParambin->parametricReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX ); + mvl2l( parametricReverberationEneCorrections_fx, hrtfParambin->parametricReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX ); mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX ); @@ -663,7 +667,46 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs( return IVAS_ERR_OK; } +#else +ivas_error ivas_dirac_dec_binaural_copy_hrtfs( + HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ +) +{ + int16_t i, j; + if ( hHrtfParambin != NULL && *hHrtfParambin != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_PARAMBIN *hrtfParambin; + + if ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" ); + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS ); + mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS ); + } + } + mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfParambin = hrtfParambin; + } + + return IVAS_ERR_OK; +} +#endif /*------------------------------------------------------------------------- * void ivas_dirac_dec_binaural_render() diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_rend/ivas_dirac_output_synthesis_dec.c index ca6c7b02fe3b6cde45ffd3093e65006272f243c5..ebfc55f9745827dafc4c74164584836e7d64843c 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec.c @@ -59,6 +59,7 @@ #define DIRAC_ALPHA_MAX_FAST 0.12f #define DIRAC_ALPHA_MAX_FAST_Q15 3932 #define DIRECTION_SMOOTHNESS_ALPHA 0.01f +#define DIRECTION_SMOOTHNESS_ALPHA_Q31 (Word32)(0.01f * ONE_IN_Q31) /*------------------------------------------------------------------------- @@ -68,11 +69,11 @@ #ifdef IVAS_FLOAT_FIXED static void computeTargetPSDs_direct_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word32 *direct_power_factor, const Word32 *reference_power, const Word16 *q_reference_power, const Word32 *direct_responses, const Word32 *direct_responses_square, Word32 *cy_auto_dir_smooth, Word16 *q_cy_auto_dir_smooth, Word32 *cy_cross_dir_smooth, Word16 *q_cy_cross_dir_smooth ); -static void computeTargetPSDs_direct_subframe_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word32 *direct_power_factor, const Word32 *reference_power, const Word32 *direct_responses, const Word32 *direct_responses_square, Word32 *cy_auto_dir_smooth, Word32 *cy_cross_dir_smooth ); +static void computeTargetPSDs_direct_subframe_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word32 *direct_power_factor, const Word32 *reference_power, const Word16 *q_reference_power, const Word32 *direct_responses, const Word32 *direct_responses_square, Word32 *cy_auto_dir_smooth, Word16 *q_cy_auto_dir_smooth, Word32 *cy_cross_dir_smooth, Word16 *q_cy_cross_dir_smooth ); static void computeTargetPSDs_diffuse_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word16 start_band, const Word32 *diffuse_power_factor, const Word32 *reference_power, const Word16 *q_reference_power, const Word32 *diffuse_responses_square, Word32 *cy_auto_diff_smooth, Word16 *q_cy_auto_diff_smooth ); -static void computeTargetPSDs_diffuse_subframe_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word16 start_band, const Word32 *diffuse_power_factor, const Word32 *reference_power, const Word32 *diffuse_responses_square, Word32 *cy_auto_diff_smooth ); +static void computeTargetPSDs_diffuse_subframe_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word16 start_band, const Word32 *diffuse_power_factor, const Word32 *reference_power, const Word16 *q_reference_power, const Word32 *diffuse_responses_square, Word32 *cy_auto_diff_smooth, Word16 *q_cy_auto_diff_smooth ); static void computeTargetPSDs_diffuse_with_onsets_fx( const Word16 num_channels, const Word16 num_freq_bands, const Word16 num_decorr_freq_bands, const Word16 *proto_frame_diff_index, const Word32 *diffuse_power_factor, const Word32 *reference_power, const Word16 *q_reference_power, const Word32 *diffuse_responses_square, const Word32 *onset_filter, Word32 *cy_auto_diff_smooth, Word16 *q_cy_auto_diff_smooth ); #endif @@ -193,9 +194,9 @@ ivas_error ivas_dirac_dec_output_synthesis_open_fx( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - IF ((dirac_output_synthesis_state->proto_power_smooth_prev_fx = (Word16 *)malloc(hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir * sizeof(Word16))) == NULL) + IF( ( dirac_output_synthesis_state->proto_power_smooth_prev_fx = (Word32 *) malloc( hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir * sizeof( Word32 ) ) ) == NULL ) { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n")); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } IF ( dirac_output_synthesis_params->max_band_decorr > 0 && ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) ) @@ -205,9 +206,9 @@ ivas_error ivas_dirac_dec_output_synthesis_open_fx( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - IF ((dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx = (Word16 *)malloc(dirac_output_synthesis_params->max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE * sizeof(Word16))) == NULL) + IF( ( dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx = (Word32 *) malloc( dirac_output_synthesis_params->max_band_decorr * hDirACRend->hOutSetup.nchan_out_woLFE * sizeof( Word32 ) ) ) == NULL ) { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n")); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } } ELSE @@ -392,16 +393,16 @@ ivas_error ivas_dirac_dec_output_synthesis_open_fx( } Copy(temp_alpha_synthesis_fx, dirac_output_synthesis_params->alpha_synthesis_fast_fx, dirac_output_synthesis_params->numAlphasFast); - IF((dirac_output_synthesis_state->reference_power_smooth_prev_fx = (Word16 *)malloc(hSpatParamRendCom->num_freq_bands * sizeof(Word16))) == NULL) + IF( ( dirac_output_synthesis_state->reference_power_smooth_prev_fx = (Word32 *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( Word32 ) ) ) == NULL ) { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n")); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - IF((dirac_output_synthesis_state->direction_smoothness_prev_fx = (Word16 *)malloc(hSpatParamRendCom->num_freq_bands * sizeof(Word16))) == NULL) + IF( ( dirac_output_synthesis_state->direction_smoothness_prev_fx = (Word32 *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( Word32 ) ) ) == NULL ) { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n")); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC synthesis\n" ) ); } - set16_fx(dirac_output_synthesis_state->reference_power_smooth_prev_fx, 0, hSpatParamRendCom->num_freq_bands); - set16_fx(dirac_output_synthesis_state->direction_smoothness_prev_fx, 0, hSpatParamRendCom->num_freq_bands); + set32_fx( dirac_output_synthesis_state->reference_power_smooth_prev_fx, 0, hSpatParamRendCom->num_freq_bands ); + set32_fx( dirac_output_synthesis_state->direction_smoothness_prev_fx, 0, hSpatParamRendCom->num_freq_bands ); /*TODO : remove float code*/ if ((dirac_output_synthesis_params->alpha_synthesis_fast = (float *)malloc(dirac_output_synthesis_params->numAlphasFast * sizeof(float))) == NULL) @@ -962,9 +963,9 @@ void ivas_dirac_dec_output_synthesis_init_fx( } h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev = 0; - IF (h_dirac_output_synthesis_state->proto_power_smooth_prev_fx != NULL) + IF( h_dirac_output_synthesis_state->proto_power_smooth_prev_fx != NULL ) { - set16_fx(h_dirac_output_synthesis_state->proto_power_smooth_prev_fx, 0, hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir); + set32_fx( h_dirac_output_synthesis_state->proto_power_smooth_prev_fx, 0, hSpatParamRendCom->num_freq_bands * hDirACRend->num_protos_dir ); } set32_fx( h_dirac_output_synthesis_state->gains_dir_prev_fx, 0, size ); h_dirac_output_synthesis_state->gains_dir_prev_q = 0; @@ -979,9 +980,9 @@ void ivas_dirac_dec_output_synthesis_init_fx( } h_dirac_output_synthesis_state->gains_diff_prev_q = 0; - IF (h_dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx != NULL) + IF( h_dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx != NULL ) { - set16_fx(h_dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx, 0, h_dirac_output_synthesis_params->max_band_decorr * nchan_out_woLFE); + set32_fx( h_dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx, 0, h_dirac_output_synthesis_params->max_band_decorr * nchan_out_woLFE ); } #endif @@ -3163,6 +3164,624 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( } +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * ivas_dirac_dec_output_synthesis_process_subframe_psd_ls_fx() + * + * + *------------------------------------------------------------------------*/ + +void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls_fx( + Word32 RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ + Word32 ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const Word16 nbslots, /* i : number of slots to process */ + Word32 *diffuseness_vector, /* i : diffuseness (needed for direction smoothing)*/ + Word32 *reference_power_smooth, + Word16 *q_reference_power_smooth, + Word32 qualityBasedSmFactor, + const Word16 enc_param_start_band, + Word16 *q_Cldfb ) +{ + Word16 buf_idx, num_freq_bands; + Word16 diff_start_band; + Word16 k, l; + Word16 nchan_out_woLFE; + Word32 *p_power_smooth_prev, *p_power_diff_smooth_prev; + Word32 *p_gain_1, *p_gain_2; + Word32 *p_power_smooth_diff, *p_power_smooth; + Word32 *p_gains_dir, *p_gains_diff; + Word32 g, g1, g2; + Word32 *p_cy_auto_dir_smooth, *p_cy_auto_dir_smooth_prev; + Word32 *p_cy_cross_dir_smooth, *p_cy_cross_dir_smooth_prev; + Word32 *p_cy_auto_diff_smooth, *p_cy_auto_diff_smooth_prev; + Word32 gains_dir[CLDFB_NO_CHANNELS_MAX * MAX_OUTPUT_CHANNELS]; + Word32 gains_diff[CLDFB_NO_CHANNELS_MAX * MAX_OUTPUT_CHANNELS]; + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; + DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; + Word16 *proto_direct_index, num_protos_dir; + Word32 target_power_y, target_power_y1; + Word16 q_target_power_y, q_target_power_y1; + Word32 subtract_power_y; + Word32 subtract_target_ratio; + Word32 subtract_target_ratio_db; + Word32 a, b; + UWord16 nchan_target_psds; + Word32 alpha[CLDFB_NO_CHANNELS_MAX]; + Word16 *alpha_synthesis; + Word16 *alpha_synthesis_fast; + Word16 alphaMaxBin; + Word16 alphaMaxBinFast; + Word32 L_tmp; + Word16 exp_arr[CLDFB_NO_CHANNELS_MAX * MAX_OUTPUT_CHANNELS]; + Word16 exp = 0, exp1, tmp, q_com, q_tmp, min_exp; + move16(); + + push_wmops( "dirac_out_synth_sfr" ); + + h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + + /* collect some often used parameters */ + proto_direct_index = hDirACRend->proto_index_dir; + move16(); + num_protos_dir = hDirACRend->num_protos_dir; + move16(); + nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; + move16(); + num_freq_bands = hSpatParamRendCom->num_freq_bands; + move16(); + + /*-----------------------------------------------------------------* + * compute target PSDs + *-----------------------------------------------------------------*/ + + IF( EQ_16( enc_param_start_band, 0 ) ) + { + diff_start_band = EQ_16( h_dirac_output_synthesis_params->use_onset_filters, 1 ) ? h_dirac_output_synthesis_params->max_band_decorr : 0; + move16(); + + IF( EQ_32( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) ) + { + nchan_target_psds = 2; + move16(); + } + ELSE + { + nchan_target_psds = nchan_out_woLFE; + move16(); + } + + computeTargetPSDs_direct_subframe_fx( nchan_target_psds, num_freq_bands, + h_dirac_output_synthesis_state->direct_power_factor_fx, + reference_power_smooth, + q_reference_power_smooth, + h_dirac_output_synthesis_state->direct_responses_fx, + h_dirac_output_synthesis_state->direct_responses_square_fx, + h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx, + &h_dirac_output_synthesis_state->q_cy_auto_dir_smooth, + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx, + &h_dirac_output_synthesis_state->q_cy_cross_dir_smooth ); + + // Scale cy_auto_diff_smooth_fx if required + IF( NE_32( diff_start_band, 0 ) ) + { + q_com = s_min( *q_reference_power_smooth, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ); + scale_sig32( reference_power_smooth, num_freq_bands, sub( q_com, *q_reference_power_smooth ) ); + scale_sig32( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, + i_mult( num_freq_bands, nchan_target_psds ), + sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ) ); + *q_reference_power_smooth = q_com; + move16(); + h_dirac_output_synthesis_state->q_cy_auto_diff_smooth = q_com; + move16(); + } + + computeTargetPSDs_diffuse_subframe_fx( nchan_target_psds, num_freq_bands, diff_start_band, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + reference_power_smooth, + q_reference_power_smooth, + h_dirac_output_synthesis_state->diffuse_responses_square_fx, + h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, + &h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ); + } + + /*-----------------------------------------------------------------* + * compute variables for stereo transport signal type detection + *-----------------------------------------------------------------*/ + + IF( hDirACRend->masa_stereo_type_detect != NULL ) + { + MASA_STEREO_TYPE_DETECT *masa_stereo_type_detect = hDirACRend->masa_stereo_type_detect; + + p_cy_auto_dir_smooth = h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx; // q_cy_auto_dir_smooth + p_cy_auto_diff_smooth = h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx; // q_cy_auto_diff_smooth + q_com = s_min( h_dirac_output_synthesis_state->q_cy_auto_dir_smooth, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ); + + IF( EQ_32( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) ) + { + exp = sub( Q31, Q31 ); + exp1 = 0; + move16(); + tmp = BASOP_Util_Divide3232_Scale( L_shl( p_cy_auto_dir_smooth[num_freq_bands], sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth ) ), + ( L_add( Sqrt32( h_dirac_output_synthesis_state->direct_power_factor_fx[0], &exp ), EPSILON_FX ) ), // (Q31 - exp) + &exp1 ); + target_power_y = L_shl( L_deposit_l( tmp ), exp1 ); // Q15 + (q_com - (31 - exp)) + q_target_power_y = add( Q15, sub( q_com, sub( Q31, exp ) ) ); + + exp = sub( Q31, Q31 ); + exp1 = 0; + move16(); + tmp = BASOP_Util_Divide3232_Scale( L_shl( p_cy_auto_diff_smooth[num_freq_bands], sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ) ), + ( L_add( Sqrt32( h_dirac_output_synthesis_state->diffuse_power_factor_fx[0], &exp ), EPSILON_FX ) ), // (Q31 - exp) + &exp1 ); + target_power_y1 = L_shl( L_deposit_l( tmp ), exp1 ); // Q15 + (q_com - (31 - exp)) + q_target_power_y1 = add( Q15, sub( q_com, sub( Q31, exp ) ) ); + + target_power_y = L_add( target_power_y, target_power_y1 ); + exp = q_target_power_y; + move16(); + } + ELSE + { + target_power_y = L_add( + L_shl( p_cy_auto_dir_smooth[num_freq_bands], sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth ) ), + L_shl( p_cy_auto_diff_smooth[num_freq_bands], sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ) ) ); // q_com + exp = q_com; + move16(); + } + + subtract_power_y = masa_stereo_type_detect->subtract_power_y_fx; // q_subtract_power_y + move32(); + + a = (Word32) ( 0.0004f * ONE_IN_Q31 ); /* Temporal smoothing coefficient */ + b = L_sub( ONE_IN_Q31, a ); /* Temporal smoothing coefficient */ + + q_com = s_min( exp, masa_stereo_type_detect->q_target_power_y_smooth ); + target_power_y = L_shl( target_power_y, sub( q_com, exp ) ); + masa_stereo_type_detect->target_power_y_smooth_fx = L_shl( masa_stereo_type_detect->target_power_y_smooth_fx, + sub( q_com, masa_stereo_type_detect->q_target_power_y_smooth ) ); + masa_stereo_type_detect->target_power_y_smooth_fx = + L_add( Mpy_32_32( a, target_power_y ), + Mpy_32_32( b, masa_stereo_type_detect->target_power_y_smooth_fx ) ); //(Q31, q_com) -> q_com + masa_stereo_type_detect->q_target_power_y_smooth = q_com; + move16(); + + masa_stereo_type_detect->subtract_power_y_smooth_fx = + L_add( Mpy_32_32( a, subtract_power_y ), + Mpy_32_32( b, masa_stereo_type_detect->subtract_power_y_smooth_fx ) ); //(Q31, q_subtract_power_y) -> q_subtract_power_y + + exp = 0; + move16(); + tmp = BASOP_Util_Divide3232_Scale( masa_stereo_type_detect->subtract_power_y_smooth_fx, + L_add( masa_stereo_type_detect->target_power_y_smooth_fx, EPSILON_FX ), + &exp ); + exp = add( sub( Q15, exp ), sub( masa_stereo_type_detect->q_subtract_power_y, q_com ) ); + subtract_target_ratio = L_shl( L_deposit_l( tmp ), sub( Q15, exp ) ); // Q15 + + L_tmp = BASOP_Util_Log2( subtract_target_ratio ); // Q25 + L_tmp = L_add( L_tmp, L_shl( L_sub( Q31, Q15 ), Q25 ) ); // Q25 + subtract_target_ratio_db = Mpy_32_32( (Word32) ( 10.0f * ONE_IN_Q27 ), + Mpy_32_32( L_tmp, LOG10_2_Q31 ) ); // (Q27, (Q25, Q31)) -> (Q27, Q25) -> Q21 + + masa_stereo_type_detect->subtract_target_ratio_db_fx = subtract_target_ratio_db; // Q21 + move32(); + masa_stereo_type_detect->subtract_power_y_fx = 0; + move32(); + } + + /*-----------------------------------------------------------------* + * compute smoothing coefficients + *-----------------------------------------------------------------*/ + + alpha_synthesis = h_dirac_output_synthesis_params->alpha_synthesis_fx; // Q15 + alpha_synthesis_fast = h_dirac_output_synthesis_params->alpha_synthesis_fast_fx; // Q15 + alphaMaxBin = sub( h_dirac_output_synthesis_params->numAlphas, 1 ); + alphaMaxBinFast = sub( h_dirac_output_synthesis_params->numAlphasFast, 1 ); + + FOR( l = 0; l < num_freq_bands; l++ ) + { + Word32 instDirectionSmoothness, weightedDirectionSmoothness, smoothedDirectionSmoothness; + Word32 currWeight, prevWeight, sumWeight; + Word16 indexFast, indexSlow; + Word32 alpha_quality_based = (Word32) ( 0.02f * ONE_IN_Q31 ); + move32(); + + indexSlow = s_min( l, alphaMaxBin ); + indexFast = s_min( l, alphaMaxBinFast ); + + /* Estimate the smoothness of the directions based on the diffuseness parameter */ + instDirectionSmoothness = L_sub( ONE_IN_Q31, diffuseness_vector[l] ); // Q31 + instDirectionSmoothness = L_min( L_max( instDirectionSmoothness, 0 ), ONE_IN_Q31 ); // Q31 + + /* Average the direction smoothness parameter over time */ + currWeight = Mpy_32_32( DIRECTION_SMOOTHNESS_ALPHA_Q31, + reference_power_smooth[l] ); //(Q31, q_reference_power_smooth) -> q_reference_power_smooth + prevWeight = Mpy_32_32( L_sub( ONE_IN_Q31, DIRECTION_SMOOTHNESS_ALPHA_Q31 ), + h_dirac_output_synthesis_state->reference_power_smooth_prev_fx[l] ); //(Q31, q_reference_power_smooth) -> q_reference_power_smooth + + weightedDirectionSmoothness = + L_add( Mpy_32_32( currWeight, instDirectionSmoothness ), + Mpy_32_32( prevWeight, h_dirac_output_synthesis_state->direction_smoothness_prev_fx[l] ) ); //(q_reference_power_smooth, Q31) -> q_reference_power_smooth + sumWeight = L_add( currWeight, prevWeight ); // q_reference_power_smooth + + exp = 0; + move16(); + tmp = BASOP_Util_Divide3232_Scale( weightedDirectionSmoothness, L_add( sumWeight, EPSILON_FX ), &exp ); + smoothedDirectionSmoothness = L_shl_sat( L_deposit_l( tmp ), add( sub( Q31, Q15 ), exp ) ); // Q31 + + h_dirac_output_synthesis_state->direction_smoothness_prev_fx[l] = smoothedDirectionSmoothness; // Q31 + move32(); + h_dirac_output_synthesis_state->reference_power_smooth_prev_fx[l] = sumWeight; // q_reference_power_smooth + move32(); + + /* Determine smoothing parameter for rendering. The smoother the directions, the less smoothing is required (i.e., faster smoothing can be used). */ + alpha[l] = + L_add( Mpy_32_16_1( smoothedDirectionSmoothness, alpha_synthesis_fast[indexFast] ), + Mpy_32_16_1( L_sub( ONE_IN_Q31, smoothedDirectionSmoothness ), alpha_synthesis[indexSlow] ) ); //(Q31, Q15) -> Q31 + move32(); + + /* Adjust smoothing parameter based on encoding quality */ + alpha[l] = + L_add( Mpy_32_32( qualityBasedSmFactor, alpha[l] ), + Mpy_32_32( L_sub( ONE_IN_Q31, qualityBasedSmFactor ), alpha_quality_based ) ); //(Q31, Q31) -> Q31 + move32(); + } + + /*-----------------------------------------------------------------* + * compute gains + *-----------------------------------------------------------------*/ + + /*Direct normalization gains on reduced number of protos*/ + p_power_smooth_prev = h_dirac_output_synthesis_state->proto_power_smooth_prev_fx; + p_power_smooth = h_dirac_output_synthesis_state->proto_power_smooth_fx; + set16_fx( exp_arr, 0, i_mult( num_protos_dir, num_freq_bands ) ); + + FOR( k = 0; k < num_protos_dir; k++ ) + { + FOR( l = 0; l < num_freq_bands; l++ ) + { + g1 = alpha[l]; // Q31 + g2 = L_sub( ONE_IN_Q31, g1 ); // Q31 + *p_power_smooth_prev = L_add( EPSILON_FX, Mpy_32_32( g2, ( *p_power_smooth_prev ) ) ); //(Q31, q_proto_power_smooth) -> q_proto_power_smooth + move32(); + *( p_power_smooth_prev ) = L_add( *( p_power_smooth_prev ), Mpy_32_32( g1, ( *p_power_smooth ) ) ); //(Q31, q_proto_power_smooth) -> q_proto_power_smooth + move32(); + + IF( EQ_32( *( p_power_smooth_prev ), EPSILON_FX ) ) + { + p_power_smooth_prev++; + L_tmp = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q31, 4612, &exp ); // 1e-15 in Q62 is 4612 + exp_arr[add( i_mult( k, num_freq_bands ), l )] = exp; + move16(); + + *( p_power_smooth++ ) = L_tmp; + move32(); + } + ELSE + { + L_tmp = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q31, *( p_power_smooth_prev++ ), &exp ); + exp_arr[add( i_mult( k, num_freq_bands ), l )] = exp; + move16(); + + *( p_power_smooth++ ) = L_tmp; + move32(); + } + } + } + + // Move proto_power_smooth_fx to common Q-factor + min_exp = 0; + move16(); + q_tmp = Q31; + move16(); + + FOR( k = 0; k < num_protos_dir; k++ ) + { + FOR( l = 0; l < num_freq_bands; l++ ) + { + IF( GT_16( exp_arr[add( i_mult( k, num_freq_bands ), l )], min_exp ) ) + { + min_exp = exp_arr[add( i_mult( k, num_freq_bands ), l )]; + move16(); + } + } + } + + p_power_smooth_prev = h_dirac_output_synthesis_state->proto_power_smooth_prev_fx; + p_power_smooth = h_dirac_output_synthesis_state->proto_power_smooth_fx; + + FOR( k = 0; k < num_protos_dir; k++ ) + { + FOR( l = 0; l < num_freq_bands; l++ ) + { + *( p_power_smooth++ ) = L_shr( *p_power_smooth, sub( min_exp, exp_arr[add( i_mult( k, num_freq_bands ), l )] ) ); + move32(); + IF( EQ_32( *( p_power_smooth_prev ), EPSILON_FX ) ) + { + q_tmp = add( sub( Q31, min_exp ), sub( Q31, 62 ) ); + } + ELSE + { + q_tmp = add( sub( Q31, min_exp ), sub( Q31, h_dirac_output_synthesis_state->proto_power_smooth_q ) ); + } + } + } + + // Update the Q-factor + h_dirac_output_synthesis_state->proto_power_smooth_prev_q = h_dirac_output_synthesis_state->proto_power_smooth_q; + h_dirac_output_synthesis_state->proto_power_smooth_q = q_tmp; + + /*Direct gains and diffuse gains on number of output channels*/ + p_power_diff_smooth_prev = h_dirac_output_synthesis_state->proto_power_diff_smooth_prev_fx; + p_power_smooth_diff = h_dirac_output_synthesis_state->proto_power_diff_smooth_fx; + + p_gains_diff = gains_diff; + p_gains_dir = gains_dir; + + p_cy_auto_dir_smooth = h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx; + p_cy_auto_dir_smooth_prev = h_dirac_output_synthesis_state->cy_auto_dir_smooth_prev_fx; + q_com = s_min( h_dirac_output_synthesis_state->q_cy_auto_dir_smooth, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth_prev ); + scale_sig32( p_cy_auto_dir_smooth, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth ) ); + scale_sig32( p_cy_auto_dir_smooth_prev, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth_prev ) ); + h_dirac_output_synthesis_state->q_cy_auto_dir_smooth = h_dirac_output_synthesis_state->q_cy_auto_dir_smooth_prev = q_com; + + p_cy_cross_dir_smooth = h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx; + p_cy_cross_dir_smooth_prev = h_dirac_output_synthesis_state->cy_cross_dir_smooth_prev_fx; + q_com = s_min( h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth_prev ); + scale_sig32( p_cy_cross_dir_smooth, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth ) ); + scale_sig32( p_cy_cross_dir_smooth_prev, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth_prev ) ); + h_dirac_output_synthesis_state->q_cy_cross_dir_smooth = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth_prev = q_com; + + p_cy_auto_diff_smooth = h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx; + p_cy_auto_diff_smooth_prev = h_dirac_output_synthesis_state->cy_auto_diff_smooth_prev_fx; + q_com = s_min( h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev ); + scale_sig32( p_cy_auto_diff_smooth, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ) ); + scale_sig32( p_cy_auto_diff_smooth_prev, imult1616( nchan_out_woLFE, num_freq_bands ), sub( q_com, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev ) ); + h_dirac_output_synthesis_state->q_cy_auto_diff_smooth = h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev = q_com; + + FOR( k = 0; k < nchan_out_woLFE; k++ ) + { + Word32 power_smooth_temp; + p_power_smooth = h_dirac_output_synthesis_state->proto_power_smooth_fx + i_mult( proto_direct_index[k], num_freq_bands ); // q_proto_power_smooth + FOR( l = 0; l < h_dirac_output_synthesis_params->max_band_decorr; l++ ) + { + /*Direct*/ + g1 = alpha[l]; // Q31 + move32(); + g2 = L_sub( ONE_IN_Q31, g1 ); // Q31 + *( p_cy_auto_dir_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_auto_dir_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_auto_dir_smooth_prev ) ) ) ); // (Q31, q_cy_auto_dir_smooth_prev) -> q_cy_auto_dir_smooth_prev + move32(); + *( p_cy_cross_dir_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_cross_dir_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_cross_dir_smooth_prev ) ) ) ); // (Q31, q_cy_cross_dir_smooth_prev) -> q_cy_cross_dir_smooth_prev + move32(); + + power_smooth_temp = L_shl( *p_power_smooth, norm_l( *p_power_smooth ) ); + L_tmp = Mpy_32_32( power_smooth_temp, ( *( p_cy_auto_dir_smooth_prev++ ) ) ); // proto_power_smooth_q + norm_l( *p_power_smooth ) ) + q_cy_auto_dir_smooth_prev - 31 + exp = sub( Q31, sub( add( add( h_dirac_output_synthesis_state->proto_power_smooth_q, norm_l( *p_power_smooth ) ), + h_dirac_output_synthesis_state->q_cy_auto_dir_smooth_prev ), + Q31 ) ); + p_power_smooth++; + + *( p_gains_dir ) = Sqrt32( L_tmp, &exp ); // (Q31 - exp) + move32(); + *( p_gains_dir ) = L_shl_sat( *( p_gains_dir ), sub( h_dirac_output_synthesis_state->gains_dir_prev_q, sub( Q31, exp ) ) ); // gains_dir_prev_q + move32(); + + IF( LT_32( *( p_gains_dir ), 0 ) ) + { + *( p_gains_dir ) = 0; + move32(); + } + ELSE IF( GT_32( *( p_gains_dir ), (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_dir_prev_q ) ) ) ) + { + *( p_gains_dir ) = (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_dir_prev_q ) ); + move32(); + } + + IF( LT_32( *( p_cy_cross_dir_smooth_prev++ ), 0 ) ) + { + *( p_gains_dir ) = L_negate( *( p_gains_dir ) ); + } + p_gains_dir++; + + /*diffuse*/ + *p_power_diff_smooth_prev = L_add( L_add( Mpy_32_32( g1, ( *( p_power_smooth_diff++ ) ) ), + Mpy_32_32( g2, ( *( p_power_diff_smooth_prev ) ) ) ), + EPSILLON_FX ); // (Q31, q_power_diff_smooth_prev) -> q_power_diff_smooth_prev + *( p_cy_auto_diff_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_auto_diff_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_auto_diff_smooth_prev ) ) ) ); // (Q31, q_cy_auto_diff_smooth_prev) -> q_cy_auto_diff_smooth_prev + + exp = 0; + move16(); + L_tmp = BASOP_Util_Divide3232_Scale_cadence( *( p_cy_auto_diff_smooth_prev++ ), ( *( p_power_diff_smooth_prev++ ) ), &exp ); // (Q31 - exp) + (q_a - q_b) + exp = sub( Q31, add( sub( Q31, exp ), sub( h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev, h_dirac_output_synthesis_state->proto_power_diff_smooth_q ) ) ); + + *( p_gains_diff ) = Sqrt32( L_tmp, &exp ); // (31 - exp) + move32(); + *( p_gains_diff ) = L_shl_sat( *( p_gains_diff ), sub( h_dirac_output_synthesis_state->gains_diff_prev_q, sub( Q31, exp ) ) ); // gains_diff_prev_q + move32(); + + IF( LT_32( *( p_gains_diff ), 0 ) ) + { + *( p_gains_diff ) = 0; + move32(); + } + ELSE IF( GT_32( *( p_gains_diff ), (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_diff_prev_q ) ) ) ) + { + *( p_gains_diff ) = (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_diff_prev_q ) ); + move32(); + } + p_gains_diff++; + } + + /*Only direct prototype*/ + FOR( ; l < num_freq_bands; l++ ) + { + /*Direct*/ + g1 = alpha[l]; // Q31 + g2 = L_sub( ONE_IN_Q31, g1 ); // Q31 + *( p_cy_auto_dir_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_auto_dir_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_auto_dir_smooth_prev ) ) ) ); // (Q31, q_cy_auto_dir_smooth_prev) -> q_cy_auto_dir_smooth_prev + move32(); + *( p_cy_cross_dir_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_cross_dir_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_cross_dir_smooth_prev ) ) ) ); // (Q31, q_cy_cross_dir_smooth_prev) -> q_cy_cross_dir_smooth_prev + move32(); + + power_smooth_temp = L_shl( *p_power_smooth, norm_l( *p_power_smooth ) ); + L_tmp = Mpy_32_32( power_smooth_temp, ( *( p_cy_auto_dir_smooth_prev++ ) ) ); // proto_power_smooth_q + norm_l( *p_power_smooth ) ) + q_cy_auto_dir_smooth_prev - 31 + exp = sub( Q31, sub( add( add( h_dirac_output_synthesis_state->proto_power_smooth_q, norm_l( *p_power_smooth ) ), + h_dirac_output_synthesis_state->q_cy_auto_dir_smooth_prev ), + Q31 ) ); + + *( p_gains_dir ) = Sqrt32( L_tmp, &exp ); // (Q31 - exp) + move32(); + *( p_gains_dir ) = L_shl_sat( *( p_gains_dir ), sub( h_dirac_output_synthesis_state->gains_dir_prev_q, sub( Q31, exp ) ) ); // gains_dir_prev_q + move32(); + + IF( LT_32( *( p_gains_dir ), 0 ) ) + { + *( p_gains_dir ) = 0; + move32(); + } + ELSE IF( GT_32( *( p_gains_dir ), (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_dir_prev_q ) ) ) ) + { + *( p_gains_dir ) = (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_dir_prev_q ) ); + move32(); + } + + IF( LT_32( *( p_cy_cross_dir_smooth_prev++ ), 0 ) ) + { + *( p_gains_dir ) = L_negate( *( p_gains_dir ) ); + } + p_gains_dir++; + + /*diffuse*/ + *( p_cy_auto_diff_smooth_prev ) = L_add( Mpy_32_32( g1, ( *( p_cy_auto_diff_smooth++ ) ) ), + Mpy_32_32( g2, ( *( p_cy_auto_diff_smooth_prev ) ) ) ); // (Q31, q_cy_auto_diff_smooth_prev) -> q_cy_auto_diff_smooth_prev + move32(); + + power_smooth_temp = L_shl( *p_power_smooth, norm_l( *p_power_smooth ) ); + L_tmp = Mpy_32_32( power_smooth_temp, ( *( p_cy_auto_diff_smooth_prev++ ) ) ); // proto_power_smooth_q + norm_l( *p_power_smooth ) ) + q_cy_auto_diff_smooth_prev - 31 + exp = sub( Q31, sub( add( add( h_dirac_output_synthesis_state->proto_power_smooth_q, norm_l( *p_power_smooth ) ), + h_dirac_output_synthesis_state->q_cy_auto_diff_smooth_prev ), + Q31 ) ); + p_power_smooth++; + + *( p_gains_diff ) = Sqrt32( L_tmp, &exp ); + move32(); + *( p_gains_diff ) = L_shl_sat( *( p_gains_diff ), sub( h_dirac_output_synthesis_state->gains_diff_prev_q, sub( Q31, exp ) ) ); // gains_diff_prev_q + move32(); + + IF( LT_32( *( p_gains_diff ), 0 ) ) + { + *( p_gains_diff ) = 0; + move32(); + } + ELSE IF( GT_32( *( p_gains_diff ), (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_diff_prev_q ) ) ) ) + { + *( p_gains_diff ) = (Word32) ( DIRAC_GAIN_LIMIT * L_shl( 1U, h_dirac_output_synthesis_state->gains_diff_prev_q ) ); + move32(); + } + p_gains_diff++; + } + } + + /*-----------------------------------------------------------------* + * gain interpolation and output streams + *-----------------------------------------------------------------*/ + + FOR( buf_idx = 0; buf_idx < nbslots; ++buf_idx ) + { + g1 = L_deposit_h( h_dirac_output_synthesis_params->interpolator_fx[buf_idx] ); // Q15 -> Q31 + g2 = L_sub( ONE_IN_Q31, g1 ); // Q31 + + /*Direct stream*/ + p_gain_1 = gains_dir; + p_gain_2 = h_dirac_output_synthesis_state->gains_dir_prev_fx; // gains_dir_prev_q + FOR( k = 0; k < nchan_out_woLFE; k++ ) + { + p_power_smooth = h_dirac_output_synthesis_state->proto_direct_buffer_f_fx + + shl( i_mult( buf_idx, i_mult( num_freq_bands, num_protos_dir ) ), Q1 ) + + shl( i_mult( proto_direct_index[k], num_freq_bands ), Q1 ); + FOR( l = 0; l < num_freq_bands; l++ ) + { + g = L_add( Mpy_32_32( g1, *( p_gain_1++ ) ), Mpy_32_32( g2, *( p_gain_2++ ) ) ); // (Q31, gains_dir_prev_q) -> gains_dir_prev_q + RealBuffer[k][buf_idx][l] = Mpy_32_32( g, ( *( p_power_smooth++ ) ) ); // (gains_dir_prev_q, q_proto_direct_buffer) -> gains_dir_prev_q + q_proto_direct_buffer - 31 + move32(); + ImagBuffer[k][buf_idx][l] = Mpy_32_32( g, ( *( p_power_smooth++ ) ) ); // (gains_dir_prev_q, q_proto_direct_buffer) -> gains_dir_prev_q + q_proto_direct_buffer - 31 + move32(); + } + } + + /*Diffuse stream*/ + IF( NE_16( h_dirac_output_synthesis_params->max_band_decorr, 0 ) ) + { + p_power_smooth_diff = h_dirac_output_synthesis_state->proto_diffuse_buffer_f_fx + + shl( i_mult( buf_idx, i_mult( h_dirac_output_synthesis_params->max_band_decorr, nchan_out_woLFE ) ), Q1 ); + } + p_gain_1 = gains_diff; + p_gain_2 = h_dirac_output_synthesis_state->gains_diff_prev_fx; // gains_diff_prev_q + FOR( k = 0; k < nchan_out_woLFE; k++ ) + { + FOR( l = 0; l < h_dirac_output_synthesis_params->max_band_decorr; l++ ) + { + g = L_add( Mpy_32_32( g1, *( p_gain_1++ ) ), Mpy_32_32( g2, *( p_gain_2++ ) ) ); // (Q31, gains_diff_prev_q) -> gains_diff_prev_q + RealBuffer[k][buf_idx][l] = L_add( L_shr( RealBuffer[k][buf_idx][l], Q1 ), + L_shr( Mpy_32_32( g, ( *( p_power_smooth_diff++ ) ) ), Q1 ) ); // (gains_diff_prev_q, q_proto_direct_buffer) >> Q1 -> gains_diff_prev_q + q_proto_direct_buffer - 32 + move32(); + ImagBuffer[k][buf_idx][l] = L_add( L_shr( ImagBuffer[k][buf_idx][l], Q1 ), + L_shr( Mpy_32_32( g, ( *( p_power_smooth_diff++ ) ) ), Q1 ) ); // (gains_diff_prev_q, q_proto_direct_buffer) >> Q1 -> gains_diff_prev_q + q_proto_direct_buffer - 32 + move32(); + } + + /*Direct proto*/ + p_power_smooth = h_dirac_output_synthesis_state->proto_direct_buffer_f_fx + + shl( i_mult( buf_idx, i_mult( num_freq_bands, num_protos_dir ) ), Q1 ) + + shl( i_mult( proto_direct_index[k], num_freq_bands ), Q1 ) + + shl( h_dirac_output_synthesis_params->max_band_decorr, Q1 ); + FOR( ; l < num_freq_bands; l++ ) + { + g = L_add( Mpy_32_32( g1, *( p_gain_1++ ) ), Mpy_32_32( g2, *( p_gain_2++ ) ) ); // (Q31, gains_diff_prev_q) -> gains_diff_prev_q + RealBuffer[k][buf_idx][l] = L_add( L_shr( RealBuffer[k][buf_idx][l], Q1 ), + L_shr( Mpy_32_32( g, ( *( p_power_smooth++ ) ) ), Q1 ) ); // (gains_diff_prev_q, q_proto_direct_buffer) >> Q1 -> gains_diff_prev_q + q_proto_direct_buffer - 32 + move32(); + ImagBuffer[k][buf_idx][l] = L_add( L_shr( ImagBuffer[k][buf_idx][l], Q1 ), + L_shr( Mpy_32_32( g, ( *( p_power_smooth++ ) ) ), Q1 ) ); // (gains_diff_prev_q, q_proto_direct_buffer) >> Q1 -> gains_diff_prev_q + q_proto_direct_buffer - 32 + move32(); + } + } + } + *q_Cldfb = sub( sub( add( h_dirac_output_synthesis_state->proto_direct_buffer_f_q, h_dirac_output_synthesis_state->gains_dir_prev_q ), Q31 ), Q1 ); + + /*-----------------------------------------------------------------* + * update buffers + *-----------------------------------------------------------------*/ + + /* store estimates for next synthesis block */ + mvl2l( gains_dir, h_dirac_output_synthesis_state->gains_dir_prev_fx, num_freq_bands * nchan_out_woLFE ); + mvl2l( gains_diff, h_dirac_output_synthesis_state->gains_diff_prev_fx, num_freq_bands * nchan_out_woLFE ); + + /* reset values */ + set_zero_fx( h_dirac_output_synthesis_state->proto_power_smooth_fx, num_freq_bands * num_protos_dir ); + IF( h_dirac_output_synthesis_state->proto_power_diff_smooth_fx != NULL ) + { + set_zero_fx( h_dirac_output_synthesis_state->proto_power_diff_smooth_fx, h_dirac_output_synthesis_params->max_band_decorr * nchan_out_woLFE ); + } + + set_zero_fx( h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx, num_freq_bands * nchan_out_woLFE ); + set_zero_fx( h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx, num_freq_bands * nchan_out_woLFE ); + set_zero_fx( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, num_freq_bands * nchan_out_woLFE ); + + pop_wmops(); + + return; +} +#endif + + /*------------------------------------------------------------------------- * ivas_dirac_dec_output_synthesis_process_subframe_psd_ls() * @@ -5523,10 +6142,13 @@ static void computeTargetPSDs_direct_subframe_fx( const Word16 num_freq_bands, const Word32 *direct_power_factor, const Word32 *reference_power, + const Word16 *q_reference_power, const Word32 *direct_responses, const Word32 *direct_responses_square, Word32 *cy_auto_dir_smooth, - Word32 *cy_cross_dir_smooth ) + Word16 *q_cy_auto_dir_smooth, + Word32 *cy_cross_dir_smooth, + Word16 *q_cy_cross_dir_smooth ) { Word16 ch_idx, cur_idx; @@ -5534,17 +6156,22 @@ static void computeTargetPSDs_direct_subframe_fx( Word32 direct_power[CLDFB_NO_CHANNELS_MAX]; /* size: num_freq_bands. */ /* estimate direct and diffuse power */ - v_mult_fixed( direct_power_factor, reference_power, direct_power, num_freq_bands ); + v_mult_fixed( direct_power_factor, reference_power, direct_power, num_freq_bands ); // (Q31, q_reference_power) -> q_reference_power /* compute target auto and cross PSDs of current frame (smoothed) */ FOR( ch_idx = 0; ch_idx < num_channels; ++ch_idx ) { cur_idx = imult1616( ch_idx, num_freq_bands ); - v_mult_fixed( direct_power, &direct_responses_square[cur_idx], &cy_auto_dir_smooth[cur_idx], num_freq_bands ); - v_mult_fixed( direct_power, &direct_responses[cur_idx], &cy_cross_dir_smooth[cur_idx], num_freq_bands ); + v_mult_fixed( direct_power, &direct_responses_square[cur_idx], &cy_auto_dir_smooth[cur_idx], num_freq_bands ); // (q_reference_power, Q31) -> q_reference_power + v_mult_fixed( direct_power, &direct_responses[cur_idx], &cy_cross_dir_smooth[cur_idx], num_freq_bands ); // (q_reference_power, Q31) -> q_reference_power } + *q_cy_auto_dir_smooth = *q_reference_power; + move16(); + *q_cy_cross_dir_smooth = *q_reference_power; + move16(); + return; } #endif @@ -5607,7 +6234,7 @@ static void computeTargetPSDs_diffuse_fx( { cur_idx = imult1616( ch_idx, num_freq_bands ); - v_multc_fixed( &diffuse_power[start_band], diffuse_responses_square[ch_idx], aux_buffer_res, num_freq_bands - start_band ); // (q_cy_auto_diff_smooth, Q31) -> q_cy_auto_diff_smooth + v_multc_fixed( &diffuse_power[start_band], diffuse_responses_square[ch_idx], aux_buffer_res, num_freq_bands - start_band ); // (q_reference_power, Q31) -> q_reference_power Scale_sig32( aux_buffer_res, num_freq_bands - start_band, sub( *q_cy_auto_diff_smooth, *q_reference_power ) ); // q_cy_auto_diff_smooth Scale_sig32( &cy_auto_diff_smooth[cur_idx], start_band, negate( Q1 ) ); // (q_cy_auto_diff_smooth - Q1) v_add_fixed( &cy_auto_diff_smooth[cur_idx + start_band], aux_buffer_res, &cy_auto_diff_smooth[cur_idx + start_band], num_freq_bands - start_band, Q1 ); // (q_cy_auto_diff_smooth - Q1) @@ -5659,23 +6286,28 @@ static void computeTargetPSDs_diffuse_subframe_fx( const Word16 start_band, const Word32 *diffuse_power_factor, const Word32 *reference_power, + const Word16 *q_reference_power, const Word32 *diffuse_responses_square, - Word32 *cy_auto_diff_smooth ) + Word32 *cy_auto_diff_smooth, + Word16 *q_cy_auto_diff_smooth ) { Word16 ch_idx, cur_idx; Word32 diffuse_power[CLDFB_NO_CHANNELS_MAX]; /* segment auxiliary buffer; size: num_freq_bands. */ /* estimate direct and diffuse power */ - v_mult_fixed( diffuse_power_factor, reference_power, diffuse_power, num_freq_bands ); + v_mult_fixed( diffuse_power_factor, reference_power, diffuse_power, num_freq_bands ); // (Q31, q_reference_power) -> q_reference_power /* compute target auto and cross PSDs of current frame (smoothed) */ FOR( ch_idx = 0; ch_idx < num_channels; ++ch_idx ) { cur_idx = imult1616( ch_idx, num_freq_bands ); - v_multc_fixed( &diffuse_power[start_band], diffuse_responses_square[ch_idx], &cy_auto_diff_smooth[cur_idx + start_band], num_freq_bands - start_band ); + v_multc_fixed( &diffuse_power[start_band], diffuse_responses_square[ch_idx], &cy_auto_diff_smooth[cur_idx + start_band], num_freq_bands - start_band ); // (q_reference_power, Q31) -> q_reference_power } + *q_cy_auto_diff_smooth = *q_reference_power; + move16(); + return; } #endif diff --git a/lib_rend/ivas_dirac_rend.c b/lib_rend/ivas_dirac_rend.c index 3e2acd87330ba30d4dea6f838e0a87fd79d92f18..10c54d1fe2d0e89d96e41d16f8a5c88fbe628a43 100644 --- a/lib_rend/ivas_dirac_rend.c +++ b/lib_rend/ivas_dirac_rend.c @@ -1513,6 +1513,13 @@ 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->proto_power_smooth, size ); +#ifdef IVAS_FLOAT_FIXED + if ( ( hDirAC_mem->proto_power_smooth_fx = (Word32 *) malloc( sizeof( Word32 ) * size ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); + } + set_zero_fx( hDirAC_mem->proto_power_smooth_fx, size ); +#endif if ( ( hDirAC_mem->proto_power_diff_smooth = (float *) malloc( sizeof( float ) * size ) ) == NULL ) { @@ -1524,7 +1531,7 @@ ivas_error ivas_dirac_alloc_mem( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate stack memory for DirAC\n" ) ); } - set32_fx( hDirAC_mem->proto_power_diff_smooth_fx, 0, size ); + set_zero_fx( hDirAC_mem->proto_power_diff_smooth_fx, size ); hDirAC_mem->proto_power_diff_smooth_len = size; hDirAC_mem->proto_power_diff_smooth_q = 31; #endif @@ -3514,7 +3521,7 @@ void protoSignalComputation2_fx( temp = BASOP_Util_Log2( temp ); IF( NE_32( temp, MIN_32 ) ) { - temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), INV_LOG10_2_Q31 ); // Q25 + temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), LOG10_2_Q31 ); // Q25 } // 20480 = 10 in Q11 lr_total_bb_ratio_fx = Mpy_32_16_1( temp, 20480 ); // Q21 @@ -3572,7 +3579,7 @@ void protoSignalComputation2_fx( temp = BASOP_Util_Log2( temp ); IF( NE_32( temp, MIN_32 ) ) { - temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), INV_LOG10_2_Q31 ); // Q25 + temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), LOG10_2_Q31 ); // Q25 } // 20480 = 10 in Q11 lr_total_hi_ratio_fx = Mpy_32_16_1( temp, 20480 ); // Q21 @@ -3582,7 +3589,7 @@ void protoSignalComputation2_fx( temp = BASOP_Util_Log2( min_sum_total_ratio_fx ); IF( NE_32( temp, MIN_32 ) ) { - temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), INV_LOG10_2_Q31 ); // Q25 + temp = Mpy_32_32( L_add( L_shl( exp, Q25 ), temp ), LOG10_2_Q31 ); // Q25 } // 20480 = 10 in Q11 min_sum_total_ratio_db_fx = Mpy_32_16_1( temp, 20480 ); // Q21 diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c index 0cbdbdb7fd5076b9310b7e65d3bed3df84dc99c7..42e7d9509a599036bc6732a19749624fe2a13d59 100644 --- a/lib_rend/ivas_orient_trk.c +++ b/lib_rend/ivas_orient_trk.c @@ -1208,7 +1208,7 @@ ivas_error ivas_orient_trk_SetReferenceVector_fx( Word16 q_min = s_min( listenerPos.q_fact, refPos.q_fact ); refPosLevel.x_fx = L_shr( refPosLevel.x_fx, sub( refPos.q_fact, q_min ) ); refPosLevel.y_fx = L_shr( refPosLevel.y_fx, sub( refPos.q_fact, q_min ) ); - refPosLevel.z_fx = L_shr( refPosLevel.z_fx, sub( listenerPos.q_fact, q_min ) ); + refPosLevel.z_fx = L_shr( refPosLevel.z_fx, sub( refPos.q_fact, q_min ) ); refPosLevel.q_fact = q_min; acousticFrontVector = VectorSubtract_fx( listenerPosLevel, refPosLevel ); @@ -1217,7 +1217,9 @@ ivas_error ivas_orient_trk_SetReferenceVector_fx( return IVAS_ERR_WRONG_PARAMS; } + Word16 accoustic_q = acousticFrontVector.q_fact; acousticFrontVectorLength = VectorLength_fx( acousticFrontVector, &acousticFrontVector.q_fact ); + acousticFrontVector.q_fact = accoustic_q; /* if the length is zero, the user has entered insensible listener and reference positions */ IF( LE_32( acousticFrontVectorLength, 0 ) ) { diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index ec03c0ead90e9de4c6eaf689c6e06bec02bb9823..bc6836520ed76e507e354a34265e4c86ec38c640 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -882,6 +882,22 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( const int16_t dec_param_estim /* i : flag to indicate parameter estimation mode */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls_fx( + Word32 RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + Word32 ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const Word16 nbslots, /* i : number of slots to process */ + Word32 *diffuseness_vector, /* i : diffuseness (needed for direction smoothing)*/ + Word32 *reference_power_smooth, + Word16 *q_reference_power_smooth, + Word32 qualityBasedSmFactor, + const Word16 enc_param_start_band, + Word16 *q_Cldfb +); +#endif + void ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( float RealBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ float ImagBuffer[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],/* i : LS signals */ @@ -1724,13 +1740,13 @@ void ivas_binaural_reverb_processSubframe_fx( #endif #ifdef IVAS_FLOAT_FIXED -ivas_error ivas_reverb_open( +ivas_error ivas_reverb_open_fx( REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ const Word32 *lr_energy_and_iac_fx[], /* i : precomuputed lr energies and iac */ RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */ - const int32_t output_Fs /* i : output sampling rate */ + const Word32 output_Fs /* i : output sampling rate */ ); #else ivas_error ivas_reverb_open( diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index d9500910162510d5768b41eec807ff7067199a30..be4a8c0632f5d8c387ea186d0903455e3b6b0e92 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -52,13 +52,13 @@ static Word16 wrap_rad_fixed( { Word32 L_tmp = angle; /* Wrap azimuth value */ - while(L_tmp > EVS_PI_FX ) + WHILE( GT_32( L_tmp, EVS_PI_FX ) ) { - L_tmp -= EVS_2PI_FX; + L_tmp = L_sub( L_tmp, EVS_2PI_FX ); } - while (L_tmp <= -EVS_PI_FX) + WHILE( LE_32( L_tmp, -EVS_PI_FX ) ) { - L_tmp += EVS_2PI_FX; + L_tmp = L_add( L_tmp, EVS_2PI_FX ); } return extract_l(L_tmp); @@ -130,15 +130,15 @@ typedef struct ivas_reverb_params_t /* Currently this is fixed to 2. */ /* Mix [S][L] matrix from feedback loops to outputs. */ Word16 pLoop_extract_matrix_fx[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. */ Word16 t60_filter_order; /* Filter order (length of vector) */ - float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Filters [][] in feedback loops, controlling T60. */ + //float pT60_filter_coeff[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Filters [][] in feedback loops, controlling T60. */ #ifdef IVAS_FLOAT_FIXED Word16 pT60_filter_coeff_fx[MAX_NR_OUTPUTS * IVAS_REV_MAX_NR_BRANCHES * IVAS_REV_MAX_IIR_FILTER_LENGTH]; #endif /* 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 */ + //float *pFc; /* Center frequencies for FFT filter design */ + //float *pRt60; /* RT60 values at these frequencies */ + //float *pDsr; /* DSR values at these frequencies */ #ifdef IVAS_FLOAT_FIXED Word32 *pFc_fx; /* Center frequencies for FFT filter design */ Word32 *pRt60_fx; /* RT60 values at these frequencies */ @@ -146,12 +146,12 @@ typedef struct ivas_reverb_params_t Word32 *pDsr_fx; /* DSR values at these frequencies */ Word16 *pDsr_e; /* DSR values at these frequencies */ #endif - 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 */ - 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 */ + // 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 */ #ifdef IVAS_FLOAT_FIXED Word32 *pHrtf_avg_pwr_response_l_fx; /* The HRTF set's average left ear power response */ @@ -392,7 +392,7 @@ static void ivas_binaural_reverb_setReverbTimes_fx( const Word32 *revEnes_fx /* i : spectrum for reverberated sound at each CLDFB bin */ ) { - int16_t bin, ch, tap, sample; + Word16 bin, ch, tap, sample; Word32 binCenterFreq_fx, diffuseFieldICC_fx, tmpVal_fx, attenuationFactorPerSample_fx, L_tmp; Word32 intendedEnergy_fx, actualizedEnergy_fx, energyBuildup_fx, currentEnergy_fx, attenuationFactorPerSampleSq_fx; @@ -596,11 +596,11 @@ static ivas_error compute_feedback_matrix_fx( u = MATRIX_CONSTANT; pFeedbackMatrix[0] = u; - for ( x = 1; x < n; x += x ) + FOR( x = 1; x < n; x += x ) { - for ( i = 0; i < x; i++ ) + FOR( i = 0; i < x; i++ ) { - for ( j = 0; j < x; j++ ) + FOR( j = 0; j < x; j++ ) { pFeedbackMatrix[( i + x ) * n + j] = pFeedbackMatrix[i * n + j]; pFeedbackMatrix[i * n + j + x] = pFeedbackMatrix[i * n + j]; @@ -628,7 +628,7 @@ static void compute_2_out_extract_matrix_fx( Word16 i; ff = 1; - for ( i = 0; i < n; i++ ) + FOR( i = 0; i < n; i++ ) { pExtractMatrix[i] = 1; pExtractMatrix[i + n] = ff; @@ -744,7 +744,7 @@ static void compute_2_out_extract_matrix( * Set all jot reverb parameters that are independent of the input reverb configuration *-----------------------------------------------------------------------------------------*/ -static ivas_error set_base_config( +static ivas_error set_base_config_fx( ivas_reverb_params_t *pParams, const Word32 output_Fs ) { @@ -934,7 +934,7 @@ static void calc_predelay_fx( move16(); return; } -#endif +#else static void calc_predelay( ivas_reverb_params_t *pParams, float acoustic_predelay_sec, @@ -961,7 +961,7 @@ static void calc_predelay( return; } - +#endif /*-----------------------------------------------------------------------------------------* * Function compute_t60_coeffs() @@ -1039,7 +1039,7 @@ static ivas_error compute_t60_coeffs_fx( } len = ( pParams->t60_filter_order + 1 ) >> 1; /* == floor( (order+1) / 2) */ - for ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) + FOR ( loop_idx = 0; loop_idx < pParams->nr_loops; loop_idx++ ) { pParams->pLoop_delays[loop_idx] -= len; } @@ -1171,7 +1171,7 @@ static void calc_low_shelf_first_order_filter_fx( Word16 gain_fx; gain_fx = BASOP_Util_Divide1616_Scale(lin_gain_lf, lin_gain_hf, &gain_exp); - IF ( gain_fx < 16384) + IF( LT_16( gain_fx, 16384 ) ) { tmp = mult(tan_val, gain_fx); @@ -1376,12 +1376,12 @@ static ivas_error calc_jot_t60_coeffs_fx( FOR ( f_idx = 0; f_idx < nrFrequencies; f_idx++ ) { - IF ( ( pFrequencies_fx[f_idx] >= ref_lf_min_norm_fx ) && ( pFrequencies_fx[f_idx] <= ref_lf_max_norm_fx ) ) + IF( GE_16( pFrequencies_fx[f_idx], ref_lf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_lf_max_norm_fx ) ) { L_tmpl = L_add( L_tmpl, pH_dB_fx[f_idx] ); n_points_lf++; } - IF ( ( pFrequencies_fx[f_idx] >= ref_hf_min_norm_fx ) && ( pFrequencies_fx[f_idx] <= ref_hf_max_norm_fx ) ) + IF( GE_16( pFrequencies_fx[f_idx], ref_hf_min_norm_fx ) && LE_16( pFrequencies_fx[f_idx], ref_hf_max_norm_fx ) ) { L_tmph = L_add(L_tmph, pH_dB_fx[f_idx]); n_points_hf++; @@ -1421,7 +1421,7 @@ static ivas_error calc_jot_t60_coeffs_fx( tmp_fx = BASOP_Util_Cmp_Mant32Exp(L_deposit_h(tmp1), e, minval_fx, minval_e); - IF (tmp_fx == -1) + IF( EQ_16( tmp_fx, -1 ) ) { minval_fx = L_deposit_h(tmp1); minval_e = e; @@ -1450,7 +1450,43 @@ static ivas_error calc_jot_t60_coeffs_fx( * * Set the number of branches (feedback loops) and Initializes the memory structure (pointers to data) *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static ivas_error initialize_reverb_filters_fx( + REVERB_HANDLE hReverb ) +{ + ivas_error error; + + error = IVAS_ERR_OK; + + /* init correlation and coloration filters */ + IF( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_0, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_correl_1, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_0, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_reverb_fft_filter_init( &hReverb->fft_filter_color_1, hReverb->fft_size ) ) != IVAS_ERR_OK ) + { + return error; + } + return error; +} +#else static ivas_error initialize_reverb_filters( REVERB_HANDLE hReverb ) { @@ -1486,7 +1522,7 @@ static ivas_error initialize_reverb_filters( return error; } - +#endif /*-----------------------------------------------------------------------------------------* * Function set_t60_filter() @@ -1547,12 +1583,12 @@ static ivas_error set_t60_filter( * Sets Delay of feedback branch in number of samples *-----------------------------------------------------------------------------------------*/ -static ivas_error set_feedback_delay( +static ivas_error set_feedback_delay_fx( REVERB_HANDLE hReverb, const UWord16 branch, const Word16 fb_delay ) { - if ( branch >= hReverb->nr_of_branches ) + IF( branch >= hReverb->nr_of_branches ) { return IVAS_ERR_INTERNAL; } @@ -1596,12 +1632,12 @@ static ivas_error set_feedback_gain_fx( const Word32 *pGain ) { UWord16 gain_idx; - if ( branch >= hReverb->nr_of_branches ) + IF( branch >= hReverb->nr_of_branches ) { return IVAS_ERR_INTERNAL; } - for ( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ ) + FOR( gain_idx = 0; gain_idx < hReverb->nr_of_branches; gain_idx++ ) { hReverb->gain_matrix_fx[branch][gain_idx] = pGain[gain_idx]; } @@ -1614,7 +1650,7 @@ static ivas_error set_feedback_gain_fx( * Sets correlation filter complex gains *-----------------------------------------------------------------------------------------*/ -static ivas_error set_correl_fft_filter( +static ivas_error set_correl_fft_filter_fx( REVERB_HANDLE hReverb, const UWord16 channel, rv_fftwf_type_complex_fx *pSpectrum ) @@ -1643,7 +1679,7 @@ static ivas_error set_correl_fft_filter( * Sets coloration filter complex gains *-----------------------------------------------------------------------------------------*/ -static ivas_error set_color_fft_filter( +static ivas_error set_color_fft_filter_fx( REVERB_HANDLE hReverb, const UWord16 channel, rv_fftwf_type_complex_fx *pSpectrum ) @@ -1657,7 +1693,7 @@ static ivas_error set_color_fft_filter( { ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_0.fft_spectrum_fx, hReverb->fft_filter_color_0.fft_size ); } - else + ELSE { ivas_reverb_fft_filter_ConvertFFTWF_2_FFTR_fx( pSpectrum, hReverb->fft_filter_color_1.fft_spectrum_fx, hReverb->fft_filter_color_1.fft_size ); } @@ -1751,7 +1787,7 @@ static ivas_error set_color_fft_filter( #ifdef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------------------------------* - * Function set_mixer_level() + * Function set_mixer_level_fx() * * Sets Mixer level: to mix 2 output channels from 8 feedback branches *-----------------------------------------------------------------------------------------*/ @@ -1762,12 +1798,12 @@ static ivas_error set_mixer_level_fx( const Word16 level[] ) { uint16_t branch_idx; - if ( channel >= BINAURAL_CHANNELS ) + IF ( channel >= BINAURAL_CHANNELS ) { return IVAS_ERR_INTERNAL; } - for ( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ ) + FOR ( branch_idx = 0; branch_idx < hReverb->nr_of_branches; branch_idx++ ) { hReverb->mixer_fx[channel][branch_idx] = level[branch_idx]; } @@ -1775,19 +1811,19 @@ static ivas_error set_mixer_level_fx( return IVAS_ERR_OK; } /*-----------------------------------------------------------------------------------------* - * Function clear_buffers() + * Function clear_buffers_fx() * * Clears buffers of delay lines and filters *-----------------------------------------------------------------------------------------*/ -static void clear_buffers( +static void clear_buffers_fx( REVERB_HANDLE hReverb ) { Word16 branch_idx; ivas_rev_iir_filter_t *iirFilter; ivas_rev_delay_line_t *delay_line; - for ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ ) + FOR ( branch_idx = 0; branch_idx < IVAS_REV_MAX_NR_BRANCHES; branch_idx++ ) { delay_line = &( hReverb->delay_line[branch_idx] ); set_val_Word32( delay_line->pBuffer_fx, 0, delay_line->MaxDelay ); @@ -1803,32 +1839,32 @@ static void clear_buffers( } /*-----------------------------------------------------------------------------------------* - * Function set_fft_and_datablock_sizes() + * Function set_fft_and_datablock_sizes_fx() * * Sets frame size and fft-filter related sizes *-----------------------------------------------------------------------------------------*/ -static void set_fft_and_datablock_sizes( +static void set_fft_and_datablock_sizes_fx( REVERB_HANDLE hReverb, const Word16 subframe_len ) { hReverb->full_block_size = subframe_len; - if ( subframe_len == L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES ) + IF( EQ_16( subframe_len, 240 /*L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) ) { hReverb->fft_size = IVAS_REVERB_FFT_SIZE_48K; hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_48K; } - else if ( subframe_len == L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES ) + ELSE IF( EQ_16( subframe_len, 160 /*L_FRAME32k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) ) { hReverb->fft_size = IVAS_REVERB_FFT_SIZE_32K; hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_32K; } - else if ( subframe_len == L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES ) + ELSE IF( EQ_16( subframe_len, 80 /*L_FRAME16k / MAX_PARAM_SPATIAL_SUBFRAMES*/ ) ) { hReverb->fft_size = IVAS_REVERB_FFT_SIZE_16K; hReverb->num_fft_subblocks = IVAS_REVERB_FFT_N_SUBBLOCKS_16K; } - else + ELSE { assert( 0 ); /* unsupported block size */ } @@ -1975,7 +2011,7 @@ static void set_reverb_acoustic_data_fx( move16(); FOR ( iter_idx = 0; iter_idx < hHrtf->num_iterations[hrtf_idx][nr_out_ch] - 1; iter_idx++ ) { - offset += hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][iter_idx]; + offset = add( offset, hHrtf->pIndex_frequency_max[hrtf_idx][nr_out_ch][iter_idx] ); } IF ( EQ_16( nr_out_ch, 0 ) ) @@ -2023,7 +2059,8 @@ static void set_reverb_acoustic_data_fx( // 23 in Q26 tmp_flag = BASOP_Util_Cmp_Mant32Exp(L_deposit_h(exp_argument_fx), exp_argument_e, 1543503872, 5 ); - IF(tmp_flag > 0) { + IF( GT_16( tmp_flag, 0 ) ) + { exp_argument_fx = 23552; move16(); exp_argument_e = 5; @@ -2031,9 +2068,11 @@ static void set_reverb_acoustic_data_fx( } tmp_flag = BASOP_Util_Cmp_Mant32Exp(L_deposit_h(exp_argument_fx), exp_argument_e, 0, 31); - IF(tmp_flag < 0) { + IF( LT_16( tmp_flag, 0 ) ) + { tmp_flag = BASOP_Util_Cmp_Mant32Exp(L_deposit_h(negate( exp_argument_fx) ), exp_argument_e, 1543503872, 5); - IF (tmp_flag < 0) { + IF( LT_16( tmp_flag, 0 ) ) + { exp_argument_fx = -23552; move16(); exp_argument_e = 5; @@ -2044,7 +2083,7 @@ static void set_reverb_acoustic_data_fx( Word16 tmp_exp; /* expf(exp_argument) -> pow(2, log2(e) * exp_argument) */ tmp = mult(23637, exp_argument_fx); // exp_argument_e + 1 - tmp_exp = exp_argument_e + 1; + tmp_exp = add( exp_argument_e, 1 ); L_tmp = BASOP_util_Pow2(L_deposit_h(tmp), tmp_exp, &pow_exp); L_tmp = Mpy_32_32( L_tmp, pDsr_fx[bin_idx] ); tmp_exp = tmp_exp + pDsr_e[bin_idx]; @@ -2136,12 +2175,12 @@ static void set_reverb_acoustic_data( #ifdef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------------------------------* - * Function setup_FDN_branches() + * Function setup_FDN_branches_fx() * * Sets up feedback delay network system *-----------------------------------------------------------------------------------------*/ -static ivas_error setup_FDN_branches( +static ivas_error setup_FDN_branches_fx( REVERB_HANDLE hReverb, ivas_reverb_params_t *pParams ) { @@ -2158,7 +2197,7 @@ static ivas_error setup_FDN_branches( hReverb->mixer_fx[0][branch_idx] = 0; hReverb->mixer_fx[1][branch_idx] = 0; } - clear_buffers( hReverb ); + clear_buffers_fx( hReverb ); nr_coefs = add(pParams->t60_filter_order , 1); IF ( LT_16(IVAS_REV_MAX_IIR_FILTER_LENGTH , nr_coefs) ) @@ -2177,7 +2216,7 @@ static ivas_error setup_FDN_branches( return error; } - IF ( ( error = set_feedback_delay( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ) != IVAS_ERR_OK ) + IF ( ( error = set_feedback_delay_fx( hReverb, branch_idx, pParams->pLoop_delays[branch_idx] ) ) != IVAS_ERR_OK ) { return error; } @@ -2265,18 +2304,18 @@ static ivas_error setup_FDN_branches( #endif #ifdef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- - * ivas_reverb_open() + * ivas_reverb_open_fx() * * Allocate and initialize Crend reverberation handle *------------------------------------------------------------------------*/ -ivas_error ivas_reverb_open( +ivas_error ivas_reverb_open_fx( REVERB_HANDLE *hReverb, /* i/o: Reverberator handle */ const AUDIO_CONFIG input_audio_config, /* i : reverb. input audio configuration */ const HRTFS_HANDLE hHrtf, /* i : HRTF handle */ const Word32 *lr_energy_and_iac_fx[], /* i : precomuputed lr energies and iac */ RENDER_CONFIG_HANDLE hRenderConfig, /* i : Renderer configuration handle */ - const int32_t output_Fs /* i : output sampling rate */ + const Word32 output_Fs /* i : output sampling rate */ ) { ivas_error error; @@ -2304,7 +2343,7 @@ ivas_error ivas_reverb_open( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Reverberator " ); } - IF ( ( error = set_base_config( ¶ms, output_Fs ) ) != IVAS_ERR_OK ) + IF ( ( error = set_base_config_fx( ¶ms, output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -2325,7 +2364,7 @@ ivas_error ivas_reverb_open( } pState->nr_of_branches = IVAS_REV_MAX_NR_BRANCHES; - set_fft_and_datablock_sizes( pState, subframe_len ); + set_fft_and_datablock_sizes_fx( pState, subframe_len ); nr_fc_fft_filter = add( extract_l( L_shr( pState->fft_size, 1 ) ), 1 ); /* === 'Control logic': compute the reverb processing parameters from the === */ @@ -2430,7 +2469,7 @@ ivas_error ivas_reverb_open( pState->do_corr_filter = params.do_corr_filter; /* clear & init jot reverb fft filters */ - IF ( ( error = initialize_reverb_filters( pState ) ) != IVAS_ERR_OK ) + IF ( ( error = initialize_reverb_filters_fx( pState ) ) != IVAS_ERR_OK ) { return error; } @@ -2471,12 +2510,12 @@ ivas_error ivas_reverb_open( pFft_wf_filter_ch1_fx[i][1] = L_shl( pFft_wf_filter_ch1_fx[i][1], 31 - q_pFft_wf_filter_ch1_fx ); } /* Copying the computed FFT correlation filters to the fft_filter components */ - IF ( ( error = set_correl_fft_filter( pState, 0, pFft_wf_filter_ch0_fx ) ) != IVAS_ERR_OK ) + IF ( ( error = set_correl_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ) != IVAS_ERR_OK ) { return error; } - IF ( ( error = set_correl_fft_filter( pState, 1, pFft_wf_filter_ch1_fx ) ) != IVAS_ERR_OK ) + IF ( ( error = set_correl_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ) != IVAS_ERR_OK ) { return error; } @@ -2500,12 +2539,12 @@ ivas_error ivas_reverb_open( Scale_sig32( params.pFc_fx, nr_fc_fft_filter, 17 ); /*Scaling ( *hReverb )->fft_filter_color_1.fft_spectrum_fx to Q31*/ /* Copying the computed FFT colorations filters to the fft_filter components */ - IF ( ( error = set_color_fft_filter( pState, 0, pFft_wf_filter_ch0_fx ) ) != IVAS_ERR_OK ) + IF ( ( error = set_color_fft_filter_fx( pState, 0, pFft_wf_filter_ch0_fx ) ) != IVAS_ERR_OK ) { return error; } - IF ( ( error = set_color_fft_filter( pState, 1, pFft_wf_filter_ch1_fx ) ) != IVAS_ERR_OK ) + IF ( ( error = set_color_fft_filter_fx( pState, 1, pFft_wf_filter_ch1_fx ) ) != IVAS_ERR_OK ) { return error; } @@ -2514,7 +2553,7 @@ ivas_error ivas_reverb_open( ivas_rev_delay_line_init( &( pState->predelay_line ), pState->pPredelay_buffer_fx, params.pre_delay, predelay_bf_len ); /* set up feedback delay network */ - IF ( ( error = setup_FDN_branches( pState, ¶ms ) ) != IVAS_ERR_OK ) + IF ( ( error = setup_FDN_branches_fx( pState, ¶ms ) ) != IVAS_ERR_OK ) { return error; } @@ -2803,14 +2842,14 @@ static void post_fft_filter_fx( Word32 *buffer_R_fx ) { - if ( hReverb->do_corr_filter ) + IF( hReverb->do_corr_filter ) { ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx ); ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_0, buffer_L_fx ); ivas_reverb_fft_filter_ComplexMul_fx( &hReverb->fft_filter_correl_1, buffer_R_fx ); ivas_reverb_fft_filter_CrossMix_fx( buffer_L_fx, buffer_R_fx, hReverb->fft_filter_correl_0.fft_size ); } - else + ELSE { ivas_reverb_t2f_f2t_in_fx( &hReverb->fft_filter_ols, input_L_fx, input_R_fx, buffer_L_fx, buffer_R_fx ); } @@ -2881,23 +2920,23 @@ static void reverb_block_fx( pFFT_buf[0] = &FFT_buf_1[0]; pFFT_buf[1] = &FFT_buf_2[0]; - for ( branch_idx = 0; branch_idx < nr_branches; branch_idx++ ) + FOR( branch_idx = 0; branch_idx < nr_branches; branch_idx++ ) { ppOutput_fx[branch_idx] = (Word32 *) Output_fx + branch_idx * inner_bsize; } - for ( k = 0; k < bsize; k += inner_bsize ) + FOR( k = 0; k < bsize; k += inner_bsize ) { Word32 *pO0 = &pOut0_fx[k]; Word32 *pO1 = &pOut1_fx[k]; - for ( i = 0; i < inner_bsize; i++ ) + FOR( i = 0; i < inner_bsize; i++ ) { pO0[i] = 0; pO1[i] = 0; } /* feedback network: */ - for ( i = 0; i < nr_branches; i++ ) + FOR( i = 0; i < nr_branches; i++ ) { Word32 *pOutput_i_fx = &ppOutput_fx[i][0]; Word16 mixer_0_i = hReverb->mixer_fx[0][i]; @@ -2905,27 +2944,27 @@ static void reverb_block_fx( /* output and feedback are same, get sample from delay line ... */ ivas_rev_delay_line_get_sample_blk_fx( &( hReverb->delay_line[i] ), inner_bsize, pTemp_fx ); ivas_reverb_iir_filt_2taps_feed_blk_fx( &( hReverb->t60[i] ), inner_bsize, pTemp_fx, ppOutput_fx[i] ); - for ( ns = 0; ns < inner_bsize; ns++ ) + FOR( ns = 0; ns < inner_bsize; ns++ ) { pO0[ns] = L_add( pOutput_i_fx[ns] * mixer_0_i, pO0[ns] ); /* mixer ch 0 */ pO1[ns] = L_add( pOutput_i_fx[ns] * mixer_1_i, pO1[ns] ); /* mixer ch 1 */ } } - for ( i = 0; i < nr_branches; i++ ) + FOR( i = 0; i < nr_branches; i++ ) { Word32 *pIn = &pInput_fx[k]; - for ( ns = 0; ns < inner_bsize; ns++ ) + FOR( ns = 0; ns < inner_bsize; ns++ ) { pFeedback_input_fx[ns] = pIn[ns] >> 3; // to make the Qfactor similar to pOutput } - for ( j = 0; j < nr_branches; j++ ) + FOR( j = 0; j < nr_branches; j++ ) { Word32 gain_matrix_j_i = hReverb->gain_matrix_fx[j][i]; Word32 *pOutput = &ppOutput_fx[j][0]; - for ( ns = 0; ns < inner_bsize; ns++ ) + FOR( ns = 0; ns < inner_bsize; ns++ ) { pFeedback_input_fx[ns] = ( L_add( Mpy_32_32( gain_matrix_j_i, pOutput[ns] ), pFeedback_input_fx[ns] ) ); } @@ -2938,13 +2977,13 @@ static void reverb_block_fx( Word16 r_shift; r_shift = find_guarded_bits_fx( hReverb->fft_filter_ols.fft_size ); // Applying guard bits for the DoRTFT inside the post_fft_filter function - for ( k = 0; k < hReverb->fft_filter_ols.block_size; k++ ) + FOR( k = 0; k < hReverb->fft_filter_ols.block_size; k++ ) { pOut0_fx[k] = (Word32) pOut0_fx[k] >> ( r_shift ); pOut1_fx[k] = (Word32) pOut1_fx[k] >> ( r_shift ); } /* Applying FFT filter to each sub-frame */ - for ( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ ) + FOR( blk_idx = 0; blk_idx < hReverb->num_fft_subblocks; blk_idx++ ) { start_sample_idx = blk_idx * hReverb->fft_subblock_size; post_fft_filter_fx( hReverb, pOut0_fx + start_sample_idx, pOut1_fx + start_sample_idx, pFFT_buf[0], pFFT_buf[1] ); @@ -3061,7 +3100,7 @@ static ivas_error downmix_input_block_fx( { Word16 i, s, nchan_transport; Word32 dmx_gain_fx = hReverb->dmx_gain_fx; - switch ( input_audio_config ) + SWITCH( input_audio_config ) { case IVAS_AUDIO_CONFIG_STEREO: case IVAS_AUDIO_CONFIG_5_1: @@ -3075,31 +3114,31 @@ static ivas_error downmix_input_block_fx( case IVAS_AUDIO_CONFIG_ISM4: { nchan_transport = audioCfg2channels( input_audio_config ); - for ( s = 0; s < hReverb->full_block_size; s++ ) + FOR( s = 0; s < hReverb->full_block_size; s++ ) { Word32 temp = pcm_in[0][input_offset + s]; - for ( i = 1; i < nchan_transport; i++ ) + FOR( i = 1; i < nchan_transport; i++ ) { temp = L_add( temp, pcm_in[i][input_offset + s] ); } pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( temp, 7 ) ) << 1; } - break; + BREAK; } case IVAS_AUDIO_CONFIG_MONO: /* ~'ZOA_1' */ case IVAS_AUDIO_CONFIG_FOA: case IVAS_AUDIO_CONFIG_HOA2: case IVAS_AUDIO_CONFIG_HOA3: { - for ( s = 0; s < hReverb->full_block_size; s++ ) + FOR( s = 0; s < hReverb->full_block_size; s++ ) { pPcm_out[s] = Mpy_32_32( dmx_gain_fx, L_shl_sat( pcm_in[0][input_offset + s], 8 ) ); } - break; + BREAK; } default: return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported input format for reverb" ); - break; + BREAK; } return IVAS_ERR_OK; @@ -3179,32 +3218,32 @@ static void predelay_block_fx( { UWord16 i, idx, n_samples, blk_size; UWord16 max_blk_size = (UWord16) hReverb->predelay_line.Delay; - if ( max_blk_size < 2 ) + IF( max_blk_size < 2 ) { - if ( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */ + IF( max_blk_size == 0 ) /* zero-length delay line: just copy the data from input to output */ { - for ( i = 0; i < hReverb->full_block_size; i++ ) + FOR( i = 0; i < hReverb->full_block_size; i++ ) { pOutput[i] = pInput[i]; } } - else /* 1-sample length delay line: feed the data sample-by-sample */ + ELSE /* 1-sample length delay line: feed the data sample-by-sample */ { - for ( i = 0; i < hReverb->full_block_size; i++ ) + FOR( i = 0; i < hReverb->full_block_size; i++ ) { pOutput[i] = ivas_rev_delay_line_get_sample_fx( &( hReverb->predelay_line ) ); ivas_rev_delay_line_feed_sample_fx( &( hReverb->predelay_line ), pInput[i] ); } } } - else /* multiple-sample length delay line: use block processing */ + ELSE /* multiple-sample length delay line: use block processing */ { idx = 0; n_samples = hReverb->full_block_size; - while ( n_samples > 0 ) + WHILE( n_samples > 0 ) { blk_size = n_samples; - if ( blk_size > max_blk_size ) + IF( blk_size > max_blk_size ) { blk_size = max_blk_size; } @@ -3287,7 +3326,7 @@ static void mix_output_block_fx( { UWord16 i; - for ( i = 0; i < hReverb->full_block_size; i++ ) + FOR( i = 0; i < hReverb->full_block_size; i++ ) { pOutL[i] = L_add( pInL[i], ( ( pOutL[i] ) >> 2 ) ); pOutR[i] = L_add( pInR[i], ( ( pOutR[i] ) >> 2 ) ); @@ -3339,7 +3378,7 @@ ivas_error ivas_reverb_process_fx( Word32 tmp0_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp1_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES], tmp2_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; ivas_error error; - if ( ( error = downmix_input_block_fx( hReverb, pcm_in_fx, input_audio_config, tmp1_fx, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK ) + IF( ( error = downmix_input_block_fx( hReverb, pcm_in_fx, input_audio_config, tmp1_fx, i_ts * hReverb->full_block_size ) ) != IVAS_ERR_OK ) { return error; } @@ -3348,11 +3387,11 @@ ivas_error ivas_reverb_process_fx( reverb_block_fx( hReverb, tmp0_fx, tmp1_fx, tmp2_fx ); - if ( mix_signals ) + IF( mix_signals ) { mix_output_block_fx( hReverb, tmp1_fx, tmp2_fx, &pcm_out_fx[0][i_ts * hReverb->full_block_size], &pcm_out_fx[1][i_ts * hReverb->full_block_size] ); } - else + ELSE { mvr2r_Word32( tmp1_fx, &pcm_out_fx[0][i_ts * hReverb->full_block_size], hReverb->full_block_size ); mvr2r_Word32( tmp2_fx, &pcm_out_fx[1][i_ts * hReverb->full_block_size], hReverb->full_block_size ); @@ -3744,6 +3783,120 @@ void ivas_binaural_reverb_processSubframe_fx( * * Allocate and initialize binaural room reverberator handle *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static ivas_error ivas_binaural_reverb_open_fx( + REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ + const Word16 numBins, /* i : number of CLDFB bins */ + const Word16 numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + const Word32 sampling_rate, /* i : sampling rate */ + const Word32 *revTimes_fx, /* i : reverberation times T60 for each CLDFB bin in seconds */ + const Word32 *revEnes_fx, /* i : spectrum for reverberated sound at each CLDFB bin */ + const Word16 preDelay /* i : reverb pre-delay in CLDFB slots */ +) +{ + int16_t bin, chIdx, k, len; + REVERB_STRUCT_HANDLE hReverb; + + if ( ( *hReverbPr = (REVERB_STRUCT_HANDLE) malloc( sizeof( REVERB_STRUCT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + hReverb = *hReverbPr; + + hReverb->useBinauralCoherence = 1; + hReverb->preDelayBufferLength = 1; + hReverb->preDelayBufferIndex = 0; + + hReverb->numBins = numBins; + hReverb->blockSize = numCldfbSlotsPerFrame; + + for ( k = 0; k < REVERB_PREDELAY_MAX + 1; k++ ) + { + set32_fx( hReverb->preDelayBufferReal_fx[k], 0, hReverb->numBins ); + set32_fx( hReverb->preDelayBufferImag_fx[k], 0, hReverb->numBins ); + } + + for ( bin = 0; bin < hReverb->numBins; bin++ ) + { + /* Loop Buffer */ + hReverb->loopBufLengthMax[bin] = (int16_t) ( 500 / ( 1 + bin ) + ( CLDFB_NO_CHANNELS_MAX - bin ) ); + + len = hReverb->loopBufLengthMax[bin] + hReverb->blockSize; + + if ( ( hReverb->loopBufReal_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->loopBufImag_fx[bin] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + set32_fx( hReverb->loopBufReal_fx[bin], 0, len ); + set32_fx( hReverb->loopBufImag_fx[bin], 0, len ); + + /* Determine loop buffer length. The following formula is manually tuned to generate sufficiently long + * but not excessively long loops to generate reverberation. */ + /* Note: the resulted length is very sensitive to the precision of the constants below (e.g. 1.45 vs. 1.45f) */ + //hReverb->loopBufLength[bin] = (int16_t) ( 1.45 * (int16_t) ( revTimes[bin] * 150.0 ) + 1 ); + Word32 L_tmp_BufLength = L_shl( L_shr( Mpy_32_32( revTimes_fx[bin], 1258291200 /*150.0 in Q23*/ ), 23 ), 23 ); + L_tmp_BufLength = L_add( Mpy_32_32( 1556925645 /*1.45 in Q30*/, L_tmp_BufLength ), ONE_IN_Q22 ); + hReverb->loopBufLength[bin] = (Word16) L_shr( L_tmp_BufLength, 22 ); + hReverb->loopBufLength[bin] = min( hReverb->loopBufLength[bin], hReverb->loopBufLengthMax[bin] ); + + /* Sparse Filter Tap Locations */ + for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + len = hReverb->loopBufLength[bin]; + + if ( ( hReverb->tapPhaseShiftType[bin][chIdx] = (int16_t *) malloc( len * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + set_s( hReverb->tapPhaseShiftType[bin][chIdx], 0, len ); + + if ( ( hReverb->tapPointersReal_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->tapPointersImag_fx[bin][chIdx] = (Word32 **) malloc( len * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + len = hReverb->blockSize; + if ( ( hReverb->outputBufferReal_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + + if ( ( hReverb->outputBufferImag_fx[bin][chIdx] = (Word32 *) malloc( len * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Reverberator\n" ) ); + } + set32_fx( hReverb->outputBufferReal_fx[bin][chIdx], 0, len ); + set32_fx( hReverb->outputBufferImag_fx[bin][chIdx], 0, len ); + } + } + + /*Word32 *revTimes_fx = (Word32 *)malloc(sizeof(Word32) * hReverb->numBins); + Word32 *revEnes_fx = (Word32 *)malloc(sizeof(Word32) * hReverb->numBins); + FOR(int i = 0; i < hReverb->numBins; i++) { + revTimes_fx[i] = (Word32)(revTimes[i] * ONE_IN_Q31); + revEnes_fx[i] = (Word32)(revEnes[i] * ONE_IN_Q31); + }*/ + ivas_binaural_reverb_setReverbTimes_fx( hReverb, sampling_rate, revTimes_fx, revEnes_fx ); + + /*free(revTimes_fx); + free(revEnes_fx);*/ + + ivas_binaural_reverb_setPreDelay_fx( hReverb, preDelay ); + + return IVAS_ERR_OK; +} +#endif static ivas_error ivas_binaural_reverb_open( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ @@ -3962,7 +4115,49 @@ ivas_error ivas_binaural_reverb_open_fastconv( * * Allocate and initialize binaural room reverberator handle for ParamBin *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_binaural_reverb_open_parambin( + REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ + const int16_t numBins, /* i : number of CLDFB bins */ + const int16_t numCldfbSlotsPerFrame, /* i : number of CLDFB slots per frame */ + IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */ + const int32_t sampling_rate, /* i : sampling rate */ + const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ +) +{ + ivas_error error; + const Word32 *revTimes; + const Word32 *revEne; + Word32 t60[CLDFB_NO_CHANNELS_MAX]; + Word32 ene[CLDFB_NO_CHANNELS_MAX]; + int16_t preDelay; + + error = IVAS_ERR_OK; + + if ( ( roomAcoustics != NULL ) && roomAcoustics->override ) + { + revTimes = t60; + revEne = ene; + /* Todo Philips: This needs a suitable function for ParamBin here. */ + // if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, internal_config, false, sampling_rate, t60, ene ) ) != IVAS_ERR_OK ) + // { + // return error; + // } + //preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); + preDelay = (Word16) L_shr_r(Mpy_32_32(1677721600 /*800 in Q21*/, roomAcoustics->acousticPreDelay_fx /*Q27*/ ), Q17); + } + else + { + revTimes = hHrtfParambin->parametricReverberationTimes_fx; + revEne = hHrtfParambin->parametricReverberationEneCorrections_fx; + preDelay = 10; + } + + error = ivas_binaural_reverb_open_fx( hReverbPr, numBins, numCldfbSlotsPerFrame, sampling_rate, revTimes, revEne, preDelay ); + return error; +} +#else ivas_error ivas_binaural_reverb_open_parambin( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ const int16_t numBins, /* i : number of CLDFB bins */ @@ -4003,7 +4198,7 @@ ivas_error ivas_binaural_reverb_open_parambin( return error; } - +#endif /*------------------------------------------------------------------------- * ivas_binaural_reverb_close() diff --git a/lib_rend/ivas_reverb_filter_design.c b/lib_rend/ivas_reverb_filter_design.c index e76cadc3737a56e6983916ecb3d2eed4b0eb0665..57dc79860e6b11d7b23bd9881a050c0ad9811448 100644 --- a/lib_rend/ivas_reverb_filter_design.c +++ b/lib_rend/ivas_reverb_filter_design.c @@ -1152,7 +1152,7 @@ void ivas_reverb_calc_color_levels_fx( H_filter = L_add(L_shr(L_add(L_shr(Mpy_32_32(coefB[0], coefB[0]), 1), L_shr(Mpy_32_32(coefB[1], coefB[1]), 1)), 2), L_shr(Mpy_32_32(coefB[0], Mpy_32_32(coefB[1], L_shl(cos_w, 15))), 1)); //q = 28 H_filter = BASOP_Util_Divide3232_Scale(H_filter, L_add(ONE_IN_Q28, L_shr(L_add(L_shr(Mpy_32_32(coefA[1], coefA[1]), 2), Mpy_32_32(coefA[1], L_shl(cos_w, 15))), 1)), &temp); H_filter = Sqrt32(L_shl(H_filter, 16), &temp); - T60_est = BASOP_Util_Divide3232_Scale(L_shl(i_mult(-3, pLoop_delays[loop_idx]), 2), Mpy_32_32(Mpy_32_32(L_add(BASOP_Util_Log2(H_filter), L_shl(temp, 25)), INV_LOG10_2_Q31), L_shl(output_Fs, 8)), &temp);//conversion of log2 to log10. + T60_est = BASOP_Util_Divide3232_Scale(L_shl(i_mult(-3, pLoop_delays[loop_idx]), 2), Mpy_32_32(Mpy_32_32(L_add(BASOP_Util_Log2(H_filter), L_shl(temp, 25)), LOG10_2_Q31), L_shl(output_Fs, 8)), &temp);//conversion of log2 to log10. T60_est = L_shl(T60_est, 16); t60[freq_idx] = BASOP_Util_Add_Mant32Exp(T60_est, temp, t60[freq_idx], t60_e[freq_idx], &result_e); t60_e[freq_idx] = result_e; diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 807dce497528019ce91f9c0b7ad5e45ddea4b1fa..2684fe020a706f4441efb46172daef04732fba1f 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -410,14 +410,14 @@ typedef struct dirac_output_synthesis_state_structure Word32 *proto_power_smooth_fx; /* Smoothed power of the prototype signals. Size: num_freq_bands*num_channels. */ Word16 proto_power_smooth_q; - Word16 *proto_power_smooth_prev_fx; /* Smoothed power of the prototype signals of the previous synthesis block. Size: num_freq_bands*num_channels. */ + Word32 *proto_power_smooth_prev_fx; /* Smoothed power of the prototype signals of the previous synthesis block. Size: num_freq_bands*num_channels. */ + Word16 proto_power_smooth_prev_q; Word32 *proto_power_diff_smooth_fx; + Word32 *proto_power_diff_smooth_prev_fx; Word16 proto_power_diff_smooth_q; Word16 proto_power_diff_smooth_len; - Word16 *proto_power_diff_smooth_prev_fx; - /* only pointer to local buffers */ Word32 *proto_direct_buffer_f_fx; /* Buffer for direct sound prototype signals. Size: 2*num_freq_bands*num_channels*buffer_length (complex interleaved). */ Word16 proto_direct_buffer_f_q; @@ -453,8 +453,8 @@ typedef struct dirac_output_synthesis_state_structure const Word32 *onset_filter_fx; /* Temporal smoothing memories */ - Word16 *reference_power_smooth_prev_fx; - Word16 *direction_smoothness_prev_fx; + Word32 *reference_power_smooth_prev_fx; + Word32 *direction_smoothness_prev_fx; // Q31 #endif } DIRAC_OUTPUT_SYNTHESIS_STATE; @@ -509,14 +509,17 @@ typedef struct Word16 q_total_power; Word32 subtract_power_y_fx; + Word32 subtract_power_y_smooth_fx; + Word32 target_power_y_smooth_fx; + Word16 q_subtract_power_y; - Word16 subtract_power_y_smooth_fx; - Word16 target_power_y_smooth_fx; + Word16 q_subtract_power_y_smooth; + Word16 q_target_power_y_smooth; Word32 lr_total_bb_ratio_db_fx; Word32 lr_total_hi_ratio_db_fx; Word32 min_sum_total_ratio_db_fx; - Word32 subtract_target_ratio_db_fx; + Word32 subtract_target_ratio_db_fx; // Q21 #endif int16_t counter; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 5f5f80b40bad351263447166cceec0773f5ce9ef..83fd23f699154f6f0b04ddd138000cb647c62f2c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -156,6 +156,9 @@ typedef struct CREND_WRAPPER_HANDLE crendWrapper; REVERB_HANDLE hReverb; rotation_matrix rot_mat_prev; +#ifdef IVAS_FLOAT_FIXED + pan_vector_fx prev_pan_gains_fx; +#endif pan_vector prev_pan_gains; int8_t firstFrameRendered; float *bufferData; @@ -1799,74 +1802,6 @@ static ivas_error getEfapGains_fx( return IVAS_ERR_OK; } -#endif -#ifdef IVAS_FLOAT_FIXED -static ivas_error getEfapGains( - EFAP_WRAPPER efapWrapper, - const float azi, - const float ele, - pan_vector panGains ) -{ - pan_vector tmpPanGains; /* tmp pan gain buffer without LFE channels */ - pan_vector_fx tmpPanGains_fx; /* tmp pan gain buffer without LFE channels */ - float *readPtr; - int16_t i; - int16_t lfeCount; - int16_t numChannels; - ivas_error error; - - /* EFAP returns an array of gains only for non-LFE speakers */ - efap_determine_gains_fx( efapWrapper.hEfap, tmpPanGains_fx, floatToFixed( azi, Q22 ), floatToFixed( ele, Q22 ), EFAP_MODE_EFAP ); - /* float2fix to be removed */ - - /*fix2float: to be removed*/ - fixedToFloat_arrL(tmpPanGains_fx, tmpPanGains, Q30, efapWrapper.hEfap->numSpk); - - /* Now copy to buffer that includes LFE channels */ - if ( efapWrapper.speakerConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) - { - numChannels = efapWrapper.pCustomLsSetup->num_spk + efapWrapper.pCustomLsSetup->num_lfe; - readPtr = tmpPanGains; - - for ( i = 0, lfeCount = 0; i < numChannels; ++i ) - { - if ( lfeCount < efapWrapper.pCustomLsSetup->num_lfe && i == efapWrapper.pCustomLsSetup->lfe_idx[lfeCount] ) - { - panGains[i] = 0.0f; - ++lfeCount; - } - else - { - panGains[i] = *readPtr; - ++readPtr; - } - } - } - else - { - if ( ( error = getAudioConfigNumChannels( efapWrapper.speakerConfig, &numChannels ) ) != IVAS_ERR_OK ) - { - return error; - } - - readPtr = tmpPanGains; - - for ( i = 0; i < numChannels; ++i ) - { - if ( i == LFE_CHANNEL ) - { - panGains[i] = 0.0f; - } - else - { - panGains[i] = *readPtr; - ++readPtr; - } - } - } - - return IVAS_ERR_OK; -} #else static ivas_error getEfapGains( EFAP_WRAPPER efapWrapper, @@ -2387,7 +2322,7 @@ static ivas_error setRendInputActiveIsm( hRendCfg->roomAcoustics.inputPreDelay_fx = (Word32) ( hRendCfg->roomAcoustics.inputPreDelay * ONE_IN_Q27 ); #endif - if ( ( error = ivas_reverb_open( &( inputIsm->hReverb ), outConfig, NULL,inputIsm->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_reverb_open_fx( &( inputIsm->hReverb ), outConfig, NULL,inputIsm->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) { return error; } @@ -2713,7 +2648,7 @@ static ivas_error initMcPanGainsWithEfap_fx( } return IVAS_ERR_OK; } -#endif +#else static ivas_error initMcPanGainsWithEfap( input_mc *inputMc, const AUDIO_CONFIG outConfig ) @@ -2779,7 +2714,7 @@ static ivas_error initMcPanGainsWithEfap( return IVAS_ERR_OK; } - +#endif #ifdef IVAS_FLOAT_FIXED static ivas_error getRendInputNumChannels( const void *rendInput, @@ -3817,7 +3752,7 @@ static ivas_error initMcBinauralRendering( hRendCfg->roomAcoustics.inputPreDelay_fx = (Word32) ( hRendCfg->roomAcoustics.inputPreDelay * ONE_IN_Q27 ); #endif - if ( ( error = ivas_reverb_open( &( inputMc->hReverb ), outConfig, NULL,inputMc->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, outSampleRate ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_reverb_open_fx( &( inputMc->hReverb ), outConfig, NULL,inputMc->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, outSampleRate ) ) != IVAS_ERR_OK ) { return error; } @@ -8203,6 +8138,7 @@ static ivas_error renderIsmToBinauralRoom( float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; ivas_error error; pan_vector currentPanGains; + pan_vector_fx currentPanGains_fx; IVAS_REND_AudioBuffer tmpMcBuffer; IVAS_ISM_METADATA rotatedPosPrev; IVAS_ISM_METADATA rotatedPos; @@ -8287,21 +8223,30 @@ static ivas_error renderIsmToBinauralRoom( position_changed = !ismInput->firstFrameRendered || checkObjectPositionChanged( &rotatedPos, &rotatedPosPrev ); /* set previous gains if this is the first frame */ - if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, rotatedPosPrev.azimuth, rotatedPosPrev.elevation, ismInput->prev_pan_gains ) ) != IVAS_ERR_OK ) + /*float2fix to be removed*/ + Word32 azimuth_fx_tmp = floatToFixed(rotatedPosPrev.azimuth, Q22); + Word32 elevation_fx_tmp = floatToFixed(rotatedPosPrev.elevation, Q22); + if ( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, azimuth_fx_tmp, elevation_fx_tmp, ismInput->prev_pan_gains_fx ) ) != IVAS_ERR_OK ) { return error; } - + /* fix2float to be removed */ + fixedToFloat_arrL(ismInput->prev_pan_gains_fx, ismInput->prev_pan_gains, Q31, MAX_OUTPUT_CHANNELS); /* compute gains only if position changed */ if ( position_changed ) { - if ( ( error = getEfapGains( *ismInput->base.ctx.pEfapOutWrapper, - rotatedPos.azimuth, - rotatedPos.elevation, - currentPanGains ) ) != IVAS_ERR_OK ) + /*float2fix to be removed*/ + azimuth_fx_tmp = floatToFixed(rotatedPos.azimuth, Q22); + elevation_fx_tmp = floatToFixed(rotatedPos.elevation, Q22); + if ( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, + azimuth_fx_tmp, + elevation_fx_tmp, + currentPanGains_fx ) ) != IVAS_ERR_OK ) { return error; } + /* fix2float to be removed */ + fixedToFloat_arrL(currentPanGains_fx, currentPanGains, Q31, MAX_OUTPUT_CHANNELS); } /* intermediate rendering to 7_1_4 */ @@ -8587,13 +8532,14 @@ static ivas_error renderIsmToBinauralReverb( return IVAS_ERR_OK; } - +#ifdef IVAS_FLOAT_FIXED static ivas_error renderIsmToMc( input_ism *ismInput, const IVAS_REND_AudioBuffer outAudio ) { int8_t position_changed; pan_vector currentPanGains; + pan_vector_fx currentPanGains_fx; ivas_error error; push_wmops( "renderIsmToMc" ); @@ -8610,23 +8556,104 @@ static ivas_error renderIsmToMc( { set_zero( currentPanGains, MAX_OUTPUT_CHANNELS ); -#ifdef IVAS_FLOAT_FIXED Word16 gains_fx[2]; ivas_ism_get_stereo_gains_fx( (Word16) ismInput->currentPos.azimuth, (Word16) ismInput->currentPos.elevation, &gains_fx[0], &gains_fx[1] ); currentPanGains[0] = (float) gains_fx[0] / 32768.f; currentPanGains[1] = (float) gains_fx[1] / 32768.f; -#else - ivas_ism_get_stereo_gains( ismInput->currentPos.azimuth, ismInput->currentPos.elevation, ¤tPanGains[0], ¤tPanGains[1] ); -#endif set_zero( ismInput->prev_pan_gains, MAX_OUTPUT_CHANNELS ); -#ifdef IVAS_FLOAT_FIXED ivas_ism_get_stereo_gains_fx( (Word16) ismInput->previousPos.azimuth, (Word16) ismInput->previousPos.elevation, &gains_fx[0], &gains_fx[1] ); ismInput->prev_pan_gains[0] = (float) gains_fx[0] / 32768.f; ismInput->prev_pan_gains[1] = (float) gains_fx[1] / 32768.f; + } + } + else + { + /* compute gains only if position changed */ + if ( position_changed ) + { + // TODO tmu review when #215 is resolved + /*float2fix to be removed*/ + Word32 azimuth_fx_tmp = (int16_t)floorf(ismInput->currentPos.azimuth + 0.5f); + azimuth_fx_tmp = azimuth_fx_tmp << 22; + Word32 elevation_fx_tmp = (int16_t)floorf(ismInput->currentPos.elevation + 0.5f); + elevation_fx_tmp = elevation_fx_tmp << 22; + if ( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, + azimuth_fx_tmp, + elevation_fx_tmp, + currentPanGains_fx ) ) != IVAS_ERR_OK ) + { + return error; + } + /* fix2float to be removed */ + fixedToFloat_arrL(currentPanGains_fx, currentPanGains, Q31, MAX_OUTPUT_CHANNELS); + } + + /* set previous gains if this is the first frame */ + if ( !ismInput->firstFrameRendered ) + { + // TODO tmu review when #215 is resolved + /*float2fix to be removed*/ + Word32 azimuth_fx_tmp = (int16_t)floorf(ismInput->previousPos.azimuth + 0.5f); + azimuth_fx_tmp = azimuth_fx_tmp << 22; + Word32 elevation_fx_tmp = (int16_t)floorf(ismInput->previousPos.elevation + 0.5f); + elevation_fx_tmp = elevation_fx_tmp << 22; + if ( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, + azimuth_fx_tmp, + elevation_fx_tmp, + ismInput->prev_pan_gains_fx) ) != IVAS_ERR_OK ) + { + return error; + } + /* fix2float to be removed */ + fixedToFloat_arrL(ismInput->prev_pan_gains_fx, ismInput->prev_pan_gains, Q31, MAX_OUTPUT_CHANNELS); + } + } + + /* Assume num channels in audio buffer to be 1. + * This should have been validated in IVAS_REND_FeedInputAudio() */ + renderBufferChannelLerp( ismInput->base.inputBuffer, 0, + position_changed ? currentPanGains : ismInput->prev_pan_gains, + position_changed ? ismInput->prev_pan_gains : NULL, + outAudio ); + + if ( position_changed ) + { + mvr2r( currentPanGains, ismInput->prev_pan_gains, MAX_OUTPUT_CHANNELS ); + } + + pop_wmops(); + + return IVAS_ERR_OK; +} #else +static ivas_error renderIsmToMc( + input_ism *ismInput, + const IVAS_REND_AudioBuffer outAudio ) +{ + int8_t position_changed; + pan_vector currentPanGains; + ivas_error error; + + push_wmops( "renderIsmToMc" ); + + position_changed = !ismInput->firstFrameRendered || checkObjectPositionChanged( &ismInput->currentPos, &ismInput->previousPos ); + if ( *ismInput->base.ctx.pOutConfig == IVAS_AUDIO_CONFIG_STEREO ) + { + if ( ismInput->nonDiegeticPan ) + { + ismInput->prev_pan_gains[0] = currentPanGains[0] = ( ismInput->nonDiegeticPanGain + 1.f ) * 0.5f; + ismInput->prev_pan_gains[1] = currentPanGains[1] = 1.f - currentPanGains[0]; + } + else + { + set_zero( currentPanGains, MAX_OUTPUT_CHANNELS ); + + ivas_ism_get_stereo_gains( ismInput->currentPos.azimuth, ismInput->currentPos.elevation, ¤tPanGains[0], ¤tPanGains[1] ); + + set_zero( ismInput->prev_pan_gains, MAX_OUTPUT_CHANNELS ); + ivas_ism_get_stereo_gains( ismInput->previousPos.azimuth, ismInput->previousPos.elevation, &ismInput->prev_pan_gains[0], &ismInput->prev_pan_gains[1] ); -#endif } } else @@ -8674,7 +8701,7 @@ static ivas_error renderIsmToMc( return IVAS_ERR_OK; } - +#endif static ivas_error renderIsmToSba( input_ism *ismInput, diff --git a/lib_util/hrtf_file_reader.c b/lib_util/hrtf_file_reader.c index f35783a9b3c04c4a9e084ee0fc8a3219774072b6..219a52c607b09a0139b835ceff08d28dbe2751df 100644 --- a/lib_util/hrtf_file_reader.c +++ b/lib_util/hrtf_file_reader.c @@ -1766,7 +1766,7 @@ ivas_error load_fastconv_HRTF_from_binary( * * *---------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED static ivas_error create_parambin_HRTF_from_rawdata( HRTFS_PARAMBIN_HANDLE *hHRTF, /* i/o: Parametric binauralizer HRTF handle */ char *hrtf_data /* i : pointer to binary file */ @@ -1820,16 +1820,83 @@ static ivas_error create_parambin_HRTF_from_rawdata( memcpy( ( *hHRTF )->parametricReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + /*adding conversion as file reading is done in float*/ + floatToFixed_arrL( ( *hHRTF )->parametricReverberationTimes, ( *hHRTF )->parametricReverberationTimes_fx, Q31, CLDFB_NO_CHANNELS_MAX ); memcpy( ( *hHRTF )->parametricReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + /*adding conversion as file reading is done in float*/ + floatToFixed_arrL( ( *hHRTF )->parametricReverberationEneCorrections, ( *hHRTF )->parametricReverberationEneCorrections_fx, Q31, CLDFB_NO_CHANNELS_MAX ); memcpy( ( *hHRTF )->parametricEarlyPartEneCorrection, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); return IVAS_ERR_OK; } +#else +static ivas_error create_parambin_HRTF_from_rawdata( + HRTFS_PARAMBIN_HANDLE *hHRTF, /* i/o: Parametric binauralizer HRTF handle */ + char *hrtf_data /* i : pointer to binary file */ +) +{ + int16_t i, j; + char *hrtf_data_rptr; + uint32_t data_size_tmp; + + hrtf_data_rptr = hrtf_data; + /* HRTF_SH_CHANNELS */ + if ( HRTF_SH_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_SH_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* HRTF_NUM_BINS */ + if ( HRTF_NUM_BINS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_NUM_BINS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + /* HRTF */ + data_size_tmp = HRTF_NUM_BINS * sizeof( float ); + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsRe[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsIm[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + + /* Reverb Parameters */ + if ( CLDFB_NO_CHANNELS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (CLDFB_NO_CHANNELS_MAX)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + memcpy( ( *hHRTF )->parametricReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricEarlyPartEneCorrection, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + return IVAS_ERR_OK; +} +#endif /*---------------------------------------------------------------------* * load_parambin_HRTF_from_binary()