From a38ca793b8b75c85359babde6911a31645faa5da Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Mon, 6 May 2024 13:31:08 +0530 Subject: [PATCH 1/2] Few renderer functions conv to fixed point, cleanup of float dependencies [x] chol2x2 fixed point implementation [x] efap functions cleanup [x] ivas_rotation.c and lib_rend.c intermediate float conversions cleanup [x] Fix for high MLD for EVS non-diegetic panning and OMASA case. --- apps/renderer.c | 108 +- lib_com/fft_fx.c | 18 + lib_com/ivas_prot.h | 7 +- lib_com/prot_fx2.h | 2 + lib_dec/ivas_binRenderer_internal.c | 201 ++- lib_dec/ivas_dirac_dec.c | 236 +++- lib_dec/ivas_init_dec.c | 91 +- lib_dec/ivas_ism_dec.c | 3 - lib_dec/ivas_ism_param_dec.c | 211 ++- lib_dec/ivas_ism_renderer.c | 4 +- lib_dec/ivas_mct_dec.c | 2 +- lib_dec/ivas_objectRenderer_internal.c | 415 +++--- lib_dec/ivas_osba_dec.c | 50 +- lib_dec/ivas_out_setup_conversion.c | 8 +- lib_dec/ivas_sba_dec.c | 10 +- lib_dec/lib_dec_fx.c | 17 +- lib_rend/ivas_allrad_dec.c | 6 +- lib_rend/ivas_dirac_ana.c | 472 ++++--- lib_rend/ivas_dirac_dec_binaural_functions.c | 253 +++- lib_rend/ivas_dirac_output_synthesis_dec.c | 511 ++++++- lib_rend/ivas_dirac_rend.c | 443 +++++- lib_rend/ivas_efap.c | 1279 ++++++++++++------ lib_rend/ivas_hrtf.c | 118 ++ lib_rend/ivas_objectRenderer.c | 128 +- lib_rend/ivas_objectRenderer_hrFilt.c | 124 +- lib_rend/ivas_objectRenderer_mix.c | 160 +-- lib_rend/ivas_objectRenderer_sources.c | 236 ++-- lib_rend/ivas_orient_trk.c | 13 +- lib_rend/ivas_prot_rend.h | 145 +- lib_rend/ivas_rotation.c | 32 +- lib_rend/ivas_stat_rend.h | 81 +- lib_rend/lib_rend.c | 968 ++++++++++++- lib_rend/lib_rend.h | 30 +- lib_util/hrtf_file_reader.c | 10 +- 34 files changed, 4894 insertions(+), 1498 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index bbc4213a1..bafeec725 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -643,6 +643,7 @@ int main( #ifdef IVAS_FLOAT_FIXED Word32 *outInt32Buffer; Word32 *inInt32Buffer; + Word32 gain_fx; #endif float *outFloatBuffer; IVAS_REND_AudioBuffer inBuffer; @@ -933,7 +934,9 @@ int main( } IVAS_REND_LfePanMtx lfePanMatrix; - +#ifdef IVAS_FLOAT_FIXED + IVAS_REND_LfePanMtx_fx lfePanMatrix_fx; +#endif /* parse input LFE panning matrix */ if ( args.lfeCustomRoutingEnabled && !isEmptyString( args.inLfePanningMatrixFile ) ) { @@ -968,17 +971,33 @@ int main( for ( i = 0; i < args.inConfig.numMultiChannelBuses; ++i ) { +#ifndef IVAS_FLOAT_FIXED if ( ( error = IVAS_REND_AddInput( hIvasRend, args.inConfig.multiChannelBuses[i].audioConfig, &mcIds[i] ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, mcIds[i], args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ((error = IVAS_REND_SetInputGain(hIvasRend, mcIds[i], args.inputGainGlobal * dBToLin(args.inConfig.multiChannelBuses[i].gain_dB))) != IVAS_ERR_OK) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } +#else + IF( ( error = IVAS_REND_AddInput_fx( hIvasRend, args.inConfig.multiChannelBuses[i].audioConfig, &mcIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + gain_fx = (Word32) ( ( args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) * ( 1u << 30 ) ); + + IF ((error = IVAS_REND_SetInputGain_fx(hIvasRend, mcIds[i], gain_fx)) != IVAS_ERR_OK) { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); } +#endif if ( args.inConfig.multiChannelBuses[i].audioConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { @@ -998,7 +1017,16 @@ int main( args.lfePanningEnabled = false; } +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 k = 0; k < IVAS_MAX_OUTPUT_CHANNELS; k++ ) + { + ( *lfePanMatrix_fx )[k] = (Word32) ( ( *lfePanMatrix )[k] * ( 1u << 31 ) ); + } + + IF ( ( error = IVAS_REND_SetInputLfeMtx_fx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx_fx *) &lfePanMatrix_fx ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_SetInputLfeMtx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx *) &lfePanMatrix ) ) != IVAS_ERR_OK ) +#endif // IVAS_FLOAT_FIXED { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); @@ -1007,7 +1035,12 @@ int main( /* set panning gains for input LFE */ else if ( args.lfePanningEnabled ) { +#ifdef IVAS_FLOAT_FIXED + Word32 inputGain = (Word32) ( args.lfeConfigGain * ( 1u << 31 ) ); + IF( ( error = IVAS_REND_SetInputLfePos_fx( hIvasRend, mcIds[i], inputGain, (Word16) args.lfeConfigAzimuth, (Word16) args.lfeConfigElevation ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], args.lfeConfigGain, args.lfeConfigAzimuth, args.lfeConfigElevation ) ) != IVAS_ERR_OK ) +#endif // IVAS_FLOAT_FIXED { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); @@ -1027,7 +1060,16 @@ int main( exit( -1 ); } +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 k = 0; k < IVAS_MAX_OUTPUT_CHANNELS; k++ ) + { + ( *lfePanMatrix_fx )[k] = (Word32) ( ( *lfePanMatrix )[k] * ( 1u << 31 ) ); + } + + if ( ( error = IVAS_REND_SetInputLfeMtx_fx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx_fx *) &lfePanMatrix_fx ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_SetInputLfeMtx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx *) &lfePanMatrix ) ) != IVAS_ERR_OK ) +#endif // IVAS_FLOAT_FIXED { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); @@ -1036,7 +1078,12 @@ int main( /* set position based gains */ else { +#ifdef IVAS_FLOAT_FIXED + Word32 inputGain = (Word32) ( lfeRoutingConfigs[i]->lfe_gain_dB * ( 1u << 31 ) ); + IF( ( error = IVAS_REND_SetInputLfePos_fx( hIvasRend, mcIds[i], inputGain, (Word16) lfeRoutingConfigs[i]->lfe_azi, (Word16) lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], lfeRoutingConfigs[i]->lfe_gain_dB, lfeRoutingConfigs[i]->lfe_azi, lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) +#endif // IVAS_FLOAT_FIXED { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); @@ -1046,6 +1093,7 @@ int main( } } +#ifndef IVAS_FLOAT_FIXED for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) { if ( ( error = IVAS_REND_AddInput( hIvasRend, IVAS_AUDIO_CONFIG_OBA, &ismIds[i] ) ) != IVAS_ERR_OK ) @@ -1082,7 +1130,6 @@ int main( } } - for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) { if ( ( error = IVAS_REND_AddInput( hIvasRend, args.inConfig.masaBuses[i].audioConfig, &masaIds[i] ) ) != IVAS_ERR_OK ) @@ -1097,6 +1144,61 @@ int main( exit( -1 ); } } +#else + FOR ( i = 0; i < args.inConfig.numAudioObjects; ++i ) + { + IF( ( error = IVAS_REND_AddInput_fx( hIvasRend, IVAS_AUDIO_CONFIG_OBA, &ismIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + gain_fx = (Word32) ( args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) * ( 1u << 30 ) ); + IF( ( error = IVAS_REND_SetInputGain_fx( hIvasRend, ismIds[i], gain_fx) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + /* With MASA output, all objects are handled at once, so add only one input having all objects in it */ + IF ( EQ_32(args.outConfig.audioConfig, IVAS_AUDIO_CONFIG_MASA1) || EQ_32(args.outConfig.audioConfig, IVAS_AUDIO_CONFIG_MASA2) ) + { + BREAK; + } + } + + FOR ( i = 0; i < args.inConfig.numAmbisonicsBuses; ++i ) + { + IF( ( error = IVAS_REND_AddInput_fx( hIvasRend, args.inConfig.ambisonicsBuses[i].audioConfig, &sbaIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + gain_fx = (Word32) ( args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) * ( 1u << 30 ) ); + IF ( ( error = IVAS_REND_SetInputGain_fx( hIvasRend, sbaIds[i], gain_fx ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + FOR ( i = 0; i < args.inConfig.numMasaBuses; ++i ) + { + IF( ( error = IVAS_REND_AddInput_fx( hIvasRend, args.inConfig.masaBuses[i].audioConfig, &masaIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + gain_fx = (Word32) ( ( args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) * ( 1u << 30 ) ); + IF ( ( error = IVAS_REND_SetInputGain_fx( hIvasRend, masaIds[i], gain_fx) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } +#endif // !IVAS_FLOAT_FIXED const int16_t totalNumInChannels = getTotalNumInChannels( hIvasRend, mcIds, ismIds, sbaIds, masaIds ); diff --git a/lib_com/fft_fx.c b/lib_com/fft_fx.c index f8fb4c139..d9f565bef 100644 --- a/lib_com/fft_fx.c +++ b/lib_com/fft_fx.c @@ -5467,6 +5467,24 @@ Word16 L_norm_arr( Word32 *arr, Word16 size ) return q; } +Word16 get_min_scalefactor( Word32 x, Word32 y ) +{ + Word16 scf = Q31; + IF( EQ_32( x, 0 ) && EQ_32( y, 0 ) ) + { + return 0; + } + IF( NE_32( x, 0 ) ) + { + scf = s_min( scf, norm_l( x ) ); + } + IF( NE_32( y, 0 ) ) + { + scf = s_min( scf, norm_l( y ) ); + } + return scf; +} + #if 0 /* Functions are already in fixed point and available in fft.c file */ diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 4341c8900..0361dacfa 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -6451,10 +6451,15 @@ void ivas_spar_param_to_masa_param_mapping_fx( /*---------------------------------------------------------------------------------* * Binaural FastConv Renderer Prototypes *-----------------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_binRenderer_open_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); +#else ivas_error ivas_binRenderer_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); +#endif void ivas_binRenderer_close( BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: decoder binaural renderer handle */ diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index a7e85e021..88ece4c55 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -4254,6 +4254,8 @@ Word16 find_guarded_bits_fx(Word32 n); Word16 L_norm_arr(Word32* arr, Word16 size); +Word16 get_min_scalefactor( Word32 x, Word32 y ); + void edct2_fx_ivas( const Word16 n, const Word16 isgn, diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 04c22da10..e360e599e 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -46,6 +46,7 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx1.h" #include "prot_fx2.h" +#include "ivas_rom_com_fx.h" #include "debug.h" #define float_to_fix( n, factor ) ( round( n * ( 1 << factor ) ) ) #define float_to_fixQ29( n ) float_to_fix( n, Q29 ) @@ -1601,8 +1602,8 @@ static void ivas_binaural_obtain_DMX_fx( * * Open fastconv binaural renderer handle *-------------------------------------------------------------------------*/ - -ivas_error ivas_binRenderer_open( +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_binRenderer_open_fx( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { @@ -1683,7 +1684,7 @@ ivas_error ivas_binRenderer_open( IF( st_ivas->hoa_dec_mtx == NULL ) { - IF( ( error = ivas_sba_get_hoa_dec_matrix( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_sba_get_hoa_dec_matrix_fx( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } @@ -1746,11 +1747,7 @@ ivas_error ivas_binRenderer_open( { FOR( k = 0; k < hBinRenderer->nInChannels; k++ ) { -#ifndef IVAS_FLOAT_FIXED - hBinRenderer->hReverb->dmxmtx[chIdx][k] = dmxmtx_table[chIdx][k]; -#else hBinRenderer->hReverb->dmxmtx_fx[chIdx][k] = dmxmtx_table_fx[chIdx][k]; -#endif } } } @@ -1767,17 +1764,13 @@ ivas_error ivas_binRenderer_open( { FOR( k = 0; k < 11; k++ ) { -#ifndef IVAS_FLOAT_FIXED - ivas_dirac_dec_get_response( (int16_t) ls_azimuth_CICP19[k], (int16_t) ls_elevation_CICP19[k], hBinRenderer->hReverb->foa_enc[k], 1 ); -#else - ivas_dirac_dec_get_response_fixed( (int16_t) ls_azimuth_CICP19[k], (int16_t) ls_elevation_CICP19[k], hBinRenderer->hReverb->foa_enc_fx[k], 1 ); + ivas_dirac_dec_get_response_fixed( (Word16) L_shr_r( ls_azimuth_CICP19_fx[k], 22 ), (Word16) L_shr_r( ls_elevation_CICP19_fx[k], 22 ), hBinRenderer->hReverb->foa_enc_fx[k], 1 ); // Q29: hBinRenderer->hReverb->foa_enc_fx[k] -#endif } } ELSE IF( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) { - IF( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + IF( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -1792,7 +1785,189 @@ ivas_error ivas_binRenderer_open( return error; } +#else +ivas_error ivas_binRenderer_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + BINAURAL_RENDERER_HANDLE hBinRenderer; + int16_t convBand, chIdx, k; + ivas_error error; + + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Renderer\n" ) ); + } + + hBinRenderer->hInputSetup = &st_ivas->hIntSetup; + + /* Define of head rotation has to be done in binRendeder in CLDFB*/ + hBinRenderer->rotInCldfb = 0; + if ( st_ivas->ivas_format == MC_FORMAT || st_ivas->ivas_format == SBA_FORMAT ) + { + hBinRenderer->rotInCldfb = 1; + } + + + /* Declare some common variables needed for renderer */ + /* Which format used for binaural rendering (needed for late reverb) ? MC or SBA */ + if ( st_ivas->hIntSetup.is_loudspeaker_setup ) + { + hBinRenderer->ivas_format = MC_FORMAT; + } + else + { + hBinRenderer->ivas_format = SBA_FORMAT; + } + hBinRenderer->max_band = (int16_t) ( ( BINAURAL_MAXBANDS * st_ivas->hDecoderConfig->output_Fs ) / 48000 ); + convBand = hBinRenderer->max_band; + + hBinRenderer->timeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; /* Corresponds to 5 msec sound to motion latency */ + + if ( convBand > BINAURAL_CONVBANDS ) + { + hBinRenderer->conv_band = BINAURAL_CONVBANDS; + } + else + { + hBinRenderer->conv_band = convBand; + } + + /*LFE rendering switched off by default*/ + hBinRenderer->render_lfe = 0; + + if ( st_ivas->ivas_format != ISM_FORMAT && st_ivas->hIntSetup.is_loudspeaker_setup ) + { + hBinRenderer->render_lfe = 1; + } + + /* Load HRTF tables */ + if ( ( error = ivas_binaural_hrtf_open( &st_ivas->hHrtfFastConv, st_ivas->hIntSetup.output_config, st_ivas->renderer_type ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM && ( st_ivas->hIntSetup.is_loudspeaker_setup == 0 ) ) + { + IVAS_OUTPUT_SETUP out_setup; + + /* Allocate memories and buffers needed for convolutional module in CICP19 */ + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, IVAS_AUDIO_CONFIG_7_1_4, st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_output_init( &out_setup, IVAS_AUDIO_CONFIG_7_1_4 ); + + if ( st_ivas->hoa_dec_mtx == NULL ) + { + if ( ( error = ivas_sba_get_hoa_dec_matrix( out_setup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + hBinRenderer->hoa_dec_mtx = st_ivas->hoa_dec_mtx; + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_BRIR_latency_s * 1000000000.f ); + } + else + { + /* Allocate memories and buffers needed for convolutional module */ + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + if ( hBinRenderer->ivas_format == MC_FORMAT ) + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HRIR_latency_s * 1000000000.f ); + } + else + { + if ( hBinRenderer->nInChannels == 16 ) + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HOA3_latency_s * 1000000000.f ); + } + else if ( hBinRenderer->nInChannels == 9 ) + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HOA2_latency_s * 1000000000.f ); + } + else if ( hBinRenderer->nInChannels == 4 ) + { + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_FOA_latency_s * 1000000000.f ); + } + else + { + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + } + } + else + { + /* same value for MC or HOA both use MC BRIR*/ + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_BRIR_latency_s * 1000000000.f ); + } + } + + /* Allocate memories needed for reverb module */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + if ( ( error = ivas_binaural_reverb_open_fastconv( &( hBinRenderer->hReverb ), hBinRenderer->conv_band, hBinRenderer->timeSlots, &( st_ivas->hRenderConfig->roomAcoustics ), st_ivas->hIntSetup.output_config, st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* initialize the dmx matrix */ + for ( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + for ( k = 0; k < hBinRenderer->nInChannels; k++ ) + { + hBinRenderer->hReverb->dmxmtx[chIdx][k] = dmxmtx_table[chIdx][k]; + } + } + } + else + { + hBinRenderer->hReverb = NULL; + } + + hBinRenderer->hEFAPdata = NULL; + + if ( hBinRenderer->hReverb != NULL ) + { + if ( hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 ) + { + for ( k = 0; k < 11; k++ ) + { + ivas_dirac_dec_get_response( (int16_t) ls_azimuth_CICP19[k], (int16_t) ls_elevation_CICP19[k], hBinRenderer->hReverb->foa_enc[k], 1 ); + } + } + else if ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) + { + if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + /* Copy handles to bin renderer handle*/ + hBinRenderer->hEFAPdata = st_ivas->hEFAPdata; + } + } + + /* Copy the handles to main handle */ + st_ivas->hBinRenderer = hBinRenderer; + + return error; +} +#endif /*------------------------------------------------------------------------- * ivas_binRenderer_convModuleClose() diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 0a00321e0..425d5ef1e 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -709,7 +709,7 @@ static ivas_error ivas_dirac_rend_config_fx( free( st_ivas->hoa_dec_mtx ); st_ivas->hoa_dec_mtx = NULL; } - IF( ( error = ivas_sba_get_hoa_dec_matrix( hDirACRend->hOutSetup, &st_ivas->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_sba_get_hoa_dec_matrix_fx( hDirACRend->hOutSetup, &st_ivas->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } @@ -5062,6 +5062,236 @@ void ivas_dirac_dec_render_sf_fx( } /*Compute PSDs*/ +#ifdef IVAS_FLOAT_FIXED +#if 1 // TO BE REMOVED + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; + DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; + + h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + + Word16 num_channels_dir = hDirACRend->num_outputs_dir; + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + { + num_channels_dir = hDirACRend->hOutSetup.nchan_out_woLFE; + } + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD && hodirac_flag ) + { + IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_VBAP ) ) + { + IF( EQ_16( hSpatParamRendCom->numParametricDirections, 2 ) ) + { + floatToFixed_arr( hDirACRend->diffuse_response_function, hDirACRend->diffuse_response_function_fx, Q15, hDirACRend->num_outputs_dir ); + floatToFixed_arrL( hSpatParamRendCom->energy_ratio1[md_idx], hSpatParamRendCom->energy_ratio1_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( hSpatParamRendCom->energy_ratio2[md_idx], hSpatParamRendCom->energy_ratio2_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + } + } + } + + if ( hDirAC->hConfig->dec_param_estim == FALSE && hodirac_flag ) + { + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + floatToFixed_arrL( hSpatParamRendCom->energy_ratio1[md_idx], hSpatParamRendCom->energy_ratio1_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( hSpatParamRendCom->energy_ratio2[md_idx], hSpatParamRendCom->energy_ratio2_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + } + } + else if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_VBAP ) ) + { + IF( EQ_16( hSpatParamRendCom->numParametricDirections, 2 ) ) + { + floatToFixed_arr( hDirACRend->diffuse_response_function, hDirACRend->diffuse_response_function_fx, Q15, hDirACRend->num_outputs_dir ); + floatToFixed_arrL( hSpatParamRendCom->energy_ratio1[md_idx], hSpatParamRendCom->energy_ratio1_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( hSpatParamRendCom->energy_ratio2[md_idx], hSpatParamRendCom->energy_ratio2_fx[md_idx], Q30, hSpatParamRendCom->num_freq_bands ); + } + } + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + floatToFixed_arrL32( reference_power, reference_power_fix, DirAC_mem.reference_power_q, hSpatParamRendCom->num_freq_bands * (min( 4, nchan_transport ) + 1)); + } + else + { + + } + } + + if ( h_dirac_output_synthesis_params->use_onset_filters && (hDirAC->hConfig->dec_param_estim != TRUE && hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD)) + { + h_dirac_output_synthesis_state->diffuse_power_factor_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->diffuse_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor_fx, h_dirac_output_synthesis_state->diffuse_power_factor_q, h_dirac_output_synthesis_params->max_band_decorr ); + + h_dirac_output_synthesis_state->diffuse_responses_square_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->diffuse_responses_square, h_dirac_output_synthesis_state->diffuse_responses_square_fx, h_dirac_output_synthesis_state->diffuse_responses_square_q, num_channels_dir ); + + h_dirac_output_synthesis_state->q_cy_auto_diff_smooth = L_get_q_buf( h_dirac_output_synthesis_state->cy_auto_diff_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( h_dirac_output_synthesis_state->cy_auto_diff_smooth, h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + floatToFixed_arrL(hDirACRend->stack_mem.onset_filter, p_onset_filter_fx, Q30, ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) ? hDirACRend->num_outputs_diff * hSpatParamRendCom->num_freq_bands : 2 * hSpatParamRendCom->num_freq_bands ); + } + + if ( hDirAC->hConfig->dec_param_estim == TRUE && hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD) + { + h_dirac_output_synthesis_state->direct_power_factor_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->direct_power_factor, h_dirac_output_synthesis_state->direct_power_factor_fx, h_dirac_output_synthesis_state->direct_power_factor_q, hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->q_cy_auto_dir_smooth = L_get_q_buf( h_dirac_output_synthesis_state->cy_auto_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( h_dirac_output_synthesis_state->cy_auto_dir_smooth, h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->q_cy_cross_dir_smooth = L_get_q_buf( h_dirac_output_synthesis_state->cy_cross_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( h_dirac_output_synthesis_state->cy_cross_dir_smooth, h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->direct_responses_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->direct_responses, h_dirac_output_synthesis_state->direct_responses_fx, h_dirac_output_synthesis_state->direct_responses_q, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->direct_responses_square_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->direct_responses_square, h_dirac_output_synthesis_state->direct_responses_square_fx, h_dirac_output_synthesis_state->direct_responses_square_q, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->diffuse_power_factor_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->diffuse_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor_fx, h_dirac_output_synthesis_state->diffuse_power_factor_q, hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->q_cy_auto_diff_smooth = L_get_q_buf( h_dirac_output_synthesis_state->cy_auto_diff_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( h_dirac_output_synthesis_state->cy_auto_diff_smooth, h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + + h_dirac_output_synthesis_state->diffuse_responses_square_q = Q31; + floatToFixed_arrL( h_dirac_output_synthesis_state->diffuse_responses_square, h_dirac_output_synthesis_state->diffuse_responses_square_fx, h_dirac_output_synthesis_state->diffuse_responses_square_q, num_channels_dir ); + } +#endif + IF ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order > 0 ) + { + ivas_dirac_dec_output_synthesis_process_slot_fx( reference_power_fix, + DirAC_mem.reference_power_q, + p_onset_filter_fx, + azimuth, + elevation, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + hSpatParamRendCom->q_diffuseness_vector, + hSpatParamRendCom, + hDirACRend, + st_ivas->hCombinedOrientationData->shd_rot_max_order, + p_Rmat_fx, + st_ivas->hVBAPdata, + hDirACRend->hOutSetup, + nchan_transport, + md_idx, + hodirac_flag, + hDirAC->hConfig->dec_param_estim ); + } + ELSE + { + ivas_dirac_dec_output_synthesis_process_slot_fx( reference_power_fix, + DirAC_mem.reference_power_q, + p_onset_filter_fx, + azimuth, + elevation, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + hSpatParamRendCom->q_diffuseness_vector, + hSpatParamRendCom, + hDirACRend, + 0, + 0, + st_ivas->hVBAPdata, + hDirACRend->hOutSetup, + nchan_transport, + md_idx, + hodirac_flag, + hDirAC->hConfig->dec_param_estim ); + } + +#if 1 + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD && hodirac_flag ) + { + IF( st_ivas->hMasa == NULL && EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses, hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + + IF( hodirac_flag ) + { + fixedToFloat_arrL( &hDirACRend->h_output_synthesis_psd_state.direct_responses_fx[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], &hDirACRend->h_output_synthesis_psd_state.direct_responses[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + } + } + ELSE + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses, hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + IF( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_square_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses_square, hDirACRend->h_output_synthesis_psd_state.direct_responses_square_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + } + } + } + if ( hDirAC->hConfig->dec_param_estim == FALSE && hodirac_flag ) + { + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + fixedToFloat_arrL(h_dirac_output_synthesis_state->direct_power_factor_fx, h_dirac_output_synthesis_state->direct_power_factor, h_dirac_output_synthesis_state->direct_power_factor_q, 2*hSpatParamRendCom->num_freq_bands); + fixedToFloat_arrL(h_dirac_output_synthesis_state->diffuse_power_factor_fx, h_dirac_output_synthesis_state->diffuse_power_factor, h_dirac_output_synthesis_state->diffuse_power_factor_q, 2*hSpatParamRendCom->num_freq_bands); + } + else + { + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], 31 - hDirACRend->h_output_synthesis_psd_state.direct_power_factor_q ); + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], 31 -hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_q ); + } + } + } + else if ( hDirAC->hConfig->dec_param_estim == TRUE ) + { + IF( st_ivas->hMasa == NULL && EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) ) + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses, hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + + IF( hodirac_flag ) + { + fixedToFloat_arrL( &hDirACRend->h_output_synthesis_psd_state.direct_responses_fx[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], &hDirACRend->h_output_synthesis_psd_state.direct_responses[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + } + } + ELSE + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses, hDirACRend->h_output_synthesis_psd_state.direct_responses_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + IF( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + fixedToFloat_arrL( hDirACRend->h_output_synthesis_psd_state.direct_responses_square_fx, hDirACRend->h_output_synthesis_psd_state.direct_responses_square, hDirACRend->h_output_synthesis_psd_state.direct_responses_square_q, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) ); + } + } + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], 31 - h_dirac_output_synthesis_state->direct_power_factor_q ); + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] = me2f( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], 31 - h_dirac_output_synthesis_state->diffuse_power_factor_q ); + } + fixedToFloat_arrL( h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx, h_dirac_output_synthesis_state->cy_cross_dir_smooth, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, (num_channels_dir) * hSpatParamRendCom->num_freq_bands ); + } + else + { + + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] = fix_to_float( hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], hDirACRend->h_output_synthesis_psd_state.direct_power_factor_q ); + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] = fix_to_float( hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_q ); + } + + } + } + + if ( h_dirac_output_synthesis_params->use_onset_filters && (hDirAC->hConfig->dec_param_estim != TRUE && hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD)) + { + fixedToFloat_arrL( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, h_dirac_output_synthesis_state->cy_auto_diff_smooth, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, hDirACRend->num_outputs_diff * hSpatParamRendCom->num_freq_bands ); + } + + if ( hDirAC->hConfig->dec_param_estim == TRUE && hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD) + { + fixedToFloat_arrL( h_dirac_output_synthesis_state->cy_auto_dir_smooth_fx, h_dirac_output_synthesis_state->cy_auto_dir_smooth, h_dirac_output_synthesis_state->q_cy_auto_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + fixedToFloat_arrL( h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx, h_dirac_output_synthesis_state->cy_cross_dir_smooth, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + fixedToFloat_arrL( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, h_dirac_output_synthesis_state->cy_auto_diff_smooth, h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, num_channels_dir * hSpatParamRendCom->num_freq_bands ); + } +#endif +#else if ( st_ivas->hCombinedOrientationData && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hCombinedOrientationData->shd_rot_max_order > 0 ) { ivas_dirac_dec_output_synthesis_process_slot( reference_power, @@ -5098,7 +5328,7 @@ void ivas_dirac_dec_render_sf_fx( hodirac_flag, hDirAC->hConfig->dec_param_estim ); } - +#endif if ( hDirAC->hConfig->dec_param_estim ) { float fac = 1.0f / (float) hSpatParamRendCom->subframe_nbslots[subframe_idx]; @@ -5405,7 +5635,7 @@ void ivas_dirac_dec_render_sf_fx( { const Word32 azi_fx = L_shl( az1, Q22 ); // Q0 -> Q22 const Word32 ele_fx = L_shl( el1, Q22 ); // Q0 -> Q22 - efap_determine_gains_fixed( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azi_fx, ele_fx, EFAP_MODE_EFAP ); + efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azi_fx, ele_fx, EFAP_MODE_EFAP ); } } diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 4f8a83419..389641099 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -431,9 +431,6 @@ ivas_error ivas_dec_setup( Src_p->SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f; - Src_p->SrcSpatial_p->DistAtten.RefDist = 1.0f; - Src_p->SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ - Src_p->SrcSpatial_p->DistAtten.RollOffFactor = 1.0f; FOR( Word16 nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ ) { fixedToFloat_arrL( Src_p->SrcSpatial_p->Pos_p_fx + nC * 3, Src_p->SrcSpatial_p->Pos_p + nC * 3, Q31, 3 ); @@ -572,9 +569,6 @@ ivas_error ivas_dec_setup( Src_p->SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f; - Src_p->SrcSpatial_p->DistAtten.RefDist = 1.0f; - Src_p->SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ - Src_p->SrcSpatial_p->DistAtten.RollOffFactor = 1.0f; FOR( Word16 nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ ) { fixedToFloat_arrL( Src_p->SrcSpatial_p->Pos_p_fx + nC * 3, Src_p->SrcSpatial_p->Pos_p + nC * 3, Q31, 3 ); @@ -1237,24 +1231,44 @@ ivas_error ivas_init_decoder_front( IF ( st_ivas->hDecoderConfig->Opt_HRTF_binary ) { - IF ( ( error = ivas_HRTF_binary_open( &( st_ivas->hHrtfTD ) ) ) != IVAS_ERR_OK ) +#ifdef IVAS_FLOAT_FIXED + IF( ( error = ivas_HRTF_binary_open_fx( &( st_ivas->hHrtfTD ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = ivas_HRTF_CRend_binary_open_fx( &( st_ivas->hSetOfHRTF ) ) ) != IVAS_ERR_OK ) { return error; } - IF ( ( error = ivas_HRTF_CRend_binary_open( &( st_ivas->hSetOfHRTF ) ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_HRTF_binary_open( &( st_ivas->hHrtfTD ) ) ) != IVAS_ERR_OK ) { return error; } + if ( ( error = ivas_HRTF_CRend_binary_open( &( st_ivas->hSetOfHRTF ) ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + IF ( ( error = ivas_HRTF_fastconv_binary_open( &st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) { return error; } - IF ( ( error = ivas_HRTF_parambin_binary_open( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#ifdef IVAS_FLOAT_FIXED + IF( ( error = ivas_HRTF_parambin_binary_open_fx( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { return error; } +#else + if ( ( error = ivas_HRTF_parambin_binary_open( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif } /*-------------------------------------------------------------------* @@ -1467,7 +1481,11 @@ ivas_error ivas_init_decoder_fx( /* init EFAP for custom LS output and set hTransSetup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { - IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hOutSetup.ls_azimuth, st_ivas->hOutSetup.ls_elevation, st_ivas->hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL( (float *) st_ivas->hOutSetup.ls_azimuth, (Word32 *) st_ivas->hOutSetup.ls_azimuth_fx, Q22, st_ivas->hOutSetup.nchan_out_woLFE ); + floatToFixed_arrL( (float *) st_ivas->hOutSetup.ls_elevation, (Word32 *) st_ivas->hOutSetup.ls_elevation_fx, Q22, st_ivas->hOutSetup.nchan_out_woLFE ); + /*float2fix block end*/ + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hOutSetup.ls_azimuth_fx, st_ivas->hOutSetup.ls_elevation_fx, st_ivas->hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -1540,7 +1558,11 @@ ivas_error ivas_init_decoder_fx( IF ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->hOutSetup.is_loudspeaker_setup ) { - IF ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL((float *)st_ivas->hOutSetup.ls_azimuth, (Word32 *)st_ivas->hOutSetup.ls_azimuth_fx, Q22, st_ivas->hIntSetup.ambisonics_order); + floatToFixed_arrL((float *)st_ivas->hOutSetup.ls_elevation, (Word32 *)st_ivas->hOutSetup.ls_elevation_fx, Q22, st_ivas->hIntSetup.ambisonics_order); + /*float2fix end*/ + IF ( ( error = ivas_sba_get_hoa_dec_matrix_fx( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } @@ -1693,7 +1715,11 @@ ivas_error ivas_init_decoder_fx( IF ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_DEC && st_ivas->hOutSetup.is_loudspeaker_setup ) { - IF ( ( error = ivas_sba_get_hoa_dec_matrix( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL((float *)st_ivas->hOutSetup.ls_azimuth, (Word32 *)st_ivas->hOutSetup.ls_azimuth_fx, Q22, st_ivas->hIntSetup.ambisonics_order); + floatToFixed_arrL((float *)st_ivas->hOutSetup.ls_elevation, (Word32 *)st_ivas->hOutSetup.ls_elevation_fx, Q22, st_ivas->hIntSetup.ambisonics_order); + /*float2fix end*/ + IF ( ( error = ivas_sba_get_hoa_dec_matrix_fx( st_ivas->hOutSetup, &st_ivas->hoa_dec_mtx, st_ivas->hIntSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } @@ -1889,7 +1915,11 @@ ivas_error ivas_init_decoder_fx( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { - IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_azimuth_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->ls_elevation_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + /*float2fix block end*/ + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth_fx, st_ivas->hLsSetupCustom->ls_elevation_fx, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -1924,7 +1954,11 @@ ivas_error ivas_init_decoder_fx( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { - IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_azimuth_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->ls_elevation_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + /*float2fix block end*/ + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth_fx, st_ivas->hLsSetupCustom->ls_elevation_fx, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -1964,7 +1998,11 @@ ivas_error ivas_init_decoder_fx( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { - IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + /*float2fix block: to be removed*/ + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_azimuth_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + floatToFixed_arrL(st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->ls_elevation_fx, Q22, st_ivas->hLsSetupCustom->num_spk); + /*float2fix block end*/ + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth_fx, st_ivas->hLsSetupCustom->ls_elevation_fx, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -2195,8 +2233,7 @@ ivas_error ivas_init_decoder_fx( IF ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { - - IF ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_binRenderer_open_fx( st_ivas ) ) != IVAS_ERR_OK ) { return error; } @@ -2261,7 +2298,7 @@ ivas_error ivas_init_decoder_fx( { IF ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) { - IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -4124,20 +4161,36 @@ void ivas_destroy_dec( #ifdef IVAS_FLOAT_FIXED BSplineModelEvalDealloc_fx( &st_ivas->hHrtfTD->ModelParams, &st_ivas->hHrtfTD->ModelEval ); #endif +#ifdef IVAS_FLOAT_FIXED + ivas_HRTF_binary_close_fx( &st_ivas->hHrtfTD ); +#else ivas_HRTF_binary_close( &st_ivas->hHrtfTD ); +#endif } /* CRend binaural renderer handle */ +#ifdef IVAS_FLOAT_FIXED + ivas_HRTF_CRend_binary_close_fx( &st_ivas->hSetOfHRTF ); +#else ivas_HRTF_CRend_binary_close( &st_ivas->hSetOfHRTF ); +#endif /* Fastconv HRTF memories */ ivas_binaural_hrtf_close( &st_ivas->hHrtfFastConv ); +#ifdef IVAS_FLOAT_FIXED + /* Fastconv HRTF filters */ + ivas_HRTF_fastconv_binary_close_fx( &st_ivas->hHrtfFastConv ); + + /* Parametric binauralizer HRTF filters */ + ivas_HRTF_parambin_binary_close_fx( &st_ivas->hHrtfParambin ); +#else /* Fastconv HRTF filters */ ivas_HRTF_fastconv_binary_close( &st_ivas->hHrtfFastConv ); /* Parametric binauralizer HRTF filters */ - ivas_HRTF_parambin_binary_close( &st_ivas->hHrtfParambin ); + ivas_HRTF_parambin_binary_close(&st_ivas->hHrtfParambin); +#endif /* Config. Renderer */ ivas_render_config_close( &( st_ivas->hRenderConfig ) ); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 57fa0c8ce..2028e6cf8 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -657,9 +657,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( Src_p->SrcSpatial_p->DirAtten.ConeInnerAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterAngle = 360.0f; Src_p->SrcSpatial_p->DirAtten.ConeOuterGain = 1.0f; - Src_p->SrcSpatial_p->DistAtten.RefDist = 1.0f; - Src_p->SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ - Src_p->SrcSpatial_p->DistAtten.RollOffFactor = 1.0f; FOR( Word16 nC = 0; nC < SPAT_BIN_MAX_INPUT_CHANNELS; nC++ ) { fixedToFloat_arrL( Src_p->SrcSpatial_p->Pos_p_fx + nC * 3, Src_p->SrcSpatial_p->Pos_p + nC * 3, Q31, 3 ); diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index e17a48831..eb6e5a174 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -865,7 +865,7 @@ static void ivas_param_ism_update_mixing_matrix( * * Open Param ISM handle *-------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED ivas_error ivas_param_ism_dec_open( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) @@ -981,7 +981,7 @@ ivas_error ivas_param_ism_dec_open( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) { /* Initialize efap handle */ - if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + if ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth_fx, hOutSetup.ls_elevation_fx, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -1118,7 +1118,210 @@ ivas_error ivas_param_ism_dec_open( pop_wmops(); return error; } +#else +ivas_error ivas_param_ism_dec_open( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + int16_t i; + PARAM_ISM_DEC_HANDLE hParamIsmDec; + IVAS_OUTPUT_SETUP hOutSetup; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + AUDIO_CONFIG output_config; + int32_t output_Fs; + ivas_error error; + + error = IVAS_ERR_OK; + + push_wmops( "ivas_param_ism_dec_open" ); + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hParamIsmDec = (PARAM_ISM_DEC_HANDLE) malloc( sizeof( PARAM_ISM_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ParamISM\n" ) ); + } + + if ( ( hSpatParamRendCom = (SPAT_PARAM_REND_COMMON_DATA_HANDLE) malloc( sizeof( SPAT_PARAM_REND_COMMON_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + /* Assign memory to Param Object handle */ + if ( ( hParamIsmDec->hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ParamISM\n" ) ); + } + + if ( ( hParamIsmDec->hParamIsmRendering = (PARAM_ISM_RENDERING_HANDLE) malloc( sizeof( PARAM_ISM_RENDERING_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ParamISM Rendering handle\n" ) ); + } + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + output_config = st_ivas->hDecoderConfig->output_config; + + ivas_param_ism_config( hParamIsmDec->hParamIsm, st_ivas->nchan_ism ); + + /*-----------------------------------------------------------------* + * set input parameters + *-----------------------------------------------------------------*/ + + hSpatParamRendCom->slot_size = (int16_t) ( ( output_Fs / FRAMES_PER_SEC ) / CLDFB_NO_COL_MAX ); + set_s( hSpatParamRendCom->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hSpatParamRendCom->subframe_nbslots, JBM_CLDFB_SLOTS_IN_SUBFRAME, DEFAULT_JBM_SUBFRAMES_5MS ); + hSpatParamRendCom->nb_subframes = DEFAULT_JBM_SUBFRAMES_5MS; + hSpatParamRendCom->subframes_rendered = 0; + hSpatParamRendCom->slots_rendered = 0; + hSpatParamRendCom->num_slots = DEFAULT_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME; + hSpatParamRendCom->num_freq_bands = (int16_t) ( output_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + + hParamIsmDec->hParamIsm->nbands = MAX_PARAM_ISM_NBANDS; + + for ( i = 0; i < ( hParamIsmDec->hParamIsm->nbands + 1 ); i++ ) + { + hParamIsmDec->hParamIsm->band_grouping[i] = Param_ISM_band_grouping[i]; + + if ( hParamIsmDec->hParamIsm->band_grouping[i] > hSpatParamRendCom->num_freq_bands ) + { + hParamIsmDec->hParamIsm->band_grouping[i] = hSpatParamRendCom->num_freq_bands; + } + } + + /*-----------------------------------------------------------------* + * output setup + *-----------------------------------------------------------------*/ + + /* hIntSetup and hOutSetup differs only for Binaural rendering */ + if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) + { + /* nchan_out is essential for memory initialization for CLDFB Synthesis */ + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->nchan_ism; + st_ivas->hIntSetup.is_loudspeaker_setup = 1; + } + + hOutSetup = st_ivas->hIntSetup; + + if ( !( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) + { + /* Initialize Param ISM Rendering handle */ + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { + if ( ( error = ivas_param_ism_rendering_init( hParamIsmDec->hParamIsmRendering, hOutSetup, st_ivas->nchan_transport, MAX_JBM_CLDFB_TIMESLOTS, output_config ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_param_ism_rendering_init( hParamIsmDec->hParamIsmRendering, hOutSetup, st_ivas->nchan_transport, CLDFB_NO_COL_MAX, output_config ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + if ( !( output_config == IVAS_AUDIO_CONFIG_EXTERNAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB || + output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) + { + /* Initialize efap handle */ + if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Azi and Ele values are transmitted once per frame per object */ + set_zero( hParamIsmDec->azimuth_values, MAX_NUM_OBJECTS ); + set_zero( hParamIsmDec->elevation_values, MAX_NUM_OBJECTS ); + + hSpatParamRendCom->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; + hSpatParamRendCom->dirac_bs_md_write_idx = 0; + hSpatParamRendCom->dirac_read_idx = 0; + + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_dirac_allocate_parameters( hSpatParamRendCom, 2 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + st_ivas->hISMDTX.dtx_flag = 0; + + st_ivas->hParamIsmDec = hParamIsmDec; + st_ivas->hSpatParamRendCom = hSpatParamRendCom; + + + if ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE ) + { + int16_t nchan_transport = st_ivas->nchan_transport; + int16_t nchan_full = 0; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + nchan_full = nchan_transport; + hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + } + else + { + int16_t n_slots_to_alloc; + if ( st_ivas->hDecoderConfig->Opt_tsm == 1 ) + { + n_slots_to_alloc = MAX_JBM_CLDFB_TIMESLOTS; + } + else + { + n_slots_to_alloc = CLDFB_SLOTS_PER_SUBFRAME * MAX_PARAM_SPATIAL_SUBFRAMES; + } + if ( ( hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc = (float *) malloc( n_slots_to_alloc * nchan_transport * hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM JBM Rendering handle\n" ) ); + } + set_zero( hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc, n_slots_to_alloc * nchan_transport * hSpatParamRendCom->num_freq_bands ); + + if ( ( hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc = (float *) malloc( n_slots_to_alloc * nchan_transport * hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM JBM Rendering handle\n" ) ); + } + set_zero( hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc, n_slots_to_alloc * nchan_transport * hSpatParamRendCom->num_freq_bands ); + } + + if ( st_ivas->hTcBuffer == NULL ) + { + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, nchan_transport, nchan_transport, nchan_full, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else + { + hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc = NULL; + hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc = NULL; + if ( st_ivas->hTcBuffer == NULL ) + { + int16_t nchan_to_allocate = st_ivas->hDecoderConfig->nchan_out; + if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_BUFFER, nchan_to_allocate, nchan_to_allocate, nchan_to_allocate, NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ) ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + pop_wmops(); + return error; +} +#endif /*-------------------------------------------------------------------------* * ivas_param_ism_dec_close() @@ -1649,7 +1852,7 @@ void ivas_ism_dec_digest_tc_fx( { azimuth_fx = L_shl( azimuth_fx, Q22 ); elevation_fx = L_shl( elevation_fx, Q22 ); - efap_determine_gains_fixed( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); + efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); } } ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) || @@ -1877,7 +2080,7 @@ void ivas_param_ism_dec_digest_tc( #ifdef IVAS_FLOAT_FIXED FOR( i = 0; i < st_ivas->nchan_ism; i++ ) { - efap_determine_gains_fixed( st_ivas->hEFAPdata, direct_response_fx[i], hParamIsmDec->azimuth_values_fx[i], hParamIsmDec->elevation_values_fx[i], EFAP_MODE_EFAP ); + efap_determine_gains_fx( st_ivas->hEFAPdata, direct_response_fx[i], hParamIsmDec->azimuth_values_fx[i], hParamIsmDec->elevation_values_fx[i], EFAP_MODE_EFAP ); } FOR( i = 0; i < st_ivas->nchan_ism; i++ ) diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 0e7d2deaa..1b45dbe78 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -129,7 +129,7 @@ ivas_error ivas_ism_renderer_open_fx( IF ( st_ivas->hIntSetup.is_loudspeaker_setup && st_ivas->hIntSetup.ls_azimuth != NULL && st_ivas->hIntSetup.ls_elevation != NULL && st_ivas->hEFAPdata == NULL ) { - IF ( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + IF ( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth_fx, st_ivas->hIntSetup.ls_elevation_fx, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { return error; } @@ -433,7 +433,7 @@ void ivas_ism_render_sf_fx( IF ( st_ivas->hEFAPdata != NULL ) { - efap_determine_gains_fixed( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl(azimuth, 22), L_shl(elevation, 22), EFAP_MODE_EFAP ); + efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl(azimuth, 22), L_shl(elevation, 22), EFAP_MODE_EFAP ); } } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 9f79b6a6f..9aa0a7109 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -2054,7 +2054,7 @@ static ivas_error ivas_mc_dec_reconfig( /* init necessary new renderers */ IF ( st_ivas->hBinRenderer == NULL && ( EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV) || EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV_ROOM) ) ) { - IF ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_binRenderer_open_fx( st_ivas ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 235e1cfad..1c9ec0308 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -130,213 +130,6 @@ ivas_error ivas_td_binaural_renderer( * and renders the current frame. *---------------------------------------------------------------------*/ -ivas_error ivas_td_binaural_renderer_sf( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - float *output[], /* i/o: SCE channels / Binaural synthesis */ - const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ -) -{ - int16_t first_sf, last_sf, subframe_idx; - float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; - float *p_reverb_signal[BINAURAL_CHANNELS]; - float *output_f_local[BINAURAL_CHANNELS]; - float *tc_local[MAX_TRANSPORT_CHANNELS]; - int16_t ch, slot_size, slots_to_render, output_frame; - ivas_error error; - - int16_t ism_md_subframe_update_jbm; - int16_t c_indx, nS; - int16_t nchan_ism_internal, nchan_ism, ch_offset; - - /* Set the number of ISMs */ - if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) - { - nchan_ism_internal = st_ivas->nchan_ism; - nchan_ism = st_ivas->nchan_ism; - ch_offset = 2; - } - else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) - { - nchan_ism_internal = st_ivas->nchan_ism; - nchan_ism = st_ivas->nchan_ism; - ch_offset = 0; - } - else - { - nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal; - nchan_ism = st_ivas->nchan_transport; - ch_offset = 0; - } - - /* Number of subframes to delay metadata to sync with audio */ - if ( st_ivas->hDecoderConfig->Opt_delay_comp ) - { - ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 3 ); - } - else - { - ism_md_subframe_update_jbm = st_ivas->hTcBuffer->nb_subframes - 2; - } - - if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) - { - ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 2 ); - } - - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - p_reverb_signal[ch] = reverb_signal[ch]; - } - - for ( ch = 0; ch < nchan_ism_internal; ch++ ) - { - tc_local[ch] = st_ivas->hTcBuffer->tc[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered; - } - - for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) - { - output_f_local[ch] = output[ch]; - } - - slot_size = st_ivas->hTcBuffer->n_samples_granularity; - - /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, n_samples_granularity / slot_size ); - first_sf = st_ivas->hTcBuffer->subframes_rendered; - last_sf = first_sf; - st_ivas->hTcBuffer->slots_rendered += slots_to_render; - - while ( slots_to_render > 0 ) - { - slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf]; - last_sf++; - } - - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) - { - output_frame = st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] * st_ivas->hTcBuffer->n_samples_granularity; - - /* Update object position(s) */ - c_indx = 0; - - for ( nS = 0; nS < nchan_ism; nS++ ) - { - if ( !( st_ivas->ivas_format == MC_FORMAT && nS == LFE_CHANNEL ) ) /* Skip LFE for MC */ - { - st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p = tc_local[nS]; - st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE; - c_indx++; - } - } - if ( subframe_idx == ism_md_subframe_update_jbm ) - { - if ( ( error = TDREND_Update_object_positions( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK ) - { - return error; - } - } - - /* Update the listener's location/orientation */ - if ( ( error = TDREND_Update_listener_orientation( st_ivas->hBinRendererTd, - ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] : 0, - ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx] : NULL, - ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx] : NULL ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) - { -#ifdef IVAS_FLOAT_FIXED - Word16 i,j,exp; - Word32 pcm_in_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - Word32 pcm_out_buff[BINAURAL_CHANNELS][L_FRAME48k]; - Word32 *pcm_in_fx[MAX_OUTPUT_CHANNELS]; - Word32 *pcm_out_fx[BINAURAL_CHANNELS]; - Word16 nchan_transport = audioCfg2channels( st_ivas->transport_config ); - REVERB_HANDLE hReverb = st_ivas->hReverb; - exp = Q7; - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) - { - pcm_in_fx[i] = pcm_in_buff[i]; - } - for ( i = 0; i < nchan_transport; i++ ) - { - - for ( j = 0; j < ( ( 0 + 1 ) * hReverb->full_block_size ); j++ ) - { - - pcm_in_fx[i][j] = (Word32) float_to_fixed( tc_local[i][j], exp ); - } - } - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - pcm_out_fx[i] = pcm_out_buff[i]; - } - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - - for ( j = 0; j < ( hReverb->full_block_size ); j++ ) - { - pcm_out_fx[i][0 * hReverb->full_block_size + j] = (Word32) float_to_fixed( p_reverb_signal[i][0 * hReverb->full_block_size + j], ( exp ) ); - } - } - - if ( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, pcm_in_fx, pcm_out_fx, 0 ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_reverb_process( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local, p_reverb_signal, 0 ) ) != IVAS_ERR_OK ) -#endif - { - return error; - } -#ifdef IVAS_FLOAT_FIXED - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - - for ( j = 0; j < ( hReverb->full_block_size ); j++ ) - { - - p_reverb_signal[i][0 * hReverb->full_block_size + j] = fixed_to_float( pcm_out_fx[i][0 * hReverb->full_block_size + j], ( exp - 2 ) ); - } - } -#endif - } - - /* Render subframe */ - /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx, - where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */ - if ( ( error = TDREND_GetMix( st_ivas->hBinRendererTd, output_f_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) - { - /* add reverb to rendered signals */ - v_add( reverb_signal[0], output_f_local[0], output_f_local[0], output_frame ); - v_add( reverb_signal[1], output_f_local[1], output_f_local[1], output_frame ); - } - - - for ( ch = 0; ch < nchan_ism_internal; ch++ ) - { - tc_local[ch] += output_frame; - } - - for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) - { - output_f_local[ch] += output_frame; - } - - /* update combined orientation access index */ - ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame ); - } - - st_ivas->hTcBuffer->subframes_rendered = last_sf; - - return IVAS_ERR_OK; -} - #ifdef IVAS_FLOAT_FIXED ivas_error ivas_td_binaural_renderer_sf_fx( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ @@ -362,16 +155,16 @@ ivas_error ivas_td_binaural_renderer_sf_fx( Word16 enableCombinedOrientation; /* Set the number of ISMs */ - IF ( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) { nchan_ism_internal = st_ivas->nchan_ism; move16(); nchan_ism = st_ivas->nchan_ism; move16(); ch_offset = 2; - move16(); + move16(); } - ELSE IF ( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + ELSE IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) { nchan_ism_internal = st_ivas->nchan_ism; move16(); @@ -383,7 +176,7 @@ ivas_error ivas_td_binaural_renderer_sf_fx( ELSE { nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal; - move16(); + move16(); nchan_ism = st_ivas->nchan_transport; move16(); ch_offset = 0; @@ -424,24 +217,24 @@ ivas_error ivas_td_binaural_renderer_sf_fx( /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ tmp = 0; - IF(n_samples_granularity != 0) + IF( n_samples_granularity != 0 ) { - tmp = idiv1616(n_samples_granularity, slot_size); + tmp = idiv1616( n_samples_granularity, slot_size ); } slots_to_render = s_min( sub( st_ivas->hTcBuffer->num_slots, st_ivas->hTcBuffer->slots_rendered ), tmp ); first_sf = st_ivas->hTcBuffer->subframes_rendered; move16(); last_sf = first_sf; move16(); - st_ivas->hTcBuffer->slots_rendered = add(st_ivas->hTcBuffer->slots_rendered, slots_to_render); + st_ivas->hTcBuffer->slots_rendered = add( st_ivas->hTcBuffer->slots_rendered, slots_to_render ); WHILE( slots_to_render > 0 ) { - slots_to_render = sub(slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf]); - last_sf = add(last_sf, 1); + slots_to_render = sub( slots_to_render, st_ivas->hTcBuffer->subframe_nbslots[last_sf] ); + last_sf = add( last_sf, 1 ); } - FOR ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) { output_frame = i_mult( st_ivas->hTcBuffer->subframe_nbslots[subframe_idx], st_ivas->hTcBuffer->n_samples_granularity ); @@ -457,13 +250,13 @@ ivas_error ivas_td_binaural_renderer_sf_fx( st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p_q = q_factor; st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE; move16(); - c_indx = add(c_indx, 1); + c_indx = add( c_indx, 1 ); } } - IF ( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) ) + IF( EQ_16( subframe_idx, ism_md_subframe_update_jbm ) ) { - IF ( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK ) + IF( ( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK ) { return error; } @@ -478,9 +271,7 @@ ivas_error ivas_td_binaural_renderer_sf_fx( /* Shifting w_fx, x_fx, y_fx, z_fx to a common Q-factor if they are not having the same Q-factor */ Word16 min_q; - IF ( !( EQ_16( tmp_Quaternion_fx->w_qfact, tmp_Quaternion_fx->x_qfact ) - && EQ_16( tmp_Quaternion_fx->x_qfact, tmp_Quaternion_fx->y_qfact ) - && EQ_16( tmp_Quaternion_fx->y_qfact, tmp_Quaternion_fx->z_qfact ) ) ) + IF( !( EQ_16( tmp_Quaternion_fx->w_qfact, tmp_Quaternion_fx->x_qfact ) && EQ_16( tmp_Quaternion_fx->x_qfact, tmp_Quaternion_fx->y_qfact ) && EQ_16( tmp_Quaternion_fx->y_qfact, tmp_Quaternion_fx->z_qfact ) ) ) { min_q = MAX16B; move16(); @@ -526,17 +317,17 @@ ivas_error ivas_td_binaural_renderer_sf_fx( move16(); } - IF ( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd, - enableCombinedOrientation, - tmp_Quaternion_fx, - tmp_vector_fx ) ) != IVAS_ERR_OK ) + IF( ( error = TDREND_Update_listener_orientation_fx( st_ivas->hBinRendererTd, + enableCombinedOrientation, + tmp_Quaternion_fx, + tmp_vector_fx ) ) != IVAS_ERR_OK ) { return error; } - IF ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + IF( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - IF ( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_reverb_process_fx( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local_fx, p_reverb_signal_fx, 0 ) ) != IVAS_ERR_OK ) { return error; } @@ -545,24 +336,24 @@ ivas_error ivas_td_binaural_renderer_sf_fx( /* Render subframe */ /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx, where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */ - IF ( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ) != IVAS_ERR_OK ) + IF( ( error = TDREND_GetMix_fx( st_ivas->hBinRendererTd, output_fx_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ) != IVAS_ERR_OK ) { return error; } - IF ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + IF( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { /* add reverb to rendered signals */ v_add_32( reverb_signal_fx[0], output_fx_local[0], output_fx_local[0], output_frame ); v_add_32( reverb_signal_fx[1], output_fx_local[1], output_fx_local[1], output_frame ); } - FOR ( ch = 0; ch < nchan_ism_internal; ch++ ) + FOR( ch = 0; ch < nchan_ism_internal; ch++ ) { tc_local_fx[ch] += output_frame; } - FOR ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { output_fx_local[ch] += output_frame; } @@ -576,4 +367,162 @@ ivas_error ivas_td_binaural_renderer_sf_fx( return IVAS_ERR_OK; } +#else +ivas_error ivas_td_binaural_renderer_sf( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + float *output[], /* i/o: SCE channels / Binaural synthesis */ + const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ +) +{ + int16_t first_sf, last_sf, subframe_idx; + float reverb_signal[BINAURAL_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; + float *p_reverb_signal[BINAURAL_CHANNELS]; + float *output_f_local[BINAURAL_CHANNELS]; + float *tc_local[MAX_TRANSPORT_CHANNELS]; + int16_t ch, slot_size, slots_to_render, output_frame; + ivas_error error; + + int16_t ism_md_subframe_update_jbm; + int16_t c_indx, nS; + int16_t nchan_ism_internal, nchan_ism, ch_offset; + + /* Set the number of ISMs */ + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + nchan_ism_internal = st_ivas->nchan_ism; + nchan_ism = st_ivas->nchan_ism; + ch_offset = 2; + } + else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) + { + nchan_ism_internal = st_ivas->nchan_ism; + nchan_ism = st_ivas->nchan_ism; + ch_offset = 0; + } + else + { + nchan_ism_internal = st_ivas->hTcBuffer->nchan_transport_internal; + nchan_ism = st_ivas->nchan_transport; + ch_offset = 0; + } + + /* Number of subframes to delay metadata to sync with audio */ + if ( st_ivas->hDecoderConfig->Opt_delay_comp ) + { + ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 3 ); + } + else + { + ism_md_subframe_update_jbm = st_ivas->hTcBuffer->nb_subframes - 2; + } + + if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + ism_md_subframe_update_jbm = max( 0, st_ivas->hTcBuffer->nb_subframes - 2 ); + } + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_reverb_signal[ch] = reverb_signal[ch]; + } + + for ( ch = 0; ch < nchan_ism_internal; ch++ ) + { + tc_local[ch] = st_ivas->hTcBuffer->tc[ch + ch_offset] + st_ivas->hTcBuffer->n_samples_rendered; + } + + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + output_f_local[ch] = output[ch]; + } + + slot_size = st_ivas->hTcBuffer->n_samples_granularity; + + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( st_ivas->hTcBuffer->num_slots - st_ivas->hTcBuffer->slots_rendered, n_samples_granularity / slot_size ); + first_sf = st_ivas->hTcBuffer->subframes_rendered; + last_sf = first_sf; + st_ivas->hTcBuffer->slots_rendered += slots_to_render; + + while ( slots_to_render > 0 ) + { + slots_to_render -= st_ivas->hTcBuffer->subframe_nbslots[last_sf]; + last_sf++; + } + + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + output_frame = st_ivas->hTcBuffer->subframe_nbslots[subframe_idx] * st_ivas->hTcBuffer->n_samples_granularity; + + /* Update object position(s) */ + c_indx = 0; + + for ( nS = 0; nS < nchan_ism; nS++ ) + { + if ( !( st_ivas->ivas_format == MC_FORMAT && nS == LFE_CHANNEL ) ) /* Skip LFE for MC */ + { + st_ivas->hBinRendererTd->Sources[c_indx]->InputFrame_p = tc_local[nS]; + st_ivas->hBinRendererTd->Sources[c_indx]->SrcRend_p->InputAvailable = TRUE; + c_indx++; + } + } + if ( subframe_idx == ism_md_subframe_update_jbm ) + { + if ( ( error = TDREND_Update_object_positions( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Update the listener's location/orientation */ + if ( ( error = TDREND_Update_listener_orientation( st_ivas->hBinRendererTd, + ( st_ivas->hCombinedOrientationData != NULL ) ? st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] : 0, + ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->Quaternions[st_ivas->hCombinedOrientationData->subframe_idx] : NULL, + ( st_ivas->hCombinedOrientationData != NULL ) ? &st_ivas->hCombinedOrientationData->listenerPos[st_ivas->hCombinedOrientationData->subframe_idx] : NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + if ( ( error = ivas_reverb_process( st_ivas->hReverb, st_ivas->transport_config, 0, tc_local, p_reverb_signal, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Render subframe */ + /* ism_md_subframe_update_jbm != subframe_idx: trigger update only for ism_md_subframe_update_jbm == subframe_idx, + where then the two TDREND_GetMix()-arguments subframe_idx and ism_md_subframe_update are equal, and we want to enforce the update inside TDREND_GetMix to use subframe_idx == 0 */ + if ( ( error = TDREND_GetMix( st_ivas->hBinRendererTd, output_f_local, output_frame, 0, ism_md_subframe_update_jbm != subframe_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hRenderConfig != NULL && st_ivas->hIntSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + /* add reverb to rendered signals */ + v_add( reverb_signal[0], output_f_local[0], output_f_local[0], output_frame ); + v_add( reverb_signal[1], output_f_local[1], output_f_local[1], output_frame ); + } + + + for ( ch = 0; ch < nchan_ism_internal; ch++ ) + { + tc_local[ch] += output_frame; + } + + for ( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + output_f_local[ch] += output_frame; + } + + /* update combined orientation access index */ + ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, output_frame ); + } + + st_ivas->hTcBuffer->subframes_rendered = last_sf; + + return IVAS_ERR_OK; +} #endif diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 7a6d7e05e..15fd1f788 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -139,15 +139,16 @@ void ivas_osba_data_close( * * Binaural rendering in JBM OSBA format *--------------------------------------------------------------------------*/ + #ifdef IVAS_FLOAT_FIXED ivas_error ivas_osba_dirac_td_binaural_jbm_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const UWord16 nSamplesAsked, /* i : number of CLDFB slots requested */ UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */ UWord16 *nSamplesAvailable, /* o : number of CLDFB slots still to render */ - Word32 *output_fx[], /* o : rendered time signal */ - const Word16 q_factor, /* i : q_factor of rendered time signal */ - Word16 out_len/*Store the length of values in each channel*/ + Word32 *output_fx[], /* o : rendered time signal */ + const Word16 q_factor, /* i : q_factor of rendered time signal */ + Word16 out_len /*Store the length of values in each channel*/ ) { Word16 n; @@ -156,7 +157,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( Word32 *p_sepobj_fx[BINAURAL_CHANNELS]; int16_t channel_offset; - FOR ( n = 0; n < BINAURAL_CHANNELS; n++ ) + FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) { p_sepobj_fx[n] = &output_separated_objects_fx[n][0]; } @@ -164,29 +165,27 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( channel_offset = st_ivas->nchan_ism; move16(); - IF ( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailable, &output_fx[channel_offset], out_len) ) != IVAS_ERR_OK ) + IF( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailable, &output_fx[channel_offset], out_len ) ) != IVAS_ERR_OK ) { return error; } - IF ( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, q_factor, *nSamplesRendered ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, q_factor, *nSamplesRendered ) ) != IVAS_ERR_OK ) { return error; } - FOR ( n = 0; n < BINAURAL_CHANNELS; n++ ) + FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) { Word16 i; - FOR ( i = 0; i < nSamplesAsked; i++ ) + FOR( i = 0; i < nSamplesAsked; i++ ) { - output_fx[n][i] = L_add(L_shr(output_fx[channel_offset + n][i],1) , L_shr(p_sepobj_fx[n][i],1)); + output_fx[n][i] = L_add( L_shr( output_fx[channel_offset + n][i], 1 ), L_shr( p_sepobj_fx[n][i], 1 ) ); } } return IVAS_ERR_OK; } - -#endif // IVAS_FLOAT_FIXED - +#else ivas_error ivas_osba_dirac_td_binaural_jbm( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ @@ -208,33 +207,10 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( channel_offset = st_ivas->nchan_ism; -#ifndef IVAS_FLOAT_FIXED if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailable, &output_f[channel_offset] ) ) != IVAS_ERR_OK ) { return error; } -#else - { - Word32 output_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - Word32 *output_f_fx[MAX_OUTPUT_CHANNELS]; - for (int i = 0; i < MAX_OUTPUT_CHANNELS; i++) - { - output_f_fx[i] = &output_fx[0][0]; - } - for ( n = 0; n < channel_offset; n++ ) - { - floatToFixed_arr32( output_f[n], output_fx[n], Q8, 960 ); - } - if ((error = ivas_sba_dec_render_fx(st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailable, &output_f_fx[channel_offset], 960)) != IVAS_ERR_OK) - { - return error; - } - for ( n = 0; n < channel_offset; n++ ) - { - fixedToFloat_arrL( output_fx[n], output_f[n], Q8, 960 ); - } - } -#endif if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_sepobj, *nSamplesRendered ) ) != IVAS_ERR_OK ) { @@ -249,9 +225,9 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( output_f[n][i] = 0.5f * output_f[channel_offset + n][i] + 0.5f * p_sepobj[n][i]; } } - return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------------* diff --git a/lib_dec/ivas_out_setup_conversion.c b/lib_dec/ivas_out_setup_conversion.c index e6c2a6f63..f2960375f 100644 --- a/lib_dec/ivas_out_setup_conversion.c +++ b/lib_dec/ivas_out_setup_conversion.c @@ -271,7 +271,7 @@ static void get_custom_ls_conversion_matrix_fx( Word32 dmxCoeff_LFE; /* TODO: remove the floating point dependency */ - float tmp_gains[MAX_OUTPUT_CHANNELS]; + Word32 tmp_gains[MAX_OUTPUT_CHANNELS]; lfe_in_idx = -1; move16(); @@ -324,7 +324,8 @@ static void get_custom_ls_conversion_matrix_fx( ELSE IF( NE_16( lfe_out_idx, ch_in ) ) { /* Set the values of hLsSetUpConversion->dmxMtx to EFAP gains, skipping LFE */ - efap_determine_gains( hEFAPdata, tmp_gains, hTransSetup.ls_azimuth[ch_in_woLFE], hTransSetup.ls_elevation[ch_in_woLFE], EFAP_MODE_EFAP ); + /*angles float2fix conversion: to be removed*/ + efap_determine_gains_fx( hEFAPdata, tmp_gains, L_shl((Word32)hTransSetup.ls_azimuth[ch_in_woLFE], Q22), L_shl((Word32)hTransSetup.ls_elevation[ch_in_woLFE], Q22), EFAP_MODE_EFAP ); FOR( ( ch_out = 0, ch_out_woLFE = 0 ); ch_out < nchan_out; ( ch_out++, ch_out_woLFE++ ) ) { @@ -334,8 +335,7 @@ static void get_custom_ls_conversion_matrix_fx( } ELSE { - // Currently efap_determine_gains returns float tmp_gains. - hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = float_to_fix( tmp_gains[ch_out_woLFE], Q30 ); + hLsSetUpConversion->dmxMtx_fx[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; move32(); } } diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index dcf1bcdbf..b27b05f87 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -1314,8 +1314,16 @@ ivas_error ivas_sba_dec_reconfigure_fx( if ( st_ivas->hBinRenderer == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) { + /*float2fix block: to be removed*/ + if (st_ivas->hIntSetup.ls_azimuth && st_ivas->hIntSetup.ls_azimuth_fx) { + floatToFixed_arrL((float *)st_ivas->hIntSetup.ls_azimuth, (Word32 *)st_ivas->hIntSetup.ls_azimuth_fx, Q22, st_ivas->hIntSetup.nchan_out_woLFE); + } + if (st_ivas->hIntSetup.ls_elevation && st_ivas->hIntSetup.ls_elevation_fx) { + floatToFixed_arrL((float *)st_ivas->hIntSetup.ls_elevation, (Word32 *)st_ivas->hIntSetup.ls_elevation_fx, Q22, st_ivas->hIntSetup.nchan_out_woLFE); + } + /*float2fix block end*/ /* open fastconv binaural renderer */ - if ( ( error = ivas_binRenderer_open( st_ivas ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_binRenderer_open_fx( st_ivas ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 9c42a0bf6..92d4479b2 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -1448,9 +1448,9 @@ ivas_error IVAS_DEC_FeedHeadTrackData( /* Move head-tracking data to the decoder handle */ /* check for Euler angle signaling */ - IF( orientation.w == -3.0f ) + IF( EQ_32( orientation.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { - Euler2Quat( deg2rad( orientation.x ), deg2rad( orientation.y ), deg2rad( orientation.z ), &orientation ); + Euler2Quat_fx( deg2rad_fx( orientation.x_fx ), deg2rad_fx( orientation.y_fx ), deg2rad_fx( orientation.z_fx ), &orientation ); } #ifdef IVAS_FLOAT_FIXED @@ -2939,6 +2939,12 @@ static ivas_error evs_dec_main( } st_ivas->BER_detect = hCoreCoder[0]->BER_detect; +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 i = 0; i < nOutSamples; i++ ) + { + p_output[0][i] = output_16[i]; + } +#endif IF( EQ_16( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) { mixer_left = ( st_ivas->hDecoderConfig->non_diegetic_pan_gain + 1.f ) * 0.5f; @@ -2946,12 +2952,7 @@ static ivas_error evs_dec_main( v_multc( p_output[0], mixer_rigth, p_output[1], nOutSamples ); v_multc( p_output[0], mixer_left, p_output[0], nOutSamples ); } -#ifdef IVAS_FLOAT_FIXED - FOR( Word16 i = 0; i < nOutSamples; i++ ) - { - p_output[0][i] = output_16[i]; - } -#endif + IF( !st_ivas->hDecoderConfig->Opt_tsm ) { ivas_jbm_dec_copy_tc_no_tsm( st_ivas, p_output, nOutSamples ); diff --git a/lib_rend/ivas_allrad_dec.c b/lib_rend/ivas_allrad_dec.c index 9900e16c6..e72dcf82e 100644 --- a/lib_rend/ivas_allrad_dec.c +++ b/lib_rend/ivas_allrad_dec.c @@ -162,7 +162,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( } #else #define TEMP_VAL 1963413621 // Q37 (1.f / num_td) -ivas_error ivas_sba_get_hoa_dec_matrix( +ivas_error ivas_sba_get_hoa_dec_matrix_fx( const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ const Word16 ambisonics_order /* i : Ambisonics order */ @@ -213,7 +213,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( ELSE IF( hOutSetup.is_loudspeaker_setup ) { /* init EFIP */ - IF( ( error = efap_init_data( &( hEFAP ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, num_spk, EFAP_MODE_EFIP ) ) != IVAS_ERR_OK ) + IF( ( error = efap_init_data_fx( &( hEFAP ), hOutSetup.ls_azimuth_fx, hOutSetup.ls_elevation_fx, num_spk, EFAP_MODE_EFIP ) ) != IVAS_ERR_OK ) { return error; } @@ -239,7 +239,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( } /* t-design to real LS panning gains */ - efap_determine_gains_fixed( hEFAP, G_td_int, t_design_azi[i], t_design_ele[i], EFAP_MODE_EFIP ); // G_td_int Q30 + efap_determine_gains_fx( hEFAP, G_td_int, t_design_azi[i], t_design_ele[i], EFAP_MODE_EFIP ); // G_td_int Q30 p_dec_mtx = *hoa_dec_mtx; FOR( j = 0; j < num_spk; j++ ) diff --git a/lib_rend/ivas_dirac_ana.c b/lib_rend/ivas_dirac_ana.c index c9f493c2c..a7f86d310 100644 --- a/lib_rend/ivas_dirac_ana.c +++ b/lib_rend/ivas_dirac_ana.c @@ -49,13 +49,12 @@ * Local function prototypes *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_param_est_ana( DIRAC_ANA_HANDLE hDirAC, Word32 data_f[][L_FRAME48k], Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const Word16 input_frame ); +static void ivas_dirac_param_est_ana_fx( DIRAC_ANA_HANDLE hDirAC, Word32 data_f[][L_FRAME48k], Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const Word16 input_frame ); static void ivas_dirac_dmx_fx( Word32 data_in_fx[][L_FRAME48k], const Word16 input_frame, const Word16 nchan_transport ); - #else static void ivas_dirac_param_est_ana( DIRAC_ANA_HANDLE hDirAC, float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const int16_t input_frame ); -#endif static void ivas_dirac_dmx( float data_in_f[][L_FRAME48k], const int16_t input_frame, const int16_t nchan_transport ); +#endif @@ -65,6 +64,113 @@ static void ivas_dirac_dmx( float data_in_f[][L_FRAME48k], const int16_t input_f * Allocate and initialize DIRAC handle *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_dirac_ana_open_fx( + DIRAC_ANA_HANDLE *hDirACPtr, /* i/o: DIRAC data handle pointer */ + Word32 input_Fs /* i : Sampling frequency */ +) +{ + Word16 i, j; + DIRAC_ANA_HANDLE hDirAC; + Word16 numAnalysisChannels; + Word16 maxBin; + ivas_error error; + + error = IVAS_ERR_OK; + + IF( ( hDirAC = (DIRAC_ANA_HANDLE) malloc( sizeof( DIRAC_ANA_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DIRAC\n" ) ); + } + + numAnalysisChannels = FOA_CHANNELS; + move16(); + + /* Determine the number of bands */ + hDirAC->nbands = MASA_FREQUENCY_BANDS; + move16(); + + /* Determine band grouping */ + Copy( MASA_band_grouping_24, hDirAC->band_grouping, 24 + 1 ); + + // maxBin = (int16_t) ( input_Fs * INV_CLDFB_BANDWIDTH + 0.5f ); + Word32 n_input_Fs = L_shl( input_Fs, 1 ); + Word32 val = L_add( Mpy_32_16_1( n_input_Fs, 41 /* INV_CLDFB_BANDWIDTH in Q15 */ ), 1 ); + val = L_shr( val, 1 ); + maxBin = extract_l( val ); + FOR( i = 1; i < hDirAC->nbands + 1; i++ ) + { + IF( GE_16( hDirAC->band_grouping[i], maxBin ) ) + { + hDirAC->band_grouping[i] = maxBin; + move16(); + hDirAC->nbands = i; + move16(); + BREAK; + } + } + + /* Determine block grouping */ + Copy( DirAC_block_grouping, hDirAC->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + + /* open/initialize CLDFB */ + hDirAC->num_Cldfb_instances = numAnalysisChannels; + move16(); + FOR( i = 0; i < hDirAC->num_Cldfb_instances; i++ ) + { + IF( ( error = openCldfb_ivas_fx( &( hDirAC->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + IF( ( hDirAC->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + IF( ( hDirAC->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set32_fx( hDirAC->direction_vector_m_fx[i][j], 0, MASA_FREQUENCY_BANDS ); + } + } + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + IF( ( hDirAC->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + set32_fx( hDirAC->buffer_intensity_real_fx[i][j], 0, MASA_FREQUENCY_BANDS ); + } + } + set32_fx( hDirAC->buffer_energy_fx, 0, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); + + hDirAC->index_buffer_intensity = 0; + move16(); + + IF( ( hDirAC->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + + IF( ( hDirAC->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + generate_gridEq_fx( hDirAC->sph_grid16 ); + + ( *hDirACPtr ) = hDirAC; + + return error; +} +#else ivas_error ivas_dirac_ana_open( DIRAC_ANA_HANDLE *hDirACPtr, /* i/o: DIRAC data handle pointer */ int32_t input_Fs /* i : Sampling frequency */ @@ -114,7 +220,7 @@ ivas_error ivas_dirac_ana_open( return error; } } -#ifndef IVAS_FLOAT_FIXED + /* intensity 3-dim */ for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { @@ -132,25 +238,7 @@ ivas_error ivas_dirac_ana_open( set_zero( hDirAC->direction_vector_m[i][j], MASA_FREQUENCY_BANDS ); } } -#else - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) - { - if ( ( hDirAC->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); - } - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) - { - if ( ( hDirAC->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); - } - set_val_Word32( hDirAC->direction_vector_m_fx[i][j], 0, MASA_FREQUENCY_BANDS ); - } - } -#endif -#ifndef IVAS_FLOAT_FIXED for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) @@ -162,21 +250,8 @@ ivas_error ivas_dirac_ana_open( set_zero( hDirAC->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS ); } } -#else - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) - { - for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) - { - if ( ( hDirAC->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); - } - set_val_Word32( hDirAC->buffer_intensity_real_fx[i][j], 0, MASA_FREQUENCY_BANDS ); - } - } - set_val_Word32( hDirAC->buffer_energy_fx, 0, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); -#endif - //set_zero( hDirAC->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); + + set_zero( hDirAC->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); hDirAC->index_buffer_intensity = 0; @@ -195,6 +270,7 @@ ivas_error ivas_dirac_ana_open( return error; } +#endif /*--------------------------------------------------------------------------* @@ -203,6 +279,52 @@ ivas_error ivas_dirac_ana_open( * Close DIRAC handle *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_ana_close_fx( + DIRAC_ANA_HANDLE( *hDirAC ) /* i/o: analysis DIRAC handle */ +) +{ + Word16 i, j; + + test(); + IF( hDirAC == NULL || *hDirAC == NULL ) + { + return; + } + + FOR( i = 0; i < ( *hDirAC )->num_Cldfb_instances; i++ ) + { + deleteCldfb_ivas_fx( &( ( *hDirAC )->cldfbAnaEnc[i] ) ); + } + + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hDirAC )->direction_vector_m_fx[i][j] ); + ( *hDirAC )->direction_vector_m_fx[i][j] = NULL; + } + free( ( *hDirAC )->direction_vector_m_fx[i] ); + ( *hDirAC )->direction_vector_m_fx[i] = NULL; + + FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hDirAC )->buffer_intensity_real_fx[i][j] ); + ( *hDirAC )->buffer_intensity_real_fx[i][j] = NULL; + } + } + + free( ( *hDirAC )->hMasaOut ); + ( *hDirAC )->hMasaOut = NULL; + free( ( *hDirAC )->sph_grid16 ); + ( *hDirAC )->sph_grid16 = NULL; + + free( ( *hDirAC ) ); + ( *hDirAC ) = NULL; + + return; +} +#else void ivas_dirac_ana_close( DIRAC_ANA_HANDLE( *hDirAC ) /* i/o: analysis DIRAC handle */ ) @@ -221,36 +343,20 @@ void ivas_dirac_ana_close( for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) { -#ifndef IVAS_FLOAT_FIXED for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { free( ( *hDirAC )->direction_vector_m[i][j] ); ( *hDirAC )->direction_vector_m[i][j] = NULL; } - free( ( *hDirAC )->direction_vector_m[i] ); - ( *hDirAC )->direction_vector_m[i] = NULL; -#else - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) - { - free( ( *hDirAC )->direction_vector_m_fx[i][j] ); - ( *hDirAC )->direction_vector_m_fx[i][j] = NULL; - } - free( ( *hDirAC )->direction_vector_m_fx[i] ); - ( *hDirAC )->direction_vector_m_fx[i] = NULL; -#endif -#ifndef IVAS_FLOAT_FIXED + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) { free( ( *hDirAC )->buffer_intensity_real[i][j] ); ( *hDirAC )->buffer_intensity_real[i][j] = NULL; } -#else - for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) - { - free( ( *hDirAC )->buffer_intensity_real_fx[i][j] ); - ( *hDirAC )->buffer_intensity_real_fx[i][j] = NULL; - } -#endif + + free( ( *hDirAC )->direction_vector_m[i] ); + ( *hDirAC )->direction_vector_m[i] = NULL; } free( ( *hDirAC )->hMasaOut ); @@ -263,7 +369,8 @@ void ivas_dirac_ana_close( return; } -#ifdef IVAS_FLOAT_FIXED +#endif + /*--------------------------------------------------------------------------* * ivas_dirac_ana() @@ -271,11 +378,12 @@ void ivas_dirac_ana_close( * DIRAC analysis function *--------------------------------------------------------------------------*/ -void ivas_dirac_ana( - DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_ana_fx( + DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ Word32 data_fx[][L_FRAME48k], /* i/o: Input / transport audio signals */ const Word16 input_frame, /* i : Input frame size */ - const Word16 nchan_transport /* i : Number of transport channels */ + const Word16 nchan_transport /* i : Number of transport channels */ ) { Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; @@ -284,24 +392,21 @@ void ivas_dirac_ana( Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; Word16 energyRatio_q, surroundingCoherence_q = 0, spreadCoherence_q = 0; + move16(); + move16(); /* Estimate MASA parameters from the SBA signals */ - ivas_dirac_param_est_ana( hDirAC, data_fx, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame ); + ivas_dirac_param_est_ana_fx( hDirAC, data_fx, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame ); energyRatio_q = 30; + move16(); /* Create MASA metadata buffer from the estimated values */ ivas_create_masa_out_meta_fx( hDirAC->hMasaOut, hDirAC->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, energyRatio_q, spreadCoherence_q, surroundingCoherence_q ); /* Downmix */ - ivas_dirac_dmx_fx( data_fx, input_frame, nchan_transport );//output Q of data_fx is same as that of input - + ivas_dirac_dmx_fx( data_fx, input_frame, nchan_transport ); // output Q of data_fx is same as that of input + return; } #else -/*--------------------------------------------------------------------------* - * ivas_dirac_ana() - * - * DIRAC analysis function - *--------------------------------------------------------------------------*/ - void ivas_dirac_ana( DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ float data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ @@ -327,16 +432,16 @@ void ivas_dirac_ana( return; } - #endif -#ifdef IVAS_FLOAT_FIXED + /*--------------------------------------------------------------------------* * Local functions *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED /* Estimate MASA parameters from the SBA signals */ -static void ivas_dirac_param_est_ana( +static void ivas_dirac_param_est_ana_fx( DIRAC_ANA_HANDLE hDirAC, Word32 data_fx[][L_FRAME48k], Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], @@ -378,235 +483,276 @@ static void ivas_dirac_param_est_ana( tmp = shr( tmp, negate( add( 1, tmp_e ) ) ); l_ts = tmp; numAnalysisChannels = FOA_CHANNELS; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + /* do processing over all CLDFB time slots */ - FOR ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) { mrange[0] = hDirAC->block_grouping[block_m_idx]; + move16(); mrange[1] = hDirAC->block_grouping[block_m_idx + 1]; + move16(); - FOR ( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) { hDirAC->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0; + move32(); hDirAC->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0; + move32(); hDirAC->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0; + move32(); } /* Need to initialize renormalization_factors, and variables to be normalized */ - set_val_Word32( renormalization_factor_diff_fx, 0, hDirAC->nbands ); - set_val_Word32( diffuseness_m_fx, 0, hDirAC->nbands ); - set_val_Word32( hDirAC->energy_fx[block_m_idx], 0, MASA_FREQUENCY_BANDS ); - set_val_Word32( hDirAC->energy_fx[block_m_idx], 0, MASA_FREQUENCY_BANDS ); + set32_fx( renormalization_factor_diff_fx, 0, hDirAC->nbands ); + set32_fx( diffuseness_m_fx, 0, hDirAC->nbands ); + set32_fx( hDirAC->energy_fx[block_m_idx], 0, MASA_FREQUENCY_BANDS ); + set32_fx( hDirAC->energy_fx[block_m_idx], 0, MASA_FREQUENCY_BANDS ); - FOR ( ts = mrange[0]; ts < mrange[1]; ts++ ) + FOR( ts = mrange[0]; ts < mrange[1]; ts++ ) { - FOR ( i = 0; i < numAnalysisChannels; i++ ) + FOR( i = 0; i < numAnalysisChannels; i++ ) { - io_q = Q7;// Input Q of data_fx + io_q = Q7; // Input Q of data_fx + move16(); cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][l_ts * ts] ), Foa_RealBuffer_fx[i], Foa_ImagBuffer_fx[i], l_ts, hDirAC->cldfbAnaEnc[i], &io_q ); } scale_fact = getScaleFactor32( (const Word32 *) Foa_RealBuffer_fx, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ); - scale_fact = min( getScaleFactor32( (const Word32 *) Foa_ImagBuffer_fx, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ), scale_fact ); - FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + scale_fact = s_min( getScaleFactor32( (const Word32 *) Foa_ImagBuffer_fx, FOA_CHANNELS * CLDFB_NO_CHANNELS_MAX ), scale_fact ); + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - Foa_RealBuffer_fx[i][j] = L_shl( Foa_RealBuffer_fx[i][j], ( scale_fact - Q3 ) ); // Q( scale_fact + Q1 ) - Foa_ImagBuffer_fx[i][j] = L_shl( Foa_ImagBuffer_fx[i][j], ( scale_fact - Q3 ) ); // Q( scale_fact + Q1 ) + Foa_RealBuffer_fx[i][j] = L_shl( Foa_RealBuffer_fx[i][j], sub( scale_fact, Q3 ) ); // Q( scale_fact + Q1 ) + move32(); + Foa_ImagBuffer_fx[i][j] = L_shl( Foa_ImagBuffer_fx[i][j], sub( scale_fact, Q3 ) ); // Q( scale_fact + Q1 ) + move32(); } } /* Compute omni energy for metadata processing */ - FOR ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ ) { brange[0] = hDirAC->band_grouping[band_m_idx]; + move16(); brange[1] = hDirAC->band_grouping[band_m_idx + 1]; - FOR ( j = brange[0]; j < brange[1]; j++ ) + move16(); + FOR( j = brange[0]; j < brange[1]; j++ ) { hDirAC->energy_fx[block_m_idx][band_m_idx] = ( L_add( hDirAC->energy_fx[block_m_idx][band_m_idx], L_add( Mpy_32_32( Foa_RealBuffer_fx[0][j], Foa_RealBuffer_fx[0][j] ), Mpy_32_32( Foa_ImagBuffer_fx[0][j], Foa_ImagBuffer_fx[0][j] ) ) ) ); // 2*( scale_fact + Q1 )-31 + move32(); } } /* Direction estimation */ computeIntensityVector_ana_fx( hDirAC->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); // 2 * ( scale_fact + Q1 ) - 31 - exp = ( 2 * ( scale_fact - Q1 ) - 31 ); + exp = sub( shl( sub( scale_fact, Q1 ), 1 ), 31 ); computeDirectionVectors_fx( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2], &exp ); /* Power estimation for diffuseness */ computeReferencePower_ana_fx( hDirAC->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); //( 2 * ( scale_fact - Q1 ) - 31 - 1 ); // computeReferencePower_ana( hDirAC->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, reference_power[ts], num_freq_bands ); - exp2 = ( 2 * ( scale_fact ) - 31 ); + exp2 = sub( shl( scale_fact, 1 ), 31 ); /* Fill buffers of length "averaging_length" time slots for intensity and energy */ - hDirAC->index_buffer_intensity = ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + hDirAC->index_buffer_intensity = add( ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */ index = hDirAC->index_buffer_intensity; + move16(); Word16 guard_bits = find_guarded_bits_fx( DIRAC_NO_COL_AVG_DIFF ); scale_fact2 = getScaleFactor32( (const Word32 *) intensity_real_fx, DIRAC_NUM_DIMS * MASA_FREQUENCY_BANDS ); - IF ( guard_bits > scale_fact2 ) + IF( GT_16( guard_bits, scale_fact2 ) ) { - FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - intensity_real_fx[i][j] = L_shr( intensity_real_fx[i][j], guard_bits - scale_fact2 ); + intensity_real_fx[i][j] = L_shr( intensity_real_fx[i][j], sub( guard_bits, scale_fact2 ) ); + move32(); } } - q_factor_intensity = 2 * ( scale_fact - 1 ) - 31 - ( guard_bits - scale_fact2 ); + q_factor_intensity = sub( sub( shl( sub( scale_fact, 1 ), 1 ), 31 ), sub( guard_bits, scale_fact2 ) ); } ELSE { - FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - intensity_real_fx[i][j] = L_shl( intensity_real_fx[i][j], scale_fact2 - guard_bits ); + intensity_real_fx[i][j] = L_shl( intensity_real_fx[i][j], sub( scale_fact2, guard_bits ) ); + move32(); } } - q_factor_intensity = 2 * ( scale_fact - 1 ) - 31 + scale_fact2 - guard_bits; + q_factor_intensity = add( sub( shl( sub( scale_fact, 1 ), 1 ), 31 ), sub( scale_fact2, guard_bits ) ); } scale_fact2 = getScaleFactor32( reference_power_fx[ts], MASA_FREQUENCY_BANDS ); - IF ( guard_bits > scale_fact2 ) + IF( GT_16( guard_bits, scale_fact2 ) ) { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - reference_power_fx[ts][j] = L_shr( reference_power_fx[ts][j], guard_bits - scale_fact2 ); + reference_power_fx[ts][j] = L_shr( reference_power_fx[ts][j], sub( guard_bits, scale_fact2 ) ); + move32(); } - q_factor_energy = 2 * ( scale_fact ) - 31 - ( guard_bits - scale_fact2 ); + q_factor_energy = sub( sub( shl( scale_fact, 1 ), 31 ), sub( guard_bits, scale_fact2 ) ); } ELSE { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - reference_power_fx[ts][j] = L_shl( reference_power_fx[ts][j], scale_fact2 - guard_bits ); + reference_power_fx[ts][j] = L_shl( reference_power_fx[ts][j], sub( scale_fact2, guard_bits ) ); + move32(); } - q_factor_energy = 2 * ( scale_fact ) - 31 + scale_fact2 - guard_bits; + q_factor_energy = add( sub( shl( scale_fact, 1 ), 31 ), sub( scale_fact2, guard_bits ) ); } - IF ( q_factor_intensity_old != 0 ) + IF( NE_16( q_factor_intensity_old, 0 ) ) { - IF ( q_factor_intensity_old < q_factor_intensity ) + IF( LT_16( q_factor_intensity_old, q_factor_intensity ) ) { - FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - intensity_real_fx[i][j] = L_shr( intensity_real_fx[i][j], q_factor_intensity - q_factor_intensity_old ); + intensity_real_fx[i][j] = L_shr( intensity_real_fx[i][j], sub( q_factor_intensity, q_factor_intensity_old ) ); + move32(); } } q_factor_intensity = q_factor_intensity_old; + move16(); } ELSE { FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { - FOR ( j = 0; j < index - 1; j++ ) + FOR( j = 0; j < index - 1; j++ ) { /* only real part needed */ - FOR ( Word16 k = 0; k < num_freq_bands; k++ ) + FOR( Word16 k = 0; k < num_freq_bands; k++ ) { - hDirAC->buffer_intensity_real_fx[i][j][k] = L_shr( hDirAC->buffer_intensity_real_fx[i][j][k], q_factor_intensity_old - q_factor_intensity ); + hDirAC->buffer_intensity_real_fx[i][j][k] = L_shr( hDirAC->buffer_intensity_real_fx[i][j][k], sub( q_factor_intensity_old, q_factor_intensity ) ); + move32(); } } } } } - IF ( q_factor_energy_old != 0 ) + IF( NE_16( q_factor_energy_old, 0 ) ) { - IF ( q_factor_energy_old < q_factor_energy ) + IF( LT_16( q_factor_energy_old, q_factor_energy ) ) { - FOR ( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - reference_power_fx[ts][j] = L_shr( reference_power_fx[ts][j], q_factor_energy - q_factor_energy_old ); + reference_power_fx[ts][j] = L_shr( reference_power_fx[ts][j], sub( q_factor_energy, q_factor_energy_old ) ); + move32(); } q_factor_energy = q_factor_energy_old; + move16(); } ELSE { - FOR ( i = 0; i < index - 1; i++ ) + FOR( i = 0; i < index - 1; i++ ) { - FOR ( j = 0; j < num_freq_bands; j++ ) + FOR( j = 0; j < num_freq_bands; j++ ) { - FOR ( Word16 k = 0; k < num_freq_bands; k++ ) + FOR( Word16 k = 0; k < num_freq_bands; k++ ) { - hDirAC->buffer_energy_fx[i * j + k] = L_shr( hDirAC->buffer_energy_fx[i * j + k], q_factor_energy_old - q_factor_energy_old ); + hDirAC->buffer_energy_fx[i * j + k] = L_shr( hDirAC->buffer_energy_fx[i * j + k], sub( q_factor_energy_old, q_factor_energy_old ) ); + move32(); } } } } } - FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) { /* only real part needed */ - mvr2r_Word32( intensity_real_fx[i], &( hDirAC->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); + Copy32( intensity_real_fx[i], &( hDirAC->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); } - mvr2r_Word32( reference_power_fx[ts], &( hDirAC->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + Copy32( reference_power_fx[ts], &( hDirAC->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands ); computeDiffuseness_fx( hDirAC->buffer_intensity_real_fx, hDirAC->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx, q_factor_intensity, q_factor_energy, diffuseness_vector_exp ); q_factor_intensity_old = q_factor_intensity; + move16(); q_factor_energy_old = q_factor_energy; - FOR ( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + move16(); + FOR( j = 0; j < MASA_FREQUENCY_BANDS; j++ ) { - IF ( diffuseness_vector_exp[j] < 10 ) + IF( LT_16( diffuseness_vector_exp[j], 10 ) ) { diffuseness_vector_fx[j] = 0; + move16(); } } - FOR ( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) { - norm_tmp_fx = Mpy_32_32( reference_power_fx[ts][band_m_idx], ( L_sub( ONE_IN_Q30, L_shr( diffuseness_vector_fx[band_m_idx], 30 - diffuseness_vector_exp[band_m_idx] ) ) ) ); // q_factor_energy-1 - - hDirAC->direction_vector_m_fx[0][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), hDirAC->direction_vector_m_fx[0][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) - hDirAC->direction_vector_m_fx[1][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), hDirAC->direction_vector_m_fx[1][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) - hDirAC->direction_vector_m_fx[2][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), hDirAC->direction_vector_m_fx[2][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) - - diffuseness_m_fx[band_m_idx] = L_add( diffuseness_m_fx[band_m_idx], Mpy_32_32( reference_power_fx[ts][band_m_idx], L_shr( diffuseness_vector_fx[band_m_idx], 30 - diffuseness_vector_exp[band_m_idx] ) ) ); // Qq_factor_energy-1 - renormalization_factor_diff_fx[band_m_idx] = L_add( renormalization_factor_diff_fx[band_m_idx], reference_power_fx[ts][band_m_idx] ); // Qq_factor_energy + norm_tmp_fx = Mpy_32_32( reference_power_fx[ts][band_m_idx], ( L_sub( ONE_IN_Q30, L_shr( diffuseness_vector_fx[band_m_idx], sub( 30, diffuseness_vector_exp[band_m_idx] ) ) ) ) ); // q_factor_energy-1 + + hDirAC->direction_vector_m_fx[0][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), hDirAC->direction_vector_m_fx[0][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) + move32(); + hDirAC->direction_vector_m_fx[1][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), hDirAC->direction_vector_m_fx[1][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) + move32(); + hDirAC->direction_vector_m_fx[2][block_m_idx][band_m_idx] = L_add( Mpy_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), hDirAC->direction_vector_m_fx[2][block_m_idx][band_m_idx] ); // Q (q_factor_energy + exp -32) + move32(); + + diffuseness_m_fx[band_m_idx] = L_add( diffuseness_m_fx[band_m_idx], Mpy_32_32( reference_power_fx[ts][band_m_idx], L_shr( diffuseness_vector_fx[band_m_idx], sub( 30, diffuseness_vector_exp[band_m_idx] ) ) ) ); // Qq_factor_energy-1 + move32(); + renormalization_factor_diff_fx[band_m_idx] = L_add( renormalization_factor_diff_fx[band_m_idx], reference_power_fx[ts][band_m_idx] ); // Qq_factor_energy + move32(); } } - FOR ( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) { - FOR ( d = 0; d < DIRAC_NUM_DIMS; d++ ) + FOR( d = 0; d < DIRAC_NUM_DIMS; d++ ) { dir_v[d] = hDirAC->direction_vector_m_fx[d][block_m_idx][band_m_idx]; + move32(); } - dir_q = q_factor_energy + exp - 32; + dir_q = add( q_factor_energy, sub( exp, 32 ) ); ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v, dir_q, &azimuth_m_values[block_m_idx][band_m_idx], &elevation_m_values[block_m_idx][band_m_idx] ); } /* Determine energy ratios */ - FOR ( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) { - IF ( renormalization_factor_diff_fx[band_m_idx] > EPSILON_FX ) + IF( GT_32( renormalization_factor_diff_fx[band_m_idx], EPSILON_FX ) ) { diffuseness_m_fx[band_m_idx] = BASOP_Util_Divide3232_Scale( diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &exp_div ); + move32(); } ELSE { diffuseness_m_fx[band_m_idx] = 0; + move32(); } - exp_div = 30 - exp_div; - energyRatio[block_m_idx][band_m_idx] = L_sub( L_shl( 1, 30 ), L_shl( diffuseness_m_fx[band_m_idx], 30 - exp_div ) ); // Q30 + exp_div = sub( 30, exp_div ); + energyRatio[block_m_idx][band_m_idx] = L_sub( L_shl( 1, 30 ), L_shl( diffuseness_m_fx[band_m_idx], sub( 30, exp_div ) ) ); // Q30 + move32(); } - FOR ( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) + FOR( band_m_idx = 0; band_m_idx < hDirAC->nbands; band_m_idx++ ) { spreadCoherence[block_m_idx][band_m_idx] = 0; + move32(); surroundingCoherence[block_m_idx][band_m_idx] = 0; + move32(); } } return; } #else -/*--------------------------------------------------------------------------* - * Local functions - *--------------------------------------------------------------------------*/ - /* Estimate MASA parameters from the SBA signals */ static void ivas_dirac_param_est_ana( DIRAC_ANA_HANDLE hDirAC, @@ -743,35 +889,36 @@ static void ivas_dirac_param_est_ana( return; } - #endif + + #ifdef IVAS_FLOAT_FIXED /* Compute downmix */ static void ivas_dirac_dmx_fx( - Word32 data_in_f[][L_FRAME48k], + Word32 data_in_fx[][L_FRAME48k], const Word16 input_frame, - const Word16 nchan_transport) + const Word16 nchan_transport ) { Word16 i; - Word32 data_out_f[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k]; + Word32 data_out_fx[MASA_MAX_TRANSPORT_CHANNELS][L_FRAME48k]; - if ( nchan_transport == 2 ) + IF( EQ_16( nchan_transport, 2 ) ) { - v_add_fx( data_in_f[0], data_in_f[1], data_out_f[0], input_frame ); - v_multc_fixed( data_out_f[0], ONE_IN_Q30, data_out_f[0], input_frame ); // ONE_IN_Q30 = 0.5* ONE_IN_Q31 + v_add_fx( data_in_fx[0], data_in_fx[1], data_out_fx[0], input_frame ); + v_multc_fixed( data_out_fx[0], ONE_IN_Q30, data_out_fx[0], input_frame ); // ONE_IN_Q30 = 0.5* ONE_IN_Q31 - v_sub_fixed( data_in_f[0], data_in_f[1], data_out_f[1], input_frame,0 ); - v_multc_fixed( data_out_f[1], ONE_IN_Q30, data_out_f[1], input_frame ); + v_sub_fixed( data_in_fx[0], data_in_fx[1], data_out_fx[1], input_frame, 0 ); + v_multc_fixed( data_out_fx[1], ONE_IN_Q30, data_out_fx[1], input_frame ); - for ( i = 0; i < nchan_transport; i++ ) + FOR( i = 0; i < nchan_transport; i++ ) { - mvr2r_Word32( data_out_f[i], data_in_f[i], input_frame ); + Copy32( data_out_fx[i], data_in_fx[i], input_frame ); } } /* output Q is same as input Q*/ return; } -#endif +#else /* Compute downmix */ static void ivas_dirac_dmx( float data_in_f[][L_FRAME48k], @@ -797,3 +944,4 @@ static void ivas_dirac_dmx( return; } +#endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 2e3ea1d4b..9968120a2 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -1485,7 +1485,7 @@ static void ivas_dirac_dec_binaural_internal( } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - FOR( slot = 0; slot < 4; slot++ ) + FOR( slot = 0; slot < numInChannels; slot++ ) { q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxRe[ch][slot], nBins ) ); q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxIm[ch][slot], nBins ) ); @@ -1510,7 +1510,7 @@ static void ivas_dirac_dec_binaural_internal( } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - FOR( slot = 0; slot < 4; slot++ ) + FOR( slot = 0; slot < numInChannels; slot++ ) { floatToFixed_arr16( hDiracDecBin->processMtxRe[ch][slot], hDiracDecBin->processMtxRe_fx[ch][slot], q_mat, nBins ); floatToFixed_arr16( hDiracDecBin->processMtxIm[ch][slot], hDiracDecBin->processMtxIm_fx[ch][slot], q_mat, nBins ); @@ -3462,7 +3462,220 @@ static void matrixTransp2Mul( return; } +#ifdef IVAS_FLOAT_FIXED +static void chol2x2_fx( + const Word32 E1, + const Word32 E2, + Word16 q_E, + const Word32 Cre, + const Word32 Cim, + Word16 q_C, + Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *q_out ) +{ + Word16 chA, chB; + Word32 sqrtVal_fx, temp; + Word16 exp, q_re1, q_re2, q_re3, q_im, q_tmp; + Word32 e1, e2, c_re, c_im; + Word16 q_e, q_c; + + exp = sub( get_min_scalefactor( E1, E2 ), 1 ); + e1 = L_shl( E1, exp ); + e2 = L_shl( E2, exp ); + q_e = add( q_E, exp ); + + exp = sub( get_min_scalefactor( Cre, Cim ), 1 ); + c_re = L_shl( Cre, exp ); + c_im = L_shl( Cim, exp ); + q_c = add( q_C, exp ); + + + FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) + { + outRe[chA][chB] = 0; + move32(); + outIm[chA][chB] = 0; + move32(); + } + } + + IF( GT_32( e1, e2 ) ) /* Perform Cholesky decomposition according to louder channel first */ + { + exp = sub( 31, q_e ); + outRe[0][0] = Sqrt32( e1, &exp ); + move32(); + q_re1 = sub( 31, exp ); + + // 4611686 = 1e-12 in Q62 + IF( EQ_32( outRe[0][0], 0 ) ) + { + outRe[1][0] = BASOP_Util_Divide3232_Scale_cadence( c_re, 4611686, &exp ); + move32(); + q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) ); + + outIm[1][0] = BASOP_Util_Divide3232_Scale_cadence( c_im, 4611686, &exp ); + move32(); + q_im = add( sub( 31, exp ), sub( q_c, 62 ) ); + } + ELSE + { + outRe[1][0] = BASOP_Util_Divide3232_Scale_cadence( c_re, outRe[0][0], &exp ); + move32(); + q_re2 = add( sub( 31, exp ), sub( q_c, q_re1 ) ); + + outIm[1][0] = BASOP_Util_Divide3232_Scale_cadence( c_im, outRe[0][0], &exp ); + move32(); + q_im = add( sub( 31, exp ), sub( q_c, q_re1 ) ); + } + IF( EQ_32( outRe[1][0], 0 ) ) + { + q_re2 = Q31; + move16(); + } + IF( EQ_32( outIm[1][0], 0 ) ) + { + q_im = Q31; + move16(); + } + + temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im ); + q_tmp = sub( add( q_c, q_c ), 31 ); + + // 4611686 = Q62 + IF( EQ_32( e1, 0 ) ) + { + temp = BASOP_Util_Divide3232_Scale_cadence( temp, 4611686, &exp ); + q_tmp = add( sub( 31, exp ), sub( q_tmp, 62 ) ); + } + ELSE + { + temp = BASOP_Util_Divide3232_Scale_cadence( temp, e1, &exp ); + q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) ); + } + IF( EQ_32( temp, 0 ) ) + { + q_tmp = Q31; + move16(); + } + + IF( LT_16( q_e, q_tmp ) ) + { + sqrtVal_fx = L_sub( e2, L_shr( temp, sub( q_tmp, q_e ) ) ); + q_tmp = q_e; + move16(); + } + ELSE + { + sqrtVal_fx = L_sub( L_shr( e2, sub( q_e, q_tmp ) ), temp ); + } + + exp = sub( 31, q_tmp ); + outRe[1][1] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp ); + move32(); + q_re3 = sub( 31, exp ); + + *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) ); + outRe[0][0] = L_shr( outRe[0][0], sub( q_re1, *q_out ) ); + move32(); + outRe[1][0] = L_shr( outRe[1][0], sub( q_re2, *q_out ) ); + move32(); + outIm[1][0] = L_shr( outIm[1][0], sub( q_im, *q_out ) ); + move32(); + outRe[1][1] = L_shr( outRe[1][1], sub( q_re3, *q_out ) ); + move32(); + } + ELSE + { + exp = sub( 31, q_e ); + outRe[1][1] = Sqrt32( e2, &exp ); + move32(); + q_re1 = sub( 31, exp ); + + // 4611686 = Q62 + IF( EQ_32( outRe[1][1], 0 ) ) + { + outRe[0][1] = BASOP_Util_Divide3232_Scale_cadence( c_re, 4611686, &exp ); + move32(); + q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) ); + + outIm[0][1] = BASOP_Util_Divide3232_Scale_cadence( -c_im, 4611686, &exp ); + move32(); + q_im = add( sub( 31, exp ), sub( q_c, 62 ) ); + } + ELSE + { + outRe[0][1] = BASOP_Util_Divide3232_Scale_cadence( c_re, outRe[1][1], &exp ); + move32(); + q_re2 = add( sub( 31, exp ), sub( q_c, q_re1 ) ); + + outIm[0][1] = BASOP_Util_Divide3232_Scale_cadence( -c_im, outRe[1][1], &exp ); + move32(); + q_im = add( sub( 31, exp ), sub( q_c, q_re1 ) ); + } + IF( EQ_32( outRe[0][1], 0 ) ) + { + q_re2 = Q31; + move16(); + } + IF( EQ_32( outIm[0][1], 0 ) ) + { + q_im = Q31; + move16(); + } + + temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im ); + q_tmp = sub( add( q_c, q_c ), 31 ); + + // 4611686 = 1e-12 in Q62 + IF( EQ_32( e2, 0 ) ) + { + temp = BASOP_Util_Divide3232_Scale_cadence( temp, 4611686, &exp ); + q_tmp = add( sub( 31, exp ), sub( q_tmp, 62 ) ); + } + ELSE + { + temp = BASOP_Util_Divide3232_Scale_cadence( temp, e2, &exp ); + q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) ); + } + IF( EQ_32( temp, 0 ) ) + { + q_tmp = Q31; + move16(); + } + IF( LT_16( q_e, q_tmp ) ) + { + sqrtVal_fx = L_sub( e1, L_shr( temp, sub( q_tmp, q_e ) ) ); + q_tmp = q_e; + move16(); + } + ELSE + { + sqrtVal_fx = L_sub( L_shr( e1, sub( q_e, q_tmp ) ), temp ); + } + + exp = sub( 31, q_tmp ); + outRe[0][0] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp ); + move32(); + q_re3 = sub( 31, exp ); + + *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) ); + outRe[1][1] = L_shr( outRe[1][1], sub( q_re1, *q_out ) ); + move32(); + outRe[0][1] = L_shr( outRe[0][1], sub( q_re2, *q_out ) ); + move32(); + outIm[0][1] = L_shr( outIm[0][1], sub( q_im, *q_out ) ); + move32(); + outRe[0][0] = L_shr( outRe[0][0], sub( q_re3, *q_out ) ); + move32(); + } + + return; +} +#else static void chol2x2( const float E1, const float E2, @@ -3502,7 +3715,7 @@ static void chol2x2( return; } - +#endif static void formulate2x2MixingMatrix( float Ein1, @@ -3540,7 +3753,12 @@ static void formulate2x2MixingMatrix( float Ghat[BINAURAL_CHANNELS]; float GhatQ[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; float Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; - +#ifdef IVAS_FLOAT_FIXED + Word32 E_out1, E_out2, Cout_re, Cout_im; + Word32 KyRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 q_eout, q_cout, q_ky = 0; + Word16 exp1 = 0, exp2 = 0; +#endif /* Normalize energy values */ maxEne = Ein1; maxEne = max( maxEne, Ein2 ); @@ -3557,8 +3775,29 @@ static void formulate2x2MixingMatrix( CoutIm *= maxEneDiv; /* Cholesky decomposition of target / output covariance matrix */ +#ifdef IVAS_FLOAT_FIXED + /////////////// to be removed //////////////////////////// + f2me( Eout1, &E_out1, &exp1 ); + f2me( Eout2, &E_out2, &exp2 ); + q_eout = sub( 31, s_max( exp1, exp2 ) ); + E_out1 = L_shr( E_out1, sub( sub( 31, exp1 ), q_eout ) ); + E_out2 = L_shr( E_out2, sub( sub( 31, exp2 ), q_eout ) ); + f2me( CoutRe, &Cout_re, &exp1 ); + f2me( CoutIm, &Cout_im, &exp2 ); + q_cout = sub( 31, s_max( exp1, exp2 ) ); + Cout_re = L_shr( Cout_re, sub( sub( 31, exp1 ), q_cout ) ); + Cout_im = L_shr( Cout_im, sub( sub( 31, exp2 ), q_cout ) ); + ///////////////////////////////////////////////////////// + + chol2x2_fx( E_out1, E_out2, q_eout, Cout_re, Cout_im, q_cout, KyRe_fx, KyIm_fx, &q_ky ); + + ///////////////// to be removed ///////////////////////// + fixedToFloat_arrL32( KyRe_fx[0], KyRe[0], q_ky, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ); + fixedToFloat_arrL32( KyIm_fx[0], KyIm[0], q_ky, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ); + ///////////////////////////////////////////////////////// +#else chol2x2( Eout1, Eout2, CoutRe, CoutIm, KyRe, KyIm ); - +#endif /* Eigendecomposition of input covariance matrix */ eig2x2( Ein1, Ein2, CinRe, CinIm, Uxre, Uxim, Sx ); @@ -4673,7 +4912,7 @@ static void ivas_masa_ext_rend_parambin_internal( } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - FOR( slot = 0; slot < 4; slot++ ) + FOR( slot = 0; slot < numInChannels; slot++ ) { q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxRe[ch][slot], nBins ) ); q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxIm[ch][slot], nBins ) ); @@ -4697,7 +4936,7 @@ static void ivas_masa_ext_rend_parambin_internal( } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - FOR( slot = 0; slot < 4; slot++ ) + FOR( slot = 0; slot < numInChannels; slot++ ) { floatToFixed_arr16( hDiracDecBin->processMtxRe[ch][slot], hDiracDecBin->processMtxRe_fx[ch][slot], q_mat, nBins ); floatToFixed_arr16( hDiracDecBin->processMtxIm[ch][slot], hDiracDecBin->processMtxIm_fx[ch][slot], q_mat, nBins ); diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_rend/ivas_dirac_output_synthesis_dec.c index 2cbe69b21..d8cbc1f26 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec.c @@ -521,7 +521,7 @@ ivas_error ivas_dirac_dec_output_synthesis_open_fx( return IVAS_ERR_OK; } -#endif +#else ivas_error ivas_dirac_dec_output_synthesis_open( SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ @@ -783,7 +783,7 @@ ivas_error ivas_dirac_dec_output_synthesis_open( return IVAS_ERR_OK; } - +#endif /*------------------------------------------------------------------------- * ivas_dirac_dec_output_synthesis_init() * @@ -1303,7 +1303,6 @@ void ivas_dirac_dec_output_synthesis_process_slot( h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); h_dirac_output_synthesis_state->onset_filter = onset; - /*-----------------------------------------------------------------* * processing *-----------------------------------------------------------------*/ @@ -1592,8 +1591,482 @@ void ivas_dirac_dec_output_synthesis_process_slot( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_output_synthesis_process_slot_fx( + const Word32 *reference_power, /* i : Estimated power */ + const Word16 q_reference_power, /* i : Estimated power */ + const Word32 *onset, /* i : onset filter */ + const Word16 *azimuth, + const Word16 *elevation, + const Word32 *diffuseness, + Word16 q_diffuseness, + 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 sh_rot_max_order, + const Word32 *p_Rmat, /* i : rotation matrix */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ + const Word16 nchan_transport, /* i : number of transport channels*/ + const Word16 md_idx, + const Word16 hodirac_flag, /* i : flag to indicate HO-DirAC mode */ + const Word16 dec_param_estim ) +{ + Word16 num_freq_bands, num_channels_dir; + Word16 num_freq_bands_diff, num_channels_diff; + Word16 ch_idx; + Word32 aux_buf[CLDFB_NO_CHANNELS_MAX]; + Word16 diff_start_band; + DIRAC_OUTPUT_SYNTHESIS_PARAMS *h_dirac_output_synthesis_params; + DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state; + Word16 q_onset; + h_dirac_output_synthesis_params = &( hDirACRend->h_output_synthesis_psd_params ); + h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state ); + + h_dirac_output_synthesis_state->onset_filter_fx = onset; + + /*-----------------------------------------------------------------* + * processing + *-----------------------------------------------------------------*/ + + /* collect some often used parameters */ + num_freq_bands = hSpatParamRendCom->num_freq_bands; + num_channels_dir = hDirACRend->num_outputs_dir; + num_channels_diff = hDirACRend->num_outputs_diff; + num_freq_bands_diff = h_dirac_output_synthesis_params->max_band_decorr; + + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_LS )) + { + num_channels_dir = hOutSetup.nchan_out_woLFE; move16(); + } + + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD) && hodirac_flag ) + { + ivas_dirac_dec_compute_directional_responses_fx( hSpatParamRendCom, + hDirACRend, + hVBAPdata, + NULL, + NULL, + azimuth, + elevation, + md_idx, + NULL, + 0, + 2, + p_Rmat, + hodirac_flag ); + { + + IF(h_dirac_output_synthesis_state->direct_responses_square_fx){ + Scale_sig32(h_dirac_output_synthesis_state->direct_responses_square_fx, num_channels_dir * num_freq_bands, sub(31, h_dirac_output_synthesis_state->direct_responses_square_q)); + h_dirac_output_synthesis_state->direct_responses_square_q = 31; + } + Scale_sig32( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ), sub(31, h_dirac_output_synthesis_state->direct_responses_q)); + IF( hodirac_flag ) + { + Scale_sig32( &hDirACRend->h_output_synthesis_psd_state.direct_responses_fx[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ), sub(31, h_dirac_output_synthesis_state->direct_responses_q)); + } + h_dirac_output_synthesis_state->direct_responses_q = 31; + } + } + + IF ( EQ_16(dec_param_estim, FALSE) && hodirac_flag ) + { + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + v_multc_fixed( hSpatParamRendCom->energy_ratio1_fx[md_idx], L_negate(MAX_32), aux_buf, num_freq_bands ); + v_addc_fixed( aux_buf, ONE_IN_Q30, aux_buf, num_freq_bands ); + Copy32( hSpatParamRendCom->energy_ratio1_fx[md_idx], + h_dirac_output_synthesis_state->direct_power_factor_fx, + num_freq_bands ); + Copy32( aux_buf, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + num_freq_bands ); + + v_multc_fixed( hSpatParamRendCom->energy_ratio2_fx[md_idx], L_negate(MAX_32), aux_buf, num_freq_bands ); + v_addc_fixed( aux_buf, ONE_IN_Q30, aux_buf, num_freq_bands ); + Copy32( hSpatParamRendCom->energy_ratio2_fx[md_idx], + &h_dirac_output_synthesis_state->direct_power_factor_fx[hSpatParamRendCom->num_freq_bands], + num_freq_bands ); + Copy32( aux_buf, + &h_dirac_output_synthesis_state->diffuse_power_factor_fx[hSpatParamRendCom->num_freq_bands], + num_freq_bands ); + + h_dirac_output_synthesis_state->diffuse_power_factor_q = 30; + h_dirac_output_synthesis_state->direct_power_factor_q = 30; + + } + ELSE + { + ivas_dirac_dec_compute_gain_factors_fx( num_freq_bands, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + h_dirac_output_synthesis_state->direct_power_factor_fx, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + h_dirac_output_synthesis_state->direct_power_factor_q, + h_dirac_output_synthesis_state->diffuse_power_factor_q); + } + } + ELSE IF ( EQ_16(dec_param_estim, TRUE )) + { + /* compute direct responses */ + ivas_dirac_dec_compute_directional_responses_fx( hSpatParamRendCom, + hDirACRend, + hVBAPdata, + NULL, + NULL, + azimuth, + elevation, + md_idx, + NULL, + 0, + sh_rot_max_order, + p_Rmat, + hodirac_flag ); + + { + IF(h_dirac_output_synthesis_state->direct_responses_square_fx){ + Scale_sig32(h_dirac_output_synthesis_state->direct_responses_square_fx, num_channels_dir * num_freq_bands, sub(31, h_dirac_output_synthesis_state->direct_responses_square_q)); + h_dirac_output_synthesis_state->direct_responses_square_q = 31; + } + Scale_sig32( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ), sub(31, h_dirac_output_synthesis_state->direct_responses_q)); + IF( hodirac_flag ) + { + Scale_sig32( &hDirACRend->h_output_synthesis_psd_state.direct_responses_fx[i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir )], i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ), sub(31, h_dirac_output_synthesis_state->direct_responses_q)); + } + h_dirac_output_synthesis_state->direct_responses_q = 31; + } + + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + ivas_dirac_dec_compute_gain_factors_fx( num_freq_bands, + diffuseness, + h_dirac_output_synthesis_state->direct_power_factor_fx, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + &h_dirac_output_synthesis_state->direct_power_factor_q, + &h_dirac_output_synthesis_state->diffuse_power_factor_q + ); + h_dirac_output_synthesis_state->direct_power_factor_q = sub(31, h_dirac_output_synthesis_state->direct_power_factor_q); + h_dirac_output_synthesis_state->diffuse_power_factor_q = sub(31, h_dirac_output_synthesis_state->diffuse_power_factor_q); + + v_multc_fixed( h_dirac_output_synthesis_state->direct_power_factor_fx, + ONE_IN_Q29, + h_dirac_output_synthesis_state->direct_power_factor_fx, + num_freq_bands ); + v_multc_fixed( h_dirac_output_synthesis_state->diffuse_power_factor_fx, + ONE_IN_Q29, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + num_freq_bands ); + + /*Direct gain*/ + + Word16 *Q_temp_cy_cross_dir_smooth_fx = (Word16*)malloc(num_freq_bands * num_channels_dir * sizeof(Word16)); + + FOR(Word16 kk = 0 ; kk < num_freq_bands * num_channels_dir; kk++) + { + Q_temp_cy_cross_dir_smooth_fx[kk] = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth; move16(); + } + + FOR ( ch_idx = 0; ch_idx < s_min( 4, nchan_transport ); ch_idx++ ) + { + Word16 k, temp = 0; + IF ( NE_16(ch_idx, 0 )) + { + Word32 a, b, c; + Word16 b_exp, sqr_exp, q_diff_aab, q_diff_c; + Word32 mpy_a_a_b, mpy_diff_c, mpy_diff_aab; + Word32 sqr_inp, sqr; + + /*Directonal sound gain nrg compensation*/ + FOR ( k = 0; k < num_freq_bands_diff; k++ ) + { + a = h_dirac_output_synthesis_state->direct_responses_fx[add(i_mult(ch_idx, num_freq_bands), k)];// Q = h_dirac_output_synthesis_state->q_direct_responses + IF(EQ_32(reference_power[k + num_freq_bands], 0)) + { + b = 0; + b_exp = 0; + } + ELSE + { + b = BASOP_Util_Divide3232_Scale(reference_power[k + num_freq_bands], L_add(reference_power[k + ( ch_idx + 1 ) * num_freq_bands], EPSILON_FX), &b_exp); + } + c = L_add(ONE_IN_Q29, Mpy_32_16_1( L_sub(h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr_fx, ONE_IN_Q29) , 5461)); /*Diffuseness modellling nrg compensation*/ /* 1.0 / 6.0 = 5461 in Q15*/ + + mpy_a_a_b = Mpy_32_32(a, Mpy_32_16_1(a, b)); //Q = (h_dirac_output_synthesis_state->q_direct_responses + (31 - b_exp) - 31) + (h_dirac_output_synthesis_state->q_direct_responses) - 31 + mpy_diff_aab = Mpy_32_32(L_sub(L_shl(1, q_diffuseness), diffuseness[k]), mpy_a_a_b); // Q = 2*(h_dirac_output_synthesis_state->q_direct_responses) - b_exp - 31 + q_diffuseness -31 + mpy_diff_c = Mpy_32_32(diffuseness[k], c); // Q = q_diffuseness - 2 + + q_diff_aab = (h_dirac_output_synthesis_state->direct_responses_q + (31 - b_exp) - 31) + (h_dirac_output_synthesis_state->direct_responses_q) - 31 + q_diffuseness - 31; + q_diff_c = sub(q_diffuseness, 2); + + IF(NE_32(mpy_diff_c, 0) && NE_32(mpy_diff_aab, 0)) + { + sqr_inp = BASOP_Util_Add_Mant32Exp(mpy_diff_c, sub(31, q_diff_c), mpy_diff_aab, sub(31, q_diff_aab), &sqr_exp); + } + ELSE + { + IF(EQ_32(mpy_diff_c, 0)) + { + sqr_inp = mpy_diff_aab; + sqr_exp = sub(31, q_diff_aab); + } + ELSE + { + sqr_inp = mpy_diff_c; + sqr_exp = sub(31, q_diff_c); + } + } + sqr = Sqrt32(sqr_inp, &sqr_exp); + sqr = L_shr(sqr, 2); + IF(NE_32(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], 0)) + { + IF(LT_16(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_shr(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sub(h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, sub(31, sqr_exp))); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31, sqr_exp); + } + ELSE + { + sqr = L_shr(sqr, sub(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth; + } + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + } + ELSE + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31 , sqr_exp); + } + } + FOR ( ; k < num_freq_bands; k++ ) + { + a = h_dirac_output_synthesis_state->direct_responses_fx[add(i_mult(ch_idx, num_freq_bands), k)];// Q = h_dirac_output_synthesis_state->q_direct_responses + IF(EQ_32(reference_power[k + num_freq_bands], 0)) + { + b = 0; + b_exp = 0; + } + ELSE + { + IF(EQ_32(reference_power[k + ( ch_idx + 1 ) * num_freq_bands], 0)) + { + b = MAXVAL_WORD16; + b_exp = 40; + } + ELSE + { + b = BASOP_Util_Divide3232_Scale(reference_power[k + num_freq_bands], reference_power[k + ( ch_idx + 1 ) * num_freq_bands], &b_exp); + } + } + c = L_add(ONE_IN_Q29, Mpy_32_16_1( L_sub(h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr_fx, ONE_IN_Q29) , 5461)); /*Diffuseness modellling nrg compensation*/ /* 1.0 / 6.0 = 5461 in Q15*/ + + mpy_a_a_b = Mpy_32_32(a, Mpy_32_16_1(a, b)); //Q = (h_dirac_output_synthesis_state->q_direct_responses + (31 - b_exp) - 31) + (h_dirac_output_synthesis_state->q_direct_responses) - 31 + mpy_diff_aab = Mpy_32_32(L_sub(L_shl(1, q_diffuseness), diffuseness[k]), mpy_a_a_b); // Q = 2*(h_dirac_output_synthesis_state->q_direct_responses) - b_exp - 31 + q_diffuseness -31 + mpy_diff_c = Mpy_32_32(diffuseness[k], c); // Q = q_diffuseness - 2 + + q_diff_aab = (h_dirac_output_synthesis_state->direct_responses_q + (31 - b_exp) - 31) + (h_dirac_output_synthesis_state->direct_responses_q) - 31 + q_diffuseness - 31; + q_diff_c = sub(q_diffuseness, 2); + + IF(NE_32(mpy_diff_c, 0) && NE_32(mpy_diff_aab, 0)) + { + sqr_inp = BASOP_Util_Add_Mant32Exp(mpy_diff_c, sub(31, q_diff_c), mpy_diff_aab, sub(31, q_diff_aab), &sqr_exp); + } + ELSE + { + IF(EQ_32(mpy_diff_c, 0)) + { + sqr_inp = mpy_diff_aab; + sqr_exp = sub(31, q_diff_aab); + } + ELSE + { + sqr_inp = mpy_diff_c; + sqr_exp = sub(31, q_diff_c); + } + } + sqr = Sqrt32(sqr_inp, &sqr_exp); + sqr = L_shr(sqr, 2); + IF(NE_32(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], 0)) + { + IF(LT_16(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_shr(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sub(h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, sub(31, sqr_exp))); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31, sqr_exp); + } + ELSE + { + sqr = L_shr(sqr, sub(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth; + } + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + } + ELSE + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31 , sqr_exp); + } + } + } + ELSE + { + Word32 sqr_inp, mpy_diff, sqr; + Word16 sqr_exp; + /*Diffuseness modellling nrg compensation*/ + FOR ( k = 0; k < num_freq_bands_diff; k++ ) + { + mpy_diff = Mpy_32_32(diffuseness[k] ,L_sub(h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr_fx, ONE_IN_Q29));//Q = q_diff - 1 + sqr_inp = L_add(L_shl(1, sub(q_diffuseness, 1)) , mpy_diff); + sqr_exp = sub(31 , sub(q_diffuseness, 1)); + sqr = Sqrt32(sqr_inp, &sqr_exp); + sqr = L_shr(sqr, 2); + IF(NE_32(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], 0)) + { + IF(LT_16(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_shr(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sub(h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, sub(31, sqr_exp))); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31, sqr_exp); + } + ELSE + { + sqr = L_shr(sqr, sub(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth; + } + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + } + ELSE + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31 , sqr_exp); + } + } + FOR ( ; k < num_freq_bands; k++ ) + { + mpy_diff = Mpy_32_32(diffuseness[k] ,L_sub(h_dirac_output_synthesis_params->diffuse_compensation_factor_decorr_fx, ONE_IN_Q29));//Q = q_diff - 1 + sqr_inp = L_add(L_shl(1, sub(q_diffuseness, 1)) , mpy_diff); + sqr_exp = sub(31 , sub(q_diffuseness, 1)); + sqr = Sqrt32(sqr_inp, &sqr_exp); + sqr = L_shr(sqr, 2); + IF(NE_32(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], 0)) + { + IF(LT_16(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_shr(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sub(h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, sub(31, sqr_exp))); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31, sqr_exp); + } + ELSE + { + sqr = L_shr(sqr, sub(sub(31, sqr_exp), h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = h_dirac_output_synthesis_state->q_cy_cross_dir_smooth; + } + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + } + ELSE + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = L_add(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)], sqr); + Q_temp_cy_cross_dir_smooth_fx[L_add(i_mult(ch_idx, num_freq_bands), k)] = sub(31 , sqr_exp); + } + } + } + } + Word16 temp = MAX_16; + FOR(Word16 kk = 0 ; kk < num_freq_bands * num_channels_dir; kk++) + { + temp = s_min(Q_temp_cy_cross_dir_smooth_fx[kk], temp); + } + h_dirac_output_synthesis_state->q_cy_cross_dir_smooth = temp; move16(); + FOR(Word16 kk = 0 ; kk < num_freq_bands * num_channels_dir; kk++) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[kk] = L_shl(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[kk], sub(temp, Q_temp_cy_cross_dir_smooth_fx[kk])); + } + free(Q_temp_cy_cross_dir_smooth_fx); + /*Directional gain (panning)*/ + Word16 temp_q = sub(add(h_dirac_output_synthesis_state->direct_power_factor_q, h_dirac_output_synthesis_state->direct_responses_q), 31); + IF(LT_16(temp_q, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + FOR(Word16 kk = 0 ; kk < num_freq_bands * num_channels_dir; kk++) + { + h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[kk] = L_shl(h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[kk], sub(temp_q, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)); + } + h_dirac_output_synthesis_state->q_cy_cross_dir_smooth = temp_q; + } + FOR ( ch_idx = s_min( 4, nchan_transport ); ch_idx < num_channels_dir; ch_idx++ ) + { + v_mult_fixed( h_dirac_output_synthesis_state->direct_power_factor_fx, + &h_dirac_output_synthesis_state->direct_responses_fx[i_mult(ch_idx, num_freq_bands)], + aux_buf, + num_freq_bands ); + + IF(NE_16(temp_q, h_dirac_output_synthesis_state->q_cy_cross_dir_smooth)) + { + Scale_sig32(aux_buf, num_freq_bands, sub(h_dirac_output_synthesis_state->q_cy_cross_dir_smooth, temp_q)); + } + + v_add_fixed( aux_buf, + &h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[ch_idx * num_freq_bands], + &h_dirac_output_synthesis_state->cy_cross_dir_smooth_fx[ch_idx * num_freq_bands], + num_freq_bands, 0); // Todo:Hdrm + } + + /*Diffuse gain*/ + FOR ( ch_idx = s_min( 4, nchan_transport ); ch_idx < num_channels_diff; ch_idx++ ) + { + v_multc_fixed( h_dirac_output_synthesis_state->diffuse_power_factor_fx, + hDirACRend->diffuse_response_function_fx[ch_idx], + aux_buf, + num_freq_bands_diff ); + + v_add_fixed( aux_buf, + &h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx[ch_idx * num_freq_bands_diff], + &h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx[ch_idx * num_freq_bands_diff], + num_freq_bands_diff, 0); // Todo:Hdrm + } + + return; + } + ELSE + { + /* compute reference and diffuse power factor for this frame */ + ivas_dirac_dec_compute_power_factors_fx( num_freq_bands, + diffuseness, + h_dirac_output_synthesis_params->max_band_decorr, + h_dirac_output_synthesis_state->direct_power_factor_fx, + h_dirac_output_synthesis_state->diffuse_power_factor_fx ); + + Scale_sig32(h_dirac_output_synthesis_state->direct_power_factor_fx, num_freq_bands, 2); + Scale_sig32(h_dirac_output_synthesis_state->diffuse_power_factor_fx, num_freq_bands, 2); + h_dirac_output_synthesis_state->diffuse_power_factor_q = 31; + h_dirac_output_synthesis_state->direct_power_factor_q = 31; + } + } + + diff_start_band = 0; move16(); + IF ( h_dirac_output_synthesis_params->use_onset_filters ) + { + computeTargetPSDs_diffuse_with_onsets_fx( num_channels_dir, + num_freq_bands, h_dirac_output_synthesis_params->max_band_decorr, + hDirACRend->proto_index_diff, + h_dirac_output_synthesis_state->diffuse_power_factor_fx, + reference_power, + &q_reference_power, + h_dirac_output_synthesis_state->diffuse_responses_square_fx, + onset, + h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, + &h_dirac_output_synthesis_state->q_cy_auto_diff_smooth ); + + diff_start_band = h_dirac_output_synthesis_params->max_band_decorr; move16(); + } + + /* process other PSDs only slot wise for 4 transport channels */ + IF ( EQ_16(dec_param_estim, TRUE )) + { + computeTargetPSDs_direct_fx( num_channels_dir, num_freq_bands, h_dirac_output_synthesis_state->direct_power_factor_fx, reference_power, &q_reference_power, 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 ); + + computeTargetPSDs_diffuse_fx( num_channels_dir, num_freq_bands, diff_start_band, h_dirac_output_synthesis_state->diffuse_power_factor_fx, reference_power, &q_reference_power, 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 ); + } + + return; +} +#endif #ifdef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * ivas_dirac_dec_output_synthesis_process_subframe_gain_shd_fx() @@ -2023,10 +2496,10 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd_fx( // ((p_gains_dir_q - 1, p_proto_dir_q - 1) >> 1) -> (p_gains_dir_q + p_proto_dir_q - 32) output_real[l * num_channels_dir + ch_idx] = L_add( - Mpy_32_32( gs1, ( L_add( Mpy_32_32( (Word32) ( 1.772454e+00f * ONE_IN_Q30 ), ( *p_proto ) ), - Mpy_32_32( (Word32) ( 1.023327e+00f * ONE_IN_Q30 ), ( *p_proto2 ) ) ) ) ), /* s1 */ - Mpy_32_32( gs2, ( L_sub( Mpy_32_32( (Word32) ( 1.772454e+00f * ONE_IN_Q30 ), ( *p_proto ) ), - Mpy_32_32( (Word32) ( 1.023327e+00f * ONE_IN_Q30 ), ( *p_proto2 ) ) ) ) ) ); /* s2 */ + Mpy_32_32( gs1, ( L_add( Mpy_32_32( (Word32) ( 1903158016 ), ( *p_proto ) ), + Mpy_32_32( (Word32) ( 1098788992 ), ( *p_proto2 ) ) ) ) ), /* s1 */ + Mpy_32_32( gs2, ( L_sub( Mpy_32_32( (Word32) ( 1903158016 ), ( *p_proto ) ), + Mpy_32_32( (Word32) ( 1098788992 ), ( *p_proto2 ) ) ) ) ) ); /* s2 */ move32(); p_proto++; p_proto2++; @@ -2034,10 +2507,10 @@ void ivas_dirac_dec_output_synthesis_process_subframe_gain_shd_fx( // ((p_gains_dir_q - 1, p_proto_dir_q - 1) >> 1) -> (p_gains_dir_q + p_proto_dir_q - 32) output_imag[l * num_channels_dir + ch_idx] = L_add( - Mpy_32_32( gs1, ( L_add( Mpy_32_32( (Word32) ( 1.772454e+00f * ONE_IN_Q30 ), ( *p_proto ) ), - Mpy_32_32( (Word32) ( 1.023327e+00f * ONE_IN_Q30 ), ( *p_proto2 ) ) ) ) ), - Mpy_32_32( gs2, ( L_sub( Mpy_32_32( (Word32) ( 1.772454e+00f * ONE_IN_Q30 ), ( *p_proto ) ), - Mpy_32_32( (Word32) ( 1.023327e+00f * ONE_IN_Q30 ), ( *p_proto2 ) ) ) ) ) ); + Mpy_32_32( gs1, ( L_add( Mpy_32_32( (Word32) ( 1903158016 ), ( *p_proto ) ), + Mpy_32_32( (Word32) ( 1098788992 ), ( *p_proto2 ) ) ) ) ), + Mpy_32_32( gs2, ( L_sub( Mpy_32_32( (Word32) ( 1903158016 ), ( *p_proto ) ), + Mpy_32_32( (Word32) ( 1098788992 ), ( *p_proto2 ) ) ) ) ) ); move32(); p_proto++; p_proto2++; @@ -4826,7 +5299,7 @@ static void computeTargetPSDs_direct_fx( return; } -#endif +#else static void computeTargetPSDs_direct( @@ -4862,7 +5335,7 @@ static void computeTargetPSDs_direct( return; } - +#endif #ifdef IVAS_FLOAT_FIXED static void computeTargetPSDs_direct_subframe_fx( @@ -4966,7 +5439,7 @@ static void computeTargetPSDs_diffuse_fx( return; } -#endif +#else static void computeTargetPSDs_diffuse( @@ -4997,7 +5470,7 @@ static void computeTargetPSDs_diffuse( return; } - +#endif #ifdef IVAS_FLOAT_FIXED static void computeTargetPSDs_diffuse_subframe_fx( @@ -5103,7 +5576,7 @@ static void computeTargetPSDs_diffuse_with_onsets_fx( return; } -#endif +#else static void computeTargetPSDs_diffuse_with_onsets( @@ -5145,7 +5618,7 @@ static void computeTargetPSDs_diffuse_with_onsets( return; } - +#endif #ifdef IVAS_FLOAT_FIXED static void computeAlphaSynthesis_fx(Word16 *alpha_synthesis_fx, const Word16 averaging_length_ms, const Word16 maxAlpha_fx, Word16 *numAlphas, const Word16 slot_size, const Word16 num_freq_bands, Word16 *frequency_axis_fx, const Word32 output_Fs) { @@ -5202,7 +5675,7 @@ static void computeAlphaSynthesis_fx(Word16 *alpha_synthesis_fx, const Word16 av return; } -#endif +#else static void computeAlphaSynthesis( float *alpha_synthesis, @@ -5245,7 +5718,7 @@ static void computeAlphaSynthesis( return; } - +#endif #ifdef IVAS_FLOAT_FIXED static void spreadCoherencePanningHoa_fx( const Word16 azimuth, diff --git a/lib_rend/ivas_dirac_rend.c b/lib_rend/ivas_dirac_rend.c index e551b2205..85ef5378c 100644 --- a/lib_rend/ivas_dirac_rend.c +++ b/lib_rend/ivas_dirac_rend.c @@ -1627,7 +1627,7 @@ ivas_error ivas_dirac_alloc_mem( #ifdef IVAS_FLOAT_FIXED hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx = hDirAC_mem->cy_cross_dir_smooth_fx; hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_fx = hDirAC_mem->cy_auto_diff_smooth_fx; - hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth = 0; + hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth = 31; move16(); hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth = 0; move16(); @@ -5815,7 +5815,410 @@ static void ivas_masa_ext_dirac_render_sf( return; } +#ifdef IVAS_FLOAT_FIXED +static void ivas_masa_ext_dirac_render_sf_fx( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: IVAS decoder structure */ + Word32 *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +) +{ + int16_t i, ch, idx_in, idx_lfe; + DIRAC_REND_HANDLE hDirACRend; + Word32 dirEne; + Word32 surCohEner; + Word16 surCohRatio[CLDFB_NO_CHANNELS_MAX]; + Word16 surCohRatio_exp; + Word16 subframe_idx; + Word16 slot_idx, index_slot; + Word16 slot_idx_start, slot_idx_start_cldfb_synth, md_idx; + Word16 nchan_transport, q_cldfb; + Word16 masa_band_mapping[MASA_FREQUENCY_BANDS + 1]; + + /* CLDFB: last output channels reserved to LFT for CICPx */ + Word32 Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + + /* local copies of azi, ele, diffuseness */ + Word16 azimuth[CLDFB_NO_CHANNELS_MAX]; + Word16 elevation[CLDFB_NO_CHANNELS_MAX]; + Word32 diffuseness_vector[CLDFB_NO_CHANNELS_MAX]; + + DIRAC_DEC_STACK_MEM DirAC_mem; + Word32 *reference_power, *reference_power_smooth; + Word16 q_reference_power; + Word32 *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; + uint16_t coherence_flag; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + + push_wmops( "ivas_masa_ext_dirac_render_sf" ); + + /* Initialize aux buffers */ + hDirACRend = hMasaExtRend->hDirACRend; + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + nchan_transport = hMasaExtRend->nchan_input; + move16(); + DirAC_mem = hDirACRend->stack_mem; + + reference_power = DirAC_mem.reference_power_fx; move32(); + reference_power_smooth = ( DirAC_mem.reference_power_fx == NULL ) ? NULL : DirAC_mem.reference_power_fx + hSpatParamRendCom->num_freq_bands; + onset_filter = DirAC_mem.onset_filter_fx; + onset_filter_subframe = ( DirAC_mem.onset_filter_fx == NULL ) ? NULL : DirAC_mem.onset_filter_fx + hSpatParamRendCom->num_freq_bands; + coherence_flag = 1; /* There is always coherence assumed for ext rend of MASA */ + move16(); + /* Construct default MASA band mapping */ + FOR ( i = 0; i < MASA_FREQUENCY_BANDS + 1; i++ ) + { + masa_band_mapping[i] = i; move16(); + } + + /* Subframe loop */ + slot_idx_start = hSpatParamRendCom->slots_rendered; move16(); + slot_idx_start_cldfb_synth = 0; move16(); + + subframe_idx = hSpatParamRendCom->subframes_rendered; move16(); + md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; move16(); + + /* copy parameters into local buffers*/ + Copy( hSpatParamRendCom->azimuth[hSpatParamRendCom->render_to_md_map[subframe_idx]], azimuth, hSpatParamRendCom->num_freq_bands ); + Copy( hSpatParamRendCom->elevation[hSpatParamRendCom->render_to_md_map[subframe_idx]], elevation, hSpatParamRendCom->num_freq_bands ); + Copy32( hSpatParamRendCom->diffuseness_vector_fx[hSpatParamRendCom->render_to_md_map[subframe_idx]], diffuseness_vector, hSpatParamRendCom->num_freq_bands ); + + IF ( NE_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + set32_fx( reference_power_smooth, 0, hSpatParamRendCom->num_freq_bands ); + } + ELSE + { + set32_fx( onset_filter_subframe, 0, hSpatParamRendCom->num_freq_bands ); + } + + /* compute response */ + IF ( NE_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + ivas_dirac_dec_compute_power_factors_fx( hSpatParamRendCom->num_freq_bands, + diffuseness_vector, + hDirACRend->h_output_synthesis_psd_params.max_band_decorr, + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx ); + + IF ( coherence_flag ) + { + FOR ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + dirEne = hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i]; move32(); + surCohEner = Mpy_32_16_1(hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], hSpatParamRendCom->surroundingCoherence_fx[md_idx][i]); //Q.31 + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i] = L_sub(hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx[i], surCohEner); + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i] = L_add(hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx[i], surCohEner); + + surCohRatio[i] = BASOP_Util_Divide3232_Scale( surCohEner, L_add( L_add(1, dirEne), surCohEner ), &surCohRatio_exp); + } + } + ELSE + { + set16_fx( surCohRatio, 0, hSpatParamRendCom->num_freq_bands ); + } + } + ELSE + { + ivas_dirac_dec_compute_gain_factors_fx( hSpatParamRendCom->num_freq_bands, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + hDirACRend->h_output_synthesis_psd_state.direct_power_factor_fx, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_fx, + &hDirACRend->h_output_synthesis_psd_state.direct_power_factor_q, + &hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor_q + ); + + IF ( coherence_flag ) + { + FOR ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + surCohRatio[i] = hSpatParamRendCom->surroundingCoherence_fx[md_idx][i]; move16(); + } + } + ELSE + { + set16_fx( surCohRatio, 0, hSpatParamRendCom->num_freq_bands ); + } + } + + ivas_dirac_dec_compute_directional_responses_fx( hSpatParamRendCom, + hDirACRend, + hMasaExtRend->hVBAPdata, + masa_band_mapping, + NULL, + azimuth, + elevation, + md_idx, + surCohRatio, + surCohRatio_exp, + 0, + NULL, + 0 ); + + + FOR ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = add(slot_idx_start, slot_idx); + md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; move16(); + + /* CLDFB Analysis*/ + FOR ( ch = 0; ch < nchan_transport; ch++ ) + { + cldfbAnalysis_ts_fx( &( output_f[ch][hSpatParamRendCom->num_freq_bands * index_slot] ), + Cldfb_RealBuffer[ch][0], + Cldfb_ImagBuffer[ch][0], + hSpatParamRendCom->num_freq_bands, + hMasaExtRend->cldfbAnaRend[ch], q_cldfb); + } + + + IF ( EQ_16(nchan_transport, 1 )) + { + /* Need to set second CLDFB channel to zero as further processing assumes CNA content in it */ + set16_fx( Cldfb_RealBuffer[1][0], 0, hSpatParamRendCom->num_freq_bands ); + set16_fx( Cldfb_ImagBuffer[1][0], 0, hSpatParamRendCom->num_freq_bands ); + } + + /*-----------------------------------------------------------------* + * prototype signal computation + *-----------------------------------------------------------------*/ + + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + protoSignalComputation_shd_fx( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_fx, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q, + reference_power, q_reference_power, slot_idx, nchan_transport, + hDirACRend->num_outputs_diff, + hSpatParamRendCom->num_freq_bands, + 0, q_cldfb); + } + ELSE IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO )) + { + protoSignalComputation2_fx( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirACRend->proto_frame_f_fx, hDirACRend->proto_frame_f_q, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_fx, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q, + reference_power, q_reference_power, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, + 0, slot_idx, hSpatParamRendCom->num_freq_bands, hDirACRend->masa_stereo_type_detect, q_cldfb); + } + ELSE + { + SWITCH ( nchan_transport ) + { + case 2: + protoSignalComputation2_fx( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->proto_frame_f_fx, + hDirACRend->proto_frame_f_q, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_fx, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q, + reference_power, + q_reference_power, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, + hDirACRend->hOutSetup.is_loudspeaker_setup, + slot_idx, + hSpatParamRendCom->num_freq_bands, + hDirACRend->masa_stereo_type_detect, q_cldfb); + BREAK; + case 1: + protoSignalComputation1_fx( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->proto_frame_f_fx, + hDirACRend->proto_frame_f_q, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_fx, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f_q, + reference_power, + q_reference_power, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q, + slot_idx, + hDirACRend->num_protos_diff, + hSpatParamRendCom->num_freq_bands, q_cldfb); + BREAK; + default: + return; + } + } + + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + + IF ( EQ_16(hDirACRend->proto_signal_decorr_on, 1 )) + { + /* decorrelate prototype frame */ + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + ivas_dirac_dec_decorr_process_fx( hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + nchan_transport, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx + i_mult(i_mult(slot_idx, hSpatParamRendCom->num_freq_bands), shl( hDirACRend->num_outputs_diff, 1)), + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q, + hDirACRend->num_protos_diff, + hDirACRend->proto_index_diff, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx + add (i_mult(i_mult(slot_idx, hSpatParamRendCom->num_freq_bands), shl(hDirACRend->num_outputs_diff, 1)) , shl(i_mult(hSpatParamRendCom->num_freq_bands, s_min( 4, nchan_transport )), 1)), + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q, + onset_filter, + hDirACRend->h_freq_domain_decorr_ap_params, + hDirACRend->h_freq_domain_decorr_ap_state ); + + v_multc_fixed( onset_filter, ONE_IN_Q28, onset_filter, hSpatParamRendCom->num_freq_bands ); /*0.25 in Q31 = Q28*/ + v_add_fixed( onset_filter, onset_filter_subframe, onset_filter_subframe, hSpatParamRendCom->num_freq_bands, 1); + p_onset_filter = onset_filter_subframe; + } + ELSE + { + ivas_dirac_dec_decorr_process_fx( hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + nchan_transport, + hDirACRend->proto_frame_f_fx, + hDirACRend->proto_frame_f_q, + hDirACRend->num_protos_diff, + hDirACRend->proto_index_diff, + DirAC_mem.frame_dec_f_fx, + DirAC_mem.frame_dec_f_q, + onset_filter, + hDirACRend->h_freq_domain_decorr_ap_params, + hDirACRend->h_freq_domain_decorr_ap_state ); + + hDirACRend->proto_frame_dec_f_fx = DirAC_mem.frame_dec_f_fx; + p_onset_filter = onset_filter; + } + } + ELSE + { + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + set32_fx( onset_filter_subframe, MAX_32, hSpatParamRendCom->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + ELSE + { + /* no frequency domain decorrelation: use prototype frame */ + hDirACRend->proto_frame_dec_f_fx = hDirACRend->proto_frame_f_fx; + p_onset_filter = NULL; + } + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + test(); + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_LS) || EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD )) + { + /* Compute diffuse prototypes */ + ivas_dirac_dec_compute_diffuse_proto_fx( hDirACRend, hSpatParamRendCom->num_freq_bands, slot_idx ); + } + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + azimuth, + elevation, + hSpatParamRendCom->diffuseness_vector_fx[md_idx], + hSpatParamRendCom, + hDirACRend, + 0, + 0, + hMasaExtRend->hVBAPdata, + hDirACRend->hOutSetup, + nchan_transport, + md_idx, + 0, + 0 ); + + IF ( NE_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + v_add_fixed( reference_power, reference_power_smooth, reference_power_smooth, hSpatParamRendCom->num_freq_bands, 1); + } + } + + ivas_dirac_dec_output_synthesis_get_interpolator_fx( &hDirACRend->h_output_synthesis_psd_params, hSpatParamRendCom->subframe_nbslots[subframe_idx] ); + + IF ( EQ_16(hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD )) + { + ivas_dirac_dec_output_synthesis_process_subframe_gain_shd_fx( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hSpatParamRendCom, + hDirACRend, + nchan_transport, + hSpatParamRendCom->subframe_nbslots[subframe_idx], + p_onset_filter, + diffuseness_vector, + 0, + 0, + &hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev, + &hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev + ); + } + ELSE + { + ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hSpatParamRendCom, + hDirACRend, + hSpatParamRendCom->subframe_nbslots[subframe_idx], + diffuseness_vector, + reference_power_smooth, + 1.0f, + 0 ); + } + + /*-----------------------------------------------------------------* + * CLDFB synthesis (and binaural rendering) + *-----------------------------------------------------------------*/ + + index_slot = slot_idx_start_cldfb_synth; move16(); + + { + Word32 *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 outchannels; + + idx_in = 0; move16(); + idx_lfe = 0; move16(); + + outchannels = add(hDirACRend->hOutSetup.nchan_out_woLFE, hDirACRend->hOutSetup.num_lfe); + + /* Note here that compared to decoder path, there is no separate channel ever for MASA ext rend path */ + + FOR ( ch = 0; ch < outchannels; ch++ ) + { + IF ( GT_16( hDirACRend->hOutSetup.num_lfe, 0 ) && ( EQ_16(hDirACRend->hOutSetup.index_lfe[idx_lfe], ch )) ) + { + /* No LFE for MASA rendering */ + set32_fx( &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), 0, hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->num_freq_bands ); + + IF ( LT_16(idx_lfe, sub( hDirACRend->hOutSetup.num_lfe, 1 ) )) + { + idx_lfe++; + } + } + ELSE + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + FOR ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis_ivas_fx( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], hMasaExtRend->cldfbSynRend[idx_in] ); + idx_in++; + } + } + } + hSpatParamRendCom->slots_rendered = add(hSpatParamRendCom->subframe_nbslots[subframe_idx], hSpatParamRendCom->slots_rendered); + hSpatParamRendCom->subframes_rendered++; + + pop_wmops(); + + return; +} +#endif void ivas_masa_ext_dirac_render( MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ float *output_f[], /* i/o: input/output signals in time domain */ @@ -5852,3 +6255,41 @@ void ivas_masa_ext_dirac_render( return; } +#ifdef IVAS_FLOAT_FIXED +void ivas_masa_ext_dirac_render_fx( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ + Word32 *output_f[], /* i/o: input/output signals in time domain */ + const Word16 num_subframes /* i : number of subframes to render */ +) +{ + Word16 subframe_idx; + Word32 *output_f_local[MAX_OUTPUT_CHANNELS]; + Word16 n, n_samples_sf; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + + n_samples_sf = i_mult(JBM_CLDFB_SLOTS_IN_SUBFRAME, hSpatParamRendCom->slot_size); + + FOR ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + output_f_local[n] = output_f[n]; + } + + hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx; + + FOR ( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ ) + { + hSpatParamRendCom->slots_rendered = 0; + ivas_masa_ext_dirac_render_sf_fx( hMasaExtRend, output_f_local ); + FOR ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + output_f_local[n] += n_samples_sf; + } + + hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + } + + return; +} +#endif \ No newline at end of file diff --git a/lib_rend/ivas_efap.c b/lib_rend/ivas_efap.c index 03d3403b0..be1678638 100644 --- a/lib_rend/ivas_efap.c +++ b/lib_rend/ivas_efap.c @@ -68,23 +68,26 @@ * Local function prototypes *-----------------------------------------------------------------------*/ -static ivas_error poly_init( EFAP *efap, const int16_t efip_flag ); #ifndef IVAS_FLOAT_FIXED +static ivas_error poly_init(EFAP *efap, const int16_t efip_flag); static ivas_error sphere_triangulation( const int16_t numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, float ***dmTranspose, int16_t *numTot, const int16_t efip_flag ); static void initial_polyeder( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, int16_t *numTri, int16_t *vtxInHull ); static void add_ghost_speakers( EFAP_VERTEX *vertexArray, int16_t *numVtx, const int16_t efip_flag ); static void add_vertex_to_convex_hull( const EFAP_VERTEX_DATA *vtxData, const int16_t vtxIdx, int16_t *vtxInHull, EFAP_LS_TRIANGLE *triArray, int16_t *szTri ); +static void sort_vertices(const EFAP_VERTEX *vertexArray, const int16_t *numVtx, int16_t *order); +static void visible_edges(const EFAP_LS_TRIANGLE *triArray, const int16_t *visible, const int16_t numSurface, int16_t *numEdges, int16_t *edges); #else -static ivas_error sphere_triangulation( const int16_t numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, Word32 ***dmTranspose, int16_t *numTot, const int16_t efip_flag ); -static void initial_polyeder_fixed( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, Word16 *numTri, Word16 *vtxInHull ); -static void add_ghost_speakers_fixed( EFAP_VERTEX *vertexArray, Word16 *numVtx, const Word16 efip_flag ); -static void add_vertex_to_convex_hull_fixed( const EFAP_VERTEX_DATA *vtxData, const Word16 vtxIdx, Word16 *vtxInHull, EFAP_LS_TRIANGLE *triArray, Word16 *szTri ); +static ivas_error poly_init_fx(EFAP *efap, const Word16 efip_flag); +static ivas_error sphere_triangulation_fx( const Word16 numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, Word32 ***dmTranspose, Word16 *numTot, const Word16 efip_flag ); +static void initial_polyeder_fx( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, Word16 *numTri, Word16 *vtxInHull ); +static void add_ghost_speakers_fx( EFAP_VERTEX *vertexArray, Word16 *numVtx, const Word16 efip_flag ); +static void add_vertex_to_convex_hull_fx( const EFAP_VERTEX_DATA *vtxData, const Word16 vtxIdx, Word16 *vtxInHull, EFAP_LS_TRIANGLE *triArray, Word16 *szTri ); +static void sort_vertices_fx(const EFAP_VERTEX *vertexArray, const Word16 *numVtx, Word16 *order); +static void visible_edges_fx(const EFAP_LS_TRIANGLE *triArray, const Word16 *visible, const Word16 numSurface, Word16 *numEdges, Word16 *edges); #endif -static void sort_vertices( const EFAP_VERTEX *vertexArray, const int16_t *numVtx, int16_t *order ); -static void visible_edges( const EFAP_LS_TRIANGLE *triArray, const Word16 *visible, const Word16 numSurface, Word16 *numEdges, Word16 *edges ); #ifndef IVAS_FLOAT_FIXED static void flip_plane( const EFAP_VERTEX *vtxArray, int16_t *surface, const float centroid[3] ); @@ -94,12 +97,12 @@ static void efap_panning( const float azi, const float ele, const EFAP_POLYSET_D static void get_poly_gains( const float azi, const float ele, const float aziPoly[EFAP_MAX_CHAN_NUM], const float elePoly[EFAP_MAX_CHAN_NUM], const int16_t numChan, float *buffer ); static float get_tri_gain( const float A[2], const float B[2], const float C[2], const float P_minus_A[2] ); #else -static void flip_plane_fixed( const EFAP_VERTEX *vtxArray, Word16 *surface, const Word32 centroid[3] ); -static void remap_ghosts_fixed( EFAP_VERTEX *vtxArray, EFAP_LS_TRIANGLE *triArray, Word16 numSpk, Word16 *numVertex, Word16 numTri, Word32 **downmixMatrix ); -static void vertex_init_fixed( const Word32 *aziSpk, const Word32 *eleSpk, EFAP_VERTEX_DATA *efapVtxData ); -static void efap_panning_fixed( const Word32 azi, const Word32 ele, const EFAP_POLYSET_DATA *polyData, Word32 *bufferL ); -static void get_poly_gains_fixed( const Word32 azi, const Word32 ele, const Word32 aziPoly[EFAP_MAX_CHAN_NUM], const Word32 elePoly[EFAP_MAX_CHAN_NUM], const Word16 numChan, Word32 *buffer ); -static Word32 get_tri_gain_fixed( const Word32 A[2], const Word32 B[2], const Word32 C[2], const Word32 P_minus_A[2] ); +static void flip_plane_fx( const EFAP_VERTEX *vtxArray, Word16 *surface, const Word32 centroid[3] ); +static void remap_ghosts_fx( EFAP_VERTEX *vtxArray, EFAP_LS_TRIANGLE *triArray, Word16 numSpk, Word16 *numVertex, Word16 numTri, Word32 **downmixMatrix ); +static void vertex_init_fx( const Word32 *aziSpk, const Word32 *eleSpk, EFAP_VERTEX_DATA *efapVtxData ); +static void efap_panning_fx( const Word32 azi, const Word32 ele, const EFAP_POLYSET_DATA *polyData, Word32 *bufferL ); +static void get_poly_gains_fx( const Word32 azi, const Word32 ele, const Word32 aziPoly[EFAP_MAX_CHAN_NUM], const Word32 elePoly[EFAP_MAX_CHAN_NUM], const Word16 numChan, Word32 *buffer ); +static Word32 get_tri_gain_fx( const Word32 A[2], const Word32 B[2], const Word32 C[2], const Word32 P_minus_A[2] ); #endif /*-----------------------------------------------------------------------* @@ -108,37 +111,43 @@ static Word32 get_tri_gain_fixed( const Word32 A[2], const Word32 B[2], const Wo #ifndef IVAS_FLOAT_FIXED static void add_vertex( EFAP_VERTEX *vtxArray, const float azi, const float ele, const int16_t pos, const EFAP_VTX_DMX_TYPE ); +static void efap_sort_s(int16_t *x, int16_t *idx, const int16_t len); #else -static void add_vertex_fixed( EFAP_VERTEX *vtxArray, const Word32 azi, const Word32 ele, const Word16 pos, const EFAP_VTX_DMX_TYPE ); +static void add_vertex_fx( EFAP_VERTEX *vtxArray, const Word32 azi, const Word32 ele, const Word16 pos, const EFAP_VTX_DMX_TYPE ); +static void efap_sort_s_fx(Word16 *x, Word16 *idx, const Word16 len); #endif -static void efap_sort_s( int16_t *x, int16_t *idx, const int16_t len ); #ifndef IVAS_FLOAT_FIXED static float vertex_distance( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const int16_t vtxIdx ); static float point_plane_distance( const float P1[3], const float P2[3], const float P3[3], const float X[3] ); static float point_poly_distance( const EFAP_POLYSET poly, const float X[3] ); static void efap_crossp( const float *v1, const float *v2, float *v ); +static int16_t find_int_in_tri(const EFAP_LS_TRIANGLE *tri, const int16_t n, const int16_t r, int16_t *pos); +static void remove_vertex(EFAP_VERTEX *vtxArray, const int16_t idx, const int16_t L); +static int16_t get_neighbours(const EFAP_LS_TRIANGLE *triArray, const int16_t vtxIdx, const int16_t numTri, int16_t *neighbours); #else -static Word32 vertex_distance_fixed( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const Word16 vtxIdx ); -static Word32 point_plane_distance_fixed( const Word32 P1[3], const Word32 P2[3], const Word32 P3[3], const Word32 X[3] ); -static Word32 point_poly_distance_fixed( const EFAP_POLYSET poly, const Word32 X[3] ); -static void efap_crossp_fixed( const Word32 *v1, const Word32 *v2, Word32 *v ); +static Word32 vertex_distance_fx( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const Word16 vtxIdx ); +static Word32 point_plane_distance_fx( const Word32 P1[3], const Word32 P2[3], const Word32 P3[3], const Word32 X[3] ); +static Word32 point_poly_distance_fx( const EFAP_POLYSET poly, const Word32 X[3] ); +static void efap_crossp_fx( const Word32 *v1, const Word32 *v2, Word32 *v ); +static Word16 find_int_in_tri_fx(const EFAP_LS_TRIANGLE *tri, const Word16 n, const Word16 r, Word16 *pos); +static void remove_vertex_fx(EFAP_VERTEX *vtxArray, const Word16 idx, const Word16 L); +static Word16 get_neighbours_fx(const EFAP_LS_TRIANGLE *triArray, const Word16 vtxIdx, const Word16 numTri, Word16 *neighbours); #endif -static int16_t find_int_in_tri( const EFAP_LS_TRIANGLE *tri, const int16_t n, const int16_t r, int16_t *pos ); -static void remove_vertex( EFAP_VERTEX *vtxArray, const int16_t idx, const int16_t L ); -static int16_t get_neighbours( const EFAP_LS_TRIANGLE *triArray, const int16_t vtxIdx, const int16_t numTri, int16_t *neighbours ); #ifndef IVAS_FLOAT_FIXED static void matrix_times_row( float mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const float *vec, const int16_t L, float *out ); +static void tri_to_poly(const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, const int16_t numVtx, const int16_t numTri, int16_t sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM], int16_t *outLengthPS, int16_t outLengthSorted[EFAP_MAX_POLY_SET]); +static int16_t compare_poly(int16_t *old, int16_t lenOld, int16_t *new, int16_t lenNew); #else -static void matrix_times_row_fixed( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const Word32 *vec, const Word16 L, Word32 *out ); +static void matrix_times_row_fx( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const Word32 *vec, const Word16 L, Word32 *out ); +static void tri_to_poly_fx(const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, const Word16 numVtx, const Word16 numTri, Word16 sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM], Word16 *outLengthPS, Word16 outLengthSorted[EFAP_MAX_POLY_SET]); +static Word16 compare_poly_fx(Word16 *old, Word16 lenOld, Word16 *new, Word16 lenNew); #endif -static void tri_to_poly( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, const int16_t numVtx, const int16_t numTri, int16_t sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM], int16_t *outLengthPS, int16_t outLengthSorted[EFAP_MAX_POLY_SET] ); -static int16_t compare_poly( int16_t *old, int16_t lenOld, int16_t *new, int16_t lenNew ); #ifndef IVAS_FLOAT_FIXED static void sort_channels_vertex( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, int16_t channels[EFAP_MAX_CHAN_NUM], const int16_t lengthChannels, int16_t idxTri ); @@ -148,34 +157,33 @@ static int16_t in_poly( const float P[2], const EFAP_POLYSET poly ); static int16_t in_tri( float A[2], float B[2], float C[2], float P_minus_A[2] ); static void sph2cart( const float azi, const float ele, float *pos ); #else -static void sort_channels_vertex_fixed( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, Word16 channels[EFAP_MAX_CHAN_NUM], const Word16 lengthChannels, Word16 idxTri ); +static void sort_channels_vertex_fx( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, Word16 channels[EFAP_MAX_CHAN_NUM], const Word16 lengthChannels, Word16 idxTri ); static Word32 efap_lmodl( const Word32 x, const Word32 y ); -static Word16 get_poly_num_fixed( const Word32 P[2], const EFAP_POLYSET_DATA *polyData ); -static Word16 in_poly_fixed( const Word32 P[2], const EFAP_POLYSET poly ); -static Word16 in_tri_fixed( Word32 A[2], Word32 B[2], Word32 C[2], Word32 P_minus_A[2] ); -static void sph2cart_fixed( const Word32 azi, const Word32 ele, Word32 *pos ); +static Word16 get_poly_num_fx( const Word32 P[2], const EFAP_POLYSET_DATA *polyData ); +static Word16 in_poly_fx( const Word32 P[2], const EFAP_POLYSET poly ); +static Word16 in_tri_fx( Word32 A[2], Word32 B[2], Word32 C[2], Word32 P_minus_A[2] ); +static void sph2cart_fx( const Word32 azi, const Word32 ele, Word32 *pos ); #endif /*-----------------------------------------------------------------------* * Global function definitions *-----------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* - * efap_init_data() + * efap_init_data_fx() * * Wrap the internal functions to initialize the EFAP data structure *-------------------------------------------------------------------------*/ -ivas_error efap_init_data( +ivas_error efap_init_data_fx( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ - const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ - const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ + const Word32 *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) (Q22) */ + const Word32 *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) (Q22) */ + const Word16 num_speaker_nodes, /* i : number of speaker nodes in the set */ + const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ ) { -#ifndef IVAS_FLOAT_FIXED /* Handle instance declaration */ EFAP *efap; ivas_error error; @@ -183,7 +191,7 @@ ivas_error efap_init_data( error = IVAS_ERR_OK; /* Basic init checks */ - if ( !speaker_node_azi_deg || !speaker_node_ele_deg ) + IF( !speaker_node_azi_deg || !speaker_node_ele_deg ) { hEFAPdata = NULL; return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "EFAP requires arrays of speaker azimuths and elevations" ); @@ -194,29 +202,29 @@ ivas_error efap_init_data( *-----------------------------------------------------------------*/ /* Memory Allocations for efap */ - if ( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) + IF( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP handle\n" ) ); } /* Memory Allocation and update for aziSpk & eleSpk arrays*/ - if ( ( efap->aziSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + IF( ( efap->aziSpk = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker azimuths\n" ) ); } - if ( ( efap->eleSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + IF( ( efap->eleSpk = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker elevations\n" ) ); } /* Memory Allocation for vertexArray */ - if ( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) + IF( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Array\n" ) ); } /* Memory allocation for the tmp buffer short */ - if ( ( efap->bufferShort = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + IF( ( efap->bufferShort_fx = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); } @@ -231,50 +239,39 @@ ivas_error efap_init_data( efap->vtxData.numVtx = num_speaker_nodes; /* Loudspeaker configuration */ - mvr2r( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); - mvr2r( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); + mvl2l( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); + mvl2l( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); /* Initialization of the vertex */ - vertex_init( efap->aziSpk, efap->eleSpk, &efap->vtxData ); + vertex_init_fx( efap->aziSpk, efap->eleSpk, &efap->vtxData ); /* Initialization of polygons and ghost LS */ - if ( ( error = poly_init( efap, efap_mode ) ) != IVAS_ERR_OK ) + IF( ( error = poly_init_fx( efap, efap_mode ) ) != IVAS_ERR_OK ) { return error; } /* Memory allocation for the tmp buffer long */ - if ( ( efap->bufferLong = (float *) malloc( efap->vtxData.numVtx * sizeof( float ) ) ) == NULL ) + IF( ( efap->bufferLong_fx = (Word32 *) malloc( efap->vtxData.numVtx * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferL\n" ) ); } *hEFAPdata = efap; return error; -#else - /* Following conversion should be removed once all inputs are converted to Word32 azi and ele angles */ - Word32 azi_inp[MAX_OUTPUT_CHANNELS], ele_inp[MAX_OUTPUT_CHANNELS]; - FOR( int spk_idx = 0; spk_idx < num_speaker_nodes; spk_idx++ ) - { - azi_inp[spk_idx] = (Word32) ( speaker_node_azi_deg[spk_idx] * Q22_1 ); - ele_inp[spk_idx] = (Word32) ( speaker_node_ele_deg[spk_idx] * Q22_1 ); - } - return efap_init_data_fixed( hEFAPdata, azi_inp, ele_inp, num_speaker_nodes, efap_mode ); -#endif } -#ifdef IVAS_FLOAT_FIXED -/*-------------------------------------------------------------------------* - * efap_init_data_fixed() - * - * Wrap the internal functions to initialize the EFAP data structure - *-------------------------------------------------------------------------*/ - -ivas_error efap_init_data_fixed( +#else + /*-------------------------------------------------------------------------* + * efap_init_data() + * + * Wrap the internal functions to initialize the EFAP data structure + *-------------------------------------------------------------------------*/ +ivas_error efap_init_data( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const Word32 *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) (Q22) */ - const Word32 *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) (Q22) */ - const Word16 num_speaker_nodes, /* i : number of speaker nodes in the set */ - const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ + const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ + const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ + const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ ) { /* Handle instance declaration */ @@ -284,7 +281,7 @@ ivas_error efap_init_data_fixed( error = IVAS_ERR_OK; /* Basic init checks */ - IF( !speaker_node_azi_deg || !speaker_node_ele_deg ) + if ( !speaker_node_azi_deg || !speaker_node_ele_deg ) { hEFAPdata = NULL; return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "EFAP requires arrays of speaker azimuths and elevations" ); @@ -295,29 +292,29 @@ ivas_error efap_init_data_fixed( *-----------------------------------------------------------------*/ /* Memory Allocations for efap */ - IF( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) + if ( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP handle\n" ) ); } /* Memory Allocation and update for aziSpk & eleSpk arrays*/ - IF( ( efap->aziSpk = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) + if ( ( efap->aziSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker azimuths\n" ) ); } - IF( ( efap->eleSpk = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) + if ( ( efap->eleSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker elevations\n" ) ); } /* Memory Allocation for vertexArray */ - IF( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) + if ( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Array\n" ) ); } /* Memory allocation for the tmp buffer short */ - IF( ( efap->bufferShort_fx = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) + if ( ( efap->bufferShort = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); } @@ -332,20 +329,20 @@ ivas_error efap_init_data_fixed( efap->vtxData.numVtx = num_speaker_nodes; /* Loudspeaker configuration */ - mvl2l( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); - mvl2l( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); + mvr2r( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); + mvr2r( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); /* Initialization of the vertex */ - vertex_init_fixed( efap->aziSpk, efap->eleSpk, &efap->vtxData ); + vertex_init( efap->aziSpk, efap->eleSpk, &efap->vtxData ); /* Initialization of polygons and ghost LS */ - IF( ( error = poly_init( efap, efap_mode ) ) != IVAS_ERR_OK ) + if ( ( error = poly_init( efap, efap_mode ) ) != IVAS_ERR_OK ) { return error; } /* Memory allocation for the tmp buffer long */ - IF( ( efap->bufferLong_fx = (Word32 *) malloc( efap->vtxData.numVtx * sizeof( Word32 ) ) ) == NULL ) + if ( ( efap->bufferLong = (float *) malloc( efap->vtxData.numVtx * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferL\n" ) ); } @@ -355,102 +352,16 @@ ivas_error efap_init_data_fixed( } #endif -/*-------------------------------------------------------------------------* - * efap_determine_gains() - * - * Obtain amplitude panning gains for all speaker nodes based on the - * given direction - *-------------------------------------------------------------------------*/ - -void efap_determine_gains( - EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - float *gains, /* o : gain vector for speaker nodes for given direction */ - const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ - const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ -) -{ -#ifndef IVAS_FLOAT_FIXED - int16_t i, j; - float azi_wrap, ele_wrap; - float normBuffer; - - /* Resetting bufferShort and bufferLong */ - set_zero( hEFAPdata->bufferShort, hEFAPdata->numSpk ); - set_zero( hEFAPdata->bufferLong, hEFAPdata->vtxData.numVtx ); - - /* Wrap angles to correct range */ - panning_wrap_angles( azi_deg, ele_deg, &azi_wrap, &ele_wrap ); - - /* Panning */ - efap_panning( azi_wrap, ele_wrap, &hEFAPdata->polyData, hEFAPdata->bufferLong ); - - if ( efap_mode == EFAP_MODE_EFAP ) - { - normBuffer = 0.f; - for ( j = 0; j < hEFAPdata->numSpk; ++j ) - { - hEFAPdata->bufferShort[j] = 0.f; - /* Multiplying by the downmixMatrix */ - for ( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) - { - hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; - } - normBuffer = normBuffer + hEFAPdata->bufferShort[j] * hEFAPdata->bufferShort[j]; - } - normBuffer = inv_sqrt( normBuffer ); - - for ( j = 0; j < hEFAPdata->numSpk; ++j ) - { - hEFAPdata->bufferShort[j] *= normBuffer; - } - } - else - { - normBuffer = 0.f; - for ( j = 0; j < hEFAPdata->numSpk; ++j ) - { - hEFAPdata->bufferShort[j] = 0.f; - /* Multiplying by the downmixMatrix */ - for ( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) - { - hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; - } - normBuffer = normBuffer + hEFAPdata->bufferShort[j]; - } - normBuffer = 1.f / normBuffer; - - for ( j = 0; j < hEFAPdata->numSpk; ++j ) - { - hEFAPdata->bufferShort[j] = sqrtf( hEFAPdata->bufferShort[j] * normBuffer ); - } - } - - /* Copy gains to output */ - mvr2r( hEFAPdata->bufferShort, gains, hEFAPdata->numSpk ); - - return; -#else - /* block to be removed once efap_determine_gains_fixed() is integrated into all calling places */ - const Word32 azi_fx = (Word32) ( azi_deg * Q22_1 ); - const Word32 ele_fx = (Word32) ( ele_deg * Q22_1 ); - Word32 gains_fx[MAX_OUTPUT_CHANNELS]; - efap_determine_gains_fixed( hEFAPdata, gains_fx, azi_fx, ele_fx, efap_mode ); - FOR( Word32 i = 0; i < hEFAPdata->numSpk; i++ ) - { - gains[i] = ( (float) gains_fx[i] ) / L_shl( 1, Q30 ); - } -#endif -} #ifdef IVAS_FLOAT_FIXED + /*-------------------------------------------------------------------------* - * efap_determine_gains_fixed() + * efap_determine_gains_fx() * * Obtain amplitude panning gains for all speaker nodes based on the * given direction *-------------------------------------------------------------------------*/ -void efap_determine_gains_fixed( +void efap_determine_gains_fx( EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ Word32 *gains, /* o : gain vector for speaker nodes for given direction */ const Word32 azi_deg, @@ -473,9 +384,9 @@ void efap_determine_gains_fixed( panning_wrap_angles_fixed( azi_deg, ele_deg, &azi_wrap_int, &ele_wrap_int ); /* Panning */ - efap_panning_fixed( azi_wrap_int, ele_wrap_int, &hEFAPdata->polyData, hEFAPdata->bufferLong_fx ); + efap_panning_fx( azi_wrap_int, ele_wrap_int, &hEFAPdata->polyData, hEFAPdata->bufferLong_fx ); - IF( efap_mode == EFAP_MODE_EFAP ) + IF( EQ_16( efap_mode, EFAP_MODE_EFAP ) ) { normBuffer = 0; FOR( j = 0; j < hEFAPdata->numSpk; ++j ) @@ -517,7 +428,7 @@ void efap_determine_gains_fixed( { Word16 exp_temp = exp + 1; hEFAPdata->bufferShort_fx[j] = Sqrt32( Mpy_32_16_1( hEFAPdata->bufferShort_fx[j], (Word16) normBuffer ), &exp_temp ); - hEFAPdata->bufferShort_fx[j] = L_shl( hEFAPdata->bufferShort_fx[j], exp_temp - 1 ); // Q30 + hEFAPdata->bufferShort_fx[j] = L_shl( hEFAPdata->bufferShort_fx[j], sub( exp_temp, 1 ) ); // Q30 } } @@ -526,6 +437,82 @@ void efap_determine_gains_fixed( return; } +#else + +/*-------------------------------------------------------------------------* + * efap_determine_gains() + * + * Obtain amplitude panning gains for all speaker nodes based on the + * given direction + *-------------------------------------------------------------------------*/ +void efap_determine_gains( + EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + float *gains, /* o : gain vector for speaker nodes for given direction */ + const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ + const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ +) +{ + int16_t i, j; + float azi_wrap, ele_wrap; + float normBuffer; + + /* Resetting bufferShort and bufferLong */ + set_zero( hEFAPdata->bufferShort, hEFAPdata->numSpk ); + set_zero( hEFAPdata->bufferLong, hEFAPdata->vtxData.numVtx ); + + /* Wrap angles to correct range */ + panning_wrap_angles( azi_deg, ele_deg, &azi_wrap, &ele_wrap ); + + /* Panning */ + efap_panning( azi_wrap, ele_wrap, &hEFAPdata->polyData, hEFAPdata->bufferLong ); + + if ( efap_mode == EFAP_MODE_EFAP ) + { + normBuffer = 0.f; + for ( j = 0; j < hEFAPdata->numSpk; ++j ) + { + hEFAPdata->bufferShort[j] = 0.f; + /* Multiplying by the downmixMatrix */ + for ( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) + { + hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; + } + normBuffer = normBuffer + hEFAPdata->bufferShort[j] * hEFAPdata->bufferShort[j]; + } + normBuffer = inv_sqrt( normBuffer ); + + for ( j = 0; j < hEFAPdata->numSpk; ++j ) + { + hEFAPdata->bufferShort[j] *= normBuffer; + } + } + else + { + normBuffer = 0.f; + for ( j = 0; j < hEFAPdata->numSpk; ++j ) + { + hEFAPdata->bufferShort[j] = 0.f; + /* Multiplying by the downmixMatrix */ + for ( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) + { + hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; + } + normBuffer = normBuffer + hEFAPdata->bufferShort[j]; + } + normBuffer = 1.f / normBuffer; + + for ( j = 0; j < hEFAPdata->numSpk; ++j ) + { + hEFAPdata->bufferShort[j] = sqrtf( hEFAPdata->bufferShort[j] * normBuffer ); + } + } + + /* Copy gains to output */ + mvr2r( hEFAPdata->bufferShort, gains, hEFAPdata->numSpk ); + + return; +} #endif /*-------------------------------------------------------------------------* * efap_free_data() @@ -643,21 +630,17 @@ void efap_free_data( * Main function for the Efap initialization whose purpose is to initialize * the different polygons and to add the ghost speakers *-------------------------------------------------------------------------*/ - -static ivas_error poly_init( +#ifdef IVAS_FLOAT_FIXED +static ivas_error poly_init_fx( EFAP *efap, /* i/o: A pointer to a handle to efap instance */ - const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ + const Word16 efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ ) { int16_t n, m, j; int16_t finalLength, lengthTri2PolyPS; int16_t lengthTri2PolySorted[EFAP_MAX_POLY_SET]; int16_t sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM]; -#ifndef IVAS_FLOAT_FIXED - float tmpMax, tmpMin; -#else Word32 tmpMax, tmpMin; -#endif ivas_error error; error = IVAS_ERR_OK; @@ -671,11 +654,7 @@ static ivas_error poly_init( } /* Computing the different ghost vertex, the downmix matrix and the triangle array */ -#ifndef IVAS_FLOAT_FIXED - IF( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) -#else - IF( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose_fx, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) -#endif + IF( ( error = sphere_triangulation_fx( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose_fx, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) { return error; } @@ -683,20 +662,15 @@ static ivas_error poly_init( /* set isNaN for ghost loudspeakers */ FOR( n = 0; n < efap->vtxData.numVtx; ++n ) { -#ifndef IVAS_FLOAT_FIXED - IF( efap->vtxData.vertexArray[n].ele > 90.0 - 1e-6 || - efap->vtxData.vertexArray[n].ele < 1e-6 - 90.0 ) -#else IF( GT_32( efap->vtxData.vertexArray[n].ele, L_sub( Q22_90_DEG, 4 ) ) || LT_32( efap->vtxData.vertexArray[n].ele, L_sub( 4, Q22_90_DEG ) ) ) -#endif { efap->vtxData.vertexArray[n].isNaN = 1; } } /* Converting the triangle to polygon structure */ - tri_to_poly( efap->vtxData.vertexArray, efap->polyData.triArray, efap->vtxData.numVtx, efap->polyData.numTri, sortedChan, &lengthTri2PolyPS, lengthTri2PolySorted ); + tri_to_poly_fx( efap->vtxData.vertexArray, efap->polyData.triArray, efap->vtxData.numVtx, efap->polyData.numTri, sortedChan, &lengthTri2PolyPS, lengthTri2PolySorted ); /* Completing the polyData Structure */ finalLength = -1; @@ -717,32 +691,115 @@ static ivas_error poly_init( efap->polyData.polysetArray[m].numChan = lengthTri2PolySorted[n]; /* In case tmpMax - tmpMin > 180, wrap polygon azimuth */ -#ifndef IVAS_FLOAT_FIXED + maximum_l( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMax ); + minimum_l( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMin ); + + IF( GT_32( L_sub( tmpMax, tmpMin ), Q22_180_DEG ) /*180 in Q22*/ ) + { + FOR( j = 0; j < lengthTri2PolySorted[n]; ++j ) + { + assert( ( m + 2 < EFAP_MAX_POLY_SET ) && "EFAP: maximum polygons exceeded!" ); + + /* add two new polygons with azimuths wrapped to differing bounds */ + efap->polyData.polysetArray[m + 1].polyAzi[j] = efap_lmodl( efap->polyData.polysetArray[m].polyAzi[j], Q22_360_DEG ); + efap->polyData.polysetArray[m + 2].polyAzi[j] = L_sub( efap->polyData.polysetArray[m + 1].polyAzi[j], Q22_360_DEG ); + + /* Copy the rest of the fields */ + efap->polyData.polysetArray[m + 1].chan[j] = efap->polyData.polysetArray[m].chan[j]; + efap->polyData.polysetArray[m + 1].polyEle[j] = efap->polyData.polysetArray[m].polyEle[j]; + efap->polyData.polysetArray[m + 1].isNaN[j] = efap->polyData.polysetArray[m].isNaN[j]; + efap->polyData.polysetArray[m + 1].numChan = lengthTri2PolySorted[n]; + + efap->polyData.polysetArray[m + 2].chan[j] = efap->polyData.polysetArray[m].chan[j]; + efap->polyData.polysetArray[m + 2].polyEle[j] = efap->polyData.polysetArray[m].polyEle[j]; + efap->polyData.polysetArray[m + 2].isNaN[j] = efap->polyData.polysetArray[m].isNaN[j]; + efap->polyData.polysetArray[m + 2].numChan = lengthTri2PolySorted[n]; + } + finalLength = add( finalLength, 2 ); + } + finalLength = add( finalLength, 1 ); + } + finalLength = add( finalLength, 1 ); + + /* Updating the number of polygons */ + efap->polyData.numPoly = finalLength; + + + return error; +} +#else +static ivas_error poly_init( + EFAP *efap, /* i/o: A pointer to a handle to efap instance */ + const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ +) +{ + int16_t n, m, j; + int16_t finalLength, lengthTri2PolyPS; + int16_t lengthTri2PolySorted[EFAP_MAX_POLY_SET]; + int16_t sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM]; + float tmpMax, tmpMin; + ivas_error error; + + error = IVAS_ERR_OK; + + /* Safety Check */ + assert( efap != NULL && "EFAP: efap == NULL" ); + + for ( n = 0; n < EFAP_MAX_POLY_SET; n++ ) + { + set_s( sortedChan[n], 0, EFAP_MAX_CHAN_NUM ); + } + + /* Computing the different ghost vertex, the downmix matrix and the triangle array */ + if ( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* set isNaN for ghost loudspeakers */ + for ( n = 0; n < efap->vtxData.numVtx; ++n ) + { + if ( efap->vtxData.vertexArray[n].ele > 90.0 - 1e-6 || + efap->vtxData.vertexArray[n].ele < 1e-6 - 90.0 ) + { + efap->vtxData.vertexArray[n].isNaN = 1; + } + } + + /* Converting the triangle to polygon structure */ + tri_to_poly( efap->vtxData.vertexArray, efap->polyData.triArray, efap->vtxData.numVtx, efap->polyData.numTri, sortedChan, &lengthTri2PolyPS, lengthTri2PolySorted ); + + /* Completing the polyData Structure */ + finalLength = -1; + + for ( n = 0; n < lengthTri2PolyPS; ++n ) + { + m = finalLength + 1; + + /* Complete the fields of the polygon */ + for ( j = 0; j < lengthTri2PolySorted[n]; ++j ) + { + efap->polyData.polysetArray[m].chan[j] = sortedChan[n][j]; + efap->polyData.polysetArray[m].polyAzi[j] = efap->vtxData.vertexArray[sortedChan[n][j]].azi; + efap->polyData.polysetArray[m].polyEle[j] = efap->vtxData.vertexArray[sortedChan[n][j]].ele; + efap->polyData.polysetArray[m].isNaN[j] = efap->vtxData.vertexArray[sortedChan[n][j]].isNaN; + } + + efap->polyData.polysetArray[m].numChan = lengthTri2PolySorted[n]; + + /* In case tmpMax - tmpMin > 180, wrap polygon azimuth */ maximum( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMax ); minimum( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMin ); -#else - maximum_l( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMax ); - minimum_l( efap->polyData.polysetArray[m].polyAzi, lengthTri2PolySorted[n], &tmpMin ); -#endif -#ifndef IVAS_FLOAT_FIXED if ( ( tmpMax - tmpMin ) > 180 ) -#else - IF( GT_32( L_sub( tmpMax, tmpMin ), Q22_180_DEG ) /*180 in Q22*/ ) -#endif { - FOR( j = 0; j < lengthTri2PolySorted[n]; ++j ) + for ( j = 0; j < lengthTri2PolySorted[n]; ++j ) { assert( ( m + 2 < EFAP_MAX_POLY_SET ) && "EFAP: maximum polygons exceeded!" ); /* add two new polygons with azimuths wrapped to differing bounds */ -#ifndef IVAS_FLOAT_FIXED efap->polyData.polysetArray[m + 1].polyAzi[j] = efap_fmodf( efap->polyData.polysetArray[m].polyAzi[j], 360 ); efap->polyData.polysetArray[m + 2].polyAzi[j] = efap->polyData.polysetArray[m + 1].polyAzi[j] - 360; -#else - efap->polyData.polysetArray[m + 1].polyAzi[j] = efap_lmodl( efap->polyData.polysetArray[m].polyAzi[j], Q22_360_DEG ); - efap->polyData.polysetArray[m + 2].polyAzi[j] = L_sub( efap->polyData.polysetArray[m + 1].polyAzi[j], Q22_360_DEG ); -#endif /* Copy the rest of the fields */ efap->polyData.polysetArray[m + 1].chan[j] = efap->polyData.polysetArray[m].chan[j]; @@ -767,24 +824,20 @@ static ivas_error poly_init( return error; } - +#endif /*-------------------------------------------------------------------------* * sphere_triangulation() * * *-------------------------------------------------------------------------*/ - -static ivas_error sphere_triangulation( - const int16_t numSpk, /* i : Number of speakers */ +#ifdef IVAS_FLOAT_FIXED +static ivas_error sphere_triangulation_fx( + const Word16 numSpk, /* i : Number of speakers */ EFAP_VERTEX_DATA *vtxData, /* i/o: Vertex data structure */ EFAP_POLYSET_DATA *polyData, /* o : Polygon data structure */ -#ifndef IVAS_FLOAT_FIXED - float ***dmTranspose, /* o : Transpose of the downmix matrix */ -#else Word32 ***dmTranspose_fx, /* o : Transpose of the downmix matrix */ -#endif - int16_t *numTot, /* o : Number of speakers (real + ghost) */ + Word16 *numTot, /* o : Number of speakers (real + ghost) */ const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ ) { @@ -795,11 +848,7 @@ static ivas_error sphere_triangulation( set_s( vtxInHull, 0, EFAP_MAX_SIZE_TMP_BUFF ); /* Add Imaginary Speakers */ -#ifndef IVAS_FLOAT_FIXED - add_ghost_speakers( vtxData->vertexArray, &vtxData->numVtx, efip_flag ); -#else - add_ghost_speakers_fixed( vtxData->vertexArray, &vtxData->numVtx, efip_flag ); -#endif + add_ghost_speakers_fx( vtxData->vertexArray, &vtxData->numVtx, efip_flag ); /* Sort the vertices according to their index */ IF( ( vtxData->vtxOrder = (int16_t *) malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) @@ -807,33 +856,21 @@ static ivas_error sphere_triangulation( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Order\n" ) ); } - sort_vertices( vtxData->vertexArray, &vtxData->numVtx, vtxData->vtxOrder ); + sort_vertices_fx( vtxData->vertexArray, &vtxData->numVtx, vtxData->vtxOrder ); /* Computing the initial Polyeder */ -#ifndef IVAS_FLOAT_FIXED - initial_polyeder( vtxData, polyData->triArray, &polyData->numTri, &vtxInHull[0] ); -#else - initial_polyeder_fixed( vtxData, polyData->triArray, &polyData->numTri, &vtxInHull[0] ); -#endif + initial_polyeder_fx( vtxData, polyData->triArray, &polyData->numTri, &vtxInHull[0] ); /* Add the vertex to the convex hull */ FOR( i = 0; i < vtxData->numVtx; ++i ) { -#ifndef IVAS_FLOAT_FIXED - add_vertex_to_convex_hull( vtxData, vtxData->vtxOrder[i], &vtxInHull[0], polyData->triArray, &polyData->numTri ); -#else - add_vertex_to_convex_hull_fixed( vtxData, vtxData->vtxOrder[i], &vtxInHull[0], polyData->triArray, &polyData->numTri ); -#endif + add_vertex_to_convex_hull_fx( vtxData, vtxData->vtxOrder[i], &vtxInHull[0], polyData->triArray, &polyData->numTri ); } assert( polyData->numTri != 0 && "EFAP: failed to construct convex hull!" ); /* Allocate the DM matrix transpose */ -#ifndef IVAS_FLOAT_FIXED - IF( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) -#else IF( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( Word32 * ) ) ) == NULL ) -#endif { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } @@ -843,30 +880,80 @@ static ivas_error sphere_triangulation( FOR( i = 0; i < vtxData->numVtx; i++ ) { -#ifndef IVAS_FLOAT_FIXED - IF( ( p_dmTranspose[i] = malloc( numSpk * sizeof( float ) ) ) == NULL ) -#else IF( ( p_dmTranspose[i] = malloc( numSpk * sizeof( Word32 ) ) ) == NULL ) -#endif { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } } -#ifndef IVAS_FLOAT_FIXED - *dmTranspose = (float **) p_dmTranspose; -#else *dmTranspose_fx = (Word32 **) p_dmTranspose; -#endif /* Remap Ghosts */ -#ifndef IVAS_FLOAT_FIXED - remap_ghosts( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose ); + remap_ghosts_fx( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose_fx ); + + return IVAS_ERR_OK; +} #else - remap_ghosts_fixed( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose_fx ); -#endif +static ivas_error sphere_triangulation( + const int16_t numSpk, /* i : Number of speakers */ + EFAP_VERTEX_DATA *vtxData, /* i/o: Vertex data structure */ + EFAP_POLYSET_DATA *polyData, /* o : Polygon data structure */ + float ***dmTranspose, /* o : Transpose of the downmix matrix */ + int16_t *numTot, /* o : Number of speakers (real + ghost) */ + const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ +) +{ + int16_t i; + void **p_dmTranspose; + int16_t vtxInHull[EFAP_MAX_SIZE_TMP_BUFF]; + + set_s( vtxInHull, 0, EFAP_MAX_SIZE_TMP_BUFF ); + + /* Add Imaginary Speakers */ + add_ghost_speakers( vtxData->vertexArray, &vtxData->numVtx, efip_flag ); + + /* Sort the vertices according to their index */ + if ( ( vtxData->vtxOrder = (int16_t *) malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Order\n" ) ); + } + + sort_vertices( vtxData->vertexArray, &vtxData->numVtx, vtxData->vtxOrder ); + + /* Computing the initial Polyeder */ + initial_polyeder( vtxData, polyData->triArray, &polyData->numTri, &vtxInHull[0] ); + + /* Add the vertex to the convex hull */ + for ( i = 0; i < vtxData->numVtx; ++i ) + { + add_vertex_to_convex_hull( vtxData, vtxData->vtxOrder[i], &vtxInHull[0], polyData->triArray, &polyData->numTri ); + } + + assert( polyData->numTri != 0 && "EFAP: failed to construct convex hull!" ); + + /* Allocate the DM matrix transpose */ + if ( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); + } + + /* Store the value of numVtx to be used for freeing later (numVtx will change after remap_ghosts() ) */ + *numTot = vtxData->numVtx; + + for ( i = 0; i < vtxData->numVtx; i++ ) + { + if ( ( p_dmTranspose[i] = malloc( numSpk * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); + } + } + *dmTranspose = (float **) p_dmTranspose; + + /* Remap Ghosts */ + remap_ghosts( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose ); return IVAS_ERR_OK; } +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* @@ -1001,7 +1088,7 @@ static void initial_polyeder( * *-------------------------------------------------------------------------*/ -static void initial_polyeder_fixed( +static void initial_polyeder_fx( EFAP_VERTEX_DATA *vtxData, /* i : Vertex data structure */ EFAP_LS_TRIANGLE *triArray, /* o : Triangle array structure */ Word16 *numTri, /* o : Size of triangle array */ @@ -1050,7 +1137,7 @@ static void initial_polyeder_fixed( WHILE( LT_16( tetrahedron[2], numVtx ) ) { v_sub_fixed( vtxData->vertexArray[tetrahedron[2]].pos, vtxData->vertexArray[tetrahedron[0]].pos, tmp2, 3, 1 ); - efap_crossp_fixed( tmp1, tmp2, tmpCross ); // tmpCross Q29 + efap_crossp_fx( tmp1, tmp2, tmpCross ); // tmpCross Q29 FOR( i = 0; i < 3; i++ ) { tmp = L_add( tmp, Mpy_32_32( tmpCross[i], tmpCross[i] ) ); // tmp Q27 @@ -1059,7 +1146,7 @@ static void initial_polyeder_fixed( { break; } - tetrahedron[2]++; + tetrahedron[2] = add( tetrahedron[2], 1 ); } assert( tetrahedron[2] < numVtx && "EFAP: convex hull construction failed, vertices are colinear!" ); @@ -1073,7 +1160,7 @@ static void initial_polyeder_fixed( { break; } - tetrahedron[3]++; + tetrahedron[3] = add( tetrahedron[3], 1 ); } assert( tetrahedron[3] < numVtx && "EFAP: convex hull construction failed, vertices are coplanar!" ); @@ -1095,25 +1182,25 @@ static void initial_polyeder_fixed( tmpSurface[0] = tetrahedron[0]; tmpSurface[1] = tetrahedron[1]; tmpSurface[2] = tetrahedron[2]; - flip_plane_fixed( vtxData->vertexArray, tmpSurface, centroid ); + flip_plane_fx( vtxData->vertexArray, tmpSurface, centroid ); mvs2s( tmpSurface, triArray[0].LS, 3 ); tmpSurface[0] = tetrahedron[0]; tmpSurface[1] = tetrahedron[1]; tmpSurface[2] = tetrahedron[3]; - flip_plane_fixed( vtxData->vertexArray, tmpSurface, centroid ); + flip_plane_fx( vtxData->vertexArray, tmpSurface, centroid ); mvs2s( tmpSurface, triArray[1].LS, 3 ); tmpSurface[0] = tetrahedron[0]; tmpSurface[1] = tetrahedron[2]; tmpSurface[2] = tetrahedron[3]; - flip_plane_fixed( vtxData->vertexArray, tmpSurface, centroid ); + flip_plane_fx( vtxData->vertexArray, tmpSurface, centroid ); mvs2s( tmpSurface, triArray[2].LS, 3 ); tmpSurface[0] = tetrahedron[1]; tmpSurface[1] = tetrahedron[2]; tmpSurface[2] = tetrahedron[3]; - flip_plane_fixed( vtxData->vertexArray, tmpSurface, centroid ); + flip_plane_fx( vtxData->vertexArray, tmpSurface, centroid ); mvs2s( tmpSurface, triArray[3].LS, 3 ); /* set numTri */ @@ -1288,12 +1375,12 @@ static void add_ghost_speakers( } #else /*-------------------------------------------------------------------------* - * add_ghost_speakers_fixed() + * add_ghost_speakers_fx() * * *-------------------------------------------------------------------------*/ -static void add_ghost_speakers_fixed( +static void add_ghost_speakers_fx( EFAP_VERTEX *vertexArray, /* i/o: Vertex array */ Word16 *numVtx, /* i/o: Size of vertex array */ const Word16 efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ @@ -1342,7 +1429,7 @@ static void add_ghost_speakers_fixed( vtxDmxType = EFAP_DMX_AMPLITUDE; } } - add_vertex_fixed( vertexArray, 0, Q22_90_DEG, numVertex + a, vtxDmxType ); + add_vertex_fx( vertexArray, 0, Q22_90_DEG, numVertex + a, vtxDmxType ); ++lengthVertGhst; ++a; } @@ -1363,7 +1450,7 @@ static void add_ghost_speakers_fixed( } } - add_vertex_fixed( vertexArray, 0, -Q22_90_DEG, numVertex + a, vtxDmxType ); + add_vertex_fx( vertexArray, 0, -Q22_90_DEG, numVertex + a, vtxDmxType ); ++lengthVertGhst; ++a; @@ -1384,16 +1471,16 @@ static void add_ghost_speakers_fixed( lengthHorGhst = 0; IF( EQ_16( k, 0 ) ) /* no speakers found: add a triangle of ghost speakers */ { - add_vertex_fixed( vertexArray, 0, 0, numVertex + a, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, Q22_120_DEG, 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, Q22_240_DEG, 0, numVertex + a + 2, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, 0, 0, numVertex + a, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, Q22_120_DEG, 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, Q22_240_DEG, 0, numVertex + a + 2, EFAP_DMX_INTENSITY ); a += 3; lengthHorGhst += 3; } ELSE IF( EQ_16( k, 1 ) ) /* only one speaker found: add two ghost speakers to complete a triangle */ { - add_vertex_fixed( vertexArray, L_add( tmpAzi[0], Q22_120_DEG ), 0, numVertex + a, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, L_add( tmpAzi[0], Q22_240_DEG ), 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, L_add( tmpAzi[0], Q22_120_DEG ), 0, numVertex + a, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, L_add( tmpAzi[0], Q22_240_DEG ), 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); a += 2; lengthHorGhst += 2; } @@ -1434,7 +1521,7 @@ static void add_ghost_speakers_fixed( { newAzi = L_add( tmpAzi[i], L_shl( ( j + 1 ) * newDiff, Q22 ) ); - add_vertex_fixed( vertexArray, newAzi, 0, numVertex + a, EFAP_DMX_INTENSITY ); + add_vertex_fx( vertexArray, newAzi, 0, numVertex + a, EFAP_DMX_INTENSITY ); ++a; IF( GT_16( j, 0 ) ) @@ -1445,7 +1532,7 @@ static void add_ghost_speakers_fixed( } } } - *numVtx = numVertex + lengthHorGhst + lengthVertGhst; + *numVtx = add( add( numVertex, lengthHorGhst ), lengthVertGhst ); return; } @@ -1457,6 +1544,28 @@ static void add_ghost_speakers_fixed( * *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void sort_vertices_fx( + const EFAP_VERTEX *vertexArray, /* i : Vertex array */ + const Word16 *numVtx, /* i : Size of vertex array */ + Word16 *order /* o : Original index positions */ +) +{ + Word16 tmpIdx[EFAP_MAX_SIZE_TMP_BUFF]; + Word16 i; + + /* Initializing tmpIdx */ + FOR( i = 0; i < *numVtx; ++i ) + { + tmpIdx[i] = vertexArray[i].idx; + } + + /* Sorting indexes */ + efap_sort_s_fx( tmpIdx, order, *numVtx ); + + return; +} +#else static void sort_vertices( const EFAP_VERTEX *vertexArray, /* i : Vertex array */ const int16_t *numVtx, /* i : Size of vertex array */ @@ -1467,7 +1576,7 @@ static void sort_vertices( int16_t i; /* Initializing tmpIdx */ - FOR( i = 0; i < *numVtx; ++i ) + for ( i = 0; i < *numVtx; ++i ) { tmpIdx[i] = vertexArray[i].idx; } @@ -1477,7 +1586,7 @@ static void sort_vertices( return; } - +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * add_vertex_to_convex_hull() @@ -1575,12 +1684,12 @@ static void add_vertex_to_convex_hull( } #else /*-------------------------------------------------------------------------* - * add_vertex_to_convex_hull_fixed() + * add_vertex_to_convex_hull_fx() * * *-------------------------------------------------------------------------*/ -static void add_vertex_to_convex_hull_fixed( +static void add_vertex_to_convex_hull_fx( const EFAP_VERTEX_DATA *vtxData, /* i : Vertex data structure */ const Word16 vtxIdx, /* i : Vertex to be added to the hull */ Word16 *vtxInHull, /* i/o: Array indicating whether the vertex is part of the hull */ @@ -1612,7 +1721,7 @@ static void add_vertex_to_convex_hull_fixed( { IF( vtxInHull[i] ) { - numHullVtx++; + numHullVtx = L_add( numHullVtx, 1 ); centroid[0] = L_add( centroid[0], L_shr( vtxData->vertexArray[i].pos[0], Q4 ) ); centroid[1] = L_add( centroid[1], L_shr( vtxData->vertexArray[i].pos[1], Q4 ) ); centroid[2] = L_add( centroid[2], L_shr( vtxData->vertexArray[i].pos[2], Q4 ) ); @@ -1634,7 +1743,7 @@ static void add_vertex_to_convex_hull_fixed( FOR( i = 0; i < *szTri; ++i ) { - tmpDist = vertex_distance_fixed( vtxData->vertexArray, triArray[i], vtxIdx ); // Q28 + tmpDist = vertex_distance_fx( vtxData->vertexArray, triArray[i], vtxIdx ); // Q28 IF( GT_32( tmpDist, threshold ) ) { visible[k] = i; @@ -1647,7 +1756,7 @@ static void add_vertex_to_convex_hull_fixed( } } - visible_edges( triArray, visible, k, numEdges, edges ); + visible_edges_fx( triArray, visible, k, numEdges, edges ); FOR( i = 0; i < numEdges[0]; i += 2 ) { @@ -1655,7 +1764,7 @@ static void add_vertex_to_convex_hull_fixed( surface[1] = edges[i + 1]; surface[2] = vtxIdx; - flip_plane_fixed( vtxData->vertexArray, surface, centroid ); + flip_plane_fx( vtxData->vertexArray, surface, centroid ); mvs2s( surface, triArrayNew[l].LS, 3 ); ++l; @@ -1679,8 +1788,8 @@ static void add_vertex_to_convex_hull_fixed( * * *-------------------------------------------------------------------------*/ - -static void visible_edges( +#ifdef IVAS_FLOAT_FIXED +static void visible_edges_fx( const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ const Word16 *visible, /* i : Visible surface flag */ const Word16 numSurface, /* i : Number of surfaces */ @@ -1688,17 +1797,13 @@ static void visible_edges( Word16 *edges /* i/o: Array of edges */ ) { - int16_t maxVertex; - int16_t i, j, k; - int16_t a, b; - int16_t tmpSurface[4]; - int16_t counter[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; - int16_t counterTranspose[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; -#ifndef IVAS_FLOAT_FIXED - float tmpMax[EFAP_MAX_SIZE_TMP_BUFF]; -#else + Word16 maxVertex; + Word16 i, j, k; + Word16 a, b; + Word16 tmpSurface[4]; + Word16 counter[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; + Word16 counterTranspose[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; Word16 tmpMax[EFAP_MAX_SIZE_TMP_BUFF]; -#endif /* Set counter and counterTranspose to 0 */ FOR( i = 0; i < EFAP_MAX_SIZE_TMP_BUFF; i++ ) @@ -1710,28 +1815,16 @@ static void visible_edges( /* Finding the max vertex */ FOR( i = 0; i < numSurface; ++i ) { -#ifndef IVAS_FLOAT_FIXED - tmpMax[i] = (float) triArray[visible[i]].LS[0]; -#else tmpMax[i] = triArray[visible[i]].LS[0]; -#endif FOR( j = 1; j < 3; ++j ) { IF( tmpMax[i] < triArray[visible[i]].LS[j] ) { -#ifndef IVAS_FLOAT_FIXED - tmpMax[i] = (float) triArray[visible[i]].LS[j]; -#else tmpMax[i] = triArray[visible[i]].LS[j]; -#endif } } } -#ifndef IVAS_FLOAT_FIXED - maxVertex = (int16_t) tmpMax[maximum( tmpMax, numSurface, NULL )]; -#else maxVertex = tmpMax[maximum_s( tmpMax, numSurface, NULL )]; -#endif FOR( i = 0; i < numSurface; ++i ) { tmpSurface[0] = triArray[visible[i]].LS[0]; @@ -1743,7 +1836,7 @@ static void visible_edges( { a = tmpSurface[j]; b = tmpSurface[j + 1]; - counter[a][b] = counter[a][b] + 1; + counter[a][b] = add(counter[a][b], 1); counterTranspose[b][a] = counter[a][b]; } } @@ -1752,7 +1845,7 @@ static void visible_edges( { FOR( j = 0; j < maxVertex + 1; ++j ) { - counter[i][j] = counterTranspose[i][j] + counterTranspose[j][i]; + counter[i][j] = add(counterTranspose[i][j], counterTranspose[j][i]); } } @@ -1777,7 +1870,90 @@ static void visible_edges( return; } +#else +static void visible_edges( + const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ + const int16_t *visible, /* i : Visible surface flag */ + const int16_t numSurface, /* i : Number of surfaces */ + int16_t *numEdges, /* i/o: Number of edges */ + int16_t *edges /* i/o: Array of edges */ +) +{ + int16_t maxVertex; + int16_t i, j, k; + int16_t a, b; + int16_t tmpSurface[4]; + int16_t counter[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; + int16_t counterTranspose[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF]; + float tmpMax[EFAP_MAX_SIZE_TMP_BUFF]; + + /* Set counter and counterTranspose to 0 */ + for ( i = 0; i < EFAP_MAX_SIZE_TMP_BUFF; i++ ) + { + set_s( counter[i], 0, EFAP_MAX_SIZE_TMP_BUFF ); + set_s( counterTranspose[i], 0, EFAP_MAX_SIZE_TMP_BUFF ); + } + + /* Finding the max vertex */ + for ( i = 0; i < numSurface; ++i ) + { + tmpMax[i] = (float) triArray[visible[i]].LS[0]; + for ( j = 1; j < 3; ++j ) + { + if ( tmpMax[i] < triArray[visible[i]].LS[j] ) + { + tmpMax[i] = (float) triArray[visible[i]].LS[j]; + } + } + } + maxVertex = (int16_t) tmpMax[maximum( tmpMax, numSurface, NULL )]; + + for ( i = 0; i < numSurface; ++i ) + { + tmpSurface[0] = triArray[visible[i]].LS[0]; + tmpSurface[1] = triArray[visible[i]].LS[1]; + tmpSurface[2] = triArray[visible[i]].LS[2]; + tmpSurface[3] = triArray[visible[i]].LS[0]; + + for ( j = 0; j < 3; ++j ) + { + a = tmpSurface[j]; + b = tmpSurface[j + 1]; + counter[a][b] = counter[a][b] + 1; + counterTranspose[b][a] = counter[a][b]; + } + } + + for ( i = 0; i < maxVertex + 1; ++i ) + { + for ( j = 0; j < maxVertex + 1; ++j ) + { + counter[i][j] = counterTranspose[i][j] + counterTranspose[j][i]; + } + } + + /* Finding the edges */ + k = 0; + + for ( a = 0; a < maxVertex; ++a ) + { + for ( b = a + 1; b < maxVertex + 1; ++b ) + { + if ( counter[a][b] == 1 ) + { + edges[k] = a; + edges[k + 1] = b; + k += 2; + } + } + } + + /* Outputs */ + *numEdges = k; + return; +} +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * flip_plane() @@ -1816,16 +1992,16 @@ static void flip_plane( * \ *-------------------------------------------------------------------------*/ -static void flip_plane_fixed( +static void flip_plane_fx( const EFAP_VERTEX *vtxArray, /* i : Vertex array */ Word16 *surface, /* i/o: Surface/vertices to be flipped */ const Word32 centroid[3] /* i : Centroid of convex hull from which to orient the planes outward */ ) { - int16_t tmp; + Word16 tmp; Word32 dist; - dist = point_plane_distance_fixed( + dist = point_plane_distance_fx( vtxArray[surface[0]].pos, vtxArray[surface[1]].pos, vtxArray[surface[2]].pos, @@ -1995,12 +2171,12 @@ static void remap_ghosts( } #else /*-------------------------------------------------------------------------* - * remap_ghosts_fixed() + * remap_ghosts_fx() * * *-------------------------------------------------------------------------*/ -static void remap_ghosts_fixed( +static void remap_ghosts_fx( EFAP_VERTEX *vtxArray, /* i/o: Vertex array */ EFAP_LS_TRIANGLE *triArray, /* i/o: Triangle array */ Word16 numSpk, /* i : Number of speakers */ @@ -2032,9 +2208,9 @@ static void remap_ghosts_fixed( FOR( g = numVtx - 1; g > numSpk - 1; --g ) { /* find(triangle_mat == ghost, 1, 'first') */ - IF( EQ_16( find_int_in_tri( triArray, g, numTri, posFound ), 0 ) ) + IF( EQ_16(find_int_in_tri_fx( triArray, g, numTri, posFound ), 0 ) ) { - remove_vertex( vtxArray, g, numVtx ); + remove_vertex_fx( vtxArray, g, numVtx ); --numVtx; FOR( i = 0; i < numTri; ++i ) { @@ -2042,7 +2218,7 @@ static void remap_ghosts_fixed( { IF( GT_16( triArray[i].LS[j], g ) ) { - triArray[i].LS[j] = g - 1; + triArray[i].LS[j] = sub( g, 1 ); } } } @@ -2054,7 +2230,7 @@ static void remap_ghosts_fixed( } /* Final number of LS (real + ghosts) */ - numTot = numSpk + numGhst; + numTot = add(numSpk, numGhst); /* Initializing tmpMat as the identity matrix */ FOR( i = 0; i < numTot; ++i ) @@ -2069,7 +2245,7 @@ static void remap_ghosts_fixed( /* Generate initial sound energy distribution matrix */ FOR( i = numSpk; i < numTot; ++i ) { - tmpL = get_neighbours( triArray, i, numTri, neighbours ); + tmpL = get_neighbours_fx( triArray, i, numTri, neighbours ); /* Initializing the column to 0 */ FOR( j = 0; j < numTot; ++j ) @@ -2100,14 +2276,14 @@ static void remap_ghosts_fixed( { mvl2l( tmpNewMat[i], tmpVec, numTot ); - tmpDist = sum_l( &tmpVec[numSpk], numTot - numSpk ); + tmpDist = sum_l( &tmpVec[numSpk], sub( numTot, numSpk ) ); WHILE( GT_32( tmpDist, thresh ) ) { - matrix_times_row_fixed( tmpMat, tmpVec, numTot, tmpVec2 ); + matrix_times_row_fx( tmpMat, tmpVec, numTot, tmpVec2 ); mvl2l( tmpVec2, tmpVec, numTot ); set_l( tmpVec2, 0, numTot ); - tmpDist = sum_l( &tmpVec[numSpk], numTot - numSpk ); + tmpDist = sum_l( &tmpVec[numSpk], sub( numTot, numSpk ) ); } mvl2l( tmpVec, tmpNewMat[i], numTot ); } @@ -2136,10 +2312,10 @@ static void remap_ghosts_fixed( { case EFAP_DMX_NONE: downmixMatrixTranspose[j][i] = 0; - break; + BREAK; case EFAP_DMX_AMPLITUDE: downmixMatrixTranspose[j][i] = tmpNewMat[j][i]; - break; + BREAK; case EFAP_DMX_INTENSITY: default: IF( EQ_32( tmpNewMat[j][i], 0 ) || EQ_32( tmpNewMat[j][i], 0x7fffffff ) ) @@ -2153,7 +2329,7 @@ static void remap_ghosts_fixed( tmp_sqrt = L_shl( tmp_sqrt, exp ); downmixMatrixTranspose[j][i] = tmp_sqrt; } - break; + BREAK; } } } @@ -2190,12 +2366,12 @@ static void vertex_init( } #else /*-------------------------------------------------------------------------* - * vertex_init_fixed() + * vertex_init_fx() * * Initialize the vertex structures *-------------------------------------------------------------------------*/ -static void vertex_init_fixed( +static void vertex_init_fx( const Word32 *aziSpk, /* i : Azimuths of the LS setup */ const Word32 *eleSpk, /* i : Elevations of the LS setup */ EFAP_VERTEX_DATA *efapVtxData /* i/o: Vertex data structure that will be updated */ @@ -2206,7 +2382,7 @@ static void vertex_init_fixed( /* Main Processing */ FOR( i = 0; i < efapVtxData->numVtx; i++ ) { - add_vertex_fixed( efapVtxData->vertexArray, aziSpk[i], eleSpk[i], i, EFAP_DMX_INTENSITY ); + add_vertex_fx( efapVtxData->vertexArray, aziSpk[i], eleSpk[i], i, EFAP_DMX_INTENSITY ); } return; @@ -2280,12 +2456,12 @@ static void efap_panning( } #else /*-------------------------------------------------------------------------* - * efap_panning_fixed() + * efap_panning_fx() * * Compute the gain without applying the downmix Matrix and the norm of the array *-------------------------------------------------------------------------*/ -static void efap_panning_fixed( +static void efap_panning_fx( const Word32 azi, /* i : Value of the azimuth */ const Word32 ele, /* i : Value of the elevation */ const EFAP_POLYSET_DATA *polyData, /* i : Polygon data */ @@ -2306,7 +2482,7 @@ static void efap_panning_fixed( P[1] = ele; /* Finding in which polygon the point is */ - polyIdx = get_poly_num_fixed( P, polyData ); + polyIdx = get_poly_num_fx( P, polyData ); assert( polyIdx != -1 && "EFAP: polygon not found!" ); @@ -2327,7 +2503,7 @@ static void efap_panning_fixed( } /* Computing the gain for the polygon */ - get_poly_gains_fixed( P[0], P[1], aziPoly, elePoly, numChan, tmpBuff ); + get_poly_gains_fx( P[0], P[1], aziPoly, elePoly, numChan, tmpBuff ); /* Computing the norm of the tmp buffer */ normTmpBuff = dotp_fixed( tmpBuff, tmpBuff, numChan ); @@ -2401,12 +2577,12 @@ static void get_poly_gains( } #else /*-------------------------------------------------------------------------* - * get_poly_gains_fixed() + * get_poly_gains_fx() * * Compute the gain for a precise polygon *-------------------------------------------------------------------------*/ -static void get_poly_gains_fixed( +static void get_poly_gains_fx( const Word32 azi, /* i : Value of the azimuth */ const Word32 ele, /* i : Value of the elevation */ const Word32 aziPoly[EFAP_MAX_CHAN_NUM], /* i : Azimuths of the considered polygons */ @@ -2443,9 +2619,9 @@ static void get_poly_gains_fixed( C[0] = aziPoly[idx2 - 1]; C[1] = elePoly[idx2 - 1]; - IF( in_tri_fixed( A, B, C, P_minus_A ) ) + IF( in_tri_fx( A, B, C, P_minus_A ) ) { - buffer[i - 1] = L_shl_sat( get_tri_gain_fixed( A, B, C, P_minus_A ), Q12 ); + buffer[i - 1] = L_shl_sat( get_tri_gain_fx( A, B, C, P_minus_A ), Q12 ); break; } } @@ -2496,12 +2672,12 @@ static float get_tri_gain( } #else /*-------------------------------------------------------------------------* - * get_tri_gain_fixed() + * get_tri_gain_fx() * * Compute the value of the gain for a given triangle *-------------------------------------------------------------------------*/ -static Word32 get_tri_gain_fixed( +static Word32 get_tri_gain_fx( const Word32 A[2], /* i : Coordinate of one apex of the triangle */ const Word32 B[2], /* i : Coordinate of one apex of the triangle */ const Word32 C[2], /* i : Coordinate of one apex of the triangle */ @@ -2593,12 +2769,12 @@ static void add_vertex( } #else /*-------------------------------------------------------------------------* - * add_vertex_fixed() + * add_vertex_fx() * * Add a vertex to the vertex array *-------------------------------------------------------------------------*/ -static void add_vertex_fixed( +static void add_vertex_fx( EFAP_VERTEX *vtxArray, /* i/o: Handle to the vertex array that will be updated */ const Word32 azi, /* i : Azimuth of the vertex */ const Word32 ele, /* i : Elevation of the vertex */ @@ -2613,14 +2789,14 @@ static void add_vertex_fixed( /* Updating the vertex array */ - tmp = efap_lmodl( Q22_180_DEG - azi, Q22_360_DEG ); + tmp = efap_lmodl( L_sub( Q22_180_DEG, azi ), Q22_360_DEG ); vtxArray[pos].azi = L_sub( Q22_180_DEG, tmp ); tmp = ( ( Q22_180_DEG < ele ) ? Q22_180_DEG : ele ); vtxArray[pos].ele = ( ( -Q22_180_DEG > tmp ) ? -Q22_180_DEG : tmp ); /* Converting spherical coordinates to cartesians, assuming radius = 1 */ - sph2cart_fixed( vtxArray[pos].azi, vtxArray[pos].ele, &vtxArray[pos].pos[0] ); + sph2cart_fx( vtxArray[pos].azi, vtxArray[pos].ele, &vtxArray[pos].pos[0] ); /* Computing the index defined by idx = idxAziTmp + 181 * idxEleTmp */ @@ -2634,7 +2810,7 @@ static void add_vertex_fixed( idxEleTmp = L_sub( Q22_90_DEG, idxEleTmp ); /* Final Idx */ - vtxArray[pos].idx = (Word16) idxAziTmp + 181 * (Word16) ( idxEleTmp >> Q22 ); + vtxArray[pos].idx = add( (Word16) idxAziTmp, i_mult( 181, (Word16) L_shr( idxEleTmp, Q22 ) ) ); /* Setting the nan flag to 0 */ vtxArray[pos].isNaN = 0; @@ -2653,6 +2829,37 @@ static void add_vertex_fixed( * (modified version of sort() to return an index array) *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void efap_sort_s_fx( + Word16 *x, /* i/o: Vector to be sorted */ + Word16 *idx, /* o : Original index positions */ + const Word16 len /* i : vector length */ +) +{ + Word16 i, j; + Word16 tempr, tempi; + + FOR( i = 0; i < len; i++ ) + { + idx[i] = i; + } + + FOR( i = len - 2; i >= 0; i-- ) + { + tempr = x[i]; + tempi = idx[i]; + FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) + { + x[j - 1] = x[j]; + idx[j - 1] = idx[j]; + } + x[j - 1] = tempr; + idx[j - 1] = tempi; + } + + return; +} +#else static void efap_sort_s( int16_t *x, /* i/o: Vector to be sorted */ int16_t *idx, /* o : Original index positions */ @@ -2662,16 +2869,16 @@ static void efap_sort_s( int16_t i, j; int16_t tempr, tempi; - FOR( i = 0; i < len; i++ ) + for ( i = 0; i < len; i++ ) { idx[i] = i; } - FOR( i = len - 2; i >= 0; i-- ) + for ( i = len - 2; i >= 0; i-- ) { tempr = x[i]; tempi = idx[i]; - FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) + for ( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) { x[j - 1] = x[j]; idx[j - 1] = idx[j]; @@ -2682,7 +2889,7 @@ static void efap_sort_s( return; } - +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * vertex_distance() @@ -2718,7 +2925,7 @@ static float vertex_distance( * Compute the signed distance between a vertex and a hull surface *-------------------------------------------------------------------------*/ -static Word32 vertex_distance_fixed( +static Word32 vertex_distance_fx( const EFAP_VERTEX *vtxArray, /* i : The considered vertex */ const EFAP_LS_TRIANGLE tri, /* i : The considered triangle */ const Word16 vtxIdx /* i : Index of the considered vertex */ @@ -2737,7 +2944,7 @@ static Word32 vertex_distance_fixed( P[i] = vtxArray[vtxIdx].pos[i]; } - return point_plane_distance_fixed( A, B, C, P ); + return point_plane_distance_fx( A, B, C, P ); } #endif @@ -2762,23 +2969,23 @@ static float point_poly_distance( } #else /*-------------------------------------------------------------------------* - * point_poly_distance_fixed() + * point_poly_distance_fx() * * Compute the signed distance between a point and polygon *-------------------------------------------------------------------------*/ -static Word32 point_poly_distance_fixed( +static Word32 point_poly_distance_fx( const EFAP_POLYSET poly, /* i : The polygon which forms a plane */ const Word32 X[3] /* i : Cartesian coordinates of the point of interest */ ) { Word32 P1[3], P2[3], P3[3]; - sph2cart_fixed( poly.polyAzi[0], poly.polyEle[0], &P1[0] ); - sph2cart_fixed( poly.polyAzi[1], poly.polyEle[1], &P2[0] ); - sph2cart_fixed( poly.polyAzi[2], poly.polyEle[2], &P3[0] ); + sph2cart_fx( poly.polyAzi[0], poly.polyEle[0], &P1[0] ); + sph2cart_fx( poly.polyAzi[1], poly.polyEle[1], &P2[0] ); + sph2cart_fx( poly.polyAzi[2], poly.polyEle[2], &P3[0] ); - return point_plane_distance_fixed( P1, P2, P3, X ); + return point_plane_distance_fx( P1, P2, P3, X ); } #endif @@ -2828,12 +3035,12 @@ static float point_plane_distance( } #else /*-------------------------------------------------------------------------* - * point_plane_distance_fixed() + * point_plane_distance_fx() * * Compute the signed distance between a point and a given plane *-------------------------------------------------------------------------*/ -static Word32 point_plane_distance_fixed( // returns output in Q28 +static Word32 point_plane_distance_fx( // returns output in Q28 const Word32 P1[3], /* i : First point of the triangle that defines the planes */ const Word32 P2[3], /* i : Second point of the triangle */ const Word32 P3[3], /* i : Third point of the triangle */ @@ -2859,7 +3066,7 @@ static Word32 point_plane_distance_fixed( // returns output in Q28 v_sub_fixed( P1, P3, tmpCross2, 3, 1 ); /* resultCross = cross(P1-P2,P1-P3) */ - efap_crossp_fixed( tmpCross1, tmpCross2, resultCross ); // Q29 + efap_crossp_fx( tmpCross1, tmpCross2, resultCross ); // Q29 /* Dot Product */ tmpNorm = dotp_fixed( resultCross, resultCross, 3 ); // Q27 @@ -2893,12 +3100,12 @@ static void efap_crossp( } #else /*-------------------------------------------------------------------------* - * efap_crossp_fixed() + * efap_crossp_fx() * * Compute the cross product between column vectors of float of size 3x1 *-------------------------------------------------------------------------*/ -static void efap_crossp_fixed( +static void efap_crossp_fx( const Word32 *v1, /* i : First float vector */ const Word32 *v2, /* i : Second float vector */ Word32 *v /* o : Output vector */ @@ -2917,7 +3124,33 @@ static void efap_crossp_fixed( * * Find an integer in triangle array of integers *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 find_int_in_tri_fx( + const EFAP_LS_TRIANGLE *tri, /* i : Triangle array */ + const Word16 n, /* i : The integer to find */ + const Word16 r, /* i : Number of rows */ + Word16 *pos /* o : Position of the integer */ +) +{ + Word16 i, j; + + /* Find the first element equal to n */ + FOR( i = 0; i < r; ++i ) + { + FOR( j = 0; j < 3; ++j ) + { + IF( EQ_16( tri[i].LS[j], n ) ) + { + pos[0] = i; + pos[1] = j; + return 1; + } + } + } + return 0; +} +#else static int16_t find_int_in_tri( const EFAP_LS_TRIANGLE *tri, /* i : Triangle array */ const int16_t n, /* i : The integer to find */ @@ -2928,11 +3161,11 @@ static int16_t find_int_in_tri( int16_t i, j; /* Find the first element equal to n */ - FOR( i = 0; i < r; ++i ) + for ( i = 0; i < r; ++i ) { - FOR( j = 0; j < 3; ++j ) + for ( j = 0; j < 3; ++j ) { - IF( EQ_16( tri[i].LS[j], n ) ) + if ( tri[i].LS[j] == n ) { pos[0] = i; pos[1] = j; @@ -2943,6 +3176,7 @@ static int16_t find_int_in_tri( return 0; } +#endif /*-------------------------------------------------------------------------* @@ -2950,7 +3184,29 @@ static int16_t find_int_in_tri( * * Remove a vertex from a vertex structure *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void remove_vertex_fx( + EFAP_VERTEX *vtxArray, /* i : Vertex array */ + const Word16 idx, /* i : Index of the vertex to remove */ + const Word16 L /* i : Length of the Vertex array */ +) +{ + Word16 i; + + assert( idx < L && "EFAP: index out of bounds" ); + + /* Shift all vertex of one position, so vtxArray[i] will be vtxArray[i+1] and so on */ + FOR( i = idx; i < L - 1; ++i ) + { + add_vertex_fx( vtxArray, vtxArray[i + 1].azi, vtxArray[i + 1].ele, i, EFAP_DMX_INTENSITY ); + } + + /* The last vertex is set to 0 */ + add_vertex_fx( vtxArray, 0, 0, sub( L, 1 ), EFAP_DMX_INTENSITY ); + return; +} +#else static void remove_vertex( EFAP_VERTEX *vtxArray, /* i : Vertex array */ const int16_t idx, /* i : Index of the vertex to remove */ @@ -2962,32 +3218,86 @@ static void remove_vertex( assert( idx < L && "EFAP: index out of bounds" ); /* Shift all vertex of one position, so vtxArray[i] will be vtxArray[i+1] and so on */ - FOR( i = idx; i < L - 1; ++i ) + for ( i = idx; i < L - 1; ++i ) { -#ifndef IVAS_FLOAT_FIXED add_vertex( vtxArray, vtxArray[i + 1].azi, vtxArray[i + 1].ele, i, EFAP_DMX_INTENSITY ); -#else - add_vertex_fixed( vtxArray, vtxArray[i + 1].azi, vtxArray[i + 1].ele, i, EFAP_DMX_INTENSITY ); -#endif } /* The last vertex is set to 0 */ -#ifndef IVAS_FLOAT_FIXED add_vertex( vtxArray, 0, 0, L - 1, EFAP_DMX_INTENSITY ); -#else - add_vertex_fixed( vtxArray, 0, 0, L - 1, EFAP_DMX_INTENSITY ); -#endif return; } - +#endif /*-------------------------------------------------------------------------* * get_neighbours() * * Returns the neighbouring triangles of a vertex *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 get_neighbours_fx( + const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ + const Word16 vtxIdx, /* i : Index of the vertex */ + const Word16 numTri, /* i : Number of Triangles */ + Word16 *neighbours /* o : Output vector */ +) +{ + Word16 i, j, k; + Word16 tmpPos[2]; + Word16 tmpNeighbours[EFAP_MAX_SIZE_TMP_BUFF]; + Word16 dummy[EFAP_MAX_SIZE_TMP_BUFF]; + EFAP_LS_TRIANGLE tmpTriArray[EFAP_MAX_POLY_SET]; + + /* Processing */ + FOR( i = 0; i < numTri; ++i ) + { + mvs2s( triArray[i].LS, tmpTriArray[i].LS, 3 ); + } + + k = 0; + WHILE( 1 ) + { + IF( EQ_16(find_int_in_tri_fx( tmpTriArray, vtxIdx, numTri, tmpPos ), 0 ) ) + { + BREAK; + } + ELSE + { + tmpNeighbours[k] = tmpTriArray[tmpPos[0]].LS[0]; + tmpNeighbours[k + 1] = tmpTriArray[tmpPos[0]].LS[1]; + tmpNeighbours[k + 2] = tmpTriArray[tmpPos[0]].LS[2]; + k += 3; + tmpTriArray[tmpPos[0]].LS[tmpPos[1]] = -1; + } + + IF( GT_16( k, i_mult( 3, numTri ) ) ) + { + BREAK; + } + } + + /* Sorting the neighbours vector */ + efap_sort_s_fx( tmpNeighbours, dummy, k ); + + /* Creating the output vector, by eliminating redundancies and also deleting the indice == vtxIdx*/ + neighbours[0] = tmpNeighbours[0]; + j = 1; + FOR( i = 1; i < k; ++i ) + { + IF( NE_16( tmpNeighbours[i], tmpNeighbours[i - 1] ) && + NE_16( tmpNeighbours[i], vtxIdx ) ) + { + neighbours[j] = tmpNeighbours[i]; + ++j; + } + } + + /* Output, length of neighbours */ + return j; +} +#else static int16_t get_neighbours( const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ const int16_t vtxIdx, /* i : Index of the vertex */ @@ -3002,19 +3312,19 @@ static int16_t get_neighbours( EFAP_LS_TRIANGLE tmpTriArray[EFAP_MAX_POLY_SET]; /* Processing */ - FOR( i = 0; i < numTri; ++i ) + for ( i = 0; i < numTri; ++i ) { mvs2s( triArray[i].LS, tmpTriArray[i].LS, 3 ); } k = 0; - WHILE( 1 ) + while ( 1 ) { - IF( EQ_16( find_int_in_tri( tmpTriArray, vtxIdx, numTri, tmpPos ), 0 ) ) + if ( find_int_in_tri( tmpTriArray, vtxIdx, numTri, tmpPos ) == 0 ) { break; } - ELSE + else { tmpNeighbours[k] = tmpTriArray[tmpPos[0]].LS[0]; tmpNeighbours[k + 1] = tmpTriArray[tmpPos[0]].LS[1]; @@ -3023,7 +3333,7 @@ static int16_t get_neighbours( tmpTriArray[tmpPos[0]].LS[tmpPos[1]] = -1; } - IF( GT_16( k, 3 * numTri ) ) + if ( k > 3 * numTri ) { break; } @@ -3036,10 +3346,10 @@ static int16_t get_neighbours( neighbours[0] = tmpNeighbours[0]; j = 1; - FOR( i = 1; i < k; ++i ) + for ( i = 1; i < k; ++i ) { - IF( NE_16( tmpNeighbours[i], tmpNeighbours[i - 1] ) && - NE_16( tmpNeighbours[i], vtxIdx ) ) + if ( ( tmpNeighbours[i] != tmpNeighbours[i - 1] ) && + ( tmpNeighbours[i] != vtxIdx ) ) { neighbours[j] = tmpNeighbours[i]; ++j; @@ -3049,6 +3359,7 @@ static int16_t get_neighbours( /* Output, length of neighbours */ return j; } +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* @@ -3078,12 +3389,12 @@ static void matrix_times_row( } #else /*-------------------------------------------------------------------------* - * matrix_times_row_fixed() + * matrix_times_row_fx() * * Computes the product of a matrix and a row vector *-------------------------------------------------------------------------*/ -static void matrix_times_row_fixed( +static void matrix_times_row_fx( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], /* i : The input matrix */ const Word32 *vec, /* i : The input row vector */ const Word16 L, /* i : Row length */ @@ -3109,7 +3420,98 @@ static void matrix_times_row_fixed( * * Combines triangles of a surface in order to create polygons *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void tri_to_poly_fx( + const EFAP_VERTEX *vtxArray, /* i : Vertex array */ + const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ + const Word16 numVtx, /* i : Number of vertices */ + const Word16 numTri, /* i : Number of triangles */ + Word16 sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM], /* o : The matrix that will contain the sorted channels */ + Word16 *outLengthPS, /* o : The length of the sorted channels */ + Word16 outLengthSorted[EFAP_MAX_POLY_SET] /* o : The number of channels for each poly (i.e. outLengthSorted[i] = length(sortedChan[i]) */ +) +{ + Word16 i, j; + Word16 lenPoly; + Word16 lenPolySet; + Word16 found; + Word16 replaceIdx; + + Word16 poly[EFAP_MAX_CHAN_NUM]; + + Word16 sortedLengths[EFAP_MAX_POLY_SET]; + Word16 sortedTri[EFAP_MAX_POLY_SET]; + + Word32 dist; + lenPolySet = 0; + /* Sorting the polygons */ + FOR( i = 0; i < numTri; ++i ) + { + /* search for coplanar vertices and add them to the polygon */ + lenPoly = 0; + FOR( j = 0; j < numVtx; ++j ) + { + dist = L_abs( point_plane_distance_fx( + vtxArray[triArray[i].LS[0]].pos, + vtxArray[triArray[i].LS[1]].pos, + vtxArray[triArray[i].LS[2]].pos, + vtxArray[j].pos ) ); // Q28 + + IF( LT_32( dist, 268435 ) /* 1e-3f in Q28 */ ) + { + assert( lenPoly < EFAP_MAX_CHAN_NUM && "EFAP: exceeded max polygon vertices!" ); + poly[lenPoly] = j; + ++lenPoly; + } + } + + /* search existing polygons to determine whether the new one already exists/is a subset or is a superset */ + found = 0; + replaceIdx = -1; + FOR( j = 0; j < lenPolySet; ++j ) + { + found = compare_poly_fx( sortedChan[j], sortedLengths[j], poly, lenPoly ); + + IF( GT_16( found, 0 ) ) + { + BREAK; + } + ELSE IF( LT_16( found, 0 ) ) + { + replaceIdx = j; + } + } + + IF( EQ_16( found, 0 ) ) + { + /* append new poly */ + mvs2s( poly, sortedChan[lenPolySet], lenPoly ); + sortedTri[lenPolySet] = i; + sortedLengths[lenPolySet] = lenPoly; + ++lenPolySet; + } + ELSE IF( EQ_16( found, -1 ) ) + { + /* replace with superset */ + mvs2s( poly, sortedChan[replaceIdx], lenPoly ); + sortedTri[replaceIdx] = i; + sortedLengths[replaceIdx] = lenPoly; + } + } + + /* Sorting the vertex */ + FOR( i = 0; i < lenPolySet; ++i ) + { + sort_channels_vertex_fx( vtxArray, triArray, sortedChan[i], sortedLengths[i], sortedTri[i] ); + } + + /* Output */ + *outLengthPS = lenPolySet; + mvs2s( sortedLengths, outLengthSorted, EFAP_MAX_POLY_SET ); + return; +} +#else static void tri_to_poly( const EFAP_VERTEX *vtxArray, /* i : Vertex array */ const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ @@ -3131,39 +3533,23 @@ static void tri_to_poly( int16_t sortedLengths[EFAP_MAX_POLY_SET]; int16_t sortedTri[EFAP_MAX_POLY_SET]; -#ifndef IVAS_FLOAT_FIXED float dist; -#else - Word32 dist; -#endif lenPolySet = 0; /* Sorting the polygons */ - FOR( i = 0; i < numTri; ++i ) + for ( i = 0; i < numTri; ++i ) { /* search for coplanar vertices and add them to the polygon */ lenPoly = 0; - FOR( j = 0; j < numVtx; ++j ) + for ( j = 0; j < numVtx; ++j ) { -#ifndef IVAS_FLOAT_FIXED dist = fabsf( point_plane_distance( vtxArray[triArray[i].LS[0]].pos, vtxArray[triArray[i].LS[1]].pos, vtxArray[triArray[i].LS[2]].pos, vtxArray[j].pos ) ); -#else - dist = L_abs( point_plane_distance_fixed( - vtxArray[triArray[i].LS[0]].pos, - vtxArray[triArray[i].LS[1]].pos, - vtxArray[triArray[i].LS[2]].pos, - vtxArray[j].pos ) ); // Q28 -#endif -#ifndef IVAS_FLOAT_FIXED - IF( dist < 1e-3f ) -#else - IF( LT_32( dist, 268435 ) /* 1e-3f in Q28 */ ) -#endif + if ( dist < 1e-3f ) { assert( lenPoly < EFAP_MAX_CHAN_NUM && "EFAP: exceeded max polygon vertices!" ); poly[lenPoly] = j; @@ -3174,21 +3560,21 @@ static void tri_to_poly( /* search existing polygons to determine whether the new one already exists/is a subset or is a superset */ found = 0; replaceIdx = -1; - FOR( j = 0; j < lenPolySet; ++j ) + for ( j = 0; j < lenPolySet; ++j ) { found = compare_poly( sortedChan[j], sortedLengths[j], poly, lenPoly ); - IF( GT_16( found, 0 ) ) + if ( found > 0 ) { break; } - ELSE IF( LT_16( found, 0 ) ) + else if ( found < 0 ) { replaceIdx = j; } } - IF( EQ_16( found, 0 ) ) + if ( found == 0 ) { /* append new poly */ mvs2s( poly, sortedChan[lenPolySet], lenPoly ); @@ -3196,7 +3582,7 @@ static void tri_to_poly( sortedLengths[lenPolySet] = lenPoly; ++lenPolySet; } - ELSE IF( EQ_16( found, -1 ) ) + else if ( found == -1 ) { /* replace with superset */ mvs2s( poly, sortedChan[replaceIdx], lenPoly ); @@ -3206,28 +3592,66 @@ static void tri_to_poly( } /* Sorting the vertex */ - FOR( i = 0; i < lenPolySet; ++i ) + for ( i = 0; i < lenPolySet; ++i ) { -#ifndef IVAS_FLOAT_FIXED sort_channels_vertex( vtxArray, triArray, sortedChan[i], sortedLengths[i], sortedTri[i] ); -#else - sort_channels_vertex_fixed( vtxArray, triArray, sortedChan[i], sortedLengths[i], sortedTri[i] ); -#endif } /* Output */ *outLengthPS = lenPolySet; mvs2s( sortedLengths, outLengthSorted, EFAP_MAX_POLY_SET ); + return; } - +#endif /*-------------------------------------------------------------------------* * compare_poly() * * Compares a newly created polygon with an existing one *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 compare_poly_fx( + Word16 *old, /* i : Existing polygon */ + Word16 lenOld, /* i : Length of existing polygon */ + Word16 *new, /* i : New polygon */ + Word16 lenNew /* i : Length of new polygon */ +) +{ + Word16 i, j; + Word16 count; + + count = 0; + + FOR( i = 0; i < lenOld; ++i ) + { + FOR( j = count; j < lenNew; ++j ) + { + IF( EQ_16( old[i], new[j] ) ) + { + count = add( count, 1 ); + BREAK; + } + } + } + IF( EQ_16( count, lenOld ) && LT_16( lenOld, lenNew ) ) + { + /* new polygon is a superset */ + return -1; + } + ELSE IF( EQ_16( count, lenNew ) && GE_16( lenOld, lenNew ) ) + { + /* found as subset or identical */ + return 1; + } + ELSE + { + /* not found */ + return 0; + } +} +#else static int16_t compare_poly( int16_t *old, /* i : Existing polygon */ int16_t lenOld, /* i : Length of existing polygon */ @@ -3240,11 +3664,11 @@ static int16_t compare_poly( count = 0; - FOR( i = 0; i < lenOld; ++i ) + for ( i = 0; i < lenOld; ++i ) { - FOR( j = count; j < lenNew; ++j ) + for ( j = count; j < lenNew; ++j ) { - IF( old[i] == new[j] ) + if ( old[i] == new[j] ) { ++count; break; @@ -3252,22 +3676,23 @@ static int16_t compare_poly( } } - IF( count == lenOld && lenOld < lenNew ) + if ( count == lenOld && lenOld < lenNew ) { /* new polygon is a superset */ return -1; } - ELSE IF( count == lenNew && lenOld >= lenNew ) + else if ( count == lenNew && lenOld >= lenNew ) { /* found as subset or identical */ return 1; } - ELSE + else { /* not found */ return 0; } } +#endif #ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* @@ -3367,7 +3792,7 @@ static void sort_channels_vertex( * Sort the channels of a polygon set according to the vertex azimuth *-------------------------------------------------------------------------*/ -static void sort_channels_vertex_fixed( +static void sort_channels_vertex_fx( const EFAP_VERTEX *vtxArray, /* i : Vertex array */ const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ Word16 channels[EFAP_MAX_CHAN_NUM], /* o : Channels array to be modified */ @@ -3414,7 +3839,7 @@ static void sort_channels_vertex_fixed( FOR( i = 0; i < 3; i++ ) { - tmpV2[i] = L_shl( tmpV2[i], Q2 + ( 2 * exp1 ) ); + tmpV2[i] = L_shl( tmpV2[i], add( Q2, shl( exp1, 1 ) ) ); } v_sub_fixed( tmpV1, tmpV2, tmpV3, 3, 0 ); // tmpV3 Q30 @@ -3443,7 +3868,7 @@ static void sort_channels_vertex_fixed( y = dotp_fixed( P, V, 3 ); // y Q29 - exp2 // Executing azi[i] = atan2f( y, x ); - azi[i] = L_shl( (Word32) BASOP_util_atan2( y, x, exp2 - exp1 ), Q16 ); // azi 2Q29 + azi[i] = L_shl( (Word32) BASOP_util_atan2( y, x, sub( exp2, exp1 ) ), Q16 ); // azi 2Q29 } /* Sorting the azi vec */ @@ -3563,7 +3988,7 @@ static int16_t get_poly_num( * Returns the index of the polygon in which the coordinate is *-------------------------------------------------------------------------*/ -static Word16 get_poly_num_fixed( +static Word16 get_poly_num_fx( const Word32 P[2], /* i : Azimuth and elevation of the point */ const EFAP_POLYSET_DATA *polyData /* i : Polyset struct */ ) @@ -3578,15 +4003,15 @@ static Word16 get_poly_num_fixed( num_poly = 0; - sph2cart_fixed( P[0], P[1], &pos[0] ); + sph2cart_fx( P[0], P[1], &pos[0] ); /* Filter the polygon list with a fast 2d check */ FOR( i = 0; i < polyData->numPoly; ++i ) { - IF( in_poly_fixed( P, polyData->polysetArray[i] ) ) + IF( in_poly_fx( P, polyData->polysetArray[i] ) ) { /* select only polygons which are visible from the point */ - dist_tmp = point_poly_distance_fixed( polyData->polysetArray[i], pos ); + dist_tmp = point_poly_distance_fx( polyData->polysetArray[i], pos ); IF( EQ_32( dist_tmp, 0 ) ) { return i; @@ -3692,12 +4117,12 @@ static int16_t in_poly( } #else /*-------------------------------------------------------------------------* - * in_poly_fixed() + * in_poly_fx() * * Determines if a given point is within a polygon or not *-------------------------------------------------------------------------*/ -static Word16 in_poly_fixed( /* Angles are in Q22 */ +static Word16 in_poly_fx( /* Angles are in Q22 */ const Word32 P[2], /* i : Azimuth and elevation of the point */ const EFAP_POLYSET poly /* i : Polyset struct */ ) @@ -3730,7 +4155,7 @@ static Word16 in_poly_fixed( /* Angles are in Q22 */ v_sub_fixed( P, A, P_minus_A, 2, 0 ); /* Precalculate value of (P-A) */ - FOR( n = 1; n < numVertices - 1; ++n ) + FOR( n = 1; n < sub( numVertices, 1 ); ++n ) { IF( poly.isNaN[n] ) { @@ -3752,7 +4177,7 @@ static Word16 in_poly_fixed( /* Angles are in Q22 */ } C[1] = poly.polyEle[n + 1]; - IF( in_tri_fixed( A, B, C, P_minus_A ) ) + IF( in_tri_fx( A, B, C, P_minus_A ) ) { return 1; } @@ -3822,12 +4247,12 @@ static int16_t in_tri( } #else /*-------------------------------------------------------------------------* - * in_tri_fixed() + * in_tri_fx() * * Determines if a given point is within a triangle or not *-------------------------------------------------------------------------*/ -static Word16 in_tri_fixed( +static Word16 in_tri_fx( Word32 A[2], /* i : Coordinate of one apex of the triangle */ Word32 B[2], /* i : Coordinate of one apex of the triangle */ Word32 C[2], /* i : Coordinate of one apex of the triangle */ @@ -3859,7 +4284,7 @@ static Word16 in_tri_fixed( return 0; } - invFactor_w64 = ( ( (Word64) 0x7FFFFFFFFFFFFFFF ) / ( (Word64) invFactor ) ) >> Q19; // Q31 + invFactor_w64 = W_shr( ( (Word64) 0x7FFFFFFFFFFFFFFF ) / ( (Word64) invFactor ), Q19 ); // Q31 invFactor = (Word32) invFactor_w64; Word16 invFactor_exp = norm_l( invFactor ); @@ -3950,12 +4375,12 @@ static void sph2cart( } #else /*-------------------------------------------------------------------------* - * sph2cart_fixed() + * sph2cart_fx() * * Converts a vertex position to cartesian coordinates *-------------------------------------------------------------------------*/ -static void sph2cart_fixed( +static void sph2cart_fx( const Word32 azi, /* i : Azimuth in degrees (Q22) */ const Word32 ele, /* i : Elevation in degrees (Q22) */ Word32 *pos /* o : Cartesian coordinates vector (x, y, z) */ diff --git a/lib_rend/ivas_hrtf.c b/lib_rend/ivas_hrtf.c index 6e85d16f5..2b8619284 100644 --- a/lib_rend/ivas_hrtf.c +++ b/lib_rend/ivas_hrtf.c @@ -44,6 +44,20 @@ * Allocate HRTF binary handle *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_HRTF_binary_open_fx( + TDREND_HRFILT_FiltSet_t **hHrtfTD ) +{ + /* Allocate HR filter set for headphones configuration */ + *hHrtfTD = (TDREND_HRFILT_FiltSet_t *) malloc( sizeof( TDREND_HRFILT_FiltSet_t ) ); + IF( *hHrtfTD == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF binary!" ); + } + + return IVAS_ERR_OK; +} +#else ivas_error ivas_HRTF_binary_open( TDREND_HRFILT_FiltSet_t **hHrtfTD ) { @@ -56,6 +70,7 @@ ivas_error ivas_HRTF_binary_open( return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------* @@ -64,6 +79,22 @@ ivas_error ivas_HRTF_binary_open( * Close HRTF binary handle *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_HRTF_binary_close_fx( + TDREND_HRFILT_FiltSet_t **hHrtfTD ) +{ + test(); + IF( hHrtfTD == NULL || *hHrtfTD == NULL ) + { + return; + } + + free( *hHrtfTD ); + *hHrtfTD = NULL; + + return; +} +#else void ivas_HRTF_binary_close( TDREND_HRFILT_FiltSet_t **hHrtfTD ) { @@ -77,6 +108,7 @@ void ivas_HRTF_binary_close( return; } +#endif /*-----------------------------------------------------------------------* @@ -85,6 +117,26 @@ void ivas_HRTF_binary_close( * Allocate HRTF binary handle *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_HRTF_CRend_binary_open_fx( + HRTFS_CREND **hSetOfHRTF ) +{ + /* Allocate HR filter set for headphones configuration */ + *hSetOfHRTF = (HRTFS_CREND *) malloc( sizeof( HRTFS_CREND ) ); + IF( *hSetOfHRTF == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for set of HRTF binary!" ); + } + + ( *hSetOfHRTF )->hHRTF_hrir_combined = NULL; + ( *hSetOfHRTF )->hHRTF_hrir_hoa3 = NULL; + ( *hSetOfHRTF )->hHRTF_hrir_hoa2 = NULL; + ( *hSetOfHRTF )->hHRTF_hrir_foa = NULL; + ( *hSetOfHRTF )->hHRTF_brir_combined = NULL; + + return IVAS_ERR_OK; +} +#else ivas_error ivas_HRTF_CRend_binary_open( HRTFS_CREND **hSetOfHRTF ) { @@ -103,6 +155,7 @@ ivas_error ivas_HRTF_CRend_binary_open( return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------* @@ -111,6 +164,22 @@ ivas_error ivas_HRTF_CRend_binary_open( * Close HRTF CRend binary handle *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_HRTF_CRend_binary_close_fx( + HRTFS_CREND **hSetOfHRTF ) +{ + test(); + IF( hSetOfHRTF == NULL || *hSetOfHRTF == NULL ) + { + return; + } + + free( *hSetOfHRTF ); + *hSetOfHRTF = NULL; + + return; +} +#else void ivas_HRTF_CRend_binary_close( HRTFS_CREND **hSetOfHRTF ) { @@ -124,6 +193,7 @@ void ivas_HRTF_CRend_binary_close( return; } +#endif /*-----------------------------------------------------------------------* @@ -153,6 +223,22 @@ ivas_error ivas_HRTF_fastconv_binary_open( * Close HRTF binary handle for FASTCONV renderer *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_HRTF_fastconv_binary_close_fx( + HRTFS_FASTCONV **hHrtfFastConv ) +{ + test(); + IF( hHrtfFastConv == NULL || *hHrtfFastConv == NULL ) + { + return; + } + + free( *hHrtfFastConv ); + *hHrtfFastConv = NULL; + + return; +} +#else void ivas_HRTF_fastconv_binary_close( HRTFS_FASTCONV **hHrtfFastConv ) { @@ -166,6 +252,7 @@ void ivas_HRTF_fastconv_binary_close( return; } +#endif /*-----------------------------------------------------------------------* @@ -174,6 +261,19 @@ void ivas_HRTF_fastconv_binary_close( * Allocate HRTF binary handle for parametric binauralizer *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_HRTF_parambin_binary_open_fx( + HRTFS_PARAMBIN **hHrtfParambin ) +{ + *hHrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ); + IF( *hHrtfParambin == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for parametric binauralizer HRTF tables!" ); + } + + return IVAS_ERR_OK; +} +#else ivas_error ivas_HRTF_parambin_binary_open( HRTFS_PARAMBIN **hHrtfParambin ) { @@ -185,6 +285,7 @@ ivas_error ivas_HRTF_parambin_binary_open( return IVAS_ERR_OK; } +#endif /*-----------------------------------------------------------------------* @@ -193,6 +294,22 @@ ivas_error ivas_HRTF_parambin_binary_open( * Close HRTF binary handle for parametric binauralizer *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_HRTF_parambin_binary_close_fx( + HRTFS_PARAMBIN **hHrtfParambin ) +{ + test(); + IF( hHrtfParambin == NULL || *hHrtfParambin == NULL ) + { + return; + } + + free( *hHrtfParambin ); + *hHrtfParambin = NULL; + + return; +} +#else void ivas_HRTF_parambin_binary_close( HRTFS_PARAMBIN **hHrtfParambin ) { @@ -206,3 +323,4 @@ void ivas_HRTF_parambin_binary_close( return; } +#endif diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 553b60a05..9ee54f329 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -807,148 +807,146 @@ ivas_error ivas_td_binaural_renderer_unwrap( * Render one 5 ms subframe from the mixer *---------------------------------------------------------------------*/ -ivas_error TDREND_GetMix( +#ifdef IVAS_FLOAT_FIXED +ivas_error TDREND_GetMix_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - float *output[], /* i/o: ISM object synth / rendered output in 0,1 */ - const int16_t subframe_length, /* i/o: subframe length */ - const int16_t subframe_idx, /* i : Subframe index to 5 ms subframe */ - const int16_t ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ + Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 */ + const Word16 subframe_length, /* i/o: subframe length */ + const Word16 subframe_idx, /* i : Subframe index to 5 ms subframe */ + const Word16 ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ ) { - int16_t i; + Word16 i; TDREND_SRC_t *Src_p; TDREND_SRC_SPATIAL_t *SrcSpatial_p; TDREND_SRC_REND_t *SrcRend_p; ivas_error error; - float output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */ - float hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; - float hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; - int16_t intp_count; - int16_t subframe_update_flag; + Word32 output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */ + Word32 hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + Word32 hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + Word16 intp_count; + Word16 subframe_update_flag; + Word16 hrf_left_delta_e = 0, hrf_right_delta_e = 0; - subframe_update_flag = subframe_idx == ism_md_subframe_update; + subframe_update_flag = (Word16)EQ_16( subframe_idx, ism_md_subframe_update ); error = IVAS_ERR_OK; /* Clear the output buffer to accumulate rendered sources */ - set_f( output_buf[0], 0.0f, subframe_length ); - set_f( output_buf[1], 0.0f, subframe_length ); - + set32_fx( output_buf[0], 0, subframe_length ); + set32_fx( output_buf[1], 0, subframe_length ); /* Clear interpolation buffers and counter */ - set_f( hrf_left_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set_f( hrf_right_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set32_fx( hrf_left_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set32_fx( hrf_right_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + intp_count = 0; + move16(); /* Create the mix */ /* Loop through the source list and render each source */ - for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) + FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) { Src_p = hBinRendererTd->Sources[i]; SrcSpatial_p = Src_p->SrcSpatial_p; SrcRend_p = Src_p->SrcRend_p; /* Update rendering params if needed */ - if ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) ) + test(); test(); + IF ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) ) { - TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, Src_p->hrf_left_prev, - Src_p->hrf_right_prev, hrf_left_delta, hrf_right_delta, &intp_count, &Src_p->filterlength, &Src_p->itd, &Src_p->Gain, Src_p, subframe_update_flag ); + TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( hBinRendererTd, SrcRend_p, SrcSpatial_p, + Src_p->hrf_left_prev_fx, &Src_p->hrf_left_prev_e, Src_p->hrf_right_prev_fx, &Src_p->hrf_right_prev_e, + hrf_left_delta, &hrf_left_delta_e, hrf_right_delta, &hrf_right_delta_e, + &intp_count, &Src_p->filterlength, &Src_p->itd, + &Src_p->Gain_fx, + Src_p, subframe_update_flag ); } /* Render source if needed */ - if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) + IF ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) { - error = TDREND_REND_RenderSourceHRFilt( Src_p, hrf_left_delta, hrf_right_delta, intp_count, output_buf, subframe_length ); + error = TDREND_REND_RenderSourceHRFilt_fx( Src_p, hrf_left_delta, &hrf_left_delta_e, + hrf_right_delta, &hrf_right_delta_e, intp_count, output_buf, subframe_length ); } } + /* Populate output variable */ - mvr2r( output_buf[0], output[0] + subframe_idx * subframe_length, subframe_length ); /* Left */ - mvr2r( output_buf[1], output[1] + subframe_idx * subframe_length, subframe_length ); /* Right */ + Copy32( output_buf[0], output[0] + imult1616(subframe_idx, subframe_length), subframe_length ); /* Left */ + Copy32( output_buf[1], output[1] + imult1616(subframe_idx, subframe_length), subframe_length ); /* Right */ /* Clear the PoseUpdated and Source position update flags */ - TDREND_Clear_Update_flags( hBinRendererTd ); + TDREND_Clear_Update_flags_fx( hBinRendererTd ); return error; } - - -#ifdef IVAS_FLOAT_FIXED -ivas_error TDREND_GetMix_fx( +#else +ivas_error TDREND_GetMix( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ - Word32 *output[], /* i/o: ISM object synth / rendered output in 0,1 */ - const Word16 subframe_length, /* i/o: subframe length */ - const Word16 subframe_idx, /* i : Subframe index to 5 ms subframe */ - const Word16 ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ + float *output[], /* i/o: ISM object synth / rendered output in 0,1 */ + const int16_t subframe_length, /* i/o: subframe length */ + const int16_t subframe_idx, /* i : Subframe index to 5 ms subframe */ + const int16_t ism_md_subframe_update /* i : Number of subframes to delay ism metadata to sync with audio */ ) { - Word16 i; + int16_t i; TDREND_SRC_t *Src_p; TDREND_SRC_SPATIAL_t *SrcSpatial_p; TDREND_SRC_REND_t *SrcRend_p; ivas_error error; - Word32 output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */ - Word32 hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; - Word32 hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; - Word16 intp_count; - Word16 subframe_update_flag; - Word16 hrf_left_delta_e = 0, hrf_right_delta_e = 0; + float output_buf[2][L_SPATIAL_SUBFR_48k]; /* Temp buffer for left/right rendered signal */ + float hrf_left_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + float hrf_right_delta[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; + int16_t intp_count; + int16_t subframe_update_flag; - subframe_update_flag = (Word16)EQ_16( subframe_idx, ism_md_subframe_update ); + subframe_update_flag = subframe_idx == ism_md_subframe_update; error = IVAS_ERR_OK; /* Clear the output buffer to accumulate rendered sources */ - set32_fx( output_buf[0], 0, subframe_length ); - set32_fx( output_buf[1], 0, subframe_length ); - /* Clear interpolation buffers and counter */ - set32_fx( hrf_left_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set32_fx( hrf_right_delta, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set_f( output_buf[0], 0.0f, subframe_length ); + set_f( output_buf[1], 0.0f, subframe_length ); + /* Clear interpolation buffers and counter */ + set_f( hrf_left_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); + set_f( hrf_right_delta, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); intp_count = 0; - move16(); /* Create the mix */ /* Loop through the source list and render each source */ - FOR( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) + for ( i = 0; i < hBinRendererTd->NumOfSrcs; i++ ) { Src_p = hBinRendererTd->Sources[i]; SrcSpatial_p = Src_p->SrcSpatial_p; SrcRend_p = Src_p->SrcRend_p; /* Update rendering params if needed */ - test(); test(); - IF ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) ) + if ( ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) && ( hBinRendererTd->Listener_p->PoseUpdated || SrcSpatial_p->Updated ) ) { - TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( hBinRendererTd, SrcRend_p, SrcSpatial_p, - Src_p->hrf_left_prev_fx, &Src_p->hrf_left_prev_e, Src_p->hrf_right_prev_fx, &Src_p->hrf_right_prev_e, - hrf_left_delta, &hrf_left_delta_e, hrf_right_delta, &hrf_right_delta_e, - &intp_count, &Src_p->filterlength, &Src_p->itd, - &Src_p->Gain_fx, - Src_p, subframe_update_flag ); + TDREND_SRC_REND_UpdateFiltersFromSpatialParams( hBinRendererTd, SrcRend_p, SrcSpatial_p, Src_p->hrf_left_prev, + Src_p->hrf_right_prev, hrf_left_delta, hrf_right_delta, &intp_count, &Src_p->filterlength, &Src_p->itd, &Src_p->Gain, Src_p, subframe_update_flag ); } /* Render source if needed */ - IF ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) + if ( ( SrcRend_p->InputAvailable == TRUE ) && ( SrcRend_p->PlayStatus == TDREND_PLAYSTATUS_PLAYING ) ) { - error = TDREND_REND_RenderSourceHRFilt_fx( Src_p, hrf_left_delta, &hrf_left_delta_e, - hrf_right_delta, &hrf_right_delta_e, intp_count, output_buf, subframe_length ); + error = TDREND_REND_RenderSourceHRFilt( Src_p, hrf_left_delta, hrf_right_delta, intp_count, output_buf, subframe_length ); } } - /* Populate output variable */ - Copy32( output_buf[0], output[0] + imult1616(subframe_idx, subframe_length), subframe_length ); /* Left */ - Copy32( output_buf[1], output[1] + imult1616(subframe_idx, subframe_length), subframe_length ); /* Right */ + mvr2r( output_buf[0], output[0] + subframe_idx * subframe_length, subframe_length ); /* Left */ + mvr2r( output_buf[1], output[1] + subframe_idx * subframe_length, subframe_length ); /* Right */ /* Clear the PoseUpdated and Source position update flags */ - TDREND_Clear_Update_flags_fx( hBinRendererTd ); + TDREND_Clear_Update_flags( hBinRendererTd ); return error; } #endif - /*---------------------------------------------------------------------* * TDREND_Clear_Update_flags() * diff --git a/lib_rend/ivas_objectRenderer_hrFilt.c b/lib_rend/ivas_objectRenderer_hrFilt.c index 3fdbe47f0..720816ea7 100644 --- a/lib_rend/ivas_objectRenderer_hrFilt.c +++ b/lib_rend/ivas_objectRenderer_hrFilt.c @@ -46,14 +46,14 @@ * Local function prototypes *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void getPeriodicBSplineSampVec( float *BfVec, int16_t *AzIdx, const int16_t NumBFs, const float t, int16_t *num_az_idx, const float knot_interval, const float azimKSeq_0, const int16_t azimSegSamples, const float *azimBsShape, const int16_t subSampFactor ); static void getStandardBSplineSampVec( float *BfVec, int16_t *NzIdx, int16_t *num_idx, const int16_t NumBFs, const float t, const float *KSeq, const int16_t SegSamples, const int16_t *BsLen, const int16_t *BsStart, const float *BsShape ); static void GenerateFilter( const float elev, float azim, ModelParams_t *model, ModelEval_t *modelEval ); static void GenerateITD( const float elev, float azim, ModelParamsITD_t *model, ModelEval_t *modelEval ); static void SkipSmallest_ValueIndex( int16_t *use_inds, const ValueIndex_t *VI, const int16_t N, const int16_t n_smallest ); - -#ifdef IVAS_FLOAT_FIXED -static Word32 round_fixed(Word32 n, Word16 q); +#else +static Word32 round_fixed( Word32 n, Word16 q ); static void getPeriodicBSplineSampVec_fx( Word32 *BfVec_fx, Word16 *AzIdx, const Word16 NumBFs, const Word32 t_fx, Word16 *num_az_idx, const Word32 knot_interval_fx, const Word32 azimKSeq_0_fx, const Word16 azimSegSamples, const Word32 *azimBsShape_fx, const Word16 subSampFactor ); static void getStandardBSplineSampVec_fx( Word32 *BfVec_fx, Word16 *NzIdx, Word16 *num_idx, const Word16 NumBFs, const Word32 t_fx, const Word32 *KSeq_fx, const Word16 SegSamples, const Word16 *BsLen, const Word16 *BsStart, const Word32 *BsShape_fx ); static void GenerateFilter_fx( const Word32 elev, Word32 azim, ModelParams_t *model, ModelEval_t *modelEval ); @@ -67,6 +67,7 @@ static void SkipSmallest_ValueIndex_fx( Word16 *use_inds, const ValueIndex_t *VI * Renders each object using the HR filters --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED ivas_error TDREND_REND_RenderSourceHRFilt( TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ const float *hrf_left_delta, /* i : Left filter interpolation delta */ @@ -91,21 +92,20 @@ ivas_error TDREND_REND_RenderSourceHRFilt( return IVAS_ERR_OK; } - -#ifdef IVAS_FLOAT_FIXED +#else ivas_error TDREND_REND_RenderSourceHRFilt_fx( - TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ - Word32 *hrf_left_delta_fx, /* i/o: Left filter interpolation delta */ - Word16 *hrf_left_delta_e, /* i/o: Left filter interpolation delta exp */ - Word32 *hrf_right_delta_fx, /* i/o: Right filter interpolation delta */ - Word16 *hrf_right_delta_e, /* i/o: Right filter interpolation delta exp */ - const Word16 intp_count, /* i : Interpolation count */ - Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ - const Word16 subframe_length /* i : Subframe length in use */ + TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ + Word32 *hrf_left_delta_fx, /* i/o: Left filter interpolation delta */ + Word16 *hrf_left_delta_e, /* i/o: Left filter interpolation delta exp */ + Word32 *hrf_right_delta_fx, /* i/o: Right filter interpolation delta */ + Word16 *hrf_right_delta_e, /* i/o: Right filter interpolation delta exp */ + const Word16 intp_count, /* i : Interpolation count */ + Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ + const Word16 subframe_length /* i : Subframe length in use */ ) { - Word32 LeftOutputFrame_fx[L_SPATIAL_SUBFR_48k]; // will have same Q as Src_p->InputFrame_p_fx - Word32 RightOutputFrame_fx[L_SPATIAL_SUBFR_48k]; // will have same Q as Src_p->InputFrame_p_fx + Word32 LeftOutputFrame_fx[L_SPATIAL_SUBFR_48k]; // will have same Q as Src_p->InputFrame_p_fx + Word32 RightOutputFrame_fx[L_SPATIAL_SUBFR_48k]; // will have same Q as Src_p->InputFrame_p_fx Word16 left_filter_e; Word16 right_filter_e; @@ -131,18 +131,19 @@ ivas_error TDREND_REND_RenderSourceHRFilt_fx( TDREND_firfilt_fx( LeftOutputFrame_fx, Src_p->hrf_left_prev_fx, left_filter_e, hrf_left_delta_fx, intp_count, Src_p->mem_hrf_left_fx, subframe_length, Src_p->filterlength, Src_p->Gain_fx, Src_p->prevGain_fx ); TDREND_firfilt_fx( RightOutputFrame_fx, Src_p->hrf_right_prev_fx, right_filter_e, hrf_right_delta_fx, intp_count, Src_p->mem_hrf_right_fx, subframe_length, Src_p->filterlength, Src_p->Gain_fx, Src_p->prevGain_fx ); - + Src_p->prevGain_fx = Src_p->Gain_fx; move16(); /* Copy to accumulative output frame */ - v_add_32( LeftOutputFrame_fx, output_buf_fx[0], output_buf_fx[0], subframe_length ); // Same Q as Src_p->InputFrame_p_fx - v_add_32( RightOutputFrame_fx, output_buf_fx[1], output_buf_fx[1], subframe_length ); // Same Q as Src_p->InputFrame_p_fx + v_add_32( LeftOutputFrame_fx, output_buf_fx[0], output_buf_fx[0], subframe_length ); // Same Q as Src_p->InputFrame_p_fx + v_add_32( RightOutputFrame_fx, output_buf_fx[1], output_buf_fx[1], subframe_length ); // Same Q as Src_p->InputFrame_p_fx return IVAS_ERR_OK; } #endif + /*-------------------------------------------------------------------* * GetFilterFromAngle() * @@ -150,6 +151,7 @@ ivas_error TDREND_REND_RenderSourceHRFilt_fx( * This version uses the HR filter model. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void GetFilterFromAngle( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ const float Elev, /* i : Elevation, degrees */ @@ -179,8 +181,7 @@ void GetFilterFromAngle( return; } - -#ifdef IVAS_FLOAT_FIXED +#else void GetFilterFromAngle_fx( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ const Word32 Elev_fx, /* i : Elevation, degrees Q22 */ @@ -203,7 +204,7 @@ void GetFilterFromAngle_fx( move16(); /* 4. Evaluate the ITD */ - IF ( HrFiltSet_p->ModelParams.UseItdModel ) + IF( HrFiltSet_p->ModelParams.UseItdModel ) { GenerateITD_fx( Elev_fx, Azim_fx, &HrFiltSet_p->ModelParamsITD, &HrFiltSet_p->ModelEval ); *itd = extract_l( HrFiltSet_p->ModelEval.itdMod_fx ); @@ -218,9 +219,9 @@ void GetFilterFromAngle_fx( } #endif -static Word32 round_fixed( /* o : Output value Q0 */ - Word32 num, /* i : Input value */ - Word16 q /* i : Input q-factor */ +static Word32 round_fixed( /* o : Output value Q0 */ + Word32 num, /* i : Input value */ + Word16 q /* i : Input q-factor */ ) { Word32 half = L_shl( 1, ( q - 1 ) ); @@ -252,6 +253,7 @@ static Word32 round_fixed( /* o : Output value Q0 */ * Generate an HR filter using the B Spline model. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void GenerateFilter( const float elev, /* i : Elevation angle, degrees */ float azim, /* i : Azimuth angle, degrees */ @@ -365,7 +367,7 @@ static void GenerateFilter( return; } -#ifdef IVAS_FLOAT_FIXED +#else static void GenerateFilter_fx( const Word32 elev, /* i : Elevation angle, degrees Q22 */ Word32 azim, /* i : Azimuth angle, degrees Q22 */ @@ -439,7 +441,6 @@ static void GenerateFilter_fx( FOR( i = 0; i < num_az_idx[p]; i++ ) { modelEval->BM_fx[qp + i] = L_shl( Mpy_32_32( modelEval->elevBfVec_fx[p], modelEval->azimBfVec_fx[p][i] ), Q30 - ( Q30 * 2 - 31 ) ); // Q30 - modelEval->BM[qp + i] = fix_to_float( modelEval->BM_fx[qp + i], Q30 ); BM_idx[qp + i] = model->azim_start_idx[EvIdx[p]] + AzIdx[p][i]; } qp = add( qp, num_az_idx[p] ); @@ -543,15 +544,16 @@ static void GenerateFilter_fx( return; } - #endif + /*-------------------------------------------------------------------* * GenerateITD() * * Generates an ITD value from the B Spline model. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void GenerateITD( const float elev, /* i : Elevation angle, degrees */ float azim, /* i : Azimuth angle, degrees */ @@ -664,8 +666,7 @@ static void GenerateITD( return; } - -#ifdef IVAS_FLOAT_FIXED +#else static void GenerateITD_fx( const Word32 elev_fx, /* i : Elevation angle, degrees Q22 */ Word32 azim_fx, /* i : Azimuth angle, degrees Q22 */ @@ -826,6 +827,7 @@ static void GenerateITD_fx( * Obtain a periodic sampled B Spline basis vector. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void getPeriodicBSplineSampVec( float *BfVec, /* i/o: values for non-zero basis functions */ int16_t *AzIdx, /* i/o: indices of non-zero basis functions */ @@ -865,8 +867,7 @@ static void getPeriodicBSplineSampVec( return; } - -#ifdef IVAS_FLOAT_FIXED +#else static void getPeriodicBSplineSampVec_fx( Word32 *BfVec_fx, /* o : values for non-zero basis functions Q30 */ Word16 *AzIdx, /* o : indices of non-zero basis functions */ @@ -884,7 +885,7 @@ static void getPeriodicBSplineSampVec_fx( Word32 tmp32; Word16 tmp_e1, tmp_e2; Word16 SegSamples; - + SegSamples = 0; move16(); IF( azimSegSamples != 0 ) @@ -893,19 +894,19 @@ static void getPeriodicBSplineSampVec_fx( } /* index of closest sample point */ - IF(knot_interval_fx == 0) + IF( knot_interval_fx == 0 ) { d0 = 0; move16(); } ELSE { - tmp32 = L_deposit_h(BASOP_Util_Divide3216_Scale(knot_interval_fx, SegSamples, &tmp_e1)); - tmp_e1 = add(tmp_e1, sub(9, 15)); - tmp32 = L_deposit_h(BASOP_Util_Divide3232_Scale(L_sub(t_fx, azimKSeq_0_fx), tmp32, &tmp_e2)); - tmp_e2 = add(tmp_e2, sub(9, tmp_e1)); - tmp32 = L_shr(tmp32, sub(9, tmp_e2)); // Q22 (assuming tmp32 will be in range of Q22) - d0 = extract_l(round_fixed(tmp32, Q22)); + tmp32 = L_deposit_h( BASOP_Util_Divide3216_Scale( knot_interval_fx, SegSamples, &tmp_e1 ) ); + tmp_e1 = add( tmp_e1, sub( 9, 15 ) ); + tmp32 = L_deposit_h( BASOP_Util_Divide3232_Scale( L_sub( t_fx, azimKSeq_0_fx ), tmp32, &tmp_e2 ) ); + tmp_e2 = add( tmp_e2, sub( 9, tmp_e1 ) ); + tmp32 = L_shr( tmp32, sub( 9, tmp_e2 ) ); // Q22 (assuming tmp32 will be in range of Q22) + d0 = extract_l( round_fixed( tmp32, Q22 ) ); } /* find segment */ @@ -921,14 +922,14 @@ static void getPeriodicBSplineSampVec_fx( IF( d0 % SegSamples == 0 ) { - *num_az_idx = sub(*num_az_idx, 1); /* on the knot points, the last basis function is zero */ + *num_az_idx = sub( *num_az_idx, 1 ); /* on the knot points, the last basis function is zero */ } FOR( i = 0; i < *num_az_idx; i++ ) { d = d0 - ( i + nI - 1 ) * SegSamples; /* offset of knot_interval */ - d = sub(d0, imult1616(sub(add(i, nI), 1), SegSamples)); - BfVec_fx[i] = azimBsShape_fx[abs_s(d) * subSampFactor]; + d = sub( d0, imult1616( sub( add( i, nI ), 1 ), SegSamples ) ); + BfVec_fx[i] = azimBsShape_fx[abs_s( d ) * subSampFactor]; AzIdx[i] = add( nI, i ) % NumBFs; } @@ -942,6 +943,7 @@ static void getPeriodicBSplineSampVec_fx( * Obtain a sampled B Spline basis vector. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void getStandardBSplineSampVec( float *BfVec, /* i/o: values for non-zero basis functions */ int16_t *NzIdx, /* i/o: indices of non-zero basis functions */ @@ -993,8 +995,7 @@ static void getStandardBSplineSampVec( return; } - -#ifdef IVAS_FLOAT_FIXED +#else static void getStandardBSplineSampVec_fx( Word32 *BfVec_fx, /* o : values for non-zero basis functions Q30 */ Word16 *NzIdx, /* o : indices of non-zero basis functions */ @@ -1077,16 +1078,16 @@ void HRTF_model_precalc( { Word16 sec_length; Word16 i; - sec_length = mult(model->K,10923); /*10923 == 2 ^ 15 / 3*/ - FOR ( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) + sec_length = mult( model->K, 10923 ); /*10923 == 2 ^ 15 / 3*/ + FOR( i = 0; i < HRTF_MODEL_N_SECTIONS; i++ ) { - model->iSecFirst[i] = imult1616(i , sec_length); + model->iSecFirst[i] = imult1616( i, sec_length ); } - FOR ( i = 0; i < HRTF_MODEL_N_SECTIONS - 1; i++ ) + FOR( i = 0; i < HRTF_MODEL_N_SECTIONS - 1; i++ ) { - model->iSecLast[i] = sub(imult1616(add( i , 1 ) , sec_length) , 1); + model->iSecLast[i] = sub( imult1616( add( i, 1 ), sec_length ), 1 ); } - model->iSecLast[HRTF_MODEL_N_SECTIONS - 1] = sub(model->K , 1); /* Final section is longer if (K % nSec) > 0 */ + model->iSecLast[HRTF_MODEL_N_SECTIONS - 1] = sub( model->K, 1 ); /* Final section is longer if (K % nSec) > 0 */ maximum_fx( model->azimDim3, model->elevDim3, &model->azimDim3Max ); return; } @@ -1167,8 +1168,13 @@ void BSplineModelEvalDealloc( free( model->azimKSeq ); if ( modelEval != NULL ) { +#ifdef IVAS_FLOAT_FIXED + free( modelEval->hrfModL_fx ); + free( modelEval->hrfModR_fx ); +#else free( modelEval->hrfModL ); free( modelEval->hrfModR ); +#endif } } @@ -1183,6 +1189,7 @@ void BSplineModelEvalDealloc( * unordered (i.e. skip the n_smallest values, return the remainder). --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static void SkipSmallest_ValueIndex( int16_t *use_inds, /* i/o: List of indices to use */ const ValueIndex_t *VI, /* i : List of value-index items */ @@ -1254,11 +1261,10 @@ static void SkipSmallest_ValueIndex( return; } - -#ifdef IVAS_FLOAT_FIXED +#else static void SkipSmallest_ValueIndex_fx( Word16 *use_inds, /* i/o: List of indices to use */ - const ValueIndex_t *VI, /* i : List of value-index items */ + const ValueIndex_t *VI, /* i : List of value-index items */ const Word16 N, /* i : Length of list */ const Word16 n_smallest /* i : Number of items to skip */ ) @@ -1273,7 +1279,7 @@ static void SkipSmallest_ValueIndex_fx( move32(); candidate_max_i = 0; move16(); - FOR ( j = 0; j < n_smallest; j++ ) + FOR( j = 0; j < n_smallest; j++ ) { skip_inds[j] = j; move16(); @@ -1289,9 +1295,9 @@ static void SkipSmallest_ValueIndex_fx( /* Look in the remainder of the list for smaller values */ FOR( i = n_smallest; i < N; i++ ) { - FOR ( j = 0; j < n_smallest; j++ ) + FOR( j = 0; j < n_smallest; j++ ) { - IF ( LT_32( VI[i].val_fx, VI[skip_inds[j]].val_fx ) ) + IF( LT_32( VI[i].val_fx, VI[skip_inds[j]].val_fx ) ) { /* Found a smaller value, so it goes into the list, replacing candidate_max. */ skip_inds[candidate_max_i] = i; @@ -1299,9 +1305,9 @@ static void SkipSmallest_ValueIndex_fx( candidate_max = VI[i].val_fx; move32(); /* Update candidate_max */ - FOR ( k = 0; k < n_smallest; k++ ) + FOR( k = 0; k < n_smallest; k++ ) { - IF ( GT_32( VI[skip_inds[k]].val_fx, candidate_max ) ) + IF( GT_32( VI[skip_inds[k]].val_fx, candidate_max ) ) { candidate_max = VI[skip_inds[k]].val_fx; move32(); @@ -1334,7 +1340,7 @@ static void SkipSmallest_ValueIndex_fx( { use_inds[k] = j; move16(); - k = add(k, 1); + k = add( k, 1 ); } } diff --git a/lib_rend/ivas_objectRenderer_mix.c b/lib_rend/ivas_objectRenderer_mix.c index 3926c985b..1889939a1 100644 --- a/lib_rend/ivas_objectRenderer_mix.c +++ b/lib_rend/ivas_objectRenderer_mix.c @@ -638,59 +638,41 @@ ivas_error TDREND_MIX_AddSrc( #ifdef IVAS_FLOAT_FIXED static ivas_error BSplineModelEvalAlloc_fx( - ModelParams_t *model, /* i : Model parameters */ - ModelEval_t *modelEval /* i/o: Model evaluation structure */ -) -{ - IF((modelEval->hrfModL_fx = (Word32 *)malloc(model->K * sizeof(Word32))) == NULL) - { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n")); - } - - IF((modelEval->hrfModR_fx = (Word32 *)malloc(model->K * sizeof(Word32))) == NULL) - { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n")); - } - /*To be removed later: floating pointer memory allocation*/ - IF((modelEval->hrfModL = (float *)malloc(model->K * sizeof(float))) == NULL) - { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n")); - } - IF((modelEval->hrfModR = (float *)malloc(model->K * sizeof(float))) == NULL) - { - return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n")); - } - /*---------------------------------------------ends-here*/ - return IVAS_ERR_OK; -} -#endif -static ivas_error BSplineModelEvalAlloc( ModelParams_t *model, /* i : Model parameters */ ModelEval_t *modelEval /* i/o: Model evaluation structure */ ) { - if ( ( modelEval->hrfModL = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) + IF( ( modelEval->hrfModL_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } - if ( ( modelEval->hrfModR = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) + IF( ( modelEval->hrfModR_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } -#ifdef IVAS_FLOAT_FIXED - IF ( ( modelEval->hrfModL_fx = (Word32 *) malloc( model->K * sizeof(Word32) ) ) == NULL ) + + return IVAS_ERR_OK; +} +#else +static ivas_error BSplineModelEvalAlloc( + ModelParams_t *model, /* i : Model parameters */ + ModelEval_t *modelEval /* i/o: Model evaluation structure */ +) +{ + if ( ( modelEval->hrfModL = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } - IF ( ( modelEval->hrfModR_fx = (Word32 *) malloc( model->K * sizeof(Word32) ) ) == NULL ) + + if ( ( modelEval->hrfModR = (float *) malloc( model->K * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } -#endif // DEBUG return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------* @@ -1050,7 +1032,7 @@ static ivas_error DefaultBSplineModel_fx( return IVAS_ERR_OK; } -#endif +#else static ivas_error DefaultBSplineModel( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* o : Loaded HR filter set */ const int32_t output_Fs /* i : Output sampling rate */ @@ -1114,26 +1096,13 @@ static ivas_error DefaultBSplineModel( /* float parameters */ model->elevKSeq = (const float *) defaultHRIR_rom_elevKSeq; model->elevBsShape = (const float *) defaultHRIR_rom_elevBsShape; -#ifdef IVAS_FLOAT_FIXED - model->elevKSeq_fx = defaultHRIR_rom_elevKSeq_fx; - model->elevBsShape_fx = defaultHRIR_rom_elevBsShape_fx; -#endif if ( ( model->azimBsShape = (const float **) malloc( model->num_unique_azim_splines * sizeof( float * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } -#ifdef IVAS_FLOAT_FIXED - IF ( ( model->azimBsShape_fx = (const Word32 **) malloc( model->num_unique_azim_splines * sizeof(Word32 * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); - } -#endif // IVAS_FLOAT_FIXED model->azimBsShape[0] = (const float *) defaultHRIR_rom_azimBsShape; -#ifdef IVAS_FLOAT_FIXED - model->azimBsShape_fx[0] = defaultHRIR_rom_azimBsShape_fx; -#endif if ( ( model->azimKSeq = (float **) malloc( 18 * sizeof( float * ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); @@ -1146,30 +1115,10 @@ static ivas_error DefaultBSplineModel( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } -#ifdef IVAS_FLOAT_FIXED - IF ( ( model->azimKSeq_fx = (Word32 **) malloc( 18 * sizeof(Word32 * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); - } - IF ( ( model->azimKSeq_fx[0] = (Word32 *) malloc( 2 * sizeof(Word32 * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); - } - IF ( ( model->azimKSeq_fx[model->elevDim3 - 1] = (Word32 *) malloc( 2 * sizeof(Word32 * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); - } -#endif // IVAS_FLOAT_FIXED model->azimKSeq[0][0] = 0.0f; model->azimKSeq[model->elevDim3 - 1][0] = 0.0f; model->azimKSeq[0][1] = 360.0f; model->azimKSeq[model->elevDim3 - 1][1] = 360.0f; -#ifdef IVAS_FLOAT_FIXED - model->azimKSeq_fx[0][0] = 0; - model->azimKSeq_fx[model->elevDim3 - 1][0] = 0; - model->azimKSeq_fx[0][1] = 360<azimKSeq_fx[model->elevDim3 - 1][1] = 360<elevDim3 - 1; i++ ) { @@ -1177,22 +1126,10 @@ static ivas_error DefaultBSplineModel( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); } -#ifdef IVAS_FLOAT_FIXED - IF ( ( model->azimKSeq_fx[i] = (Word32 *) malloc( model->azimDim2[i] * sizeof(Word32 * ) ) ) == NULL ) /* azimDim2[i] = 91, i=2..15 */ - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural TD renderer\n" ) ); - } -#endif for ( j = 0; j < model->azimDim2[i]; j++ ) { model->azimKSeq[i][j] = (float) defaultHRIR_rom_azimSegSamples[0] * j; } -#ifdef IVAS_FLOAT_FIXED - FOR ( j = 0; j < model->azimDim2[i]; j++ ) - { - model->azimKSeq_fx[i][j] = L_shl(L_mult0(defaultHRIR_rom_azimSegSamples[0], j), Q22); - } -#endif } switch ( output_Fs ) @@ -1202,27 +1139,10 @@ static ivas_error DefaultBSplineModel( model->AlphaR = (const float *) defaultHRIR_rom_AlphaR48; model->EL = (const float *) defaultHRIR_rom_EL48; model->ER = (const float *) defaultHRIR_rom_ER48; -#ifdef IVAS_FLOAT_FIXED - model->AlphaL_fx = (const Word32 *)defaultHRIR_rom_AlphaL48_fx; - model->AlphaL_e = 1; - move16(); - model->AlphaR_fx = (const Word32 *)defaultHRIR_rom_AlphaR48_fx; - model->AlphaR_e = 1; - move16(); - model->EL_fx = (const Word32 *)defaultHRIR_rom_EL48_fx; - model->EL_e = 3; - move16(); - model->ER_fx = (const Word32 *)defaultHRIR_rom_ER48_fx; - model->ER_e = 3; - move16(); -#endif model->K = 128; if ( HrFiltSet_p->ModelParams.UseItdModel ) { modelITD->resamp_factor = 1.0f; -#ifdef IVAS_FLOAT_FIXED - modelITD->resamp_factor_fx = ONE_IN_Q14; -#endif } break; case 32000: @@ -1230,27 +1150,10 @@ static ivas_error DefaultBSplineModel( model->AlphaR = (const float *) defaultHRIR_rom_AlphaR32; model->EL = (const float *) defaultHRIR_rom_EL32; model->ER = (const float *) defaultHRIR_rom_ER32; -#ifdef IVAS_FLOAT_FIXED - model->AlphaL_fx = (const Word32 *)defaultHRIR_rom_AlphaL32_fx; - model->AlphaL_e = 1; - move16(); - model->AlphaR_fx = (const Word32 *)defaultHRIR_rom_AlphaR32_fx; - model->AlphaR_e = 1; - move16(); - model->EL_fx = (const Word32 *)defaultHRIR_rom_EL32_fx; - model->EL_e = 3; - move16(); - model->ER_fx = (const Word32 *)defaultHRIR_rom_ER32_fx; - model->ER_e = 3; - move16(); -#endif model->K = 86; if ( HrFiltSet_p->ModelParams.UseItdModel ) { modelITD->resamp_factor = RESAMPLE_FACTOR_32_48; -#ifdef IVAS_FLOAT_FIXED - modelITD->resamp_factor_fx = RESAMPLE_FACTOR_32_48_FX; -#endif } break; case 16000: @@ -1258,27 +1161,10 @@ static ivas_error DefaultBSplineModel( model->AlphaR = (const float *) defaultHRIR_rom_AlphaR16; model->EL = (const float *) defaultHRIR_rom_EL16; model->ER = (const float *) defaultHRIR_rom_ER16; -#ifdef IVAS_FLOAT_FIXED - model->AlphaL_fx = (const Word32 *)defaultHRIR_rom_AlphaL16_fx; - model->AlphaL_e = 1; - move16(); - model->AlphaR_fx = (const Word32 *)defaultHRIR_rom_AlphaR16_fx; - model->AlphaR_e = 1; - move16(); - model->EL_fx = (const Word32 *)defaultHRIR_rom_EL16_fx; - model->EL_e = 3; - move16(); - model->ER_fx = (const Word32 *)defaultHRIR_rom_ER16_fx; - model->ER_e = 3; - move16(); -#endif model->K = 43; if ( HrFiltSet_p->ModelParams.UseItdModel ) { modelITD->resamp_factor = RESAMPLE_FACTOR_16_48; -#ifdef IVAS_FLOAT_FIXED - modelITD->resamp_factor_fx = RESAMPLE_FACTOR_16_48_FX; -#endif } break; default: @@ -1301,9 +1187,6 @@ static ivas_error DefaultBSplineModel( modelITD->elevBsStart[3] = 21; modelITD->elevKSeq = defaultHRIR_rom_ITD_elevKSeq; -#ifdef IVAS_FLOAT_FIXED - modelITD->elevKSeq_fx = defaultHRIR_rom_ITD_elevKSeq_fx; -#endif modelITD->azimBsLen[0] = 11; modelITD->azimBsLen[1] = 21; @@ -1317,19 +1200,9 @@ static ivas_error DefaultBSplineModel( modelITD->azimSegSamples = 10; modelITD->azimKSeq = defaultHRIR_rom_ITD_azimKSeq; -#ifdef IVAS_FLOAT_FIXED - modelITD->azimKSeq_fx = defaultHRIR_rom_ITD_azimKSeq_fx; -#endif modelITD->W = (const float *) defaultHRIR_rom_ITD_W; modelITD->azimBsShape = (const float *) defaultHRIR_rom_ITD_azimBsShape; modelITD->elevBsShape = (const float *) defaultHRIR_rom_ITD_elevBsShape; -#ifdef IVAS_FLOAT_FIXED - modelITD->W_fx = (const Word32 *)defaultHRIR_rom_ITD_W_fx;//Q25 - modelITD->W_e = 6; - move16(); - modelITD->azimBsShape_fx = defaultHRIR_rom_ITD_azimBsShape_fx; - modelITD->elevBsShape_fx = defaultHRIR_rom_ITD_elevBsShape_fx; -#endif HRTF_model_precalc( model ); @@ -1344,3 +1217,4 @@ static ivas_error DefaultBSplineModel( return IVAS_ERR_OK; } +#endif diff --git a/lib_rend/ivas_objectRenderer_sources.c b/lib_rend/ivas_objectRenderer_sources.c index 130a1faa6..39347f1bf 100644 --- a/lib_rend/ivas_objectRenderer_sources.c +++ b/lib_rend/ivas_objectRenderer_sources.c @@ -399,6 +399,7 @@ static void TDREND_SRC_REND_Init( * Update the HR filter due to spatial change. --------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ @@ -522,8 +523,7 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( return; } - -#ifdef IVAS_FLOAT_FIXED +#else void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ @@ -562,17 +562,18 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( *filterlength = s_min( HrFiltSet_p->FiltLength, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - IF ( SrcSpatial_p->PosType == TDREND_POSTYPE_ABSOLUTE ) + IF( SrcSpatial_p->PosType == TDREND_POSTYPE_ABSOLUTE ) { /* Absolute position */ TDREND_SPATIAL_VecMapToNewCoordSystem_fx( SrcSpatial_p->Pos_p_fx, Listener_p->Pos_fx, Listener_p->Front_fx, Listener_p->Up_fx, Listener_p->Right_fx, ListRelPos, ListRelPosAbs ); ListRelPos_e = 62 - Q25 - Q30; // output q of above function is Q25 + Q30 - 31. so exp will be 62 - Q25 - Q30. move16(); - ListRelDist = TDREND_SPATIAL_VecNorm_fx( ListRelPos, ListRelPos_e, &ListRelDist_e); + ListRelDist = TDREND_SPATIAL_VecNorm_fx( ListRelPos, ListRelPos_e, &ListRelDist_e ); /* 2. Evaluate the Elevation and Azimuth angles */ - test(); test(); + test(); + test(); IF( ( ListRelPos[0] == 0 ) && ( ListRelPos[1] == 0 ) && ( ListRelPos[2] == 0 ) ) { Elev = 0; @@ -603,7 +604,7 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( /* Directional gain */ *SrcRend_p->DirGain_p_fx = ONE_IN_Q14; move16(); - IF ( SrcSpatial_p->DirAttenEnabled ) + IF( SrcSpatial_p->DirAttenEnabled ) { *SrcRend_p->DirGain_p_fx = TDREND_SRC_SPATIAL_GetDirGain_fx( &SrcSpatial_p->DirAtten, SrcSpatial_p->Front_p_fx, ListRelPosAbs, 6 ); } @@ -611,128 +612,126 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( /* Distance gain */ *SrcRend_p->DistGain_p_fx = ONE_IN_Q14; move16(); - IF ( hBinRendererTd->UseCommonDistAttenModel ) + IF( hBinRendererTd->UseCommonDistAttenModel ) { - IF ( hBinRendererTd->DistAttenEnabled ) + IF( hBinRendererTd->DistAttenEnabled ) { SrcSpatial_p->DistAtten.DistAttenModel = hBinRendererTd->DistAttenModel; *SrcRend_p->DistGain_p_fx = TDREND_SRC_SPATIAL_GetDistGain_fx( &SrcSpatial_p->DistAtten, ListRelDist, ListRelDist_e ); } } - ELSE - { - IF ( SrcSpatial_p->DistAttenEnabled ) - { - *SrcRend_p->DistGain_p_fx = TDREND_SRC_SPATIAL_GetDistGain_fx( &SrcSpatial_p->DistAtten, ListRelDist, ListRelDist_e ); - } - } + ELSE{ + IF( SrcSpatial_p->DistAttenEnabled ){ + *SrcRend_p->DistGain_p_fx = TDREND_SRC_SPATIAL_GetDistGain_fx( &SrcSpatial_p->DistAtten, ListRelDist, ListRelDist_e ); + } +} - /* Update total gains */ - *Gain = extract_h( L_shl( Mpy_32_32( L_shl( L_mult( *SrcRend_p->SrcGain_p_fx, *SrcRend_p->DirGain_p_fx ), 1 ), L_shl( L_mult( *SrcRend_p->DistGain_p_fx, hBinRendererTd->Gain_fx ), 1 ) ), 1 ) ); +/* Update total gains */ +*Gain = extract_h( L_shl( Mpy_32_32( L_shl( L_mult( *SrcRend_p->SrcGain_p_fx, *SrcRend_p->DirGain_p_fx ), 1 ), L_shl( L_mult( *SrcRend_p->DistGain_p_fx, hBinRendererTd->Gain_fx ), 1 ) ), 1 ) ); - /* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */ +/* Delta for interpolation, in case the angular step exceeds MAX_ANGULAR_STEP */ - elev_delta = L_sub( Elev, Src_p->elev_prev_fx ); - azim_delta = L_sub( Azim, Src_p->azim_prev_fx ); +elev_delta = L_sub( Elev, Src_p->elev_prev_fx ); +azim_delta = L_sub( Azim, Src_p->azim_prev_fx ); - Src_p->elev_prev_fx = Elev; - move32(); - Src_p->azim_prev_fx = Azim; - move32(); +Src_p->elev_prev_fx = Elev; +move32(); +Src_p->azim_prev_fx = Azim; +move32(); - /* map to -180:180 range */ - IF( GT_32( azim_delta, DEG_180_IN_Q22 ) ) - { - azim_delta = L_sub( azim_delta, DEG_360_IN_Q22 ); - } - ELSE IF( LT_32( azim_delta, -DEG_180_IN_Q22 ) ) - { - azim_delta = L_add( azim_delta, DEG_360_IN_Q22 ); - } - Word16 tmp1 = extract_l( Mpy_32_32( L_abs( azim_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0 - Word16 tmp2 = extract_l( Mpy_32_32( L_abs( elev_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0 - *intp_count = s_min( MAX_INTERPOLATION_STEPS, s_max( tmp1, tmp2 ) ); - } - ELSE /* TDREND_POSTYPE_NON_DIEGETIC */ - { - *itd = 0; - move16(); - *Gain = ONE_IN_Q14; - move16(); - set32_fx( hrf_left, 0, *filterlength ); - set32_fx( hrf_right, 0, *filterlength ); - hrf_left[0] = L_shr( L_add( SrcSpatial_p->Pos_p_fx[1], ONE_IN_Q25 ), 1 ); // Q25 - move32(); - hrf_right[0] = L_sub( ONE_IN_Q25, hrf_left[0] ); // Q25 - move32(); - hrf_left_e = 6; - move16(); - hrf_right_e = 6; - move16(); - *intp_count = MAX_INTERPOLATION_STEPS; - move16(); - Src_p->elev_prev_fx = 0; - move16(); - Src_p->azim_prev_fx = DEG_360_IN_Q22; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */ - move16(); - } +/* map to -180:180 range */ +IF( GT_32( azim_delta, DEG_180_IN_Q22 ) ) +{ + azim_delta = L_sub( azim_delta, DEG_360_IN_Q22 ); +} +ELSE IF( LT_32( azim_delta, -DEG_180_IN_Q22 ) ) +{ + azim_delta = L_add( azim_delta, DEG_360_IN_Q22 ); +} +Word16 tmp1 = extract_l( Mpy_32_32( L_abs( azim_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0 +Word16 tmp2 = extract_l( Mpy_32_32( L_abs( elev_delta ), 100 << Q9 ) ); // Q22 + Q9 - Q31 = Q0 +*intp_count = s_min( MAX_INTERPOLATION_STEPS, s_max( tmp1, tmp2 ) ); +} +ELSE /* TDREND_POSTYPE_NON_DIEGETIC */ +{ + *itd = 0; + move16(); + *Gain = ONE_IN_Q14; + move16(); + set32_fx( hrf_left, 0, *filterlength ); + set32_fx( hrf_right, 0, *filterlength ); + hrf_left[0] = L_shr( L_add( SrcSpatial_p->Pos_p_fx[1], ONE_IN_Q25 ), 1 ); // Q25 + move32(); + hrf_right[0] = L_sub( ONE_IN_Q25, hrf_left[0] ); // Q25 + move32(); + hrf_left_e = 6; + move16(); + hrf_right_e = 6; + move16(); + *intp_count = MAX_INTERPOLATION_STEPS; + move16(); + Src_p->elev_prev_fx = 0; + move16(); + Src_p->azim_prev_fx = DEG_360_IN_Q22; /* Dummy angle -- sets max interpolation if switching to TDREND_POSTYPE_ABSOLUTE */ + move16(); +} - test(); - IF ( ( *intp_count > 0 ) && subframe_update_flag ) +test(); +IF( ( *intp_count > 0 ) && subframe_update_flag ) +{ + /* Set deltas for interpolation */ + Word16 tmp_e; + tmp_e = s_max( *hrf_left_prev_e, hrf_left_e ); + FOR( Word16 i = 0; i < *filterlength; i++ ) { - /* Set deltas for interpolation */ - Word16 tmp_e; - tmp_e = s_max( *hrf_left_prev_e, hrf_left_e ); - FOR( Word16 i = 0; i < *filterlength; i++ ) - { - hrf_left[i] = L_shr( hrf_left[i], sub( tmp_e, hrf_left_e ) ); - hrf_left_prev[i] = L_shr( hrf_left_prev[i], sub( tmp_e, *hrf_left_prev_e ) ); - } - *hrf_left_prev_e = tmp_e; - move16(); - hrf_left_e = tmp_e; - move16(); - v_sub_32( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength ); - *hrf_left_delta_e = tmp_e; - move16(); + hrf_left[i] = L_shr( hrf_left[i], sub( tmp_e, hrf_left_e ) ); + hrf_left_prev[i] = L_shr( hrf_left_prev[i], sub( tmp_e, *hrf_left_prev_e ) ); + } + *hrf_left_prev_e = tmp_e; + move16(); + hrf_left_e = tmp_e; + move16(); + v_sub_32( hrf_left, hrf_left_prev, hrf_left_delta, *filterlength ); + *hrf_left_delta_e = tmp_e; + move16(); - Word32 fac = L_deposit_h( div_s( 1, *intp_count ) ); - v_multc_fixed( hrf_left_delta, fac, hrf_left_delta, *filterlength ); + Word32 fac = L_deposit_h( div_s( 1, *intp_count ) ); + v_multc_fixed( hrf_left_delta, fac, hrf_left_delta, *filterlength ); - tmp_e = s_max( *hrf_right_prev_e, hrf_right_e ); - FOR( Word16 i = 0; i < *filterlength; i++ ) - { - hrf_right[i] = L_shr( hrf_right[i], sub( tmp_e, hrf_right_e ) ); - hrf_right_prev[i] = L_shr( hrf_right_prev[i], sub( tmp_e, *hrf_right_prev_e ) ); - } - *hrf_right_prev_e = tmp_e; - move16(); - hrf_right_e = tmp_e; - move16(); - v_sub_32( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength ); - *hrf_right_delta_e = tmp_e; - move16(); - - v_multc_fixed( hrf_right_delta, fac, hrf_right_delta, *filterlength ); - } - ELSE + tmp_e = s_max( *hrf_right_prev_e, hrf_right_e ); + FOR( Word16 i = 0; i < *filterlength; i++ ) { - /* No interpolation, just set the new filters and reset deltas */ - Copy32( hrf_left, hrf_left_prev, *filterlength ); - *hrf_left_prev_e = hrf_left_e; - move16(); - Copy32( hrf_right, hrf_right_prev, *filterlength ); - *hrf_right_prev_e = hrf_right_e; - move16(); - set32_fx( hrf_left_delta, 0, *filterlength ); - set32_fx( hrf_right_delta, 0, *filterlength ); - *hrf_left_delta_e = 0; - move16(); - *hrf_right_delta_e = 0; - move16(); + hrf_right[i] = L_shr( hrf_right[i], sub( tmp_e, hrf_right_e ) ); + hrf_right_prev[i] = L_shr( hrf_right_prev[i], sub( tmp_e, *hrf_right_prev_e ) ); } + *hrf_right_prev_e = tmp_e; + move16(); + hrf_right_e = tmp_e; + move16(); + v_sub_32( hrf_right, hrf_right_prev, hrf_right_delta, *filterlength ); + *hrf_right_delta_e = tmp_e; + move16(); - return; + v_multc_fixed( hrf_right_delta, fac, hrf_right_delta, *filterlength ); +} +ELSE +{ + /* No interpolation, just set the new filters and reset deltas */ + Copy32( hrf_left, hrf_left_prev, *filterlength ); + *hrf_left_prev_e = hrf_left_e; + move16(); + Copy32( hrf_right, hrf_right_prev, *filterlength ); + *hrf_right_prev_e = hrf_right_e; + move16(); + set32_fx( hrf_left_delta, 0, *filterlength ); + set32_fx( hrf_right_delta, 0, *filterlength ); + *hrf_left_delta_e = 0; + move16(); + *hrf_right_delta_e = 0; + move16(); +} + +return; } #endif @@ -847,7 +846,7 @@ static void TDREND_SRC_SPATIAL_Init_fx( move32(); SrcSpatial_p->DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ move32(); - SrcSpatial_p->DistAtten.RollOffFactor_fx = ONE_IN_Q14; + SrcSpatial_p->DistAtten.RollOffFactor_fx = ONE_IN_Q30; move16(); return; @@ -898,15 +897,16 @@ static void TDREND_SRC_SPATIAL_Init( /* Source distance attenuation */ SrcSpatial_p->DistAttenEnabled = FALSE; SrcSpatial_p->DistAtten.DistAttenModel = TDREND_DIST_ATTEN_MODEL_INV_DIST_CLAMPED; +#ifndef IVAS_FLOAT_FIXED SrcSpatial_p->DistAtten.RefDist = 1.0f; SrcSpatial_p->DistAtten.MaxDist = 15.75f; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ SrcSpatial_p->DistAtten.RollOffFactor = 1.0f; -#ifdef IVAS_FLOAT_FIXED +#else SrcSpatial_p->DistAtten.RefDist_fx = ONE_IN_Q30; move32(); SrcSpatial_p->DistAtten.MaxDist_fx = 2113929216; /* Maximum radius (2^ISM_RADIUS_NBITS-1)*0.25 */ /*15.75 in Q27*/ move32(); - SrcSpatial_p->DistAtten.RollOffFactor_fx = ONE_IN_Q14; + SrcSpatial_p->DistAtten.RollOffFactor_fx = ONE_IN_Q30; move16(); #endif @@ -1098,6 +1098,7 @@ static Word16 TDREND_SRC_SPATIAL_GetDirGain_fx( /* o : Directional Gain Output --------------------------------------------------------------------*/ /*! r: Gain value */ +#ifndef IVAS_FLOAT_FIXED static float TDREND_SRC_SPATIAL_GetDistGain( const TDREND_DistAtten_t *DistAtten_p, /* i : Distance attenuation parameters */ const float Dist /* i : Distance value */ @@ -1132,8 +1133,7 @@ static float TDREND_SRC_SPATIAL_GetDistGain( return DistGain; } - -#ifdef IVAS_FLOAT_FIXED +#else static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( /* o : Distance gain Q14 */ const TDREND_DistAtten_t *DistAtten_p, /* i : Distance attenuation parameters */ const Word32 Dist_fx, /* i : Distance value */ @@ -1161,7 +1161,7 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( /* o : Distance gain { case TDREND_DIST_ATTEN_MODEL_INV_DIST: tmp32 = BASOP_Util_Add_Mant32Exp( Dist2_fx, Dist2_e, L_negate( DistAtten_p->RefDist_fx ), 1, &tmp_e ); // exp: tmp_e - tmp32 = Mpy_32_32( tmp32, DistAtten_p->RefDist_fx ); // exp: 1 + tmp_e + tmp32 = Mpy_32_32( tmp32, DistAtten_p->RollOffFactor_fx ); // exp: 1 + tmp_e tmp32 = BASOP_Util_Add_Mant32Exp( DistAtten_p->RefDist_fx, 1, tmp32, add( 1, tmp_e ), &tmp_e ); // exp: tmp_e DistGain_fx = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, tmp32, &DistGain_e ); DistGain_e = add( DistGain_e, sub( 1, tmp_e ) ); @@ -1185,7 +1185,7 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( /* o : Distance gain move16(); } tmp32 = BASOP_Util_Add_Mant32Exp( Dist2_fx, Dist2_e, L_negate( DistAtten_p->RefDist_fx ), 1, &tmp_e ); // exp: tmp_e - tmp32 = Mpy_32_32( tmp32, DistAtten_p->RefDist_fx ); // exp: 1 + tmp_e + tmp32 = Mpy_32_32( tmp32, DistAtten_p->RollOffFactor_fx ); // exp: 1 + tmp_e tmp32 = BASOP_Util_Add_Mant32Exp( DistAtten_p->RefDist_fx, 1, tmp32, add( 1, tmp_e ), &tmp_e ); // exp: tmp_e DistGain_fx = BASOP_Util_Divide3232_Scale( DistAtten_p->RefDist_fx, tmp32, &DistGain_e ); DistGain_e = add( DistGain_e, sub( 1, tmp_e ) ); @@ -1193,7 +1193,7 @@ static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( /* o : Distance gain BREAK; } - DistGain_fx = shr( DistGain_fx, 1 - DistGain_e ); // Reducing it to Q14 + DistGain_fx = shr( DistGain_fx, 1 - DistGain_e ); // Reducing it to Q14 return DistGain_fx; } diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c index a6d08f15b..21873782f 100644 --- a/lib_rend/ivas_orient_trk.c +++ b/lib_rend/ivas_orient_trk.c @@ -1115,16 +1115,15 @@ ivas_error ivas_orient_trk_SetReferenceRotation_fx( } /* check for Euler angle signaling */ - // This part is not covered in code coverage for test streams// - /* if ( refRot.w == -3.0f ) - { - Euler2Quat( deg2rad( refRot.x ), deg2rad( refRot.y ), deg2rad( refRot.z ), &pOTR->refRot ); - }*/ + IF( EQ_32( refRot.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) + { + Euler2Quat_fx( deg2rad_fx( refRot.x_fx ), deg2rad_fx( refRot.y_fx ), deg2rad_fx( refRot.z_fx ), &pOTR->refRot ); + } pOTR->refRot = refRot; return IVAS_ERR_OK; } -#endif +#else ivas_error ivas_orient_trk_SetReferenceRotation( ivas_orient_trk_state_t *pOTR, /* i/o: orientation tracker handle */ @@ -1148,7 +1147,7 @@ ivas_error ivas_orient_trk_SetReferenceRotation( return IVAS_ERR_OK; } - +#endif /*-------------------------------------------------------------------* * ivas_orient_trk_GetMainOrientation() diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 866bd05a5..ec03c0ead 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -212,41 +212,43 @@ void ivas_td_decorr_APD_iir_filter_fx( * Amplitude Panning EFAP prototypes *----------------------------------------------------------------------------------*/ -ivas_error efap_init_data( - EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ - const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ - const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ -); #ifdef IVAS_FLOAT_FIXED -ivas_error efap_init_data_fixed( +ivas_error efap_init_data_fx( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ const Word32 *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ const Word32 *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ const Word16 num_speaker_nodes, /* i : number of speaker nodes in the set */ const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ ); +#else +ivas_error efap_init_data( + EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ + const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ + const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ + const int16_t num_speaker_nodes, /* i : number of speaker nodes in the set */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ +); #endif void efap_free_data( EFAP_HANDLE *hEFAPdata /* i/o: EFAP handle to be freed */ ); -void efap_determine_gains( - EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ - float *gains, /* o : gain vector for speaker nodes for given direction */ - const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ - const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ - const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ -); #ifdef IVAS_FLOAT_FIXED -void efap_determine_gains_fixed( +void efap_determine_gains_fx( EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ Word32 *gains, /* o : gain vector for speaker nodes for given direction */ const Word32 azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ const Word32 ele_deg, /* i : elevation in degrees for panning direction (positive up) */ const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ ); +#else +void efap_determine_gains( + EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + float *gains, /* o : gain vector for speaker nodes for given direction */ + const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */ + const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */ + const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ +); #endif /*----------------------------------------------------------------------------------* * Amplitude Panning VBAP prototypes @@ -319,7 +321,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( const Word16 ambisonics_order /* i : Ambisonics order */ ); #else -ivas_error ivas_sba_get_hoa_dec_matrix( +ivas_error ivas_sba_get_hoa_dec_matrix_fx( const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ const Word16 ambisonics_order /* i : Ambisonics order */ @@ -812,7 +814,26 @@ void ivas_dirac_dec_output_synthesis_close_fx( void ivas_dirac_dec_output_synthesis_close( DIRAC_REND_HANDLE hDirACRend /* i/o: DirAC handle */ ); - +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_output_synthesis_process_slot_fx( + const Word32 *reference_power, /* i : Estimated power */ + const Word16 q_reference_power, /* i : Estimated power */ + const Word32 *onset, /* i : onset filter */ + const Word16 *azimuth, + const Word16 *elevation, + const Word32 *diffuseness, + Word16 q_diffuseness, + 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 sh_rot_max_order, + const Word32 *p_Rmat, /* i : rotation matrix */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : output setup structure */ + const Word16 nchan_transport, /* i : number of transport channels*/ + const Word16 md_idx, + const Word16 hodirac_flag, /* i : flag to indicate HO-DirAC mode */ + const Word16 dec_param_estim); +#endif void ivas_dirac_dec_output_synthesis_process_slot( const float *reference_power, /* i : Estimated power */ const float *onset, /* i : onset filter */ @@ -1027,10 +1048,25 @@ void ivas_masa_ext_dirac_render( const int16_t num_subframes /* i : number of subframes to render */ ); +void ivas_masa_ext_dirac_render_fx( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ + Word32 *output_f[], /* i/o: input/output signals in time domain */ + const Word16 num_subframes /* i : number of subframes to render */ +); + /*----------------------------------------------------------------------------------* * HRTF *----------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_HRTF_binary_open_fx( + TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ +); + +void ivas_HRTF_binary_close_fx( + TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ +); +#else ivas_error ivas_HRTF_binary_open( TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ ); @@ -1038,11 +1074,33 @@ ivas_error ivas_HRTF_binary_open( void ivas_HRTF_binary_close( TDREND_HRFILT_FiltSet_t **hHrtfTD /* i/o: TD renderer HRTF handle */ ); +#endif ivas_error ivas_HRTF_fastconv_binary_open( HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_HRTF_fastconv_binary_close_fx( + HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ +); + +ivas_error ivas_HRTF_parambin_binary_open_fx( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); + +void ivas_HRTF_parambin_binary_close_fx( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); + +ivas_error ivas_HRTF_CRend_binary_open_fx( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); + +void ivas_HRTF_CRend_binary_close_fx( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); +#else void ivas_HRTF_fastconv_binary_close( HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ ); @@ -1062,6 +1120,7 @@ ivas_error ivas_HRTF_CRend_binary_open( void ivas_HRTF_CRend_binary_close( HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ ); +#endif /*----------------------------------------------------------------------------------* @@ -1197,6 +1256,7 @@ void BSplineModelEvalDealloc( /* ----- Object renderer - hrfilt ----- */ +#ifndef IVAS_FLOAT_FIXED void GetFilterFromAngle( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ const float Elev, /* i : Elevation, degrees */ @@ -1206,8 +1266,7 @@ void GetFilterFromAngle( float *RightFilter, /* o : Right HR filter */ int16_t *itd /* o : ITD value */ ); - -#ifdef IVAS_FLOAT_FIXED +#else void GetFilterFromAngle_fx( TDREND_HRFILT_FiltSet_t *HrFiltSet_p, /* i/o: HR filter set structure */ const Word32 Elev_fx, /* i : Elevation, degrees Q22 */ @@ -1225,14 +1284,6 @@ void HRTF_model_precalc( ModelParams_t *model /* i/o: HRTF Model parameters */ ); -ivas_error TDREND_REND_RenderSourceHRFilt( - TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ - const float *hrf_left_delta, /* i : Left filter interpolation delta */ - const float *hrf_right_delta, /* i : Right filter interpolation delta */ - const int16_t intp_count, /* i : Interpolation count */ - float output_buf[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ - const int16_t subframe_length /* i : Subframe length in use */ -); #ifdef IVAS_FLOAT_FIXED ivas_error TDREND_REND_RenderSourceHRFilt_fx( TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ @@ -1244,6 +1295,15 @@ ivas_error TDREND_REND_RenderSourceHRFilt_fx( Word32 output_buf_fx[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ const Word16 subframe_length /* i : Subframe length in use */ ); +#else +ivas_error TDREND_REND_RenderSourceHRFilt( + TDREND_SRC_t *Src_p, /* i/o: The source to be rendered */ + const float *hrf_left_delta, /* i : Left filter interpolation delta */ + const float *hrf_right_delta, /* i : Right filter interpolation delta */ + const int16_t intp_count, /* i : Interpolation count */ + float output_buf[][L_SPATIAL_SUBFR_48k], /* o : Output buffer */ + const int16_t subframe_length /* i : Subframe length in use */ +); #endif /* ----- Object renderer - sources ----- */ @@ -1299,6 +1359,7 @@ ivas_error TDREND_MIX_SRC_SetPlayState( ); #endif // IVAS_FLOAT_FIXED +#ifndef IVAS_FLOAT_FIXED void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ @@ -1314,7 +1375,7 @@ void TDREND_SRC_REND_UpdateFiltersFromSpatialParams( TDREND_SRC_t *Src_p, const int16_t subframe_update_flag /* i : Flag to determine update subframe idx */ ); -#ifdef IVAS_FLOAT_FIXED +#else void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ @@ -2140,7 +2201,14 @@ void Euler2Quat( const float roll, /* i : roll (z) */ IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ ); - +#ifdef IVAS_FLOAT_FIXED +void Euler2Quat_fx( + const Word32 yaw, /* i : yaw (x) Q22 */ + const Word32 pitch, /* i : pitch (y) Q22 */ + const Word32 roll, /* i : roll (z) Q22 */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +); +#endif float deg2rad( float degrees ); @@ -2583,12 +2651,20 @@ void ivas_create_masa_out_meta( float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS] /* i : Estimated surround coherence */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_dirac_ana_open_fx( + DIRAC_ANA_HANDLE *hDirACPtr, /* i/o: DIRAC data handle pointer */ + Word32 input_Fs +); +#else ivas_error ivas_dirac_ana_open( DIRAC_ANA_HANDLE *hDirACPtr, /* i/o: DIRAC data handle pointer */ int32_t input_Fs ); +#endif + #ifdef IVAS_FLOAT_FIXED -void ivas_dirac_ana( +void ivas_dirac_ana_fx( DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ Word32 data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ const Word16 input_frame, /* i : Input frame size */ @@ -2602,9 +2678,16 @@ void ivas_dirac_ana( const int16_t nchan_transport /* i : Number of transport channels */ ); #endif + +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_ana_close_fx( + DIRAC_ANA_HANDLE ( *hDirAC ) /* i/o: analysis DIRAC handle */ +); +#else void ivas_dirac_ana_close( DIRAC_ANA_HANDLE ( *hDirAC ) /* i/o: analysis DIRAC handle */ ); +#endif void ivas_prerend_merge_masa_metadata( MASA_DECODER_EXT_OUT_META_HANDLE outMeta, /* o : Merged metadata output */ diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index fcd93b3ac..7a9db2c79 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -318,7 +318,7 @@ void QuatToRotMat( return; } - +#ifndef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * Euler2Quat() * @@ -345,6 +345,29 @@ void Euler2Quat( return; } +#else + +void Euler2Quat_fx( + const Word32 yaw, /* i : yaw (x) */ + const Word32 pitch, /* i : pitch (y) */ + const Word32 roll, /* i : roll (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +) +{ + Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); + Word16 sr = getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ); + Word16 cp = getCosWord16( extract_l( L_shr_r( pitch, 10 ) ) ); + Word16 sp = getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ); + Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) ); + Word16 sy = getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ); + quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); + quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); + quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); + quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); + + return; +} +#endif /*------------------------------------------------------------------------- @@ -965,7 +988,7 @@ void rotateFrame_sd( { azimuth_fx = (Word32) azimuth * ONE_IN_Q22; elevation_fx = (Word32) elevation * ONE_IN_Q22; - efap_determine_gains_fixed( hEFAPdata, tmp_gains_fx, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); + efap_determine_gains_fx( hEFAPdata, tmp_gains_fx, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); FOR( ch_out = 0; ch_out < nchan; ch_out++ ) @@ -990,7 +1013,7 @@ void rotateFrame_sd( azimuth_fx = (Word32) azimuth * ONE_IN_Q22; elevation_fx = (Word32) elevation * ONE_IN_Q22; - efap_determine_gains_fixed( hEFAPdata, tmp_gains_fx, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); + efap_determine_gains_fx( hEFAPdata, tmp_gains_fx, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); FOR( ch_out = 0; ch_out < nchan; ch_out++ ) { @@ -1528,7 +1551,7 @@ void rotateFrame_sd_cldfb_fixed( IF( hEFAPdata != NULL && ( hOutputSetup->ls_azimuth[n] != azimuth || hOutputSetup->ls_elevation[n] != elevation ) ) { // efap_determine_gains( hEFAPdata, gains[n], azimuth, elevation, EFAP_MODE_EFAP ); - efap_determine_gains_fixed( hEFAPdata, gains_fx[n], L_shl( azimuth, Q22 ), L_shl( elevation, Q22 ), EFAP_MODE_EFAP ); + efap_determine_gains_fx( hEFAPdata, gains_fx[n], L_shl( azimuth, Q22 ), L_shl( elevation, Q22 ), EFAP_MODE_EFAP ); } ELSE { @@ -1633,7 +1656,6 @@ ivas_error ivas_external_orientation_open( * * Deallocate external orientation handle *-----------------------------------------------------------------------*/ - #ifdef IVAS_FLOAT_FIXED void ivas_external_orientation_close( EXTERNAL_ORIENTATION_HANDLE *hExtOrientationData /* i/o: external orientation handle */ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 677ca58fe..ece1d6785 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1165,57 +1165,43 @@ typedef struct ivas_combined_orientation_struct typedef struct _IVAS_RENDER_CONFIG RENDER_CONFIG_DATA; typedef struct _IVAS_RENDER_CONFIG *RENDER_CONFIG_HANDLE; -#ifdef IVAS_FLOAT_FIXED -typedef struct ivas_rev_delay_line_t -{ - //float *pBuffer; - Word32 *pBuffer_fx; - UWord16 MaxDelay; - Word16 Delay; - UWord16 BufferPos; - Word16 Gain_fx; -} ivas_rev_delay_line_t; -#else typedef struct ivas_rev_delay_line_t { +#ifndef IVAS_FLOAT_FIXED float *pBuffer; +#else + Word32 *pBuffer_fx; +#endif uint16_t MaxDelay; int16_t Delay; uint16_t BufferPos; +#ifndef IVAS_FLOAT_FIXED float Gain; +#else + Word16 Gain_fx; +#endif } ivas_rev_delay_line_t; -#endif -#ifdef IVAS_FLOAT_FIXED -typedef struct ivas_rev_iir_filter_t -{ - uint16_t MaxTaps; - uint16_t nr_taps; - uint16_t isFIR; - //float Output; - Word32 Output_fx; - float CoefA[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - Word32 CoefA_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - float CoefB[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - Word32 CoefB_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - // float pBuffer[IVAS_REV_MAX_IIR_FILTER_LENGTH]; - Word32 pBuffer_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; -} ivas_rev_iir_filter_t; -#else typedef struct ivas_rev_iir_filter_t { uint16_t MaxTaps; uint16_t nr_taps; uint16_t isFIR; +#ifndef IVAS_FLOAT_FIXED float Output; float CoefA[IVAS_REV_MAX_IIR_FILTER_LENGTH]; float CoefB[IVAS_REV_MAX_IIR_FILTER_LENGTH]; float pBuffer[IVAS_REV_MAX_IIR_FILTER_LENGTH]; +#else + Word32 Output_fx; + Word32 CoefA_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Q30 */ + Word32 CoefB_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; /* Q30 */ + Word32 pBuffer_fx[IVAS_REV_MAX_IIR_FILTER_LENGTH]; +#endif } ivas_rev_iir_filter_t; -#endif typedef float rv_fftwf_type_complex[2]; /* complex type of fftwf library */ #ifdef IVAS_FLOAT_FIXED @@ -1600,36 +1586,34 @@ typedef struct /* Shared memory for use when evaluating BSpline HR filter model*/ typedef struct { -#ifdef IVAS_FLOAT_FIXED - Word32 *hrfModL_fx; - Word32 *hrfModR_fx; - Word16 hrfModL_e; - Word16 hrfModR_e; -#endif +#ifndef IVAS_FLOAT_FIXED float BM[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; -#ifdef IVAS_FLOAT_FIXED +#else Word32 BM_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; // Q30 #endif ValueIndex_t BMEnergiesL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; ValueIndex_t BMEnergiesR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; int16_t UseIndsL[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; int16_t UseIndsR[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; +#ifndef IVAS_FLOAT_FIXED float *hrfModL; float *hrfModR; -#ifdef IVAS_FLOAT_FIXED - Word32 elevBfVec_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 - Word32 azimBfVec_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 -#endif float elevBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS]; float azimBfVec[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS]; float BM_ITD[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; float elevBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; float azimBfVecITD[HRTF_MODEL_BSPLINE_NUM_COEFFS]; float itdMod; -#ifdef IVAS_FLOAT_FIXED - Word32 BM_ITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; // Q30 - Word32 elevBfVecITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 - Word32 azimBfVecITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 +#else + Word32 *hrfModL_fx; + Word32 *hrfModR_fx; + Word16 hrfModL_e; + Word16 hrfModR_e; + Word32 elevBfVec_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 + Word32 azimBfVec_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS][HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 + Word32 BM_ITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS_SQ]; // Q30 + Word32 elevBfVecITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 + Word32 azimBfVecITD_fx[HRTF_MODEL_BSPLINE_NUM_COEFFS]; // Q30 Word32 itdMod_fx; #endif @@ -1693,13 +1677,14 @@ typedef struct TDREND_HRFILT_FiltSet_struct typedef struct { TDREND_DistAttenModel_t DistAttenModel; +#ifndef IVAS_FLOAT_FIXED float RefDist; float MaxDist; float RollOffFactor; -#ifdef IVAS_FLOAT_FIXED - Word32 RefDist_fx; - Word32 MaxDist_fx; - Word32 RollOffFactor_fx; // Q30 +#else + Word32 RefDist_fx; /* Q30 */ + Word32 MaxDist_fx; /* Q27 */ + Word32 RollOffFactor_fx; /* Q30 */ #endif // IVAS_FLOAT_FIXED } TDREND_DistAtten_t; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 3b93eaf6e..98730d630 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -190,13 +190,13 @@ typedef struct { Word16 numLfeChannels; bool pan_lfe; - float lfeInputGain; + //float lfeInputGain; Word32 lfeInputGain_fx; - float lfeOutputAzimuth; + //float lfeOutputAzimuth; Word16 lfeOutputAzimuth_fx; - float lfeOutputElevation; + //float lfeOutputElevation; Word16 lfeOutputElevation_fx; - IVAS_REND_LfePanMtx lfePanMtx; + //IVAS_REND_LfePanMtx lfePanMtx; IVAS_REND_LfePanMtx_fx lfePanMtx_fx; } lfe_routing; #else @@ -1586,7 +1586,84 @@ static ivas_error getMcConfigValues( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error initEfap( + EFAP_WRAPPER *pEfapWrapper, + AUDIO_CONFIG outConfig, + const LSSETUP_CUSTOM_STRUCT *pCustomLsOut ) +{ + ivas_error error; + const float *azimuths; + const float *elevations; + /*To be replaced with pointers*/ + Word32 azimuths_fx[MAX_OUTPUT_CHANNELS]; + Word32 elevations_fx[MAX_OUTPUT_CHANNELS]; + int16_t numNonLfeChannels; + + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + pEfapWrapper->speakerConfig = IVAS_AUDIO_CONFIG_7_1_4; + } + else + { + pEfapWrapper->speakerConfig = outConfig; + } + pEfapWrapper->pCustomLsSetup = pCustomLsOut; + + /* If re-initializing, free existing EFAP handle. */ + if ( pEfapWrapper->hEfap != NULL ) + { + efap_free_data( &pEfapWrapper->hEfap ); + } + + /* Only initialize EFAP handle if output config is channel-based */ + if ( getAudioConfigType( pEfapWrapper->speakerConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + pEfapWrapper->hEfap = NULL; + return IVAS_ERR_OK; + } + + if ( outConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) + { + /*float2fix block: to be removed*/ + floatToFixed_arrL( (float *) pCustomLsOut->ls_azimuth, (Word32 *) pCustomLsOut->ls_azimuth_fx, Q22, pCustomLsOut->num_spk ); + floatToFixed_arrL( (float *) pCustomLsOut->ls_elevation, (Word32 *) pCustomLsOut->ls_elevation_fx, Q22, pCustomLsOut->num_spk ); + /*float2fix block end*/ + if ( ( error = efap_init_data_fx( &pEfapWrapper->hEfap, pCustomLsOut->ls_azimuth_fx, pCustomLsOut->ls_elevation_fx, pCustomLsOut->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = getSpeakerAzimuths( pEfapWrapper->speakerConfig, &azimuths ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getSpeakerElevations( pEfapWrapper->speakerConfig, &elevations ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getNumNonLfeChannelsInSpeakerLayout( pEfapWrapper->speakerConfig, &numNonLfeChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*float2fix block: to be removed*/ + floatToFixed_arrL( (float *) azimuths, azimuths_fx, Q22, numNonLfeChannels ); + floatToFixed_arrL( (float *) elevations, elevations_fx, Q22, numNonLfeChannels ); + /*float2fix block end*/ + if ( ( error = efap_init_data_fx( &pEfapWrapper->hEfap, azimuths_fx, elevations_fx, numNonLfeChannels, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) + { + return error; + } + } + return IVAS_ERR_OK; +} +#else static ivas_error initEfap( EFAP_WRAPPER *pEfapWrapper, AUDIO_CONFIG outConfig, @@ -1652,6 +1729,7 @@ static ivas_error initEfap( return IVAS_ERR_OK; } +#endif #ifdef IVAS_FLOAT_FIXED static ivas_error getEfapGains_fx( @@ -1668,7 +1746,7 @@ static ivas_error getEfapGains_fx( ivas_error error; /* EFAP returns an array of gains only for non-LFE speakers */ - efap_determine_gains_fixed( efapWrapper.hEfap, tmpPanGains, azi, ele, EFAP_MODE_EFAP ); + efap_determine_gains_fx( efapWrapper.hEfap, tmpPanGains, azi, ele, EFAP_MODE_EFAP ); /* Now copy to buffer that includes LFE channels */ IF( EQ_32( efapWrapper.speakerConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) @@ -1722,6 +1800,74 @@ 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, const float azi, @@ -1783,6 +1929,7 @@ static ivas_error getEfapGains( return IVAS_ERR_OK; } +#endif #ifdef IVAS_FLOAT_FIXED static ivas_error initHeadRotation_fx( @@ -4135,7 +4282,7 @@ static void clearInputMc( return; } #endif - +#ifdef IVAS_FLOAT_FIXED static ivas_error initSbaPanGainsForMcOut( input_sba *inputSba, const AUDIO_CONFIG outConfig, @@ -4187,7 +4334,7 @@ static ivas_error initSbaPanGainsForMcOut( /* obtain and copy over HOA decoding matrix */ tmpDecMtx = NULL; - if ( ( error = ivas_sba_get_hoa_dec_matrix( hOutSetup, &tmpDecMtx, ambiOrderIn ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_sba_get_hoa_dec_matrix_fx( hOutSetup, &tmpDecMtx, ambiOrderIn ) ) != IVAS_ERR_OK ) { return error; } @@ -4213,6 +4360,77 @@ static ivas_error initSbaPanGainsForMcOut( return IVAS_ERR_OK; } +#else +static ivas_error initSbaPanGainsForMcOut( + input_sba *inputSba, + const AUDIO_CONFIG outConfig, + const LSSETUP_CUSTOM_STRUCT *outSetupCustom ) +{ + int16_t ambiOrderIn; + int16_t chInIdx, chOutIdx; + float *tmpDecMtx, *readPtr; + IVAS_OUTPUT_SETUP hOutSetup; + ivas_error error; + + if ( ( error = getAmbisonicsOrder( inputSba->base.inConfig, &ambiOrderIn ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( getAudioConfigType( outConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + assert( !"Invalid configuration" ); + return IVAS_ERR_WRONG_PARAMS; + } + + switch ( outConfig ) + { + case IVAS_AUDIO_CONFIG_MONO: + hOutSetup.ls_azimuth = ls_azimuth_CICP1; + hOutSetup.ls_elevation = ls_elevation_CICP1; + ivas_output_init( &hOutSetup, outConfig ); + break; + case IVAS_AUDIO_CONFIG_STEREO: + case IVAS_AUDIO_CONFIG_5_1: + case IVAS_AUDIO_CONFIG_7_1: + case IVAS_AUDIO_CONFIG_5_1_2: + case IVAS_AUDIO_CONFIG_5_1_4: + case IVAS_AUDIO_CONFIG_7_1_4: + ivas_output_init( &hOutSetup, outConfig ); + break; + case IVAS_AUDIO_CONFIG_LS_CUSTOM: + ivas_ls_custom_setup( &hOutSetup, outSetupCustom ); + break; + default: + assert( !"Invalid speaker config" ); + return IVAS_ERR_WRONG_PARAMS; + } + + /* obtain and copy over HOA decoding matrix */ + tmpDecMtx = NULL; + if ( ( error = ivas_sba_get_hoa_dec_matrix( hOutSetup, &tmpDecMtx, ambiOrderIn ) ) != IVAS_ERR_OK ) + { + return error; + } + + readPtr = &tmpDecMtx[0]; + for ( chOutIdx = 0; chOutIdx < hOutSetup.nchan_out_woLFE + hOutSetup.num_lfe; ++chOutIdx ) + { + for ( chInIdx = 0; chInIdx < SBA_NHARM_HOA3; ++chInIdx ) + { + if ( hOutSetup.num_lfe > 0 && chOutIdx == hOutSetup.index_lfe[0] ) + { + continue; /* nothing to be rendered to LFE */ + } + inputSba->hoaDecMtx[chInIdx][chOutIdx] = *readPtr++; + } + } + + free( tmpDecMtx ); + + return IVAS_ERR_OK; +} +#endif #ifdef IVAS_FLOAT_FIXED static ivas_error initSbaPanGainsForSbaOut( @@ -4423,6 +4641,7 @@ static ivas_error updateSbaPanGains( } #endif + static ivas_error initSbaMasaRendering( input_sba *inputSba, int32_t inSampleRate ) @@ -4431,14 +4650,22 @@ static ivas_error initSbaMasaRendering( ivas_rend_closeCrend( &inputSba->crendWrapper ); +#ifdef IVAS_FLOAT_FIXED + IF ( ( error = ivas_dirac_ana_open_fx( &inputSba->hDirAC, inSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_dirac_ana_open( &inputSba->hDirAC, inSampleRate ) ) != IVAS_ERR_OK ) { return error; } +#endif return IVAS_ERR_OK; } + #ifdef IVAS_FLOAT_FIXED static ivas_error setRendInputActiveSba( void *input, @@ -4559,7 +4786,7 @@ static void clearInputSba( /* Free input's internal handles */ ivas_rend_closeCrend( &inputSba->crendWrapper ); - ivas_dirac_ana_close( &( inputSba->hDirAC ) ); + ivas_dirac_ana_close_fx( &( inputSba->hDirAC ) ); return; } @@ -5521,7 +5748,7 @@ static ivas_error getConstInputById( } #endif - +#ifndef IVAS_FLOAT_FIXED static ivas_error findFreeInputSlot( const void *inputs, const int32_t inputStructSize, @@ -5562,6 +5789,48 @@ static ivas_error findFreeInputSlot( return IVAS_ERR_OK; } +#else +static ivas_error findFreeInputSlot_fx( + const void *inputs, + const Word32 inputStructSize, + const Word32 maxInputs, + Word32 *inputIndex ) +{ + /* Using a void pointer and a separately provided size is a hack for this function + to be reusable for arrays of any input type (input_ism, input_mc, input_sba, input_masa). + Assumptions: + - input_base is always the first member in the input struct + - provided size is correct + */ + + Word32 i; + bool canAddInput; + const UWord8 *pByte; + const input_base *pInputBase; + + canAddInput = false; + + /* Find first unused input in array */ + FOR( ( i = 0, pByte = inputs ); i < maxInputs; ( ++i, pByte += inputStructSize ) ) + { + pInputBase = (const input_base *) pByte; + + IF( EQ_32( pInputBase->inConfig, IVAS_AUDIO_CONFIG_INVALID ) ) + { + *inputIndex = i; + canAddInput = true; + BREAK; + } + } + + IF ( !canAddInput ) + { + return IVAS_ERR_TOO_MANY_INPUTS; + } + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* @@ -5569,7 +5838,7 @@ static ivas_error findFreeInputSlot( * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error IVAS_REND_AddInput( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const AUDIO_CONFIG inConfig, /* i : audio config for a new input */ @@ -5635,10 +5904,77 @@ ivas_error IVAS_REND_AddInput( return IVAS_ERR_OK; } - - -/*-------------------------------------------------------------------* - * IVAS_REND_ConfigureCustomInputLoudspeakerLayout() +#else +ivas_error IVAS_REND_AddInput_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const AUDIO_CONFIG inConfig, /* i : audio config for a new input */ + IVAS_REND_InputId *inputId /* o : ID of the new input */ +) +{ + ivas_error error; + Word32 maxNumInputsOfType; + void *inputsArray; + Word32 inputStructSize; + ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, RENDER_CONFIG_DATA * ); + Word32 inputIndex; + + /* Validate function arguments */ + IF ( hIvasRend == NULL || inputId == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + + SWITCH ( getAudioConfigType( inConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED: + maxNumInputsOfType = RENDERER_MAX_ISM_INPUTS; + inputsArray = hIvasRend->inputsIsm; + inputStructSize = sizeof( *hIvasRend->inputsIsm ); + activateInput = setRendInputActiveIsm; + BREAK; + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + maxNumInputsOfType = RENDERER_MAX_MC_INPUTS; + inputsArray = hIvasRend->inputsMc; + inputStructSize = sizeof( *hIvasRend->inputsMc ); + activateInput = setRendInputActiveMc; + BREAK; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + maxNumInputsOfType = RENDERER_MAX_SBA_INPUTS; + inputsArray = hIvasRend->inputsSba; + inputStructSize = sizeof( *hIvasRend->inputsSba ); + activateInput = setRendInputActiveSba; + BREAK; + case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: + maxNumInputsOfType = RENDERER_MAX_MASA_INPUTS; + inputsArray = hIvasRend->inputsMasa; + inputStructSize = sizeof( *hIvasRend->inputsMasa ); + activateInput = setRendInputActiveMasa; + BREAK; + default: + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + /* Find first free input in array corresponding to input type */ + IF ( ( error = findFreeInputSlot_fx( inputsArray, inputStructSize, maxNumInputsOfType, &inputIndex ) ) != IVAS_ERR_OK ) + { + return error; + } + + *inputId = makeInputId( inConfig, inputIndex ); + + IF ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} +#endif + + +/*-------------------------------------------------------------------* + * IVAS_REND_ConfigureCustomInputLoudspeakerLayout() * * * Note: this will reset any custom LFE routing set for the input @@ -5716,7 +6052,7 @@ ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout( * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error IVAS_REND_SetInputGain( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ @@ -5741,14 +6077,39 @@ ivas_error IVAS_REND_SetInputGain( return IVAS_ERR_OK; } +#else +ivas_error IVAS_REND_SetInputGain_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const Word32 gain /* i : linear gain (not in dB) */ +) +{ + input_base *inputBase; + ivas_error error; + + /* Validate function arguments */ + IF ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF ( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + inputBase->gain_fx = gain; + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * IVAS_REND_SetInputLfeMtx() * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error IVAS_REND_SetInputLfeMtx( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ @@ -5791,6 +6152,50 @@ ivas_error IVAS_REND_SetInputLfeMtx( return IVAS_ERR_OK; } +#else +ivas_error IVAS_REND_SetInputLfeMtx_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_LfePanMtx_fx *lfePanMtx /* i : LFE panning matrix */ +) +{ + Word16 i; + input_base *pInputBase; + input_mc *pInputMc; + ivas_error error; + + /* Validate function arguments */ + IF ( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF ( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF ( getAudioConfigType( pInputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + { + /* Custom LFE panning matrix only makes sense with channel-based input */ + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + pInputMc = (input_mc *) pInputBase; + + /* copy LFE panning matrix */ + FOR ( i = 0; i < RENDERER_MAX_INPUT_LFE_CHANNELS; i++ ) + { + Copy32( ( *lfePanMtx )[i], pInputMc->lfeRouting.lfePanMtx_fx[i], IVAS_MAX_OUTPUT_CHANNELS ); + } + + IF ( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} +#endif #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* @@ -5799,12 +6204,12 @@ ivas_error IVAS_REND_SetInputLfeMtx( * *-------------------------------------------------------------------*/ -ivas_error IVAS_REND_SetInputLfePos( +ivas_error IVAS_REND_SetInputLfePos_fx( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ - const float inputGain, /* i : Input gain to be applied to the LFE channel(s) */ - const float outputAzimuth, /* i : Output azimuth position */ - const float outputElevation /* i : Output elevation position */ + const Word32 inputGain, /* i : Input gain to be applied to the LFE channel(s) */ + const Word16 outputAzimuth, /* i : Output azimuth position */ + const Word16 outputElevation /* i : Output elevation position */ ) { input_base *pInputBase; @@ -5812,17 +6217,17 @@ ivas_error IVAS_REND_SetInputLfePos( ivas_error error; /* Validate function arguments */ - if ( hIvasRend == NULL ) + IF ( hIvasRend == NULL ) { return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ) != IVAS_ERR_OK ) + IF ( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ) != IVAS_ERR_OK ) { return error; } - if ( getAudioConfigType( pInputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + IF ( getAudioConfigType( pInputBase->inConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) { /* Custom LFE routing only makes sense with channel-based input */ return IVAS_ERR_INVALID_INPUT_FORMAT; @@ -5830,14 +6235,11 @@ ivas_error IVAS_REND_SetInputLfePos( pInputMc = (input_mc *) pInputBase; pInputMc->lfeRouting.pan_lfe = true; - pInputMc->lfeRouting.lfeInputGain = inputGain; - pInputMc->lfeRouting.lfeInputGain_fx = ( inputGain == 1.0f ) ? ONE_IN_Q31 : (Word32) (inputGain * ( ONE_IN_Q31 )); - pInputMc->lfeRouting.lfeOutputAzimuth = outputAzimuth; + pInputMc->lfeRouting.lfeInputGain_fx = inputGain; // Q31 pInputMc->lfeRouting.lfeOutputAzimuth_fx = (Word16) ( outputAzimuth ); // Q0 - pInputMc->lfeRouting.lfeOutputElevation = outputElevation; pInputMc->lfeRouting.lfeOutputElevation_fx = (Word16) ( outputElevation ); // Q0 - if ( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) + IF ( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ) != IVAS_ERR_OK ) { return error; } @@ -5941,7 +6343,7 @@ ivas_error IVAS_REND_RemoveInput( * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error IVAS_REND_GetInputNumChannels( IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ @@ -5969,14 +6371,42 @@ ivas_error IVAS_REND_GetInputNumChannels( return IVAS_ERR_OK; } +#else +ivas_error IVAS_REND_GetInputNumChannels( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + Word16 *numChannels /* o : number of channels of the input */ +) +{ + ivas_error error; + const input_base *pInput; + + /* Validate function arguments */ + IF ( hIvasRend == NULL || numChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( ( error = getConstInputById( hIvasRend, inputId, (const void **) &pInput ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF ( ( error = getRendInputNumChannels( pInput, numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * IVAS_REND_GetNumAllObjects() * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED ivas_error IVAS_REND_GetNumAllObjects( IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ int16_t *numChannels /* o : number of all objects */ @@ -5994,7 +6424,25 @@ ivas_error IVAS_REND_GetNumAllObjects( return IVAS_ERR_OK; } +#else +ivas_error IVAS_REND_GetNumAllObjects( + IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + Word16 *numChannels /* o : number of all objects */ +) +{ + IF ( hIvasRend == NULL || numChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA2 ) ) + { + *numChannels = (Word16) hIvasRend->inputsIsm[0].total_num_objects; + } + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * IVAS_REND_GetDelay() @@ -6566,22 +7014,32 @@ ivas_error IVAS_REND_SetHeadRotation( } } +#ifdef IVAS_FLOAT_FIXED /* check for Euler angle signaling */ - if ( headRot.w == -3.0f ) + IF( EQ_32( headRot.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { - Euler2Quat( deg2rad( headRot.x ), deg2rad( headRot.y ), deg2rad( headRot.z ), &rotQuat ); + Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat ); } - else + ELSE { rotQuat = headRot; } -#ifdef IVAS_FLOAT_FIXED - if ( ( error = ivas_orient_trk_Process_fx( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx] ) ) != IVAS_ERR_OK ) + IF ( ( error = ivas_orient_trk_Process_fx( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx] ) ) != IVAS_ERR_OK ) { return error; } #else + /* check for Euler angle signaling */ + if ( headRot.w == -3.0f ) + { + Euler2Quat( deg2rad( headRot.x ), deg2rad( headRot.y ), deg2rad( headRot.z ), &rotQuat ); + } + else + { + rotQuat = headRot; + } + if ( ( error = ivas_orient_trk_Process( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx] ) ) != IVAS_ERR_OK ) { return error; @@ -7202,7 +7660,7 @@ static ivas_error rotateFrameMc_fx( IF( hEFAPdata != NULL && ( NE_32( ls_azimuth[ch_in_woLFE], azimuth_fx ) || NE_32( ls_elevation[ch_in_woLFE], elevation_fx ) ) ) { - efap_determine_gains_fixed( hEFAPdata, tmp_gains, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); + efap_determine_gains_fx( hEFAPdata, tmp_gains, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); FOR( ch_out = 0; ch_out < nchan; ch_out++ ) { @@ -8268,6 +8726,10 @@ static ivas_error renderInputIsm( } ismInput->base.numNewSamplesPerChannel = 0; +#ifdef IVAS_FLOAT_FIXED + ismInput->base.gain = fix_to_float(ismInput->base.gain_fx, 30); +#endif // IVAS_FLOAT_FIXED + /* Apply input gain to new audio */ v_multc( inAudio.data, ismInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); @@ -9238,6 +9700,8 @@ static ivas_error renderInputMc( return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); } mcInput->base.numNewSamplesPerChannel = 0; + /* To be removed */ + mcInput->base.gain = fix_to_float( mcInput->base.gain_fx, Q30 ); /* Apply input gain to new audio */ v_multc( inAudio.data, mcInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); @@ -9869,7 +10333,7 @@ static void renderSbaToMasa( push_wmops( "renderMcToMasa" ); copyBufferTo2dArray_fx( sbaInput->base.inputBuffer, tmpRendBuffer ); - ivas_dirac_ana( sbaInput->hDirAC, tmpRendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels ); + ivas_dirac_ana_fx( sbaInput->hDirAC, tmpRendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels ); accumulate2dArrayToBuffer_fx( tmpRendBuffer, &outAudio ); pop_wmops(); @@ -10246,6 +10710,10 @@ static ivas_error renderInputMasa( } masaInput->base.numNewSamplesPerChannel = 0; +#ifdef IVAS_FLOAT_FIXED + masaInput->base.gain = fix_to_float( masaInput->base.gain_fx, Q30 ); +#endif // IVAS_FLOAT_FIXED + /* Apply input gain to new audio */ v_multc( inAudio.data, masaInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); @@ -10869,7 +11337,7 @@ void IVAS_REND_Close( return; } - +#ifdef IVAS_FLOAT_FIXED static ivas_error ivas_masa_ext_rend_dirac_rend_init( input_masa *inputMasa ) { @@ -11210,7 +11678,7 @@ static ivas_error ivas_masa_ext_rend_dirac_rend_init( { if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) { - if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirACRend->hOutSetup, &inputMasa->hMasaExtRend->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_sba_get_hoa_dec_matrix_fx( hDirACRend->hOutSetup, &inputMasa->hMasaExtRend->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) { return error; } @@ -11319,46 +11787,407 @@ static ivas_error ivas_masa_ext_rend_dirac_rend_init( return error; } - -static ivas_error ivas_masa_ext_rend_parambin_init( - input_masa *inputMasa /* i/o: MASA external renderer structure */ -) +#else +static ivas_error ivas_masa_ext_rend_dirac_rend_init( + input_masa *inputMasa ) { - DIRAC_DEC_BIN_HANDLE hDiracDecBin; - HRTFS_PARAMBIN_HANDLE hHrtfParambin; - int16_t nBins; + int16_t nchan_out_woLFE; + int16_t nchan_transport; + uint16_t i, j, k; + float ls_azimuth[MAX_OUTPUT_CHANNELS]; + float ls_elevation[MAX_OUTPUT_CHANNELS]; int32_t output_Fs; - RENDERER_TYPE renderer_type; - int16_t j, k, bin; - float binCenterFreq, tmpFloat; ivas_error error; - float frequency_axis[CLDFB_NO_CHANNELS_MAX]; + DIRAC_REND_HANDLE hDirACRend; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; error = IVAS_ERR_OK; - hHrtfParambin = inputMasa->hMasaExtRend->hHrtfParambin; - - /* Set common variables and defaults */ + hDirACRend = NULL; output_Fs = *( inputMasa->base.ctx.pOutSampleRate ); - nBins = inputMasa->hMasaExtRend->hSpatParamRendCom->num_freq_bands; - renderer_type = inputMasa->hMasaExtRend->renderer_type; - hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin; + hSpatParamRendCom = inputMasa->hMasaExtRend->hSpatParamRendCom; - /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */ - if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hDirACRend = (DIRAC_REND_HANDLE) malloc( sizeof( DIRAC_REND_DATA ) ) ) == NULL ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC renderer\n" ) ); } - hDiracDecBin->hTdDecorr = NULL; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; - hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */ - hDiracDecBin->useTdDecorr = 0; /* Always use frequency domain decorrelator in external renderer */ + nchan_transport = inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA2 ? 2 : 1; - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + /*-----------------------------------------------------------------* + * output setup: for parametric binaural renderer, use output setup, otherwise internal setup + *-----------------------------------------------------------------*/ + + ivas_output_init( &hDirACRend->hOutSetup, *inputMasa->base.ctx.pOutConfig ); + + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) + { + /* Copy from ivas_ls_custom_setup */ + hDirACRend->hOutSetup.nchan_out_woLFE = inputMasa->base.ctx.pCustomLsOut->num_spk; + hDirACRend->hOutSetup.ls_azimuth = inputMasa->base.ctx.pCustomLsOut->ls_azimuth; + hDirACRend->hOutSetup.ls_elevation = inputMasa->base.ctx.pCustomLsOut->ls_elevation; + + hDirACRend->hOutSetup.num_lfe = inputMasa->base.ctx.pCustomLsOut->num_lfe; + hDirACRend->hOutSetup.index_lfe[0] = inputMasa->base.ctx.pCustomLsOut->lfe_idx[0]; + + hDirACRend->hOutSetup.is_loudspeaker_setup = TRUE; + hDirACRend->hOutSetup.is_planar_setup = (int8_t) inputMasa->base.ctx.pCustomLsOut->is_planar_setup; + } + + nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; + + if ( hDirACRend->hOutSetup.ls_azimuth != NULL && hDirACRend->hOutSetup.ls_elevation != NULL ) + { + mvr2r( hDirACRend->hOutSetup.ls_azimuth, ls_azimuth, nchan_out_woLFE ); + mvr2r( hDirACRend->hOutSetup.ls_elevation, ls_elevation, nchan_out_woLFE ); + } + + if ( hDirACRend->hOutSetup.ambisonics_order == -1 ) + { + hDirACRend->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */ + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO || hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_STEREO ) + { + hDirACRend->hOutSetup.ambisonics_order = SBA_FOA_ORDER; + } + } + else if ( hDirACRend->hOutSetup.ambisonics_order >= SBA_FOA_ORDER ) + { + mvr2r( ls_azimuth_4d4, ls_azimuth, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); + mvr2r( ls_elevation_4d4, ls_elevation, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); + } + + /*-----------------------------------------------------------------* + * set input parameters + *-----------------------------------------------------------------*/ + + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_MONO; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + nchan_out_woLFE = 1; + } + else if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; + hDirACRend->panningConf = DIRAC_PANNING_VBAP; + } + else if ( !hDirACRend->hOutSetup.is_loudspeaker_setup && nchan_transport > 1 ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_SHD; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + } + else + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_GAIN_SHD; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + } + + if ( ( hDirACRend->frequency_axis = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirACRend->frequency_axis, 0.0f, hSpatParamRendCom->num_freq_bands ); + + ivas_dirac_dec_get_frequency_axis( hDirACRend->frequency_axis, output_Fs, hSpatParamRendCom->num_freq_bands ); + + if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 && nchan_transport == 2 ) + { + if ( ( hDirACRend->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + ivas_masa_init_stereotype_detection( hDirACRend->masa_stereo_type_detect ); + } + else + { + hDirACRend->masa_stereo_type_detect = NULL; + } + + hSpatParamRendCom->numIsmDirections = 0; + + /*-----------------------------------------------------------------* + * (re)configure sub-modules + *-----------------------------------------------------------------*/ + + /* prototype signal computation */ + /* allocate output setup related arrays */ + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + { + /* Directional and diffuses components in output LS format */ + hDirACRend->num_outputs_diff = nchan_out_woLFE; + hDirACRend->num_outputs_dir = nchan_out_woLFE; + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + /* Directional and diffuses components in SHD */ + /* Diffuseness components up to 1st order */ + hDirACRend->num_outputs_diff = ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ) * ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ); + hDirACRend->num_outputs_dir = ivas_sba_get_nchan( hDirACRend->hOutSetup.ambisonics_order, 0 ); + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + hDirACRend->num_outputs_diff = DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS; + hDirACRend->num_outputs_dir = nchan_out_woLFE; + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + hDirACRend->num_outputs_diff = 1; /* There is one output channel in mono */ + hDirACRend->num_outputs_dir = 2; /* Two channels are pre-rendered for stereo type detection */ + } + else + { + assert( 0 && "DirAC: not existing synthesis methods!" ); + } + + if ( ( hDirACRend->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirACRend->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + set_s( hDirACRend->proto_index_dir, 0, hDirACRend->num_outputs_dir ); + set_s( hDirACRend->proto_index_diff, 0, hDirACRend->num_outputs_diff ); + + hDirACRend->sba_map_tc = sba_map_tc; + + if ( nchan_transport == 1 ) + { + hDirACRend->num_protos_ambi = 1; + hDirACRend->num_protos_dir = 1; + hDirACRend->num_protos_diff = 1; + } + else if ( nchan_transport == 2 ) + { + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_diff = 1; + hDirACRend->num_protos_dir = 2; + hDirACRend->proto_index_dir[1] = 1; + } + else if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO ) + { + /* Following the foa rendering for code compatibility */ + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_dir = 2; + hDirACRend->num_protos_diff = 3; + hDirACRend->proto_index_dir[0] = 0; + hDirACRend->proto_index_diff[0] = 0; + } + else + { + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_diff = 3; + + for ( k = 0; k < hDirACRend->num_outputs_diff; k++ ) + { + if ( ls_azimuth[k] > 0.0f ) + { + hDirACRend->proto_index_diff[k] = 1; + } + else if ( ls_azimuth[k] < 0.0f ) + { + hDirACRend->proto_index_diff[k] = 2; + } + else + { + hDirACRend->proto_index_diff[k] = 0; + } + } + + if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + hDirACRend->num_protos_dir = 3; + mvs2s( hDirACRend->proto_index_diff, hDirACRend->proto_index_dir, nchan_out_woLFE ); + } + else + { + hDirACRend->num_protos_dir = 2; + hDirACRend->proto_index_dir[1] = 1; + } + } + } + + /* direct/diffuse responses */ + if ( ( hDirACRend->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirACRend->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) ) + { + initDiffuseResponses( hDirACRend->diffuse_response_function, nchan_out_woLFE, hDirACRend->hOutSetup.output_config, + hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID ); + } + else + { + initDiffuseResponses( hDirACRend->diffuse_response_function, hDirACRend->num_outputs_dir, IVAS_AUDIO_CONFIG_FOA, + hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID ); + } + + hDirACRend->hoa_encoder = NULL; + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + if ( ( hDirACRend->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + set_f( hDirACRend->hoa_encoder, 0.0f, nchan_out_woLFE * hDirACRend->num_outputs_diff ); + compute_hoa_encoder_mtx( ls_azimuth, ls_elevation, hDirACRend->hoa_encoder, hDirACRend->num_outputs_diff, hDirACRend->hOutSetup.ambisonics_order ); + } + + /* VBAP */ + inputMasa->hMasaExtRend->hVBAPdata = NULL; + + if ( hDirACRend->panningConf == DIRAC_PANNING_VBAP ) + { + if ( ( error = vbap_init_data( &( inputMasa->hMasaExtRend->hVBAPdata ), ls_azimuth, ls_elevation, nchan_out_woLFE, MASA_FORMAT ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* HOA panning/dec */ + hDirACRend->hoa_decoder = NULL; + if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 ) + { + if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirACRend->hOutSetup, &inputMasa->hMasaExtRend->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + { + return error; + } + + hDirACRend->hoa_decoder = inputMasa->hMasaExtRend->hoa_dec_mtx; + } + } + + /* decorrelation */ + hDirACRend->proto_signal_decorr_on = 1; + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + hDirACRend->proto_signal_decorr_on = 0; + } + + if ( hDirACRend->proto_signal_decorr_on ) + { + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirACRend->h_freq_domain_decorr_ap_params ), + &( hDirACRend->h_freq_domain_decorr_ap_state ), + hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + hDirACRend->frequency_axis, + nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* output synthesis */ + if ( ( ivas_dirac_dec_output_synthesis_open( hSpatParamRendCom, hDirACRend, RENDERER_DIRAC, nchan_transport, output_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + hDirACRend->h_output_synthesis_psd_params.use_onset_filters = hDirACRend->proto_signal_decorr_on; + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->h_output_synthesis_psd_params.use_onset_filters = 0; + } + + /*-----------------------------------------------------------------* + * memory allocation + *-----------------------------------------------------------------*/ + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->proto_frame_f = NULL; + } + else + { + if ( ( hDirACRend->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirACRend->num_protos_diff * hSpatParamRendCom->num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + } + + + hDirACRend->buffer_energy = NULL; + + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + hDirACRend->buffer_intensity_real[i][j] = NULL; + } + } + + /* output synthesis */ + ivas_dirac_dec_output_synthesis_init( hSpatParamRendCom, hDirACRend, nchan_out_woLFE, 0 ); + + /* Allocate stack memory */ + if ( ( error = ivas_dirac_alloc_mem( hDirACRend, RENDERER_DIRAC, hSpatParamRendCom->num_freq_bands, &( hDirACRend->stack_mem ), 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + inputMasa->hMasaExtRend->hDirACRend = hDirACRend; + + return error; +} +#endif + +static ivas_error ivas_masa_ext_rend_parambin_init( + input_masa *inputMasa /* i/o: MASA external renderer structure */ +) +{ + DIRAC_DEC_BIN_HANDLE hDiracDecBin; + HRTFS_PARAMBIN_HANDLE hHrtfParambin; + int16_t nBins; + int32_t output_Fs; + RENDERER_TYPE renderer_type; + int16_t j, k, bin; + float binCenterFreq, tmpFloat; + ivas_error error; + float frequency_axis[CLDFB_NO_CHANNELS_MAX]; + + error = IVAS_ERR_OK; + + hHrtfParambin = inputMasa->hMasaExtRend->hHrtfParambin; + + /* Set common variables and defaults */ + output_Fs = *( inputMasa->base.ctx.pOutSampleRate ); + nBins = inputMasa->hMasaExtRend->hSpatParamRendCom->num_freq_bands; + renderer_type = inputMasa->hMasaExtRend->renderer_type; + + hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin; + + /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */ + if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); + } + + hDiracDecBin->hTdDecorr = NULL; + hDiracDecBin->hReverb = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */ + hDiracDecBin->useTdDecorr = 0; /* Always use frequency domain decorrelator in external renderer */ + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) { @@ -11672,10 +12501,17 @@ static void freeMasaExtRenderer( #endif } +#ifdef IVAS_FLOAT_FIXED + IF( hMasaExtRend->hHrtfParambin != NULL ) + { + ivas_HRTF_parambin_binary_close_fx( &hMasaExtRend->hHrtfParambin ); + } +#else if ( hMasaExtRend->hHrtfParambin != NULL ) { ivas_HRTF_parambin_binary_close( &hMasaExtRend->hHrtfParambin ); } +#endif if ( hMasaExtRend->hVBAPdata != NULL ) { diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 4c9728612..135392215 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -160,7 +160,13 @@ ivas_error IVAS_REND_AddInput( const IVAS_AUDIO_CONFIG inConfig, /* i : audio config for a new input */ IVAS_REND_InputId *inputId /* o : ID of the new input */ ); - +#ifdef IVAS_FLOAT_FIXED +ivas_error IVAS_REND_AddInput_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_AUDIO_CONFIG inConfig, /* i : audio config for a new input */ + IVAS_REND_InputId *inputId /* o : ID of the new input */ +); +#endif /* Note: this will reset any custom LFE routing set for the input */ ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ @@ -173,7 +179,19 @@ ivas_error IVAS_REND_SetInputGain( const IVAS_REND_InputId inputId, /* i : ID of the input */ const float gain /* i : linear gain (not in dB) */ ); +#ifdef IVAS_FLOAT_FIXED +ivas_error IVAS_REND_SetInputGain_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const Word32 gain /* i : linear gain (not in dB) */ +); +ivas_error IVAS_REND_SetInputLfeMtx_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_LfePanMtx_fx *lfePanMtx /* i : LFE panning matrix */ +); +#endif // IVAS_FLOAT_FIXED ivas_error IVAS_REND_SetInputLfeMtx( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId, /* i : ID of the input */ @@ -187,7 +205,15 @@ ivas_error IVAS_REND_SetInputLfePos( const float outputAzimuth, /* i : Output azimuth position */ const float outputElevation /* i : Output elevation position */ ); - +#ifdef IVAS_FLOAT_FIXED +ivas_error IVAS_REND_SetInputLfePos_fx( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const Word32 inputGain, /* i : Input gain to be applied to the LFE channel(s) */ + const Word16 outputAzimuth, /* i : Output azimuth position */ + const Word16 outputElevation /* i : Output elevation position */ +); +#endif // IVAS_FLOAT_FIXED ivas_error IVAS_REND_RemoveInput( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_REND_InputId inputId /* i : ID of the input */ diff --git a/lib_util/hrtf_file_reader.c b/lib_util/hrtf_file_reader.c index 31be09232..29bd4a8b0 100644 --- a/lib_util/hrtf_file_reader.c +++ b/lib_util/hrtf_file_reader.c @@ -549,10 +549,10 @@ static ivas_error LoadBSplineBinary( HRTF_energy_sections_precalc( model ); HrFiltSet_p->FiltLength = HrFiltSet_p->ModelParams.K; +#ifndef IVAS_FLOAT_FIXED HrFiltSet_p->ModelEval.hrfModL = (float *) malloc( model->K * sizeof( float ) ); HrFiltSet_p->ModelEval.hrfModR = (float *) malloc( model->K * sizeof( float ) ); - -#ifdef IVAS_FLOAT_FIXED +#else HrFiltSet_p->ModelEval.hrfModL_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ); HrFiltSet_p->ModelEval.hrfModR_fx = (Word32 *) malloc( model->K * sizeof( Word32 ) ); #endif @@ -884,9 +884,13 @@ ivas_error dealloc_HRTF_binary( free( hHrtf->ModelParams.EL_dyn_fx ); free( hHrtf->ModelParams.ER_dyn_fx ); #endif - +#ifdef IVAS_FLOAT_FIXED + free( hHrtf->ModelEval.hrfModL_fx ); + free( hHrtf->ModelEval.hrfModR_fx ); +#else free( hHrtf->ModelEval.hrfModL ); free( hHrtf->ModelEval.hrfModR ); +#endif for ( i = 0; i < 3; i++ ) { -- GitLab From d18c367e89b9d439e12394a2f6cd8e535b3aa3a2 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Mon, 6 May 2024 14:36:12 +0530 Subject: [PATCH 2/2] Fix for idiv1616 BASOP zero numerator case --- lib_rend/ivas_dirac_output_synthesis_dec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_rend/ivas_dirac_output_synthesis_dec.c index d8cbc1f26..43a0cb5e8 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec.c @@ -3675,7 +3675,14 @@ static void ivas_dirac_dec_get_response_split_order_fx( tmp = BASOP_util_atan2( dv_r_1, dv_r_0, 0 ); // Q13 index_azimuth = shr( mult( tmp, _180_OVER_PI_Q9 ), 7 ); // Q0; - tmp = idiv1616( add( index_azimuth, 180 ), 360 ); + IF(EQ_16(index_azimuth, -180)) + { + tmp = 0; move16(); + } + ELSE + { + tmp = idiv1616( add( index_azimuth, 180 ), 360 ); + } index_azimuth = sub( add( index_azimuth, 180 ), i_mult( tmp, 360 ) ); // index_azimuth = (index_azimuth + 180) % 360 temp = L_add( Mpy_32_32( dv_r_0, dv_r_0 ), Mpy_32_32( dv_r_1, dv_r_1 ) ); // Q21 -- GitLab