diff --git a/.gitignore b/.gitignore index 77d081dec913b20fa620b9ad7b56b8b4e41303c3..a7a1d7a7ef6e4ef25555af59845006cffcc95815 100644 --- a/.gitignore +++ b/.gitignore @@ -66,5 +66,8 @@ __pycache__/ #history .history/ +#externals +Externals/ + # coan output files that are created when cleaning out switches coan_out_* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1da859b788d10ca1d585c17e7a593a93741cd475..b56bf35e8a23e0467d57bf5cb2914580464a4dcb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -278,7 +278,8 @@ codec-smoke-test: ### analyze for failures - if cat smoke_test_output.txt | grep -c "failed"; then echo "Smoke test without PLC failed"; exit 1; fi - if cat smoke_test_output_plc.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; exit 1; fi - - if cat smoke_test_output_jbm_noEXT.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; exit 1; fi + - if cat smoke_test_output_jbm_noEXT.txt | grep -c "failed"; then echo "Smoke test JBM part failed"; exit 1; fi + - if cat smoke_test_output_hrtf.txt | grep -c "failed"; then echo "Smoke test with external hrtf files failed"; exit 1; fi artifacts: name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" paths: @@ -286,6 +287,7 @@ codec-smoke-test: - smoke_test_output.txt - smoke_test_output_plc.txt - smoke_test_output_jbm_noEXT.txt + - smoke_test_output_hrtf.txt expose_as: "Smoke test results" # code selftest testvectors with memory-sanitizer binaries diff --git a/apps/decoder.c b/apps/decoder.c index 1ca5806331ad8527bcd3cf2b0dcd81bdcfbf2922..f018814423aefb3a2eaaf61ed84d57ea134d939c 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -93,6 +93,10 @@ typedef struct float FER; bool hrtfReaderEnabled; char *hrtfFileName; +#ifdef HRTF_BINARY_FILE + bool hrtfCRendReaderEnabled; + char *hrtfCRendFileName; +#endif IVAS_DEC_INPUT_FORMAT inputFormat; bool customLsOutputEnabled; char *customLsSetupFilename; @@ -218,7 +222,7 @@ int main( if ( arg.hrtfReaderEnabled ) { - if ( ( ( error = hrtfFileReader_open( arg.hrtfFileName, &hrtfReader ) ) != IVAS_ERR_OK ) ) + if ( ( error = hrtfFileReader_open( arg.hrtfFileName, &hrtfReader ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError: Can't open HRTF binary file %s \n\n", arg.hrtfFileName ); goto cleanup; @@ -440,6 +444,34 @@ int main( fprintf( stderr, "\nError in loading HRTF binary file %s \n\n", arg.hrtfFileName ); goto cleanup; } + +#ifdef HRTF_BINARY_FILE + + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF; + IVAS_DEC_GetHrtfCRendHandle( hIvasDec, &hSetOfHRTF ); + + if ( ( error = create_SetOfHRTF_from_binary( hSetOfHRTF, hrtfReader, arg.output_Fs ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for CRend \n\n", arg.hrtfCRendFileName ); +#ifndef FIX_FOR_TEST + goto cleanup; +#endif + } + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv; + IVAS_DEC_GetHrtfFastConvHandle( hIvasDec, &hHrtfFastConv ); + + if ( ( error = load_fastconv_HRTF_from_binary( hHrtfFastConv, hrtfReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for FastConv \n\n", arg.hrtfCRendFileName ); + } + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParambin; + IVAS_DEC_GetHrtfParamBinHandle( hIvasDec, &hHrtfParambin ); + + if ( ( error = load_parambin_HRTF_from_binary( hHrtfParambin, hrtfReader ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in loading HRTF binary file %s for parametric binauralizer \n\n", arg.hrtfCRendFileName ); + } +#endif } /*-----------------------------------------------------------------* @@ -662,6 +694,11 @@ static bool parseCmdlIVAS_dec( arg->hrtfReaderEnabled = false; arg->hrtfFileName = NULL; +#ifdef HRTF_BINARY_FILE + arg->hrtfCRendReaderEnabled = false; + arg->hrtfCRendFileName = NULL; +#endif + arg->customLsOutputEnabled = false; arg->customLsSetupFilename = NULL; @@ -1030,7 +1067,11 @@ static void usage_dec( void ) fprintf( stdout, " which of the two supported formats is in use.\n" ); fprintf( stdout, " default bitstream file format is G.192\n" ); fprintf( stdout, "-T File : Head rotation specified by external trajectory File\n" ); +#ifdef HRTF_BINARY_FILE + fprintf( stdout, "-hrtf File : HRTF filter File used in BINAURAL output configuration\n" ); +#else fprintf( stdout, "-hrtf File : HRTF filter File used in ISm format and BINAURAL output configuration\n" ); +#endif #ifdef DEBUGGING fprintf( stdout, "-force_subframe_bin : Forces parametric binauralizer code to use 5 ms time resolution even when\n" ); fprintf( stdout, " output time resolution is larger.\n" ); diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index 562d3e005d2098ba163ded26dd726cffcc10ef7d..c11c72fbaaef154e4e08cd3c961f35a207a1368f 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -73,9 +73,28 @@ if [ $BUILD -eq 1 ];then fi +# run all modes vanilla-fashion ./scripts/runIvasCodec.py -p $cfg -U 1 $WORKERS | tee smoke_test_output.txt +# run the decoding again, but with 15% frame loss ./scripts/runIvasCodec.py -p $cfg -U 1 $WORKERS -D="-fec 15" --decoder_only | tee smoke_test_output_plc.txt +# run JBM modes - EXT is excluded as not supported yet modes_with_no_ext_out=$(./scripts/runIvasCodec.py -l | grep -v MASA | grep -v ISM) ./scripts/runIvasCodec.py -m $modes_with_no_ext_out -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile | tee smoke_test_output_jbm_noEXT.txt ./scripts/runIvasCodec.py -C MASA ISM1 ISM2 ISM3 ISM4 -p $cfg -U 1 $WORKERS --decoder_only --jbm_file $dly_profile --oc BINAURAL BINAURAL_ROOM mono stereo FOA HOA3 5_1 7_1_4 | tee -a smoke_test_output_jbm_noEXT.txt + +# run all modes with binaural output using external files +modes_with_bin_out="SBA PlanarSBA MASA MC ISM1 ISM2 ISM3 ISM4" +bin_out_modes="BINAURAL BINAURAL_ROOM" + +wb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _wb_) +hrtf_wb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $wb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_wb}" --decoder_only | tee -a smoke_test_output_hrtf.txt + +swb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _swb_) +hrtf_swb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $swb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_swb}" --decoder_only | tee -a smoke_test_output_hrtf.txt + +fb_modes=$(./scripts/runIvasCodec.py -l -C $modes_with_bin_out | grep _fb_) +hrtf_fb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin" +./scripts/runIvasCodec.py -p $cfg -m $fb_modes -U 1 $WORKERS -D="-hrtf ${hrtf_fb}" --decoder_only | tee -a smoke_test_output_hrtf.txt diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index b9681d8fd630a3bb09854fd73509e4c6119ae1ef..a24e03f248de30a26ddda7320f1287a19d81ccd4 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -87,6 +87,14 @@ typedef struct ivas_masa_metadata_frame_struct *IVAS_MASA_METADATA_HANDLE; typedef struct ivas_masa_qmetadata_frame_struct *IVAS_MASA_QMETADATA_HANDLE; typedef struct TDREND_HRFILT_FiltSet_struct *IVAS_DEC_HRTF_HANDLE; +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_crend_structure *IVAS_DEC_HRTF_CREND_HANDLE; +#endif +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_fastconv_struct *IVAS_DEC_HRTF_FASTCONV_HANDLE; + +typedef struct ivas_hrtfs_parambin_struct *IVAS_DEC_HRTF_PARAMBIN_HANDLE; +#endif #ifdef DEBUGGING typedef enum diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index fbd9c006bfce6ebdd2d4a8906f4e6e948079c79b..e625095817a1d46113b9da490afa9337757a5139 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1358,10 +1358,16 @@ typedef enum #define BINAURAL_MAXBANDS 60 /* Max number of bands */ #define BINAURAL_CONVBANDS 50 /* Bands upto which convolution is performed */ +#ifdef HRTF_BINARY_FILE +#define BINAURAL_NTAPS 7 +#endif #define BINAURAL_NTAPS_MAX 96 #define HRTF_SH_ORDER 3 #define HRTF_SH_CHANNELS 16 +#ifdef HRTF_BINARY_FILE +#define HRTF_LS_CHANNELS 15 +#endif #define HRTF_NUM_BINS 60 #define REVERB_PREDELAY_MAX 20 /* Max input delay for reverb module */ #define GAIN_LFE 1.88364911f /* Gain applied to LFE during renderering */ @@ -1370,6 +1376,17 @@ typedef enum #define BINAURAL_COHERENCE_DIFFERENCE_BINS 9 /* Number of bins for direction-dependent diffuse-field binaural coherence */ +#ifdef HRTF_BINARY_FILE +typedef enum +{ + BINAURAL_INPUT_AUDIO_CONFIG_INVALID, + BINAURAL_INPUT_AUDIO_CONFIG_COMBINED, // 5_1, 5_1_2, 5_1_4, 7_1, 7_1_4 + BINAURAL_INPUT_AUDIO_CONFIG_HOA, // FOA, HOA2, HOA3 + BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED // Not used + +} BINAURAL_INPUT_AUDIO_CONFIG; + +#endif #define HEADROT_ORDER 3 #define HEADROT_SHMAT_DIM ( ( HEADROT_ORDER + 1 ) * ( HEADROT_ORDER + 1 ) ) #define HEADROT_SHMAT_DIM2 ( HEADROT_SHMAT_DIM * HEADROT_SHMAT_DIM ) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 7d43035900ba3cf2723370833bc242f0338df5f8..c91013ca92f13f78fb708d2af024fa4b0464dab9 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3312,14 +3312,27 @@ void ivas_dirac_dec( const int16_t i_sf ); +#ifdef HRTF_BINARY_FILE +ivas_error ivas_dirac_dec_init_binaural_data( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ +); +#else ivas_error ivas_dirac_dec_init_binaural_data( Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ); +#endif void ivas_dirac_dec_close_binaural_data( DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */ ); +#ifdef HRTF_BINARY_FILE +ivas_error ivas_dirac_dec_binaural_copy_hrtfs( + HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ +); +#endif + void ivas_dirac_dec_binaural( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ float output_f[][L_FRAME48k], /* i/o: synthesized core-coder transport channels/DirAC output */ @@ -3334,6 +3347,11 @@ ivas_error ivas_binaural_reverb_open( const AUDIO_CONFIG output_config, /* i : output audio configuration */ const int32_t sampling_rate, /* i : sampling rate */ const RENDERER_TYPE renderer_type /* i : renderer type */ +#ifdef HRTF_BINARY_FILE + , + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, /* i : FastConv HRTF handle */ + const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ +#endif ); void ivas_binaural_reverb_close( @@ -4610,6 +4628,24 @@ void ivas_binaural_add_LFE( float output_f[][L_FRAME48k] /* i/o: synthesized core-coder transport channels/DirAC output */ ); +#ifdef HRTF_BINARY_FILE +ivas_error ivas_HRTF_fastconv_binary_open( + HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ +); + +void ivas_HRTF_fastconv_binary_close( + HRTFS_FASTCONV **hHrtfFastConv /* i/o: FASTCONV HRTF structure */ +); + +ivas_error ivas_HRTF_parambin_binary_open( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); + +void ivas_HRTF_parambin_binary_close( + HRTFS_PARAMBIN **hHrtfParambin /* i/o: Parametric binauralizer HRTF structure */ +); +#endif + void QuatToRotMat( const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ @@ -5332,6 +5368,34 @@ int16_t ivas_get_num_bands_from_bw_idx( /*----------------------------------------------------------------------------------* * Crend renderer *----------------------------------------------------------------------------------*/ + +#ifdef HRTF_BINARY_FILE + +ivas_error ivas_HRTF_CRend_binary_open( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); + +void ivas_HRTF_CRend_binary_close( + HRTFS_CREND **hSetOfHRTF /* i/o: Set of HRTF handle */ +); + +#ifndef FIX_197_CREND_INTERFACE + +ivas_error ivas_crend_init_from_setofhrtf( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +); + +ivas_error ivas_crend_init_from_hrtf_handle( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_HANDLE hrtf); +#endif + +ivas_error destroy_SetOfHRTF( + HRTFS_CREND_HANDLE hSetOfHRTF /* i/o: Set of HRTF CRend handle */ +); + +#endif + #ifndef FIX_197_CREND_INTERFACE ivas_error ivas_crend_init_from_rom( @@ -5363,19 +5427,25 @@ ivas_error getAudioConfigNumChannels( IVAS_REND_AudioConfig getRendAudioConfigFromIvasAudioConfig( AUDIO_CONFIG config ); -ivas_error ivas_rend_openCrend( - CREND_WRAPPER_HANDLE *pCrend, +ivas_error ivas_rend_initCrend( + CREND_WRAPPER *pCrend, const IVAS_REND_AudioConfig inConfig, const IVAS_REND_AudioConfig outConfig, RENDER_CONFIG_DATA *hRendCfg, - int16_t Opt_Headrotation, - const int32_t output_Fs ); +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, +#endif + const int32_t output_Fs ); -ivas_error ivas_rend_initCrend( - CREND_WRAPPER *pCrend, +ivas_error ivas_rend_openCrend( + CREND_WRAPPER_HANDLE *pCrend, const IVAS_REND_AudioConfig inConfig, const IVAS_REND_AudioConfig outConfig, RENDER_CONFIG_DATA *hRendCfg, + int16_t Opt_Headrotation, +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, +#endif const int32_t output_Fs ); #ifdef FIX_197_CREND_INTERFACE @@ -5581,6 +5651,9 @@ void ivas_reverb_calc_color_levels( void ivas_reverb_prepare_cldfb_params( ivas_roomAcoustics_t *pInput_params, +#ifdef HRTF_BINARY_FILE + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, +#endif const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t output_Fs, diff --git a/lib_com/options.h b/lib_com/options.h index e1b51996f86cc3458c921f09d7c17f2660de0b90..1efe925fe08d986387285acd010ec241c79e052d 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -147,8 +147,20 @@ #endif #define FIX_I59_DELAY_ROUNDING /* Issue 59: rounding in sample domain instead of nanosec for IVAS_ENC_GetDelay() and IVAS_DEC_GetDelay() */ #define FIX_FIX_I59 /* Issue 59: small fix concerning LFE delay rounding */ +#define FIX_245_RANGE_CODER_VOIP_MSAN /* Issue 245: fix use-of-uninitialized-value in range coder in VoIP mode */ +#define REND_CFG_LFE /* Issue 110: Configurable LFE handling for external renderer */ +#define FIX_235 /* Issue 235: Deallocation of HR filter memory separately for lib_rend (ROM) and lib_util (from file) */ +#define ENV_STAB_FIX /* Contribution 23: HQ envelope stability memory fix */ +#define STABILIZE_GIPD /* FhG: Contribution 22: gIPD stabilization */ +#define FIX_292_VBAP_CALLOC_REMOVAL /* Nokia: Fixes issue 292 by removing the remnant callocs */ +#define FIX_293_EXT_RENDERER_CLI /* FhG: Fix bugs in external renderer CLI */ +#define FIX_268 /* Issue 268: Add low cost dry-run of memory analysis */ +#define HRTF_BINARY_FILE /* HRTF filters' binary file used for binaural rendering. */ +#define LOW_RATE_TRANS_FIX /* Eri: Fix for critical item during transitions */ + #define FIX_197_CREND_INTERFACE #define SET_TNS_FLAG_IN_EVERY_FRAME /* FhG: issue 288 - mismatch between encoder and decoder wrt TNS usage in unified stereo with frameloss */ +#define FIX_FOR_TEST /* allows tests to pass using old TD binary file, to be removed after merge*/ #define FIX_299_ISM_BWS /* VA: issue 299 - fix Band-width switching issues in ISM format */ diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c index 5bc68227355c5b348304ae811fe9312857b61de1..e58483784d970b323c72ebd3eaccc21caf3577fe 100644 --- a/lib_dec/ivas_corecoder_dec_reconfig.c +++ b/lib_dec/ivas_corecoder_dec_reconfig.c @@ -249,11 +249,6 @@ ivas_error ivas_corecoder_dec_reconfig( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->reverse_dmx = 0; st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->smooth_ratio = 1.f; #ifdef SBA_BR_SWITCHING_RECONFIG - set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); - set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->lastCoh = 1.f; - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->mdct_stereo_mode[0] = SMDCT_DUAL_MONO; - st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->mdct_stereo_mode[1] = SMDCT_DUAL_MONO; st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->IGFStereoMode[0] = -1; st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->IGFStereoMode[1] = -1; #endif diff --git a/lib_dec/ivas_dirac_dec_binaural_functions.c b/lib_dec/ivas_dirac_dec_binaural_functions.c index 5d52d6b72a7bbb848ca6bfe08b6fdadc0cbdf1b2..7cdd0cc12778250979c9d1075106d3ec02ac1d1d 100644 --- a/lib_dec/ivas_dirac_dec_binaural_functions.c +++ b/lib_dec/ivas_dirac_dec_binaural_functions.c @@ -86,9 +86,16 @@ static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], f * Initialize parametric binaural renderer *------------------------------------------------------------------------*/ +#ifdef HRTF_BINARY_FILE ivas_error ivas_dirac_dec_init_binaural_data( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ ) +#else +ivas_error ivas_dirac_dec_init_binaural_data( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +#endif { DIRAC_DEC_BIN_HANDLE hBinaural; int16_t nBins; @@ -195,7 +202,11 @@ ivas_error ivas_dirac_dec_init_binaural_data( } else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */ { +#ifdef HRTF_BINARY_FILE + mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hBinaural->earlyPartEneCorrection, nBins ); +#else mvr2r( parametricEarlyPartEneCorrection, hBinaural->earlyPartEneCorrection, nBins ); +#endif /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ if ( hBinaural->hReverb != NULL && ( ( hBinaural->hReverb->numBins != nBins ) || @@ -209,14 +220,37 @@ ivas_error ivas_dirac_dec_init_binaural_data( { if ( hBinaural->useSubframeMode ) { +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, st_ivas->hIntSetup.output_config, output_Fs, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) != IVAS_ERR_OK ) +#endif { return error; } } else { +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, + nBins, + CLDFB_NO_COL_MAX, + NULL, + st_ivas->hIntSetup.output_config, + output_Fs, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_binaural_reverb_open( &hBinaural->hReverb, nBins, CLDFB_NO_COL_MAX, NULL, st_ivas->hIntSetup.output_config, output_Fs, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -296,6 +330,53 @@ void ivas_dirac_dec_close_binaural_data( return; } +#ifdef HRTF_BINARY_FILE +/*------------------------------------------------------------------------- + * ivas_dirac_dec_binaural_copy_hrtfs() + * + * Temporary function for copying HRTF data from rom tables if no binary + * file was given. + *------------------------------------------------------------------------*/ + +ivas_error ivas_dirac_dec_binaural_copy_hrtfs( + HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */ +) +{ + int16_t i, j; + if ( hHrtfParambin != NULL && *hHrtfParambin != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_PARAMBIN *hrtfParambin; + + if ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" ); + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS ); + mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS ); + } + } + + mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfParambin = hrtfParambin; + } + + return IVAS_ERR_OK; +} +#endif /*------------------------------------------------------------------------- * ivas_dirac_dec_binaural() diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 535ba14fb7630db4e38eca535265c7d2e6cd2132..763c83dc39f6b38cfed95fb8fbb7ea5c55a19754 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -583,6 +583,22 @@ ivas_error ivas_init_decoder_front( { return error; } +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_HRTF_CRend_binary_open( &( st_ivas->hSetOfHRTF ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + 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 ) + { + return error; + } +#endif } /*-------------------------------------------------------------------* @@ -1131,10 +1147,25 @@ ivas_error ivas_init_decoder( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { +#ifdef HRTF_BINARY_FILE + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { @@ -1192,6 +1223,9 @@ ivas_error ivas_init_decoder( getRendAudioConfigFromIvasAudioConfig( st_ivas->intern_config ), getRendAudioConfigFromIvasAudioConfig( st_ivas->hDecoderConfig->output_config ), st_ivas->hRenderConfig, st_ivas->hDecoderConfig->Opt_Headrotation, +#ifdef HRTF_BINARY_FILE + st_ivas->hSetOfHRTF, +#endif st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; @@ -1512,6 +1546,11 @@ void ivas_initialize_handles_dec( #else st_ivas->hCrend = NULL; st_ivas->hHrtf = NULL; +#endif +#ifdef HRTF_BINARY_FILE + st_ivas->hSetOfHRTF = NULL; + st_ivas->hHrtfFastConv = NULL; + st_ivas->hHrtfParambin = NULL; #endif st_ivas->hoa_dec_mtx = NULL; @@ -1716,6 +1755,27 @@ void ivas_destroy_dec( ivas_HRTF_binary_close( &st_ivas->hHrtfTD ); } +#ifdef HRTF_BINARY_FILE + /* CRend binaural renderer handle */ + if ( st_ivas->hSetOfHRTF != NULL ) + { + destroy_SetOfHRTF( st_ivas->hSetOfHRTF ); + ivas_HRTF_CRend_binary_close( &st_ivas->hSetOfHRTF ); + } + + /* Fastconv HRTF filters */ + if ( st_ivas->hHrtfFastConv != NULL ) + { + ivas_HRTF_fastconv_binary_close( &st_ivas->hHrtfFastConv ); + } + + /* Parametric binauralizer HRTF filters */ + if ( st_ivas->hHrtfParambin != NULL ) + { + ivas_HRTF_parambin_binary_close( &st_ivas->hHrtfParambin ); + } +#endif + /* Config. Renderer */ ivas_render_config_close( &( st_ivas->hRenderConfig ) ); @@ -1988,6 +2048,16 @@ static ivas_error doSanityChecks_IVAS( } #endif +#ifdef HRTF_BINARY_FILE +#ifdef DEBUGGING + if ( ( st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration: Time Domain object renderer not supported in this configuration" ); + } +#endif + +#else + #ifdef DEBUGGING if ( ( st_ivas->hDecoderConfig->Opt_HRTF_binary || st_ivas->hDecoderConfig->force_rend == FORCE_TD_RENDERER ) && ( ( st_ivas->ivas_format != MC_FORMAT && st_ivas->ivas_format != ISM_FORMAT ) || output_config != AUDIO_CONFIG_BINAURAL || ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) || ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode != MC_MODE_MCT ) ) ) #else @@ -1997,6 +2067,8 @@ static ivas_error doSanityChecks_IVAS( return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration: Time Domain object renderer not supported in this configuration" ); } +#endif + #ifdef DEBUGGING if ( ( st_ivas->hHrtfTD != NULL && st_ivas->hDecoderConfig->force_rend == FORCE_CLDFB_RENDERER ) ) { diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index e35708dcd6c6934b6bfd953abf9d2424693a4ab0..2b6d0b687665f9404f4b7498dd04cd2232b16dd0 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -1091,6 +1091,9 @@ static ivas_error ivas_ism_bitrate_switching( getRendAudioConfigFromIvasAudioConfig( st_ivas->hOutSetup.output_config ), st_ivas->hRenderConfig, st_ivas->hDecoderConfig->Opt_Headrotation, +#ifdef HRTF_BINARY_FILE + st_ivas->hSetOfHRTF, +#endif st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; @@ -1112,7 +1115,12 @@ static ivas_error ivas_ism_bitrate_switching( if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL ) { /* open the parametric binaural renderer */ +#ifdef HRTF_BINARY_FILE + ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ); + ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ); +#else ivas_dirac_dec_init_binaural_data( st_ivas ); +#endif /* Close the TD Binaural renderer */ if ( st_ivas->hBinRendererTd != NULL ) @@ -1138,7 +1146,12 @@ static ivas_error ivas_ism_bitrate_switching( if ( st_ivas->hOutSetup.output_config == AUDIO_CONFIG_BINAURAL_ROOM ) { /* open the parametric binaural renderer */ +#ifdef HRTF_BINARY_FILE + ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ); + ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ); +#else ivas_dirac_dec_init_binaural_data( st_ivas ); +#endif /* close the crend binaural renderer */ #ifdef FIX_197_CREND_INTERFACE diff --git a/lib_dec/ivas_mcmasa_dec.c b/lib_dec/ivas_mcmasa_dec.c index 175c1fe8c891466b413a2f527e5b61498d3a66f5..3af2ea2c3b3558ccd3e7b2f32b6dc4a41c5b300a 100644 --- a/lib_dec/ivas_mcmasa_dec.c +++ b/lib_dec/ivas_mcmasa_dec.c @@ -109,7 +109,19 @@ ivas_error ivas_mcmasa_dec_reconfig( if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { /* open parametric binaural renderer */ +#ifdef HRTF_BINARY_FILE + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -128,7 +140,11 @@ ivas_error ivas_mcmasa_dec_reconfig( { /* st_ivas->hDiracDecBin->useTdDecorr will change => close and re-open. */ ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 3836f7b7049b70ca1b2311d555a7e3131e99ef0b..7b2fa2982c17d4273880e98c431ee1ed843df4d0 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1063,7 +1063,11 @@ static ivas_error ivas_mc_dec_reconfig( /* useTdDecorr may change => close and re-open */ ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1080,7 +1084,19 @@ static ivas_error ivas_mc_dec_reconfig( } else if ( st_ivas->hDiracDecBin == NULL && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) { +#ifdef HRTF_BINARY_FILE + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1121,6 +1137,9 @@ static ivas_error ivas_mc_dec_reconfig( getRendAudioConfigFromIvasAudioConfig( st_ivas->intern_config ), getRendAudioConfigFromIvasAudioConfig( st_ivas->hDecoderConfig->output_config ), st_ivas->hRenderConfig, st_ivas->hDecoderConfig->Opt_Headrotation, +#ifdef HRTF_BINARY_FILE + st_ivas->hSetOfHRTF, +#endif st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index c8565cf042a8dc031c076e02db593e23cd025d8c..fbdc4f5857aa8476838224c607da1be53f5c43ae 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -444,10 +444,25 @@ ivas_error ivas_sba_dec_reinit( } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { +#ifdef HRTF_BINARY_FILE + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) { return error; } +#endif } else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { @@ -494,7 +509,10 @@ ivas_error ivas_sba_dec_reinit( getRendAudioConfigFromIvasAudioConfig( st_ivas->hDecoderConfig->output_config ), st_ivas->hRenderConfig, t_ivas->hDecoderConfig->Opt_Headrotation, - st_ivas->hDecoderConfig->output_Fs ) != IVAS_ERR_OK ) ) +#ifdef HRTF_BINARY_FILE + st_ivas->hSetOfHRTF, +#endif + st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) { return error; } @@ -802,11 +820,26 @@ ivas_error ivas_sba_dec_reconfigure( #endif if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - /* open parametric binaural renderer */ - if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) +#ifdef HRTF_BINARY_FILE + if ( st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { return error; } +#else + /* open parametric binaural renderer */ + if ( ( error = ivas_dirac_dec_init_binaural_data( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif } #ifdef SBA_BR_SWITCHING } diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 3c70b7f239b26abe8fba0ad956feef3ac649a27d..6d3a678795615e3ac952fdc6161949c0be03690a 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -1279,6 +1279,47 @@ typedef struct ivas_binaural_rendering_conv_module_struct } BINRENDERER_CONV_MODULE, *BINRENDERER_CONV_MODULE_HANDLE; /* Fastconv binaural data structure */ + +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_fastconv_struct +{ + float FASTCONV_HRIR_latency_s; + float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + + float FASTCONV_HOA3_latency_s; + float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + + float FASTCONV_BRIR_latency_s; + float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + + float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float fastconvReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; +} HRTFS_FASTCONV, *HRTFS_FASTCONV_HANDLE; + +#endif + +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_parambin_struct +{ + float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + + float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; + float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; +} HRTFS_PARAMBIN, *HRTFS_PARAMBIN_HANDLE; + +#endif + typedef struct ivas_binaural_rendering_struct { /* Common variables for all modules */ @@ -1753,6 +1794,37 @@ typedef struct ivas_crend_state_t } CREND_DATA, *CREND_HANDLE; +#ifdef HRTF_BINARY_FILE + +/* htrfs from binary files. */ + +typedef struct ivas_hrtfs_crend_structure +{ + HRTFS_DATA *hHRTF_hrir_combined; + HRTFS_DATA *hHRTF_hrir_hoa3; + HRTFS_DATA *hHRTF_brir_combined; + +} HRTFS_CREND, *HRTFS_CREND_HANDLE; + +typedef struct ivas_hrtfs_header_t +{ + int32_t rend_type; + int32_t input_cfg; + int32_t frequency; + uint32_t data_size; + +} ivas_hrtfs_header_t; + +typedef struct ivas_hrtfs_file_header_t +{ + char identifier[8]; + int32_t file_size; + int16_t nb_hrtf; + int32_t max_data_size; + +} ivas_hrtfs_file_header_t; + +#endif /*----------------------------------------------------------------------------------* * LFE decoder structure @@ -1903,6 +1975,11 @@ typedef struct Decoder_Struct CREND_HANDLE hCrend; /* Convolution mixer renderer structure */ HRTFS_HANDLE hHrtf; /* HRTFs handle */ #endif +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF; /* Set of HRTFs handle (CRend) */ + HRTFS_FASTCONV_HANDLE hHrtfFastConv; /* FASTCONV HRTF tables for binaural rendering */ + HRTFS_PARAMBIN_HANDLE hHrtfParambin; /* HRTF tables for parametric binauralizer */ +#endif LSSETUP_CUSTOM_HANDLE hLsSetupCustom; /* Custom LS configuration handle */ float *hoa_dec_mtx; /* Pointer to decoder matrix for SBA */ HEAD_TRACK_DATA_HANDLE hHeadTrackData; /* Head tracking data structure */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index ea82d577163ad2a46ffa6003d9066219b62ff4a6..c14d3318a6fb5a752088100550a4033b73ce099e 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -992,6 +992,73 @@ ivas_error IVAS_DEC_GetHrtfHandle( } +#ifdef HRTF_BINARY_FILE +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfCRendHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfCRendHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hSetOfHRTF == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hSetOfHRTF = hIvasDec->st_ivas->hSetOfHRTF; + + return IVAS_ERR_OK; +} +#endif + +#ifdef HRTF_BINARY_FILE +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfFastConvHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfFastConvHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfFastConv == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hHrtfFastConv = hIvasDec->st_ivas->hHrtfFastConv; + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetHrtfParamBinHandle( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetHrtfParamBinHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHrtfParambin == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + *hHrtfParambin = hIvasDec->st_ivas->hHrtfParambin; + + return IVAS_ERR_OK; +} +#endif + /*---------------------------------------------------------------------* * IVAS_DEC_GetRenderConfig( ) * diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 62ccd85da087a2f60eaf9f531cf2d61cd7c916c0..6761ebe6285e4cf2185f0820e536908e3d0d2559 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -284,6 +284,24 @@ ivas_error IVAS_DEC_GetHrtfHandle( IVAS_DEC_HRTF_HANDLE *hHrtfTD /* o : HRTF handle */ ); +#ifdef HRTF_BINARY_FILE +/*! r: error code */ +ivas_error IVAS_DEC_GetHrtfCRendHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_CREND_HANDLE *hSetOfHRTF /* o : Set of HRTF handle */ +); + +ivas_error IVAS_DEC_GetHrtfFastConvHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/oL IVAS decoder handle */ + IVAS_DEC_HRTF_FASTCONV_HANDLE *hHrtfFastConv /* o : FASTCONV HRTF handle */ +); + +ivas_error IVAS_DEC_GetHrtfParamBinHandle( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin /* o : Parametric binauralizer HRTF handle */ +); +#endif + /*! r: error code*/ ivas_error IVAS_DEC_GetRenderConfig( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ diff --git a/lib_rend/ivas_binauralRenderer.c b/lib_rend/ivas_binauralRenderer.c index ab85dc4a7044d81720e74f73da142defac9db575..d0eaa6407cbd7019f5c92a2486fb39fd7a2c7bfc 100644 --- a/lib_rend/ivas_binauralRenderer.c +++ b/lib_rend/ivas_binauralRenderer.c @@ -124,7 +124,12 @@ static ivas_error ivas_binRenderer_convModuleOpen( const int16_t renderer_type, const int16_t isLoudspeaker, const AUDIO_CONFIG input_config, - const RENDER_CONFIG_DATA *hRenderConfig ) + const RENDER_CONFIG_DATA *hRenderConfig +#ifdef HRTF_BINARY_FILE + , + const HRTFS_FASTCONV_HANDLE hHrtf +#endif +) { int16_t bandIdx, chIdx; BINRENDERER_CONV_MODULE_HANDLE hBinRenConvModule; @@ -311,10 +316,17 @@ static ivas_error ivas_binRenderer_convModuleOpen( if ( isLoudspeaker ) { +#ifdef HRTF_BINARY_FILE + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftBRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftBRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightBRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightBRIRImag[bandIdx][tmp]; +#else hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftBRIRReal[bandIdx][tmp]; hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftBRIRImag[bandIdx][tmp]; hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightBRIRReal[bandIdx][tmp]; hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightBRIRImag[bandIdx][tmp]; +#endif } #ifdef DEBUGGING else @@ -332,18 +344,32 @@ static ivas_error ivas_binRenderer_convModuleOpen( if ( isLoudspeaker ) { +#ifdef HRTF_BINARY_FILE + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftHRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftHRIRImag[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightHRIRReal[bandIdx][tmp]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightHRIRImag[bandIdx][tmp]; +#else hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftHRIRReal[bandIdx][tmp]; hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftHRIRImag[bandIdx][tmp]; hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightHRIRReal[bandIdx][tmp]; hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightHRIRImag[bandIdx][tmp]; +#endif } else { /* HOA3 filter coefficients */ +#ifdef HRTF_BINARY_FILE + hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = hHrtf->leftHRIRReal_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = hHrtf->leftHRIRImag_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = hHrtf->rightHRIRReal_HOA3[bandIdx][chIdx]; + hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = hHrtf->rightHRIRImag_HOA3[bandIdx][chIdx]; +#else hBinRenConvModule->filterTapsLeftReal[bandIdx][chIdx] = leftHRIRReal_HOA3[bandIdx][chIdx]; hBinRenConvModule->filterTapsLeftImag[bandIdx][chIdx] = leftHRIRImag_HOA3[bandIdx][chIdx]; hBinRenConvModule->filterTapsRightReal[bandIdx][chIdx] = rightHRIRReal_HOA3[bandIdx][chIdx]; hBinRenConvModule->filterTapsRightImag[bandIdx][chIdx] = rightHRIRImag_HOA3[bandIdx][chIdx]; +#endif } } } @@ -354,6 +380,70 @@ static ivas_error ivas_binRenderer_convModuleOpen( return IVAS_ERR_OK; } +#ifdef HRTF_BINARY_FILE +/*-------------------------------------------------------------------------* + * ivas_binaural_HRTF_open() + * + * + *-------------------------------------------------------------------------*/ + +static ivas_error ivas_binaural_hrtf_open( + HRTFS_FASTCONV_HANDLE *hHrtfFastConv /* i : fastconv HRTF handle */ +) +{ + int16_t i, j; + if ( hHrtfFastConv != NULL && *hHrtfFastConv != NULL ) + { + /* Tables already loaded from file */ + return IVAS_ERR_OK; + } + else + { + /* Initialise tables from ROM */ + HRTFS_FASTCONV *HrtfFastConv; + + if ( ( HrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for FastConv HRTF tables" ); + } + + HrtfFastConv->FASTCONV_HRIR_latency_s = FASTCONV_HRIR_latency_s; + HrtfFastConv->FASTCONV_HOA3_latency_s = FASTCONV_HOA3_latency_s; + HrtfFastConv->FASTCONV_BRIR_latency_s = FASTCONV_BRIR_latency_s; + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + mvr2r( leftHRIRReal[i][j], HrtfFastConv->leftHRIRReal[i][j], 7 ); + mvr2r( leftHRIRImag[i][j], HrtfFastConv->leftHRIRImag[i][j], 7 ); + mvr2r( rightHRIRReal[i][j], HrtfFastConv->rightHRIRReal[i][j], 7 ); + mvr2r( rightHRIRImag[i][j], HrtfFastConv->rightHRIRImag[i][j], 7 ); + + mvr2r( leftBRIRReal[i][j], HrtfFastConv->leftBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( leftBRIRImag[i][j], HrtfFastConv->leftBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( rightBRIRReal[i][j], HrtfFastConv->rightBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + mvr2r( rightBRIRImag[i][j], HrtfFastConv->rightBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + } + + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + mvr2r( leftHRIRReal_HOA3[i][j], HrtfFastConv->leftHRIRReal_HOA3[i][j], 7 ); + mvr2r( leftHRIRImag_HOA3[i][j], HrtfFastConv->leftHRIRImag_HOA3[i][j], 7 ); + mvr2r( rightHRIRReal_HOA3[i][j], HrtfFastConv->rightHRIRReal_HOA3[i][j], 7 ); + mvr2r( rightHRIRImag_HOA3[i][j], HrtfFastConv->rightHRIRImag_HOA3[i][j], 7 ); + } + } + + mvr2r( fastconvReverberationTimes, HrtfFastConv->fastconvReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + mvr2r( fastconvReverberationEneCorrections, HrtfFastConv->fastconvReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + + *hHrtfFastConv = HrtfFastConv; + } + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------------* * ivas_binaural_obtain_DMX() @@ -541,12 +631,26 @@ ivas_error ivas_binRenderer_open( hBinRenderer->render_lfe = 1; } +#ifdef HRTF_BINARY_FILE + /* Load HRTF tables */ + ivas_binaural_hrtf_open( &st_ivas->hHrtfFastConv ); +#endif + 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 */ +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, + st_ivas->renderer_type, + 1, + AUDIO_CONFIG_7_1_4, + st_ivas->hRenderConfig, + st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, AUDIO_CONFIG_7_1_4, st_ivas->hRenderConfig ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -562,12 +666,25 @@ ivas_error ivas_binRenderer_open( } hBinRenderer->hoa_dec_mtx = st_ivas->hoa_dec_mtx; +#ifdef HRTF_BINARY_FILE + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_BRIR_latency_s * 1000000000.f ); +#else st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_BRIR_latency_s * 1000000000.f ); +#endif } else { /* Allocate memories and buffers needed for convolutional module */ +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, + st_ivas->renderer_type, + st_ivas->hIntSetup.is_loudspeaker_setup, + st_ivas->hIntSetup.output_config, + st_ivas->hRenderConfig, + st_ivas->hHrtfFastConv ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hRenderConfig ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -592,11 +709,19 @@ ivas_error ivas_binRenderer_open( #else if ( hBinRenderer->ivas_format == MC_FORMAT ) { +#ifdef HRTF_BINARY_FILE + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HRIR_latency_s * 1000000000.f ); +#else st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_HRIR_latency_s * 1000000000.f ); +#endif } else { +#ifdef HRTF_BINARY_FILE + st_ivas->binaural_latency_ns = (int32_t) ( st_ivas->hHrtfFastConv->FASTCONV_HOA3_latency_s * 1000000000.f ); +#else st_ivas->binaural_latency_ns = (int32_t) ( FASTCONV_HOA3_latency_s * 1000000000.f ); +#endif } #endif } @@ -604,7 +729,19 @@ ivas_error ivas_binRenderer_open( /* Allocate memories needed for reverb module */ if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM && st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) { +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_binaural_reverb_open( &( hBinRenderer->hReverb ), + hBinRenderer->conv_band, + hBinRenderer->timeSlots, + &( st_ivas->hRenderConfig->roomAcoustics ), + st_ivas->hIntSetup.output_config, + st_ivas->hDecoderConfig->output_Fs, + RENDERER_BINAURAL_FASTCONV_ROOM, + st_ivas->hHrtfFastConv, + st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_binaural_reverb_open( &( hBinRenderer->hReverb ), hBinRenderer->conv_band, hBinRenderer->timeSlots, &( st_ivas->hRenderConfig->roomAcoustics ), st_ivas->hIntSetup.output_config, st_ivas->hDecoderConfig->output_Fs, RENDERER_BINAURAL_FASTCONV_ROOM ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_rend/ivas_binaural_reverb.c b/lib_rend/ivas_binaural_reverb.c index 3798d74878135df99690caeda57c93c8727caf40..3d4c9d6fe2626565c0a9e131c3fedac9496389ae 100644 --- a/lib_rend/ivas_binaural_reverb.c +++ b/lib_rend/ivas_binaural_reverb.c @@ -376,6 +376,11 @@ ivas_error ivas_binaural_reverb_open( const AUDIO_CONFIG output_config, /* i : output audio configuration */ const int32_t sampling_rate, /* i : sampling rate */ const RENDERER_TYPE renderer_type /* i : renderer type */ +#ifdef HRTF_BINARY_FILE + , + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, /* i : FastConv HRTF handle */ + const HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : Parametric binauralizer HRTF handle */ +#endif ) { int16_t bin, chIdx, k, len; @@ -408,7 +413,11 @@ ivas_error ivas_binaural_reverb_open( { if ( !roomAcoustics->override ) { +#ifdef HRTF_BINARY_FILE + revTimes = hHrtfFastConv->fastconvReverberationTimes; +#else revTimes = fastconvReverberationTimes; +#endif } else { @@ -417,7 +426,11 @@ ivas_error ivas_binaural_reverb_open( } else { +#ifdef HRTF_BINARY_FILE + revTimes = hHrtfParambin->parametricReverberationTimes; +#else revTimes = parametricReverberationTimes; +#endif } for ( bin = 0; bin < hReverb->numBins; bin++ ) @@ -486,19 +499,31 @@ ivas_error ivas_binaural_reverb_open( { if ( !roomAcoustics->override ) { +#ifdef HRTF_BINARY_FILE + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfFastConv->fastconvReverberationTimes, hHrtfFastConv->fastconvReverberationEneCorrections ); +#else ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, fastconvReverberationTimes, fastconvReverberationEneCorrections ); +#endif ivas_binaural_reverb_setPreDelay( hReverb, 10 ); } else { +#ifdef HRTF_BINARY_FILE + ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfFastConv, output_config, roomAcoustics->use_brir, sampling_rate, t60, ene ); +#else ivas_reverb_prepare_cldfb_params( roomAcoustics, output_config, roomAcoustics->use_brir, sampling_rate, t60, ene ); +#endif ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, t60, ene ); ivas_binaural_reverb_setPreDelay( hReverb, (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ) ); } } else { +#ifdef HRTF_BINARY_FILE + ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, hHrtfParambin->parametricReverberationTimes, hHrtfParambin->parametricReverberationEneCorrections ); +#else ivas_binaural_reverb_setReverbTimes( hReverb, sampling_rate, parametricReverberationTimes, parametricReverberationEneCorrections ); +#endif ivas_binaural_reverb_setPreDelay( hReverb, 10 ); } diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 3b5d8e0e89da8060ad4ca733f44d9871ce8c81b9..cf29f0c98852865f657bc0f51e2cfcab4eda0976 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -222,7 +222,8 @@ ivas_error ivas_crend_init_from_rom( if ( output_Fs == 48000 ) { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_48kHz; + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz; @@ -236,7 +237,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 32000 ) { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_32kHz; + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz; @@ -250,7 +252,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 16000 ) { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_16kHz; + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz; @@ -340,7 +343,8 @@ ivas_error ivas_crend_init_from_rom( { if ( output_Fs == 48000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_48kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; @@ -366,7 +370,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 32000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_32kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; @@ -393,7 +398,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 16000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_16kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; @@ -434,7 +440,8 @@ ivas_error ivas_crend_init_from_rom( if ( output_Fs == 48000 ) { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_48kHz; + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz; @@ -448,7 +455,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 32000 ) { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_32kHz; + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz; @@ -462,7 +470,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 16000 ) { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_16kHz; + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz; @@ -552,7 +561,8 @@ ivas_error ivas_crend_init_from_rom( { if ( output_Fs == 48000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_48kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; @@ -579,7 +589,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 32000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_32kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; @@ -606,7 +617,8 @@ ivas_error ivas_crend_init_from_rom( } else if ( output_Fs == 16000 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_16kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; @@ -656,6 +668,291 @@ ivas_error ivas_crend_init_from_rom( } #endif +#ifndef FIX_197_CREND_INTERFACE +#ifdef HRTF_BINARY_FILE +/*------------------------------------------------------------------------- + * ivas_crend_init_from_hrtf_handle() + * + * Allocate and initialize Crend HRTF handle from external file + *------------------------------------------------------------------------*/ + +ivas_error ivas_crend_init_from_hrtf_handle( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + HRTFS_HANDLE hrtf ) +{ + int16_t i, j, as_lfe_filter; + const int16_t *hchannelIndex = NULL; + AUDIO_CONFIG transport_config; + + if ( st_ivas == NULL ) + { + return IVAS_ERR_INTERNAL; + } + + if ( hrtf == NULL ) + { + return IVAS_ERR_INVALID_HRTF; + } + + if ( st_ivas->hHrtf != NULL ) + { + ivas_hrtf_close( &st_ivas->hHrtf ); + } + + if ( ivas_hrtf_open( &( st_ivas->hHrtf ) ) != IVAS_ERR_OK ) + { + return IVAS_ERR_INTERNAL; + } + + if ( st_ivas->hHrtf != NULL ) + { + st_ivas->hHrtf->latency_s = hrtf->latency_s; + // st_ivas->hHrtf->max_num_ir->max_ir_len = hrtf->max_ir_len; + st_ivas->hHrtf->max_num_iterations = hrtf->max_num_iterations; + st_ivas->hHrtf->gain_lfe = hrtf->gain_lfe; + // st_ivas->hHrtf->crend_hr_gain_foa_to_bin = hrtf->crend_hr_gain_foa_to_bin; + st_ivas->hHrtf->max_num_ir = 0; + st_ivas->hIntSetup.nchan_out_woLFE = 0; + st_ivas->hIntSetup.num_lfe = 0; + st_ivas->hIntSetup.nchan_out_woLFE = 0; + + transport_config = st_ivas->intern_config == AUDIO_CONFIG_INVALID ? st_ivas->transport_config : st_ivas->intern_config; + + switch ( transport_config ) + { + case AUDIO_CONFIG_5_1: + st_ivas->hHrtf->max_num_ir = 5; + st_ivas->hHrtf->gain_lfe = GAIN_LFE; + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->hHrtf->max_num_ir; + st_ivas->hIntSetup.num_lfe = 1; + hchannelIndex = (const int16_t *) &channelIndex_CICP6; + break; + case AUDIO_CONFIG_7_1: + st_ivas->hHrtf->max_num_ir = 7; + st_ivas->hHrtf->gain_lfe = GAIN_LFE; + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->hHrtf->max_num_ir; + st_ivas->hIntSetup.num_lfe = 1; + hchannelIndex = (const int16_t *) &channelIndex_CICP12; + break; + case AUDIO_CONFIG_5_1_2: + st_ivas->hHrtf->max_num_ir = 7; + st_ivas->hHrtf->gain_lfe = GAIN_LFE; + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->hHrtf->max_num_ir; + st_ivas->hIntSetup.num_lfe = 1; + hchannelIndex = (const int16_t *) &channelIndex_CICP14; + break; + case AUDIO_CONFIG_5_1_4: + st_ivas->hHrtf->max_num_ir = 9; + st_ivas->hHrtf->gain_lfe = GAIN_LFE; + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->hHrtf->max_num_ir; + st_ivas->hIntSetup.num_lfe = 1; + hchannelIndex = (const int16_t *) &channelIndex_CICP16; + break; + case AUDIO_CONFIG_7_1_4: + st_ivas->hHrtf->max_num_ir = 11; + st_ivas->hHrtf->gain_lfe = GAIN_LFE; + st_ivas->hIntSetup.nchan_out_woLFE = st_ivas->hHrtf->max_num_ir; + st_ivas->hIntSetup.num_lfe = 1; + hchannelIndex = (const int16_t *) &channelIndex_CICP19; + break; + case AUDIO_CONFIG_FOA: + st_ivas->hIntSetup.ambisonics_order = 1; + st_ivas->hHrtf->max_num_ir = 4; + break; + case AUDIO_CONFIG_HOA2: + st_ivas->hIntSetup.ambisonics_order = 2; + st_ivas->hHrtf->max_num_ir = 9; + break; + case AUDIO_CONFIG_HOA3: + st_ivas->hIntSetup.ambisonics_order = 3; + st_ivas->hHrtf->max_num_ir = 16; + break; + default: + break; + } + + as_lfe_filter = 0; + if ( ( st_ivas->hHrtf->max_num_ir != hrtf->max_num_ir ) && ( st_ivas->hHrtf->max_num_ir + 1 == hrtf->max_num_ir ) ) + { + as_lfe_filter = 1; + hchannelIndex = NULL; + } + + if ( st_ivas->hHrtf->max_num_ir == 0 ) + { + return IVAS_ERR_INTERNAL; + } + + for ( i = 0; i < st_ivas->hHrtf->max_num_ir; i++ ) + { + int16_t tmp = i; + if ( hchannelIndex != NULL ) + { + tmp = hchannelIndex[i]; + } + if ( as_lfe_filter ) + { + if ( tmp > 2 ) + { + tmp++; + } + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + st_ivas->hHrtf->pOut_to_bin_re[i][j] = hrtf->pOut_to_bin_re[tmp][j]; + st_ivas->hHrtf->pOut_to_bin_im[i][j] = hrtf->pOut_to_bin_im[tmp][j]; + st_ivas->hHrtf->num_iterations[i][j] = hrtf->num_iterations[tmp][j]; + st_ivas->hHrtf->pIndex_frequency_max[i][j] = hrtf->pIndex_frequency_max[tmp][j]; + } + st_ivas->hHrtf->inv_diffuse_weight[i] = hrtf->inv_diffuse_weight[tmp]; + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + st_ivas->hHrtf->pOut_to_bin_diffuse_re[j] = hrtf->pOut_to_bin_diffuse_re[j]; + st_ivas->hHrtf->pOut_to_bin_diffuse_im[j] = hrtf->pOut_to_bin_diffuse_im[j]; + st_ivas->hHrtf->num_iterations_diffuse[j] = hrtf->num_iterations_diffuse[j]; + st_ivas->hHrtf->pIndex_frequency_max_diffuse[j] = hrtf->pIndex_frequency_max_diffuse[j]; + } + st_ivas->hHrtf->index_frequency_max_diffuse = hrtf->index_frequency_max_diffuse; + } + return IVAS_ERR_OK; +} +#endif + +#ifdef HRTF_BINARY_FILE +/*------------------------------------------------------------------------- + * ivas_crend_init_from_setofhrtf() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_crend_init_from_setofhrtf( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + ivas_error error; + AUDIO_CONFIG transport_config; + + transport_config = st_ivas->intern_config == AUDIO_CONFIG_INVALID ? st_ivas->transport_config : st_ivas->intern_config; + switch ( transport_config ) + { + case AUDIO_CONFIG_5_1: + case AUDIO_CONFIG_5_1_2: + case AUDIO_CONFIG_5_1_4: + case AUDIO_CONFIG_7_1: + case AUDIO_CONFIG_7_1_4: + if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( ( error = ivas_crend_init_from_hrtf_handle( st_ivas, st_ivas->hSetOfHRTF->hHRTF_brir_combined ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_crend_init_from_hrtf_handle( st_ivas, st_ivas->hSetOfHRTF->hHRTF_hrir_combined ) ) != IVAS_ERR_OK ) + { + return error; + } + } + break; + case AUDIO_CONFIG_FOA: + case AUDIO_CONFIG_HOA2: + case AUDIO_CONFIG_HOA3: + if ( ( error = ivas_crend_init_from_hrtf_handle( st_ivas, st_ivas->hSetOfHRTF->hHRTF_hrir_hoa3 ) ) != IVAS_ERR_OK ) + { + return error; + } + break; + default: + return IVAS_ERR_INTERNAL; + } + + return IVAS_ERR_OK; +} + +#endif +#endif + +/*---------------------------------------------------------------------* + * destroy_HRTF() + * + * Destroy the HRTF CRend handle + *---------------------------------------------------------------------*/ + +static ivas_error destroy_HRTF( + HRTFS_HANDLE *hHRTF /* i/o: HRTF CRend handle */ +) +{ + uint16_t i, j; + + if ( *hHRTF != NULL && hHRTF != NULL ) + { + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( ( *hHRTF )->pIndex_frequency_max[i][j] != NULL ) + { + free( ( *hHRTF )->pIndex_frequency_max[i][j] ); + } + if ( ( *hHRTF )->pOut_to_bin_re[i][j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_re[i][j] ); + } + if ( ( *hHRTF )->pOut_to_bin_im[i][j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_im[i][j] ); + } + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( ( *hHRTF )->pIndex_frequency_max_diffuse[j] != NULL ) + { + free( ( *hHRTF )->pIndex_frequency_max_diffuse[j] ); + } + if ( ( *hHRTF )->pOut_to_bin_diffuse_re[j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_diffuse_re[j] ); + } + if ( ( *hHRTF )->pOut_to_bin_diffuse_im[j] != NULL ) + { + free( ( *hHRTF )->pOut_to_bin_diffuse_im[j] ); + } + } + + free( *hHRTF ); + *hHRTF = NULL; + } + + return IVAS_ERR_OK; +} + +#ifdef HRTF_BINARY_FILE +/*---------------------------------------------------------------------* + * destroy_SetOfHRTF() + * + * Destroy the HRTF data set. + *---------------------------------------------------------------------*/ + +ivas_error destroy_SetOfHRTF( + HRTFS_CREND_HANDLE hSetOfHRTF /* i/o: Set of HRTF CRend handle */ +) +{ + if ( hSetOfHRTF != NULL ) + { + destroy_HRTF( &( hSetOfHRTF->hHRTF_hrir_combined ) ); + destroy_HRTF( &( hSetOfHRTF->hHRTF_hrir_hoa3 ) ); + destroy_HRTF( &( hSetOfHRTF->hHRTF_brir_combined ) ); + } + + return IVAS_ERR_OK; +} + +#endif + #ifndef FIX_197_CREND_INTERFACE /*------------------------------------------------------------------------- * ivas_crend_open() @@ -678,10 +975,27 @@ ivas_error ivas_crend_open( if ( ( st_ivas->hHrtf == NULL ) && ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) { +#ifdef HRTF_BINARY_FILE + if ( st_ivas->hSetOfHRTF != NULL ) + { + if ( ( error = ivas_crend_init_from_setofhrtf( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_crend_init_from_rom( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#else if ( ( error = ivas_crend_init_from_rom( st_ivas ) ) != IVAS_ERR_OK ) { return error; } +#endif } if ( ( hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) @@ -1145,613 +1459,758 @@ ivas_error ivas_crend_process( } #endif + /*------------------------------------------------------------------------- - * ivas_rend_openCrend() + * initCrend_from_rom() * * Allocate and initialize crend renderer handle *------------------------------------------------------------------------*/ -ivas_error ivas_rend_openCrend( -#ifdef FIX_197_CREND_INTERFACE - CREND_WRAPPER_HANDLE *pCrend, -#else +ivas_error ivas_rend_initCrend( CREND_WRAPPER *pCrend, -#endif const IVAS_REND_AudioConfig inConfig, const IVAS_REND_AudioConfig outConfig, RENDER_CONFIG_DATA *hRendCfg, -#ifdef FIX_197_CREND_INTERFACE - int16_t Opt_Headrotation, +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, #endif const int32_t output_Fs ) { - /* TODO tmu : Based on ivas_crend_open() - could be harmonized / refactored */ - int16_t i, subframe_length; - int16_t max_total_ir_len; + int16_t i, j, tmp; + int16_t nchan_in; + bool use_brir; + IVAS_REND_AudioConfigType inConfigType; HRTFS_HANDLE hHrtf; - CREND_HANDLE hCrend; ivas_error error; - error = IVAS_ERR_OK; + inConfigType = getAudioConfigType( inConfig ); + hHrtf = pCrend->hHrtfCrend; -#ifdef FIX_197_CREND_INTERFACE - if ( pCrend == NULL ) + /* Do all error checks up front so that the nested if later is easier */ + if ( inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED && inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Encountered unsupported input config in Crend" ); } - - if ( *pCrend == NULL ) + if ( outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL && outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) { - if ( ( *pCrend = (CREND_WRAPPER_HANDLE) malloc( sizeof( CREND_WRAPPER ) ) ) == NULL ) + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Encountered unsupported output type in Crend" ); + } + if ( hHrtf == NULL ) + { + if ( ivas_hrtf_open( &hHrtf ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for HRTF handle" ); } - ( *pCrend )->binaural_latency_ns = 0; - ( *pCrend )->hCrend = NULL; - ( *pCrend )->hHrtfCrend = NULL; } -#endif - - subframe_length = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; + /* set BRIR flag */ + use_brir = false; #ifdef FIX_197_CREND_INTERFACE - if ( ( *pCrend )->hHrtfCrend == NULL ) + if ( ( ( hRendCfg != NULL ) && hRendCfg->roomAcoustics.use_brir ) || ( ( hRendCfg == NULL ) && ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) ) ) { - if ( ( error = ivas_rend_initCrend( *pCrend, inConfig, outConfig, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } + use_brir = true; } #else - if ( pCrend->hHrtfCrend == NULL ) + if ( ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir ) || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) { - if ( ( error = ivas_rend_initCrend( pCrend, inConfig, outConfig, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } + use_brir = true; } #endif - if ( ( hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer handle" ); - } - hCrend->lfe_delay_line = NULL; - - for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_in ) ) != IVAS_ERR_OK ) { - hCrend->freq_buffer_re[i] = NULL; - hCrend->freq_buffer_im[i] = NULL; + return error; } + hHrtf->max_num_ir = nchan_in; - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + if ( hHrtf->max_num_ir <= 0 ) { - hCrend->prev_out_buffer[i] = NULL; + return IVAS_ERR_INTERNAL_FATAL; } - hCrend->freq_buffer_re_diffuse = NULL; - hCrend->freq_buffer_im_diffuse = NULL; - hCrend->hReverb = NULL; - hCrend->delay_line_rw_index = 0; - hCrend->diffuse_delay_line_rw_index = 0; - hCrend->hTrack = NULL; - hCrend->m_fYaw = 0; - hCrend->m_fPitch = 0; - hCrend->m_fRoll = 0; - -#ifdef FIX_197_CREND_INTERFACE - hHrtf = ( *pCrend )->hHrtfCrend; -#else - hHrtf = pCrend->hHrtfCrend; -#endif - - if ( hHrtf != NULL ) +#ifdef HRTF_BINARY_FILE + if ( hSetOfHRTF == NULL ) { - max_total_ir_len = hHrtf->max_num_iterations * subframe_length; - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) +#endif + if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) { - if ( ( hCrend->freq_buffer_re[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - set_zero( hCrend->freq_buffer_re[i], max_total_ir_len ); + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; - if ( ( hCrend->freq_buffer_im[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + if ( output_Fs == 48000 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - set_zero( hCrend->freq_buffer_im[i], max_total_ir_len ); - } + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz; + } - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - if ( ( hCrend->prev_out_buffer[i] = (float *) malloc( sizeof( float ) * subframe_length ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[j]; + } + } } - set_zero( hCrend->prev_out_buffer[i], subframe_length ); - } - - max_total_ir_len = hHrtf->num_iterations_diffuse[0] * subframe_length; - - if ( max_total_ir_len > 0 ) - { - if ( ( hCrend->freq_buffer_re_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + else if ( output_Fs == 32000 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - set_zero( hCrend->freq_buffer_re_diffuse, max_total_ir_len ); + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz; + } - if ( ( hCrend->freq_buffer_im_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[j]; + } + } } - set_zero( hCrend->freq_buffer_im_diffuse, max_total_ir_len ); - } - else - { - hCrend->freq_buffer_re_diffuse = NULL; - hCrend->freq_buffer_im_diffuse = NULL; - } - - max_total_ir_len = (int16_t) ( hHrtf->latency_s * output_Fs + 0.5f ) + subframe_length; - if ( max_total_ir_len > 0 ) - { - if ( ( hCrend->lfe_delay_line = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + else if ( output_Fs == 16000 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + if ( use_brir ) + { + hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz; + } + else + { + hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz[j]; + } + else + { + hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[j]; + } + } } - set_zero( hCrend->lfe_delay_line, max_total_ir_len ); - } - else - { - hCrend->lfe_delay_line = NULL; - } -#ifdef FIX_197_CREND_INTERFACE - if ( Opt_Headrotation ) -#else - if ( false ) /* TODO tmu : check renderer headrotation flag */ -#endif - { - if ( ( hCrend->hTrack = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) + else { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); } - ivas_orient_trk_Init( hCrend->hTrack ); - } - else - { - hCrend->hTrack = NULL; - } - - if ( ( hRendCfg != NULL ) && ( hRendCfg->roomAcoustics.late_reverb_on ) ) - { - if ( ( error = ivas_reverb_open( &( hCrend->hReverb ), - getIvasAudioConfigFromRendAudioConfig( inConfig ), -#ifdef FIX_197_CREND_INTERFACE - ( *pCrend )->hHrtfCrend, -#else - pCrend->hHrtfCrend, -#endif - hRendCfg, - output_Fs ) ) != IVAS_ERR_OK ) + for ( i = 0; i < hHrtf->max_num_ir; i++ ) { - return error; - } - } - else - { - hCrend->hReverb = NULL; - } - -#ifdef FIX_197_CREND_INTERFACE - ( *pCrend )->binaural_latency_ns = (int32_t) ( ( *pCrend )->hHrtfCrend->latency_s * 1000000000.f ); -#else - pCrend->binaural_latency_ns = (int32_t) ( pCrend->hHrtfCrend->latency_s * 1000000000.f ); -#endif - } - -#ifdef FIX_197_CREND_INTERFACE - ( *pCrend )->hCrend = hCrend; -#else - pCrend->hCrend = hCrend; -#endif - return IVAS_ERR_OK; -} - -/*------------------------------------------------------------------------- - * initCrend_from_rom() - * - * Allocate and initialize crend renderer handle - *------------------------------------------------------------------------*/ - -ivas_error ivas_rend_initCrend( - CREND_WRAPPER *pCrend, - const IVAS_REND_AudioConfig inConfig, - const IVAS_REND_AudioConfig outConfig, - RENDER_CONFIG_DATA *hRendCfg, - const int32_t output_Fs ) -{ - int16_t i, j, tmp; - int16_t nchan_in, use_brir; - IVAS_REND_AudioConfigType inConfigType; - HRTFS_HANDLE hHrtf; - ivas_error error; - - inConfigType = getAudioConfigType( inConfig ); - hHrtf = pCrend->hHrtfCrend; - - /* Do all error checks up front so that the nested if later is easier */ - if ( inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED && inConfigType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) - { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Encountered unsupported input config in Crend" ); - } - if ( outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL && outConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Encountered unsupported output type in Crend" ); - } - if ( hHrtf == NULL ) - { - if ( ivas_hrtf_open( &hHrtf ) != IVAS_ERR_OK ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for HRTF handle" ); - } - } - - /* set BRIR flag */ - use_brir = FALSE; -#ifdef FIX_197_CREND_INTERFACE - if ( ( ( hRendCfg != NULL ) && hRendCfg->roomAcoustics.use_brir ) || ( ( hRendCfg == NULL ) && ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) ) ) - { - use_brir = true; - } -#else - if ( ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir ) || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM ) - { - use_brir = TRUE; - } -#endif - - - if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_in ) ) != IVAS_ERR_OK ) - { - return error; - } - hHrtf->max_num_ir = nchan_in; - - if ( hHrtf->max_num_ir <= 0 ) - { - return IVAS_ERR_INTERNAL_FATAL; - } - + if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 ) + { + tmp = channelIndex_CICP6[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) + { + tmp = channelIndex_CICP12[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 ) + { + tmp = channelIndex_CICP14[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + tmp = channelIndex_CICP16[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1_4 ) + { + tmp = channelIndex_CICP19[i]; + } + else + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); + } - if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) - { - hHrtf->max_num_ir -= 1; /* subtract LFE */ - hHrtf->gain_lfe = GAIN_LFE; + if ( output_Fs == 48000 ) + { + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_48kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_48kHz[tmp]; + } - if ( output_Fs == 48000 ) - { - if ( use_brir ) - { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz; - } - else - { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz; - } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_48kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_48kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_48kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_48kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_48kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_48kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_48kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_48kHz[tmp][j]; + } + } + } + else if ( output_Fs == 32000 ) + { + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_32kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_32kHz[tmp]; + } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - if ( use_brir ) + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_32kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_32kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_32kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_32kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_32kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_32kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_32kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_32kHz[tmp][j]; + } + } + } + else if ( output_Fs == 16000 ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[j]; + if ( use_brir ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_16kHz[tmp]; + } + else + { + hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_16kHz[tmp]; + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( use_brir ) + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_16kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_16kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_16kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_16kHz[tmp][j]; + } + else + { + hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_16kHz[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_16kHz[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_16kHz[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_16kHz[tmp][j]; + } + } } else { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[j]; + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); } } } - else if ( output_Fs == 32000 ) + else if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) { - if ( use_brir ) - { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz; - } - else + if ( output_Fs == 48000 ) { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz; - } + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - if ( use_brir ) + for ( i = 0; i < hHrtf->max_num_ir; i++ ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[j]; + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_48kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_48kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_48kHz[i][j]; + } } - else + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[j]; + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[j]; } } - } - else if ( output_Fs == 16000 ) - { - if ( use_brir ) + else if ( output_Fs == 32000 ) { - hHrtf->latency_s = CRendBin_Combined_BRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz; + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_32kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_32kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_32kHz[i][j]; + } + } + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[j]; + } } - else + else if ( output_Fs == 16000 ) { - hHrtf->latency_s = CRendBin_Combined_HRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz; - } + hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s; + hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; + hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - if ( use_brir ) + for ( i = 0; i < hHrtf->max_num_ir; i++ ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_BRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz[j]; + hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz[i]; + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_16kHz[i][j]; + hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz[i][j]; + hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_16kHz[i][j]; + hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_16kHz[i][j]; + } } - else + + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[j]; + hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[j]; } } + else + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + } } else { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); } - - for ( i = 0; i < hHrtf->max_num_ir; i++ ) +#ifdef HRTF_BINARY_FILE + } + else + { + if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) { - if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 ) - { - tmp = channelIndex_CICP6[i]; - } - else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) - { - tmp = channelIndex_CICP12[i]; - } - else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 ) - { - tmp = channelIndex_CICP14[i]; - } - else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) - { - tmp = channelIndex_CICP16[i]; - } - else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1_4 ) + hHrtf->max_num_ir -= 1; /* subtract LFE */ + hHrtf->gain_lfe = GAIN_LFE; + + if ( use_brir ) { - tmp = channelIndex_CICP19[i]; + hHrtf->latency_s = hSetOfHRTF->hHRTF_brir_combined->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_brir_combined->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_brir_combined->index_frequency_max_diffuse; } else { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); + hHrtf->latency_s = hSetOfHRTF->hHRTF_hrir_combined->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_hrir_combined->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_hrir_combined->index_frequency_max_diffuse; } - if ( output_Fs == 48000 ) + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { if ( use_brir ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_48kHz[tmp]; + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_brir_combined->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_brir_combined->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_diffuse_im[j]; } else { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_48kHz[tmp]; + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_hrir_combined->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_hrir_combined->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_diffuse_im[j]; } + } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1 ) { - if ( use_brir ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_48kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_48kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_48kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_48kHz[tmp][j]; - } - else - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_48kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_48kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_48kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_48kHz[tmp][j]; - } + tmp = channelIndex_CICP6[i]; } - } - else if ( output_Fs == 32000 ) - { - if ( use_brir ) + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1 ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_32kHz[tmp]; + tmp = channelIndex_CICP12[i]; } - else + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_2 ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_32kHz[tmp]; + tmp = channelIndex_CICP14[i]; } - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_5_1_4 ) + { + tmp = channelIndex_CICP16[i]; + } + else if ( inConfig == IVAS_REND_AUDIO_CONFIG_7_1_4 ) + { + tmp = channelIndex_CICP19[i]; + } + else { - if ( use_brir ) - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_32kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_32kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_32kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_32kHz[tmp][j]; - } - else - { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_32kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_32kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_32kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_32kHz[tmp][j]; - } + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Channel configuration not specified!\n\n" ); } - } - else if ( output_Fs == 16000 ) - { + if ( use_brir ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_BRIR_inv_diffuse_weight_16kHz[tmp]; + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_brir_combined->inv_diffuse_weight[tmp]; } else { - hHrtf->inv_diffuse_weight[i] = CRendBin_Combined_HRIR_inv_diffuse_weight_16kHz[tmp]; + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_hrir_combined->inv_diffuse_weight[tmp]; } for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { if ( use_brir ) { - hHrtf->num_iterations[i][j] = CRendBin_Combined_BRIR_num_iterations_16kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_BRIR_pIndex_frequency_max_16kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_BRIR_coeff_re_16kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_BRIR_coeff_im_16kHz[tmp][j]; + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_brir_combined->num_iterations[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_brir_combined->pIndex_frequency_max[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_re[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_brir_combined->pOut_to_bin_im[tmp][j]; } else { - hHrtf->num_iterations[i][j] = CRendBin_Combined_HRIR_num_iterations_16kHz[tmp][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_Combined_HRIR_pIndex_frequency_max_16kHz[tmp][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_Combined_HRIR_coeff_re_16kHz[tmp][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_Combined_HRIR_coeff_im_16kHz[tmp][j]; + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_hrir_combined->num_iterations[tmp][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pIndex_frequency_max[tmp][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_re[tmp][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_hrir_combined->pOut_to_bin_im[tmp][j]; } } } - else - { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); - } } - } - else if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) - { - if ( output_Fs == 48000 ) + else if ( inConfigType == IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_48kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz; + hHrtf->latency_s = hSetOfHRTF->hHRTF_hrir_hoa3->latency_s; + hHrtf->max_num_iterations = hSetOfHRTF->hHRTF_hrir_hoa3->max_num_iterations; + hHrtf->index_frequency_max_diffuse = hSetOfHRTF->hHRTF_hrir_hoa3->index_frequency_max_diffuse; for ( i = 0; i < hHrtf->max_num_ir; i++ ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz[i]; + hHrtf->inv_diffuse_weight[i] = hSetOfHRTF->hHRTF_hrir_hoa3->inv_diffuse_weight[i]; for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_48kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_48kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_48kHz[i][j]; + hHrtf->num_iterations[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->num_iterations[i][j]; + hHrtf->pIndex_frequency_max[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pIndex_frequency_max[i][j]; + hHrtf->pOut_to_bin_re[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_re[i][j]; + hHrtf->pOut_to_bin_im[i][j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_im[i][j]; } } for ( j = 0; j < BINAURAL_CHANNELS; j++ ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[j]; + hHrtf->num_iterations_diffuse[j] = hSetOfHRTF->hHRTF_hrir_hoa3->num_iterations_diffuse[j]; + hHrtf->pIndex_frequency_max_diffuse[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pIndex_frequency_max_diffuse[j]; + hHrtf->pOut_to_bin_diffuse_re[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_diffuse_re[j]; + hHrtf->pOut_to_bin_diffuse_im[j] = hSetOfHRTF->hHRTF_hrir_hoa3->pOut_to_bin_diffuse_im[j]; } } - else if ( output_Fs == 32000 ) + else { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_32kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz; + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); + } + } +#endif - for ( i = 0; i < hHrtf->max_num_ir; i++ ) + pCrend->hHrtfCrend = hHrtf; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * ivas_rend_openCrend() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_rend_openCrend( +#ifdef FIX_197_CREND_INTERFACE + CREND_WRAPPER_HANDLE *pCrend, +#else + CREND_WRAPPER *pCrend, +#endif + const IVAS_REND_AudioConfig inConfig, + const IVAS_REND_AudioConfig outConfig, + RENDER_CONFIG_DATA *hRendCfg, +#ifdef FIX_197_CREND_INTERFACE + int16_t Opt_Headrotation, +#endif +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, +#endif + const int32_t output_Fs ) +{ + /* TODO tmu : Based on ivas_crend_open() - could be harmonized / refactored */ + int16_t i, subframe_length; + int16_t max_total_ir_len; + HRTFS_HANDLE hHrtf; + CREND_HANDLE hCrend; + ivas_error error; + + error = IVAS_ERR_OK; + +#ifdef FIX_197_CREND_INTERFACE + if ( pCrend == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + } + + if ( *pCrend == NULL ) + { + if ( ( *pCrend = (CREND_WRAPPER_HANDLE) malloc( sizeof( CREND_WRAPPER ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); + } + ( *pCrend )->binaural_latency_ns = 0; + ( *pCrend )->hCrend = NULL; + ( *pCrend )->hHrtfCrend = NULL; + } +#endif + + subframe_length = (int16_t) ( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES; + +#ifdef FIX_197_CREND_INTERFACE + if ( ( *pCrend )->hHrtfCrend == NULL ) + { +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_rend_initCrend( *pCrend, inConfig, outConfig, hRendCfg, hSetOfHRTF, output_Fs ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_rend_initCrend( *pCrend, inConfig, outConfig, hRendCfg, output_Fs ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } +#else + if ( pCrend->hHrtfCrend == NULL ) + { + if ( ( error = ivas_rend_initCrend( pCrend, inConfig, outConfig, hRendCfg, +#ifdef HRTF_BINARY_FILE + hSetOfHRTF, +#endif + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif + + if ( ( hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for renderer handle" ); + } + + hCrend->lfe_delay_line = NULL; + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + hCrend->freq_buffer_re[i] = NULL; + hCrend->freq_buffer_im[i] = NULL; + } + + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + hCrend->prev_out_buffer[i] = NULL; + } + + hCrend->freq_buffer_re_diffuse = NULL; + hCrend->freq_buffer_im_diffuse = NULL; + hCrend->hReverb = NULL; + hCrend->delay_line_rw_index = 0; + hCrend->diffuse_delay_line_rw_index = 0; + hCrend->hTrack = NULL; + hCrend->m_fYaw = 0; + hCrend->m_fPitch = 0; + hCrend->m_fRoll = 0; + +#ifdef FIX_197_CREND_INTERFACE + hHrtf = ( *pCrend )->hHrtfCrend; +#else + hHrtf = pCrend->hHrtfCrend; +#endif + + if ( hHrtf != NULL ) + { + max_total_ir_len = hHrtf->max_num_iterations * subframe_length; + + for ( i = 0; i < hHrtf->max_num_ir; i++ ) + { + if ( ( hCrend->freq_buffer_re[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz[i]; + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_re[i], max_total_ir_len ); - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_32kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_32kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_32kHz[i][j]; - } + if ( ( hCrend->freq_buffer_im[i] = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); } + set_zero( hCrend->freq_buffer_im[i], max_total_ir_len ); + } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + if ( ( hCrend->prev_out_buffer[i] = (float *) malloc( sizeof( float ) * subframe_length ) ) == NULL ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[j]; + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); } + set_zero( hCrend->prev_out_buffer[i], subframe_length ); } - else if ( output_Fs == 16000 ) + + max_total_ir_len = hHrtf->num_iterations_diffuse[0] * subframe_length; + + if ( max_total_ir_len > 0 ) { - hHrtf->latency_s = CRendBin_HOA3_HRIR_latency_s_16kHz; - hHrtf->max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; - hHrtf->index_frequency_max_diffuse = CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz; + if ( ( hCrend->freq_buffer_re_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_re_diffuse, max_total_ir_len ); - for ( i = 0; i < hHrtf->max_num_ir; i++ ) + if ( ( hCrend->freq_buffer_im_diffuse = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) { - hHrtf->inv_diffuse_weight[i] = CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz[i]; + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->freq_buffer_im_diffuse, max_total_ir_len ); + } + else + { + hCrend->freq_buffer_re_diffuse = NULL; + hCrend->freq_buffer_im_diffuse = NULL; + } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - hHrtf->num_iterations[i][j] = CRendBin_HOA3_HRIR_num_iterations_16kHz[i][j]; - hHrtf->pIndex_frequency_max[i][j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz[i][j]; - hHrtf->pOut_to_bin_re[i][j] = CRendBin_HOA3_HRIR_coeff_re_16kHz[i][j]; - hHrtf->pOut_to_bin_im[i][j] = CRendBin_HOA3_HRIR_coeff_im_16kHz[i][j]; - } + max_total_ir_len = (int16_t) ( hHrtf->latency_s * output_Fs + 0.5f ) + subframe_length; + if ( max_total_ir_len > 0 ) + { + if ( ( hCrend->lfe_delay_line = (float *) malloc( sizeof( float ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero( hCrend->lfe_delay_line, max_total_ir_len ); + } + else + { + hCrend->lfe_delay_line = NULL; + } +#ifdef FIX_197_CREND_INTERFACE + if ( Opt_Headrotation ) +#else + if ( false ) /* TODO tmu : check renderer headrotation flag */ +#endif + { + if ( ( hCrend->hTrack = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); } - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + ivas_orient_trk_Init( hCrend->hTrack ); + } + else + { + hCrend->hTrack = NULL; + } + + if ( ( hRendCfg != NULL ) && ( hRendCfg->roomAcoustics.late_reverb_on ) ) + { + if ( ( error = ivas_reverb_open( &( hCrend->hReverb ), + getIvasAudioConfigFromRendAudioConfig( inConfig ), +#ifdef FIX_197_CREND_INTERFACE + ( *pCrend )->hHrtfCrend, +#else + pCrend->hHrtfCrend, +#endif + hRendCfg, + output_Fs ) ) != IVAS_ERR_OK ) { - hHrtf->num_iterations_diffuse[j] = CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[j]; - hHrtf->pIndex_frequency_max_diffuse[j] = CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_re[j] = CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[j]; - hHrtf->pOut_to_bin_diffuse_im[j] = CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[j]; + return error; } } else { - return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Encountered Unsupported sampling rate in Crend" ); + hCrend->hReverb = NULL; } - } - else - { - return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported renderer type in Crend" ); +#ifdef FIX_197_CREND_INTERFACE + ( *pCrend )->binaural_latency_ns = (int32_t) ( ( *pCrend )->hHrtfCrend->latency_s * 1000000000.f ); +#else + pCrend->binaural_latency_ns = (int32_t) ( pCrend->hHrtfCrend->latency_s * 1000000000.f ); +#endif } - pCrend->hHrtfCrend = hHrtf; - +#ifdef FIX_197_CREND_INTERFACE + ( *pCrend )->hCrend = hCrend; +#else + pCrend->hCrend = hCrend; +#endif return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_hrtf.c b/lib_rend/ivas_hrtf.c index adb17f9b0c560d6c8cdf8566b03a7c077773ee4f..ba5f02da636d5bdd583db631b781f0e3eb1211de 100644 --- a/lib_rend/ivas_hrtf.c +++ b/lib_rend/ivas_hrtf.c @@ -258,3 +258,131 @@ void ivas_HRTF_binary_close( return; } + + +#ifdef HRTF_BINARY_FILE +/*-----------------------------------------------------------------------* + * ivas_HRTF_CRend_binary_open() + * + * Allocate HRTF binary handle + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_CRend_binary_open( + 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_brir_combined = NULL; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ivas_HRTF_CRend_binary_close() + * + * Close HRTF CRend binary handle + *-------------------------------------------------------------------*/ + +void ivas_HRTF_CRend_binary_close( + HRTFS_CREND **hSetOfHRTF ) +{ + if ( hSetOfHRTF == NULL || *hSetOfHRTF == NULL ) + { + return; + } + + destroy_SetOfHRTF( *hSetOfHRTF ); + + free( *hSetOfHRTF ); + *hSetOfHRTF = NULL; + + return; +} +#endif + +#ifdef HRTF_BINARY_FILE +/*-----------------------------------------------------------------------* + * ivas_HRTF_fastconv_binary_open() + * + * Allocate HRTF binary handle for FASTCONV renderer + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_fastconv_binary_open( + HRTFS_FASTCONV **hHrtfFastConv ) +{ + *hHrtfFastConv = (HRTFS_FASTCONV *) malloc( sizeof( HRTFS_FASTCONV ) ); + if ( *hHrtfFastConv == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FASTCONV HRTF tables!" ); + } + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------* + * ivas_HRTF_fastconv_binary_close() + * + * Close HRTF binary handle for FASTCONV renderer + *-----------------------------------------------------------------------*/ + +void ivas_HRTF_fastconv_binary_close( + HRTFS_FASTCONV **hHrtfFastConv ) +{ + if ( hHrtfFastConv == NULL || *hHrtfFastConv == NULL ) + { + return; + } + + free( *hHrtfFastConv ); + *hHrtfFastConv = NULL; + + return; +} +#endif + +#ifdef HRTF_BINARY_FILE +/*-----------------------------------------------------------------------* + * ivas_HRTF_parambin_binary_open() + * + * Allocate HRTF binary handle for parametric binauralizer + *-----------------------------------------------------------------------*/ + +ivas_error ivas_HRTF_parambin_binary_open( + 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; +} + +/*-----------------------------------------------------------------------* + * ivas_HRTF_parambin_binary_close() + * + * Close HRTF binary handle for parametric binauralizer + *-----------------------------------------------------------------------*/ + +void ivas_HRTF_parambin_binary_close( + HRTFS_PARAMBIN **hHrtfParambin ) +{ + if ( hHrtfParambin == NULL || *hHrtfParambin == NULL ) + { + return; + } + + free( *hHrtfParambin ); + *hHrtfParambin = NULL; + + return; +} +#endif diff --git a/lib_rend/ivas_lib_rend_internal.h b/lib_rend/ivas_lib_rend_internal.h index 50944fbcb218cd700b699725abee122edbc2ff44..4d36ecf7f021f085004d6770938ddeed16f1f793 100644 --- a/lib_rend/ivas_lib_rend_internal.h +++ b/lib_rend/ivas_lib_rend_internal.h @@ -78,6 +78,9 @@ ivas_error ivas_rend_openCrend( const IVAS_REND_AudioConfig inConfig, const IVAS_REND_AudioConfig outConfig, RENDER_CONFIG_DATA *hRendCfg, +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, +#endif const int32_t output_Fs ); ivas_error ivas_rend_initCrend( @@ -85,6 +88,9 @@ ivas_error ivas_rend_initCrend( const IVAS_REND_AudioConfig inConfig, const IVAS_REND_AudioConfig outConfig, RENDER_CONFIG_DATA *hRendCfg, +#ifdef HRTF_BINARY_FILE + HRTFS_CREND_HANDLE hSetOfHRTF, +#endif const int32_t output_Fs ); ivas_error ivas_rend_closeCrend( diff --git a/lib_rend/ivas_reverb_utils.c b/lib_rend/ivas_reverb_utils.c index 6defca610ff175237ed13373eb6da227f62829cd..9b19713dcebc7e9cb95cc30b0e6750b39647a165 100644 --- a/lib_rend/ivas_reverb_utils.c +++ b/lib_rend/ivas_reverb_utils.c @@ -69,7 +69,11 @@ typedef struct cldfb_convolver_state float filter_states_im[BINAURAL_CONVBANDS][CLDFB_CONVOLVER_NTAPS_MAX]; } cldfb_convolver_state; +#ifdef HRTF_BINARY_FILE +static void ivas_reverb_get_fastconv_hrtf_set_energies( const HRTFS_FASTCONV_HANDLE hHrtfFastConv, const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right ); +#else static void ivas_reverb_get_fastconv_hrtf_set_energies( const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t sampling_rate, float *avg_pwr_left, float *avg_pwr_right ); +#endif /*-----------------------------------------------------------------------------------------* @@ -80,6 +84,9 @@ static void ivas_reverb_get_fastconv_hrtf_set_energies( const AUDIO_CONFIG input void ivas_reverb_prepare_cldfb_params( ivas_roomAcoustics_t *pInput_params, +#ifdef HRTF_BINARY_FILE + HRTFS_FASTCONV_HANDLE hHrtfFastConv, +#endif const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t output_Fs, @@ -114,7 +121,11 @@ void ivas_reverb_prepare_cldfb_params( pOutput_ene[idx] *= expf( exp_argument ); } +#ifdef HRTF_BINARY_FILE + ivas_reverb_get_fastconv_hrtf_set_energies( hHrtfFastConv, input_audio_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ); +#else ivas_reverb_get_fastconv_hrtf_set_energies( input_audio_config, use_brir, output_Fs, avg_pwr_left, avg_pwr_right ); +#endif for ( idx = 0; idx < CLDFB_NO_CHANNELS_MAX; idx++ ) { @@ -198,6 +209,9 @@ static void ivas_cldfb_convolver( *-----------------------------------------------------------------------------------------*/ static void get_IR_from_filter_taps( +#ifdef HRTF_BINARY_FILE + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, +#endif const int16_t hrtf_idx, const AUDIO_CONFIG input_audio_config, const int16_t use_brir, @@ -228,10 +242,17 @@ static void get_IR_from_filter_taps( { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { +#ifdef HRTF_BINARY_FILE + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftHRIRReal_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftHRIRImag_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightHRIRReal_HOA3[band_idx][hrtf_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightHRIRImag_HOA3[band_idx][hrtf_idx]; +#else convolver_state.filter_taps_left_re[band_idx] = leftHRIRReal_HOA3[band_idx][hrtf_idx]; convolver_state.filter_taps_left_im[band_idx] = leftHRIRImag_HOA3[band_idx][hrtf_idx]; convolver_state.filter_taps_right_re[band_idx] = rightHRIRReal_HOA3[band_idx][hrtf_idx]; convolver_state.filter_taps_right_im[band_idx] = rightHRIRImag_HOA3[band_idx][hrtf_idx]; +#endif } } else @@ -262,20 +283,34 @@ static void get_IR_from_filter_taps( { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { +#ifdef HRTF_BINARY_FILE + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftBRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftBRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightBRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightBRIRImag[band_idx][array_idx]; +#else convolver_state.filter_taps_left_re[band_idx] = leftBRIRReal[band_idx][array_idx]; convolver_state.filter_taps_left_im[band_idx] = leftBRIRImag[band_idx][array_idx]; convolver_state.filter_taps_right_re[band_idx] = rightBRIRReal[band_idx][array_idx]; convolver_state.filter_taps_right_im[band_idx] = rightBRIRImag[band_idx][array_idx]; +#endif } } else { for ( band_idx = 0; band_idx < BINAURAL_CONVBANDS; band_idx++ ) { +#ifdef HRTF_BINARY_FILE + convolver_state.filter_taps_left_re[band_idx] = hHrtfFastConv->leftHRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_left_im[band_idx] = hHrtfFastConv->leftHRIRImag[band_idx][array_idx]; + convolver_state.filter_taps_right_re[band_idx] = hHrtfFastConv->rightHRIRReal[band_idx][array_idx]; + convolver_state.filter_taps_right_im[band_idx] = hHrtfFastConv->rightHRIRImag[band_idx][array_idx]; +#else convolver_state.filter_taps_left_re[band_idx] = leftHRIRReal[band_idx][array_idx]; convolver_state.filter_taps_left_im[band_idx] = leftHRIRImag[band_idx][array_idx]; convolver_state.filter_taps_right_re[band_idx] = rightHRIRReal[band_idx][array_idx]; convolver_state.filter_taps_right_im[band_idx] = rightHRIRImag[band_idx][array_idx]; +#endif } } } @@ -351,6 +386,9 @@ static void get_IR_from_filter_taps( static void ivas_reverb_get_cldfb_hrtf_set_properties( AUDIO_CONFIG input_audio_config, +#ifdef HRTF_BINARY_FILE + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, +#endif const int16_t use_brir, const int32_t sampling_rate, float *avg_pwr_left, @@ -394,7 +432,11 @@ static void ivas_reverb_get_cldfb_hrtf_set_properties( Loop over all the HRTFs available */ for ( hrtf_idx = 0; hrtf_idx < hrtf_count; hrtf_idx++ ) { +#ifdef HRTF_BINARY_FILE + get_IR_from_filter_taps( hHrtfFastConv, hrtf_idx, input_audio_config, use_brir, sampling_rate, IR_length, current_HRTF_data_L, current_HRTF_data_R ); +#else get_IR_from_filter_taps( hrtf_idx, input_audio_config, use_brir, sampling_rate, IR_length, current_HRTF_data_L, current_HRTF_data_R ); +#endif /* Perform forward FFT on both L/R channels */ fft_rel( current_HRTF_data_L, (int16_t) fft_size, (int16_t) log2_fft_size ); @@ -443,6 +485,9 @@ static void ivas_reverb_get_cldfb_hrtf_set_properties( *-----------------------------------------------------------------------------------------*/ static void ivas_reverb_get_fastconv_hrtf_set_energies( +#ifdef HRTF_BINARY_FILE + const HRTFS_FASTCONV_HANDLE hHrtfFastConv, +#endif const AUDIO_CONFIG input_audio_config, const int16_t use_brir, const int32_t sampling_rate, @@ -466,7 +511,11 @@ static void ivas_reverb_get_fastconv_hrtf_set_energies( output_fc[freq_idx] = (float) ( ( 2 * freq_idx + 1 ) * cldfb_freq_halfstep ); } +#ifdef HRTF_BINARY_FILE + ivas_reverb_get_cldfb_hrtf_set_properties( input_audio_config, hHrtfFastConv, use_brir, sampling_rate, avg_pwr_left_fft, avg_pwr_right_fft ); +#else ivas_reverb_get_cldfb_hrtf_set_properties( input_audio_config, use_brir, sampling_rate, avg_pwr_left_fft, avg_pwr_right_fft ); +#endif ivas_reverb_interpolate_acoustic_data( FFT_SPECTRUM_SIZE, input_fc, avg_pwr_left_fft, avg_pwr_right_fft, CLDFB_NO_CHANNELS_MAX, output_fc, avg_pwr_left, avg_pwr_right ); diff --git a/lib_rend/ivas_rom_binauralRenderer.c b/lib_rend/ivas_rom_binauralRenderer.c index c4305d138bd6af5c6c8b40311edd7b541b89bd8a..9d6bbd543eb7dbca0534ce84263bd49a9649298a 100644 --- a/lib_rend/ivas_rom_binauralRenderer.c +++ b/lib_rend/ivas_rom_binauralRenderer.c @@ -52,7 +52,11 @@ * Generated with Matlab version 9.3.0.713579 (R2017b) by MUXE6256 */ const float FASTCONV_HOA3_latency_s = 0.001979167f; +#ifdef HRTF_BINARY_FILE +const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= +#else const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= +#endif { { {-0.004181f, +0.093228f, +0.655506f, +0.048565f, -0.005834f, -0.005472f, -0.000066f}, @@ -956,7 +960,11 @@ const float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= } }; +#ifdef HRTF_BINARY_FILE +const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= +#else const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= +#endif { { {-0.007849f, -0.189662f, +0.310868f, +0.002657f, -0.000617f, -0.002064f, +0.000079f}, @@ -1860,7 +1868,11 @@ const float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= } }; +#ifdef HRTF_BINARY_FILE +const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= +#else const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= +#endif { { {-0.004181f, +0.093228f, +0.655506f, +0.048565f, -0.005834f, -0.005472f, -0.000066f}, @@ -2764,7 +2776,11 @@ const float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]= } }; +#ifdef HRTF_BINARY_FILE +const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]= +#else const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= +#endif { { {-0.007849f, -0.189662f, +0.310868f, +0.002657f, -0.000617f, -0.002064f, +0.000079f}, @@ -3669,7 +3685,11 @@ const float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]= }; const float FASTCONV_HRIR_latency_s = 0.000666667f; +#ifdef HRTF_BINARY_FILE +const float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= +#else const float leftHRIRReal[BINAURAL_CONVBANDS][15][7]= +#endif { { {+0.331798f, +0.500334f, +0.042057f, -0.000623f, -0.000260f}, @@ -4523,7 +4543,11 @@ const float leftHRIRReal[BINAURAL_CONVBANDS][15][7]= } }; +#ifdef HRTF_BINARY_FILE +const float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= +#else const float leftHRIRImag[BINAURAL_CONVBANDS][15][7]= +#endif { { {-0.346479f, +0.553523f, -0.074098f, +0.001288f, +0.000309f}, @@ -5377,7 +5401,11 @@ const float leftHRIRImag[BINAURAL_CONVBANDS][15][7]= } }; +#ifdef HRTF_BINARY_FILE +const float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= +#else const float rightHRIRReal[BINAURAL_CONVBANDS][15][7]= +#endif { { {+0.065097f, +0.755993f, -0.042308f, -0.016140f, -0.000353f}, @@ -6231,7 +6259,11 @@ const float rightHRIRReal[BINAURAL_CONVBANDS][15][7]= } }; +#ifdef HRTF_BINARY_FILE +const float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]= +#else const float rightHRIRImag[BINAURAL_CONVBANDS][15][7]= +#endif { { {-0.179291f, +0.196331f, +0.055128f, -0.017382f, +0.000411f}, @@ -7617,7 +7649,11 @@ const float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]= /* Binaural rendering data set based on BRIRs */ /* Tables derived from Mozart IIS BRIRs.*/ const float FASTCONV_BRIR_latency_s = 0.000937500f; +#ifdef HRTF_BINARY_FILE +const float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= +#else const float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +#endif { { { @@ -16721,7 +16757,11 @@ const float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; +#ifdef HRTF_BINARY_FILE +const float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= +#else const float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +#endif { { { @@ -25825,7 +25865,11 @@ const float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; +#ifdef HRTF_BINARY_FILE +const float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= +#else const float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +#endif { { { @@ -34929,7 +34973,11 @@ const float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= } }; +#ifdef HRTF_BINARY_FILE +const float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]= +#else const float rightBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]= +#endif { { { diff --git a/lib_rend/ivas_rom_binauralRenderer.h b/lib_rend/ivas_rom_binauralRenderer.h index b36e0f1832dfc2b80fe888e698df25800b860b04..f97883f9c37f1163fc03c79c13a9d170013709e9 100644 --- a/lib_rend/ivas_rom_binauralRenderer.h +++ b/lib_rend/ivas_rom_binauralRenderer.h @@ -44,15 +44,29 @@ /* Binaural rendering data set based on HRIRs */ extern const float FASTCONV_HRIR_latency_s; +#ifdef HRTF_BINARY_FILE +extern float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][BINAURAL_NTAPS]; +#else extern float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]; extern float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]; extern float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][16][7]; extern float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][16][7]; +#endif +#ifdef HRTF_BINARY_FILE +extern float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +extern float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]; +#else extern float leftHRIRReal[BINAURAL_CONVBANDS][15][7]; extern float leftHRIRImag[BINAURAL_CONVBANDS][15][7]; extern float rightHRIRReal[BINAURAL_CONVBANDS][15][7]; extern float rightHRIRImag[BINAURAL_CONVBANDS][15][7]; +#endif extern float FASTCONV_HOA3_latency_s; extern float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; @@ -61,10 +75,17 @@ extern float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; /* Binaural rendering data set based on BRIRs */ extern const float FASTCONV_BRIR_latency_s; +#ifdef HRTF_BINARY_FILE +extern float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +extern float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; +#else extern float leftBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; extern float leftBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; extern float rightBRIRReal[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; extern float rightBRIRImag[BINAURAL_CONVBANDS][15][BINAURAL_NTAPS_MAX]; +#endif /* Reverberation parameters based on BRIRs for fastconv */ extern float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX]; diff --git a/lib_rend/ivas_rom_binaural_crend_head.c b/lib_rend/ivas_rom_binaural_crend_head.c index f214f68f6808a10d521d27050fb4cd9ff3e432ae..082a29c3910c73da00178b5e9bb0d2ff3ba7abfc 100644 --- a/lib_rend/ivas_rom_binaural_crend_head.c +++ b/lib_rend/ivas_rom_binaural_crend_head.c @@ -40,17 +40,18 @@ /* Tables generated by the exe at "scripts/binauralRenderer_interface/generate_cren_ivas_tables*.* */ /* Can be replaced by your own generated HRIR or BRIRI tables */ - - #include #include #include "cnst.h" #include "ivas_cnst.h" -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_HRIR **********************/ + +const float CRendBin_Combined_HRIR_latency_s = 0.000020833333110f; + +/* Sample Rate = 48000 */ -const float CRendBin_Combined_HRIR_latency_s_48kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_48kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -305,9 +306,8 @@ const float CRendBin_Combined_HRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][240]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_Combined_HRIR_latency_s_32kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_32kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -502,9 +502,8 @@ const float CRendBin_Combined_HRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][160]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_Combined_HRIR_latency_s_16kHz = 0.000020833333110f; const int16_t CRendBin_Combined_HRIR_max_num_iterations_16kHz = 1; const uint16_t CRendBin_Combined_HRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]={{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1} }; const uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -639,9 +638,12 @@ const float CRendBin_Combined_HRIR_coeff_im_16kHz[15][BINAURAL_CHANNELS][80]={ const float *CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_HOA3_HRIR **********************/ + +const float CRendBin_HOA3_HRIR_latency_s = 0.001333333319053f; + +/* Sample Rate = 48000 */ -const float CRendBin_HOA3_HRIR_latency_s_48kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_48kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_48kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1040,9 +1042,8 @@ const float CRendBin_HOA3_HRIR_coeff_im_48kHz[16][BINAURAL_CHANNELS][480]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_HOA3_HRIR_latency_s_32kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_32kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_32kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1377,9 +1378,8 @@ const float CRendBin_HOA3_HRIR_coeff_im_32kHz[16][BINAURAL_CHANNELS][320]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_HOA3_HRIR_latency_s_16kHz = 0.001333333319053f; const int16_t CRendBin_HOA3_HRIR_max_num_iterations_16kHz = 2; const uint16_t CRendBin_HOA3_HRIR_num_iterations_16kHz[16][BINAURAL_CHANNELS]={{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2} }; const uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {0, 0}; @@ -1586,9 +1586,12 @@ const float CRendBin_HOA3_HRIR_coeff_im_16kHz[16][BINAURAL_CHANNELS][160]={ const float *CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; const float *CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]={NULL,NULL}; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_BRIR **********************/ + +const float CRendBin_Combined_BRIR_latency_s = 0.000145833328133f; + +/* Sample Rate = 48000 */ -const float CRendBin_Combined_BRIR_latency_s_48kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_48kHz = 22; const uint16_t CRendBin_Combined_BRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]={{22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS] = {40, 40}; @@ -3623,9 +3626,8 @@ const float CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS][288 0.008540f, 0.000569f, 0.002267f, -0.000988f, 0.001342f} }; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -const float CRendBin_Combined_BRIR_latency_s_32kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_32kHz = 22; const uint16_t CRendBin_Combined_BRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]={{22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22}, {22, 22} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS] = {40, 40}; @@ -5584,9 +5586,8 @@ const float CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS][287 -0.030519f, 0.027258f, -0.004872f, -0.024412f, -0.025958f, 0.005865f, -0.034537f, -0.048705f, 0.008013f, -0.011347f, -0.010463f, -0.010480f, 0.009340f, -0.029039f, 0.030517f, -0.017776f, 0.020717f, -0.014466f, -0.013902f, 0.000316f, 0.016725f, -0.023690f, -0.022640f, 0.012110f, -0.004311f, 0.033404f, -0.014684f, 0.019133f, 0.028780f, 0.013672f, -0.010535f, -0.004820f, -0.003049f, 0.023610f, -0.008334f, 0.015840f, 0.031862f, -0.026837f, -0.046802f, -0.018449f, 0.015820f, 0.019420f, -0.022107f, 0.036264f, -0.011732f, -0.013165f, -0.004432f, -0.004019f, -0.011290f, -0.029439f, -0.012475f, -0.030418f, -0.029136f, -0.018067f, 0.021415f, 0.005020f, -0.005215f, 0.001915f, 0.033137f, 0.031128f, 0.002152f, -0.014470f, 0.005893f, -0.003315f, 0.013612f, 0.004239f, -0.006009f, -0.013786f, -0.001289f, -0.002803f, -0.021865f, -0.005694f, 0.008246f, 0.022588f, -0.010185f, -0.000025f, 0.008581f, -0.012767f, -0.000458f, -0.000932f, 0.000324f, -0.006676f, 0.008426f, 0.000455f, 0.002150f, -0.001106f} }; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -const float CRendBin_Combined_BRIR_latency_s_16kHz = 0.000145833328133f; const int16_t CRendBin_Combined_BRIR_max_num_iterations_16kHz = 23; const uint16_t CRendBin_Combined_BRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]={{23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23}, {23, 23} }; const uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS] = {40, 40}; diff --git a/lib_rend/ivas_rom_binaural_crend_head.h b/lib_rend/ivas_rom_binaural_crend_head.h index beade7ff933e8b9fd11f28433d626137ac836dc8..4a9570f23f47c9d7cfa96579bb21c9f530194b9e 100644 --- a/lib_rend/ivas_rom_binaural_crend_head.h +++ b/lib_rend/ivas_rom_binaural_crend_head.h @@ -50,9 +50,12 @@ #include "ivas_cnst.h" -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_HRIR **********************/ + +extern float CRendBin_Combined_HRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_Combined_HRIR_latency_s_48kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -65,9 +68,8 @@ extern float CRendBin_Combined_HRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][240]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_Combined_HRIR_latency_s_32kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -80,9 +82,8 @@ extern float CRendBin_Combined_HRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][160]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_Combined_HRIR_latency_s_16kHz; extern int16_t CRendBin_Combined_HRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_Combined_HRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; @@ -95,9 +96,12 @@ extern float CRendBin_Combined_HRIR_coeff_im_16kHz[15][BINAURAL_CHANNELS][80]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]; extern float *CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_HOA3_HRIR **********************/ + +extern float CRendBin_HOA3_HRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_HOA3_HRIR_latency_s_48kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_48kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -110,9 +114,8 @@ extern float CRendBin_HOA3_HRIR_coeff_im_48kHz[16][BINAURAL_CHANNELS][480]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_HOA3_HRIR_latency_s_32kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_32kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -125,9 +128,8 @@ extern float CRendBin_HOA3_HRIR_coeff_im_32kHz[16][BINAURAL_CHANNELS][320]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_HOA3_HRIR_latency_s_16kHz; extern int16_t CRendBin_HOA3_HRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_16kHz[16][BINAURAL_CHANNELS]; extern uint16_t CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; @@ -140,9 +142,12 @@ extern float CRendBin_HOA3_HRIR_coeff_im_16kHz[16][BINAURAL_CHANNELS][160]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz[BINAURAL_CHANNELS]; extern float *CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz[BINAURAL_CHANNELS]; -/********************** Sample Rate = 48000 **********************/ +/********************** CRendBin_Combined_BRIR **********************/ + +extern float CRendBin_Combined_BRIR_latency_s; + +/* Sample Rate = 48000 */ -extern float CRendBin_Combined_BRIR_latency_s_48kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_48kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_48kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz[BINAURAL_CHANNELS]; @@ -155,9 +160,8 @@ extern float CRendBin_Combined_BRIR_coeff_im_48kHz[15][BINAURAL_CHANNELS][2955]; extern float CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz[BINAURAL_CHANNELS][2885]; extern float CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz[BINAURAL_CHANNELS][2885]; -/********************** Sample Rate = 32000 **********************/ +/* Sample Rate = 32000 */ -extern float CRendBin_Combined_BRIR_latency_s_32kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_32kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_32kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz[BINAURAL_CHANNELS]; @@ -170,9 +174,8 @@ extern float CRendBin_Combined_BRIR_coeff_im_32kHz[15][BINAURAL_CHANNELS][2819]; extern float CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz[BINAURAL_CHANNELS][2870]; extern float CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz[BINAURAL_CHANNELS][2870]; -/********************** Sample Rate = 16000 **********************/ +/* Sample Rate = 16000 */ -extern float CRendBin_Combined_BRIR_latency_s_16kHz; extern int16_t CRendBin_Combined_BRIR_max_num_iterations_16kHz; extern uint16_t CRendBin_Combined_BRIR_num_iterations_16kHz[15][BINAURAL_CHANNELS]; extern uint16_t CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz[BINAURAL_CHANNELS]; diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 4f37d92cb36612f280d1afa251bb71a8995e9ada..1b6ca5f75bf066cda8b8f0d5fa89025c0d330a3c 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -914,6 +914,79 @@ typedef struct ivas_binaural_crend_wrapper_struct HRTFS_HANDLE hHrtfCrend; } CREND_WRAPPER, *CREND_WRAPPER_HANDLE; + +#ifdef HRTF_BINARY_FILE + +/* htrfs from binary files. */ + +typedef struct ivas_hrtfs_crend_structure +{ + HRTFS_DATA *hHRTF_hrir_combined; + HRTFS_DATA *hHRTF_hrir_hoa3; + HRTFS_DATA *hHRTF_brir_combined; + +} HRTFS_CREND, *HRTFS_CREND_HANDLE; + +typedef struct ivas_hrtfs_header_t +{ + int32_t rend_type; + int32_t input_cfg; + int32_t frequency; + uint32_t data_size; + +} ivas_hrtfs_header_t; + +typedef struct ivas_hrtfs_file_header_t +{ + char identifier[8]; + int32_t file_size; + int16_t nb_hrtf; + int32_t max_data_size; + +} ivas_hrtfs_file_header_t; + +#endif + +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_fastconv_struct +{ + float FASTCONV_HRIR_latency_s; + float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][7]; + + float FASTCONV_HOA3_latency_s; + float leftHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float leftHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRReal_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + float rightHRIRImag_HOA3[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][7]; + + float FASTCONV_BRIR_latency_s; + float leftBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float leftBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + float rightBRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS_MAX]; + + float fastconvReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float fastconvReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; +} HRTFS_FASTCONV, *HRTFS_FASTCONV_HANDLE; + +#endif + +#ifdef HRTF_BINARY_FILE +typedef struct ivas_hrtfs_parambin_struct +{ + float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + float hrtfShCoeffsIm[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + + float parametricReverberationTimes[CLDFB_NO_CHANNELS_MAX]; + float parametricReverberationEneCorrections[CLDFB_NO_CHANNELS_MAX]; + float parametricEarlyPartEneCorrection[CLDFB_NO_CHANNELS_MAX]; +} HRTFS_PARAMBIN, *HRTFS_PARAMBIN_HANDLE; + +#endif + /*----------------------------------------------------------------------------------* * LFE decoder structure *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index c4d41ebc55ff7b59a2790778869ecabfd2b72ab7..c3b3ef07c285b1d58ffcbc838be71ff5c94172ab 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1069,6 +1069,9 @@ static ivas_error setRendInputActiveIsm( hRendCfg, #ifdef FIX_197_CREND_INTERFACE 0, +#endif +#ifdef HRTF_BINARY_FILE + NULL, #endif *rendCtx.pOutSampleRate ); } @@ -1773,6 +1776,9 @@ static ivas_error initMcBinauralRendering( hRendCfg, #ifdef FIX_197_CREND_INTERFACE 0, +#endif +#ifdef HRTF_BINARY_FILE + NULL, #endif outSampleRate ) ) != IVAS_ERR_OK ) { @@ -2045,9 +2051,17 @@ static ivas_error updateSbaPanGains( { case IVAS_REND_AUDIO_CONFIG_BINAURAL: #ifdef FIX_197_CREND_INTERFACE - error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, 0, *rendCtx.pOutSampleRate ); + error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, 0, +#ifdef HRTF_BINARY_FILE + NULL, +#endif + *rendCtx.pOutSampleRate ); #else - error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, *rendCtx.pOutSampleRate ); + error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, +#ifdef HRTF_BINARY_FILE + NULL, +#endif + *rendCtx.pOutSampleRate ); #endif break; case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM: @@ -2056,9 +2070,17 @@ static ivas_error updateSbaPanGains( return error; } #ifdef FIX_197_CREND_INTERFACE - error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, 0, *rendCtx.pOutSampleRate ); + error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, 0, +#ifdef HRTF_BINARY_FILE + NULL, +#endif + *rendCtx.pOutSampleRate ); #else - error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, *rendCtx.pOutSampleRate ); + error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, +#ifdef HRTF_BINARY_FILE + NULL, +#endif + *rendCtx.pOutSampleRate ); #endif break; default: @@ -2178,10 +2200,17 @@ static ivas_error initMasaDummyDecForMcOut( input_masa *inputMasa, IVAS_REND_Aud if ( decDummy->renderer_type == RENDERER_STEREO_PARAMETRIC ) { +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy ) ) != IVAS_ERR_OK ) { return error; } +#endif decDummy->hDiracDecBin->useSubframeMode = 0; /* Todo Nokia: This will disappear in later work but needs to be this now. */ } @@ -2327,10 +2356,22 @@ static ivas_error initMasaDummyDecForBinauralOut( input_masa *inputMasa, IVAS_RE { return error; } +#ifdef HRTF_BINARY_FILE + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy, decDummy->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } +#else if ( ( error = ivas_dirac_dec_init_binaural_data( decDummy ) ) != IVAS_ERR_OK ) { return error; } +#endif decDummy->hDiracDecBin->useSubframeMode = 0; /* Todo Nokia: This will disappear in later work but needs to be this now. */ diff --git a/lib_util/hrtf_file_reader.c b/lib_util/hrtf_file_reader.c index d6896ad9e1716801e0f467e26629492128d0def2..2327f8250d2f3ce19990c04937ee702650440138 100644 --- a/lib_util/hrtf_file_reader.c +++ b/lib_util/hrtf_file_reader.c @@ -36,6 +36,9 @@ #include "prot.h" #include "ivas_prot.h" +#ifdef HRTF_BINARY_FILE +#include "lib_dec.h" +#endif struct hrtfFileReader { @@ -117,6 +120,111 @@ void hrtfFileReader_close( } +#ifdef HRTF_BINARY_FILE + +/*-------------------------------------------------------------------* + * read_and_check_hrtf_binary_file_header() + * + * Check the HRTF file header read from binary file + --------------------------------------------------------------------*/ + +static ivas_error read_and_check_hrtf_binary_file_header( ivas_hrtfs_file_header_t *hrtf_file_header, FILE *f_hrtf ) +{ + int32_t file_size; + + // [Declaration of the binary file] + // File Identifier (8 bytes) + // Size of file in bytes (4 bytes) + // Number of HRTF (2 bytes) + // Max length of HRTF data (4 bytes) + + fseek( f_hrtf, 0, SEEK_END ); + file_size = ftell( f_hrtf ); + fseek( f_hrtf, 0, SEEK_SET ); + + if ( file_size < (int32_t) sizeof( ivas_hrtfs_file_header_t ) ) + { + return IVAS_ERROR( IVAS_ERR_END_OF_FILE, "HRTF binary file not compliant (size of file header)" ); + } + + fread( &( hrtf_file_header->identifier ), 8, 1, f_hrtf ); + if ( strncmp( hrtf_file_header->identifier, "IVASHRTF", 8 ) != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (identifier)" ); + } + + fread( &( hrtf_file_header->file_size ), 4, 1, f_hrtf ); + if ( hrtf_file_header->file_size != file_size ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (file size)" ); + } + + fread( &( hrtf_file_header->nb_hrtf ), 2, 1, f_hrtf ); + fread( &( hrtf_file_header->max_data_size ), 4, 1, f_hrtf ); + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * check_hrtf_binary_header() + * + * Check the HRTF section header - read from binary file + --------------------------------------------------------------------*/ + +static ivas_error check_hrtf_binary_header( ivas_hrtfs_header_t *hrtf_header ) +{ + // Check the renderer type + if ( ( hrtf_header->rend_type != RENDERER_BINAURAL_MIXER_CONV ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_MIXER_CONV_ROOM ) && +#ifdef HRTF_BINARY_FILE + ( hrtf_header->rend_type != RENDERER_BINAURAL_FASTCONV ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_FASTCONV_ROOM ) && + ( hrtf_header->rend_type != RENDERER_BINAURAL_PARAMETRIC ) && ( hrtf_header->rend_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) && +#endif + ( hrtf_header->rend_type != RENDERER_BINAURAL_OBJECTS_TD ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (renderer type)" ); + } + + // Check the output format of the decoder + if ( ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) && ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_HOA ) && ( hrtf_header->input_cfg != BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (input audio configuration)" ); + } + + // Check the sampling frequency + if ( ( hrtf_header->frequency != 48000 ) && ( hrtf_header->frequency != 32000 ) && ( hrtf_header->frequency != 16000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Header of HRTF binary file not compliant (sampling frequency)" ); + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * read_hrtf_binary_header() + * + * Read the HRTF header from binary file + --------------------------------------------------------------------*/ + +static ivas_error read_hrtf_binary_header( ivas_hrtfs_header_t *hrtf_header, FILE *f_hrtf ) +{ + // HRTF Header + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Input configuration (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + if ( ( fread( &( hrtf_header->rend_type ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->input_cfg ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->frequency ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) && ( fread( &( hrtf_header->data_size ), sizeof( int32_t ), 1, f_hrtf ) == 1 ) ) + { + return IVAS_ERR_OK; + } + + return IVAS_ERR_END_OF_FILE; +} + +#endif + + /*-------------------------------------------------------------------* * LoadBSplineBinaryITD() * @@ -327,36 +435,147 @@ static ivas_error TDREND_MIX_LoadHRTF( int16_t tmp; ivas_error error; +#ifdef HRTF_BINARY_FILE + + bool is_tdrend; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + ivas_hrtfs_header_t hrtf_header; + int32_t hrtf_data_size_max; + char *hrtf_data; + +#endif + error = IVAS_ERR_OK; - if ( fread( &tmp, sizeof( int16_t ), 1, f_hrtf ) == 0 ) +#ifdef HRTF_BINARY_FILE + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) { - return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); - } +#ifdef FIX_FOR_TEST + fseek( f_hrtf, 0, SEEK_SET ); + if ( fread( &tmp, 1, sizeof( int16_t ), f_hrtf ) == 0 ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } - HrFiltSet_p->FilterMethod = (TDREND_HRFILT_Method_t) tmp; + HrFiltSet_p->FilterMethod = (TDREND_HRFILT_Method_t) tmp; #ifdef TDREND_HRTF_TABLE_METHODS - switch ( HrFiltSet_p->FilterMethod ) - { - case TDREND_HRFILT_Method_BSplineModel: - error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); - break; - case TDREND_HRFILT_Method_Table_F: - case TDREND_HRFILT_Method_Table_S: - TDREND_HRFILT_SetFiltSet( HrFiltSet_p, f_hrtf ); - break; - default: + switch ( HrFiltSet_p->FilterMethod ) + { + case TDREND_HRFILT_Method_BSplineModel: + error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + break; + case TDREND_HRFILT_Method_Table_F: + case TDREND_HRFILT_Method_Table_S: + TDREND_HRFILT_SetFiltSet( HrFiltSet_p, f_hrtf ); + break; + default: + error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + } +#else + if ( HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) + { error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); - } + } + else + { + error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + } +#endif + if ( error != IVAS_ERR_OK ) + { + return header_check_result; + } + else + { + return error; + } #else - if ( HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) + return header_check_result; +#endif + } + + is_tdrend = FALSE; + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + for ( hrtf_id = 0; ( hrtf_id < hrtfs_file_header.nb_hrtf ) && ( !is_tdrend ); hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( ( header_check_result = check_hrtf_binary_header( &hrtf_header ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + is_tdrend = ( hrtf_header.rend_type == RENDERER_BINAURAL_OBJECTS_TD ); + if ( !is_tdrend ) + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + } + } + + free( hrtf_data ); + + if ( is_tdrend ) +#endif { - error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + if ( fread( &tmp, 1, sizeof( int16_t ), f_hrtf ) == 0 ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + HrFiltSet_p->FilterMethod = (TDREND_HRFILT_Method_t) tmp; + +#ifdef TDREND_HRTF_TABLE_METHODS + switch ( HrFiltSet_p->FilterMethod ) + { + case TDREND_HRFILT_Method_BSplineModel: + error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + break; + case TDREND_HRFILT_Method_Table_F: + case TDREND_HRFILT_Method_Table_S: + TDREND_HRFILT_SetFiltSet( HrFiltSet_p, f_hrtf ); + break; + default: + error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + } +#else + if ( HrFiltSet_p->FilterMethod != TDREND_HRFILT_Method_BSplineModel ) + { + error = IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "The HR filter set file is not a supported type." ); + } + else + { + error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + } +#endif } +#ifdef HRTF_BINARY_FILE else { - error = LoadBSplineBinary( HrFiltSet_p, f_hrtf ); + return IVAS_ERROR( IVAS_ERR_INVALID_HRTF, "HR filter not found in binary file." ); } #endif @@ -377,6 +596,10 @@ ivas_error load_HRTF_binary( { ivas_error error; +#ifdef HRTF_BINARY_FILE + fseek( hrtfReader->file, 0, SEEK_SET ); +#endif + error = TDREND_MIX_LoadHRTF( hrtfReader->file, hHrtf ); return error; @@ -455,6 +678,13 @@ ivas_error dealloc_HRTF_binary( ivas_error error; error = IVAS_ERR_OK; +#ifdef HRTF_BINARY_FILE + if ( hHrtf == NULL ) + { + return error; + } +#endif + if ( !hHrtf->ModelParams.modelROM ) { if ( hHrtf->ModelParams.UseItdModel ) @@ -499,3 +729,842 @@ ivas_error dealloc_HRTF_binary( return error; } + +#ifdef HRTF_BINARY_FILE + +/*------------------------------------------------------------------------- + * ivas_hrtf_init() + * + * Initialize hHRTF handle + *------------------------------------------------------------------------*/ + +static ivas_error ivas_hrtf_init( + HRTFS_DATA *hHRTF /* i/o: HRTF handle */ +) +{ + int16_t i, j; + + if ( hHRTF == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hHRTF->latency_s = 0; + hHRTF->max_num_ir = 0; + hHRTF->max_num_iterations = 0; + hHRTF->index_frequency_max_diffuse = 0; + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + hHRTF->inv_diffuse_weight[i] = 0; + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHRTF->num_iterations[i][j] = 0; + hHRTF->pIndex_frequency_max[i][j] = NULL; + hHRTF->pOut_to_bin_re[i][j] = NULL; + hHRTF->pOut_to_bin_im[i][j] = NULL; + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hHRTF->num_iterations_diffuse[j] = 0; + hHRTF->pIndex_frequency_max_diffuse[j] = NULL; + hHRTF->pOut_to_bin_diffuse_re[j] = NULL; + hHRTF->pOut_to_bin_diffuse_im[j] = NULL; + } + + return IVAS_ERR_OK; +} + +/*---------------------------------------------------------------------* + * create_HRTF_from_rawdata() + * + * Create HRTF from the raw data (to the HRTF CRend handle) + *---------------------------------------------------------------------*/ + +static ivas_error create_HRTF_from_rawdata( + HRTFS_HANDLE *hHRTF, /* i/o: HRTF CRend handle */ + char *hrtf_data /* i: pointer to binary file */ +) +{ + int i, j, k; + int16_t max_num_iterations_diffuse; + uint16_t max_total_num_fsamp_per_iteration, max_total_num_fsamp_per_iteration_diff; + uint32_t mem_size; + char *hrtf_data_rptr; + float *pOut_to_bin_wptr; + + if ( *hHRTF == NULL ) + { + if ( ( ( *hHRTF ) = (HRTFS_HANDLE) malloc( sizeof( HRTFS_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Can not allocate memory for HRTF binary data\n" ); + } + + ivas_hrtf_init( *hHRTF ); + } + else + { + return IVAS_ERR_INTERNAL; + } + + hrtf_data_rptr = hrtf_data; + + // latency_s + ( *hHRTF )->latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + // max_num_ir + ( *hHRTF )->max_num_ir = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + // BINAURAL_CHANNELS + if ( BINAURAL_CHANNELS != *( (int16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file format not compliant (BINAURAL_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + // max_num_iterations + ( *hHRTF )->max_num_iterations = *( (int16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( int16_t ); + + // num_iterations + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + ( *hHRTF )->num_iterations[i][j] = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + } + } + + // pIndex_frequency_max + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = ( *hHRTF )->max_num_iterations * sizeof( uint16_t ); + ( *hHRTF )->pIndex_frequency_max[i][j] = (uint16_t *) malloc( mem_size ); + if ( ( *hHRTF )->pIndex_frequency_max[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pIndex_frequency_max" ); + } + memcpy( ( *hHRTF )->pIndex_frequency_max[i][j], hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + } + } + + // max_num_iterations_diffuse + max_num_iterations_diffuse = *( (int16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( int16_t ); + + if ( max_num_iterations_diffuse != 0 ) + { + // num_iterations_diffuse + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + ( *hHRTF )->num_iterations_diffuse[j] = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + } + + // pIndex_frequency_max_diffuse (the size depends on num_iterations_diffuse) + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = ( *hHRTF )->num_iterations_diffuse[j] * sizeof( uint16_t ); + ( *hHRTF )->pIndex_frequency_max_diffuse[j] = (uint16_t *) malloc( mem_size ); + if ( ( *hHRTF )->pIndex_frequency_max_diffuse[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pIndex_frequency_max_diffuse" ); + } + memcpy( ( *hHRTF )->pIndex_frequency_max_diffuse[j], hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + } + } + + // index_frequency_max_diffuse + ( *hHRTF )->index_frequency_max_diffuse = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + // inv_diffuse_weight + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + ( *hHRTF )->inv_diffuse_weight[i] = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + } + + // max_total_num_fsamp_per_iteration + max_total_num_fsamp_per_iteration = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + // coeff_re (the size depends on pIndex_frequency_max) + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration * sizeof( float ); + ( *hHRTF )->pOut_to_bin_re[i][j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_re[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for Out_to_bin_re" ); + } + memset( ( *hHRTF )->pOut_to_bin_re[i][j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_re[i][j]; + for ( k = 0; k < ( *hHRTF )->num_iterations[i][j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max[i][j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max[i][j][k]; + } + } + } + + // coeff_im (the size depends on pIndex_frequency_max) + for ( i = 0; i < ( *hHRTF )->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration * sizeof( float ); + ( *hHRTF )->pOut_to_bin_im[i][j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_im[i][j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for Out_to_bin_im" ); + } + memset( ( *hHRTF )->pOut_to_bin_im[i][j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_im[i][j]; + for ( k = 0; k < ( *hHRTF )->num_iterations[i][j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max[i][j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max[i][j][k]; + } + } + } + + // max_total_num_fsamp_per_iteration_diff + max_total_num_fsamp_per_iteration_diff = *( (uint16_t *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( uint16_t ); + + if ( max_total_num_fsamp_per_iteration_diff != 0 ) + { + // coeff_diffuse_re : The size depends on pIndex_frequency_max_diffuse + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration_diff * sizeof( float ); + ( *hHRTF )->pOut_to_bin_diffuse_re[j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_diffuse_re[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pOut_to_bin_diffuse_re" ); + } + memset( ( *hHRTF )->pOut_to_bin_diffuse_re[j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_diffuse_re[j]; + for ( k = 0; k < ( *hHRTF )->num_iterations_diffuse[j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max_diffuse[j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max_diffuse[j][k]; + } + } + + // coeff_diffuse_im : The size depends on pIndex_frequency_max_diffuse + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mem_size = max_total_num_fsamp_per_iteration_diff * sizeof( float ); + ( *hHRTF )->pOut_to_bin_diffuse_im[j] = (float *) malloc( mem_size ); + if ( ( *hHRTF )->pOut_to_bin_diffuse_im[j] == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for pOut_to_bin_diffuse_im" ); + } + memset( ( *hHRTF )->pOut_to_bin_diffuse_im[j], 0x00, mem_size ); + + pOut_to_bin_wptr = ( *hHRTF )->pOut_to_bin_diffuse_im[j]; + for ( k = 0; k < ( *hHRTF )->num_iterations_diffuse[j]; k++ ) + { + mem_size = ( *hHRTF )->pIndex_frequency_max_diffuse[j][k] * sizeof( float ); + memcpy( pOut_to_bin_wptr, hrtf_data_rptr, mem_size ); + hrtf_data_rptr += mem_size; + pOut_to_bin_wptr += ( *hHRTF )->pIndex_frequency_max_diffuse[j][k]; + } + } + } + + return IVAS_ERR_OK; +} + +#ifdef HRTF_BINARY_FILE +static ivas_error init_fastconv_HRTF_handle( + HRTFS_FASTCONV *hHrtf /* i/o: HRTF FastConv handle */ +) +{ + int16_t i, j; + + if ( hHrtf == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + hHrtf->FASTCONV_HRIR_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + set_zero( hHrtf->leftHRIRReal[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->leftHRIRImag[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRReal[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRImag[i][j], BINAURAL_NTAPS ); + } + } + + hHrtf->FASTCONV_HOA3_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + set_zero( hHrtf->leftHRIRReal_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->leftHRIRImag_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRReal_HOA3[i][j], BINAURAL_NTAPS ); + set_zero( hHrtf->rightHRIRImag_HOA3[i][j], BINAURAL_NTAPS ); + } + } + + hHrtf->FASTCONV_BRIR_latency_s = 0; + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + set_zero( hHrtf->leftBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->leftBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->rightBRIRReal[i][j], BINAURAL_NTAPS_MAX ); + set_zero( hHrtf->rightBRIRImag[i][j], BINAURAL_NTAPS_MAX ); + } + } + + set_zero( hHrtf->fastconvReverberationTimes, CLDFB_NO_CHANNELS_MAX ); + set_zero( hHrtf->fastconvReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX ); + + return IVAS_ERR_OK; +} + +static ivas_error create_fastconv_HRTF_from_rawdata( + HRTFS_FASTCONV_HANDLE *hHRTF, /* i/o: HRTF FastConv handle */ + char *hrtf_data, /* i : pointer to binary file */ + RENDERER_TYPE rend_type, /* i : Renderer type */ + BINAURAL_INPUT_AUDIO_CONFIG input_cfg /* i : Input binaural config */ +) +{ + int i, j; + char *hrtf_data_rptr; + + // if ( hHRTF == NULL ) + // { + // if ( ( ( *hHRTF ) = (HRTFS_FASTCONV_HANDLE) count_malloc( sizeof( HRTFS_FASTCONV ) ) ) == NULL ) + // { + // return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "Can not allocate memory for Fastconv HRTF binary\n" ); + // } + + // init_fastconv_HRTF_handle( *hHRTF ); + // } + // else + // { + // return IVAS_ERR_INTERNAL; + // } + + hrtf_data_rptr = hrtf_data; + + // BINAURAL_CONVBANDS + if ( BINAURAL_CONVBANDS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_CONVBANDS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + // HRIR + if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + ( *hHRTF )->FASTCONV_HRIR_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_LS_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_LS_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + } + if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + // HRIR_HOA3 + ( *hHRTF )->FASTCONV_HOA3_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_SH_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_SH_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRReal_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftHRIRImag_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRReal_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightHRIRImag_HOA3[i][j], hrtf_data_rptr, BINAURAL_NTAPS * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS * sizeof( float ); + } + } + } + // BRIR + if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + ( *hHRTF )->FASTCONV_BRIR_latency_s = *( (float *) ( hrtf_data_rptr ) ); + hrtf_data_rptr += sizeof( float ); + + if ( HRTF_LS_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_LS_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + if ( BINAURAL_NTAPS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (BINAURAL_NTAPS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftBRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->leftBRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightBRIRReal[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < HRTF_LS_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->rightBRIRImag[i][j], hrtf_data_rptr, BINAURAL_NTAPS_MAX * sizeof( float ) ); + hrtf_data_rptr += BINAURAL_NTAPS_MAX * sizeof( float ); + } + } + + // Reverb Parameters + if ( CLDFB_NO_CHANNELS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (CLDFB_NO_CHANNELS_MAX)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + memcpy( ( *hHRTF )->fastconvReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->fastconvReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + } + return IVAS_ERR_OK; +} + +ivas_error load_fastconv_HRTF_from_binary( + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv, /* i/o: FastConv HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +) +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + + memset( hHrtfFastConv, 0x00, sizeof( HRTFS_FASTCONV ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( ( hrtf_header.frequency == 48000 ) && + ( ( hrtf_header.rend_type == RENDERER_BINAURAL_FASTCONV ) || ( hrtf_header.rend_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + // Create the HRTF reading the raw data from the binary file + if ( ( create_fastconv_HRTF_from_rawdata( &hHrtfFastConv, hrtf_data, hrtf_header.rend_type, hrtf_header.input_cfg ) ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + else + { + fseek( f_hrtf, hrtf_header.data_size, SEEK_CUR ); + } + } + free( hrtf_data ); + + return IVAS_ERR_OK; +} +#endif + + +#ifdef HRTF_BINARY_FILE +static ivas_error create_parambin_HRTF_from_rawdata( + HRTFS_PARAMBIN_HANDLE *hHRTF, /* i/o: Parametric binauralizer HRTF handle */ + char *hrtf_data /* i : pointer to binary file */ +) +{ + int i, j; + char *hrtf_data_rptr; + uint32_t data_size_tmp; + + hrtf_data_rptr = hrtf_data; + + // HRTF_SH_CHANNELS + if ( HRTF_SH_CHANNELS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_SH_CHANNELS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + // HRTF_NUM_BINS + if ( HRTF_NUM_BINS != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (HRTF_NUM_BINS)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + // HRTF + data_size_tmp = HRTF_NUM_BINS * sizeof( float ); + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsRe[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( ( *hHRTF )->hrtfShCoeffsIm[i][j], hrtf_data_rptr, data_size_tmp ); + hrtf_data_rptr += data_size_tmp; + } + } + + // Reverb Parameters + if ( CLDFB_NO_CHANNELS_MAX != *( (uint16_t *) ( hrtf_data_rptr ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (CLDFB_NO_CHANNELS_MAX)" ); + } + hrtf_data_rptr += sizeof( uint16_t ); + + memcpy( ( *hHRTF )->parametricReverberationTimes, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricReverberationEneCorrections, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + memcpy( ( *hHRTF )->parametricEarlyPartEneCorrection, hrtf_data_rptr, CLDFB_NO_CHANNELS_MAX * sizeof( float ) ); + hrtf_data_rptr += CLDFB_NO_CHANNELS_MAX * sizeof( float ); + + return IVAS_ERR_OK; +} + +ivas_error load_parambin_HRTF_from_binary( + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParamBin, /* i/o: Parametric binauralizer HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +) +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + memset( hHrtfParamBin, 0x00, sizeof( HRTFS_PARAMBIN ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + if ( hrtf_header.rend_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Parametric binauralizer data is represented as single entity */ + { + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + // Create the HRTF reading the raw data from the binary file + if ( ( create_parambin_HRTF_from_rawdata( &hHrtfParamBin, hrtf_data ) ) != IVAS_ERR_OK ) + { + free( hrtf_data ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + else + { + fseek( f_hrtf, hrtf_header.data_size, SEEK_CUR ); + } + } + free( hrtf_data ); + + return IVAS_ERR_OK; +} +#endif + + +/*---------------------------------------------------------------------* + * create_SetOfHRTF_from_binary() + * + * Create the HRTF data set from the binary file + *---------------------------------------------------------------------*/ + +ivas_error create_SetOfHRTF_from_binary( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF, /* i/o: HRTF CRend handle */ + const hrtfFileReader *hrtfReader, /* i: pointer to hrtfFileReader handle */ + int32_t output_Fs ) /* i: Output sampling frequency */ +{ + FILE *f_hrtf; + int32_t hrtf_data_size_max; + char *hrtf_data; + ivas_hrtfs_header_t hrtf_header; + HRTFS_DATA **hHRTF; + ivas_error header_check_result; + ivas_hrtfs_file_header_t hrtfs_file_header; + int16_t hrtf_id; + + f_hrtf = hrtfReader->file; + + if ( ( header_check_result = read_and_check_hrtf_binary_file_header( &hrtfs_file_header, f_hrtf ) ) != IVAS_ERR_OK ) + { + return header_check_result; + } + + hrtf_data_size_max = hrtfs_file_header.max_data_size; + + /* Allocate the memory */ + + if ( hrtf_data_size_max == 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "HRTF binary file not compliant (hrtf_data_size_max)" ); + } + + hrtf_data = (char *) malloc( hrtf_data_size_max ); + if ( hrtf_data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for hrtf data" ); + } + + /* Read & load */ + + memset( hSetOfHRTF, 0x00, sizeof( HRTFS_CREND ) ); + + for ( hrtf_id = 0; hrtf_id < hrtfs_file_header.nb_hrtf; hrtf_id++ ) + { + if ( read_hrtf_binary_header( &hrtf_header, f_hrtf ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "HRTF binary file not compliant (number of HRTF)" ); + } + + hHRTF = NULL; + if ( hrtf_header.frequency == output_Fs ) + { + if ( hrtf_header.rend_type == RENDERER_BINAURAL_MIXER_CONV ) + { + if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_hrir_combined ); + } + else if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_hrir_hoa3 ); + } + } + else if ( hrtf_header.rend_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( hrtf_header.input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + hHRTF = &( ( *hSetOfHRTF ).hHRTF_brir_combined ); + } + } + } + + if ( fread( hrtf_data, 1, hrtf_header.data_size, f_hrtf ) != hrtf_header.data_size ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "Error in HRTF file reading" ); + } + + if ( hHRTF != NULL ) + { + // Create the HRTF reading the raw data from the binary file + if ( ( create_HRTF_from_rawdata( hHRTF, hrtf_data ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create HRTF from binary file" ); + } + } + } + + free( hrtf_data ); + + if ( ( ( *hSetOfHRTF ).hHRTF_hrir_combined == NULL ) || ( ( *hSetOfHRTF ).hHRTF_brir_combined == NULL ) || ( ( *hSetOfHRTF ).hHRTF_hrir_hoa3 == NULL ) ) + { + destroy_SetOfHRTF( hSetOfHRTF ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Could not create all the HRTF from binary file" ); + } + + return IVAS_ERR_OK; +} + +#endif diff --git a/lib_util/hrtf_file_reader.h b/lib_util/hrtf_file_reader.h index e2c95bc8e54473a7eb56fd739b13f889565ce898..b4465511507b5c7afd32809479da35ec7a73b2a3 100644 --- a/lib_util/hrtf_file_reader.h +++ b/lib_util/hrtf_file_reader.h @@ -73,6 +73,57 @@ ivas_error load_HRTF_binary( const hrtfFileReader *hrtfReader /* i/o: pointer to hrtfFileReader handle */ ); +#ifdef HRTF_BINARY_FILE +/*---------------------------------------------------------------------* + * create_SetOfHRTF_from_binary() + * + * Create the HRTF data set from the binary file + *---------------------------------------------------------------------*/ + +ivas_error create_SetOfHRTF_from_binary( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF, /* i/o: Set of HRTF CRend handle */ + const hrtfFileReader *hrtfReader, /* i: pointer to hrtfFileReader handle */ + int32_t output_Fs /* i: Output sampling frequency */ +); + +/*---------------------------------------------------------------------* + * destroy_SetOfHRTF() + * + * Destroy the HRTF data set. + *---------------------------------------------------------------------*/ + +ivas_error destroy_SetOfHRTF( + IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF /* i/o: Set of HRTF CRend handle */ +); + +#endif + +#ifdef HRTF_BINARY_FILE +/*---------------------------------------------------------------------* + * load_fastconv_HRTF_from_binary() + * + * Load FastConv HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_fastconv_HRTF_from_binary( + IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv, /* i/o: FastConv HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +); + + +/*---------------------------------------------------------------------* + * load_parambin_HRTF_from_binary() + * + * Load parametric binauralizer HRTF binary data into the handle + *---------------------------------------------------------------------*/ + +ivas_error load_parambin_HRTF_from_binary( + IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParambin, /* i/o: Parambin HRTF handle */ + const hrtfFileReader *hrtfReader /* i : pointer to hrtfFileReader handle */ +); + +#endif + /*---------------------------------------------------------------------* * dealloc_HRTF_binary() * diff --git a/scripts/binauralRenderer_interface/.gitignore b/scripts/binauralRenderer_interface/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..040f10e0c87a62f49ab42c11009f17c972d87a85 --- /dev/null +++ b/scripts/binauralRenderer_interface/.gitignore @@ -0,0 +1,6 @@ +*.cmake +CMake* +Externals/ +Table_Format_Converter/CMake* +Table_Format_Converter/build* + diff --git a/scripts/binauralRenderer_interface/BRIRs_sofa/IIS_BRIR_officialMPEG_Combined.sofa b/scripts/binauralRenderer_interface/BRIRs_sofa/IIS_BRIR_officialMPEG_Combined.sofa new file mode 100644 index 0000000000000000000000000000000000000000..da5e884b2ba669ea5f3353eb19be86d246c75a5b Binary files /dev/null and b/scripts/binauralRenderer_interface/BRIRs_sofa/IIS_BRIR_officialMPEG_Combined.sofa differ diff --git a/scripts/binauralRenderer_interface/CMakeLists.txt b/scripts/binauralRenderer_interface/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..99d62c94172a328e0621e872bd097ef63e5929f4 --- /dev/null +++ b/scripts/binauralRenderer_interface/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.0) + +project(generate_crend_ivas_tables) + +set(EXTERNALS_PATH ${PROJECT_SOURCE_DIR}/Externals) +set(IVAS_TRUNK_PATH "${PROJECT_SOURCE_DIR}/../..") +set(IVAS_TRUNK_UTIL_PATH ${IVAS_TRUNK_PATH}/lib_util) +set(IVAS_TRUNK_DEC_PATH ${IVAS_TRUNK_PATH}/lib_dec) +set(IVAS_TRUNK_REND_PATH ${IVAS_TRUNK_PATH}/lib_rend) +set(IVAS_TRUNK_ENC_PATH ${IVAS_TRUNK_PATH}/lib_enc) +set(IVAS_TRUNK_COM_PATH ${IVAS_TRUNK_PATH}/lib_com) +set(IVAS_TRUNK_DEBUG_PATH ${IVAS_TRUNK_PATH}/lib_debug) + +if(WIN32) + find_path(ZLIB_DIR "zlib.h" ${EXTERNALS_PATH}/zlib/zlib-1.2.12) + + if(ZLIB_DIR) + else() + set(ZLIB_DIR ${EXTERNALS_PATH}/zlib) + find_package(Python3 REQUIRED) + + if(Python3_Interpreter_FOUND) + execute_process(COMMAND ${Python3_EXECUTABLE} resolve_build_dep.py + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + RESULT_VARIABLE py_result OUTPUT_VARIABLE ZLIB_DIR) + set(ZLIB_DIR ${PROJECT_SOURCE_DIR} ${ZLIB_DIR}) + endif() + + message(STATUS " ZLIB_DIR: ${ZLIB_DIR}") + endif() +endif() + +if(WIN32) + add_subdirectory(${ZLIB_DIR}) + set(ZLIB_INCLUDE_DIRS ${ZLIB_DIR} ${PROJECT_BINARY_DIR}/Externals/zlib/zlib-1.2.12) + set(zlib zlibstatic) + target_include_directories(example PUBLIC ${ZLIB_INCLUDE_DIRS}) + target_include_directories(minigzip PUBLIC ${ZLIB_INCLUDE_DIRS}) +endif() + +if(UNIX) + find_package(ZLIB) + + if(ZLIB_FOUND) + message(${ZLIB_INCLUDE_DIRS}) + message(${ZLIB_LIBRARIES}) + set(zlib ${ZLIB_LIBRARIES}) + else() + message(FATAL_ERROR "Zlib not found") + endif() +endif() + +find_path(SOFA_READER_DIR "libmysofa.pc.cmake" ${EXTERNALS_PATH}/libmysofa) + +if(SOFA_READER_DIR) +else() + set(SOFA_READER_DIR ${EXTERNALS_PATH}/libmysofa) + set(GIT_URL https://github.com/hoene/libmysofa.git) + execute_process(COMMAND git clone ${GIT_URL} ${EXTERNALS_PATH}/libmysofa) +endif() + +include_directories(${SOFA_READER_DIR}/src ${ZLIB_INCLUDE_DIRS} ${IVAS_TRUNK_UTIL_PATH} ${IVAS_TRUNK_ENC_PATH} ${IVAS_TRUNK_DEC_PATH} ${IVAS_TRUNK_REND_PATH} ${IVAS_TRUNK_COM_PATH} ${IVAS_TRUNK_DEBUG_PATH}) + +option(BUILD_TESTS "Build test programs" OFF) +option(BUILD_SHARED_LIBS "Build shared library" OFF) +add_subdirectory(${SOFA_READER_DIR}) +set(SOURCE_FILES_C + ${PROJECT_SOURCE_DIR}/ivas_crend_binaural_filter_design.c + ${IVAS_TRUNK_COM_PATH}/basop32.c + ${IVAS_TRUNK_COM_PATH}/basop_mpy.c + ${IVAS_TRUNK_COM_PATH}/enh40.c + ${IVAS_TRUNK_COM_PATH}/fft.c + ${IVAS_TRUNK_COM_PATH}/fft_rel.c + ${IVAS_TRUNK_COM_PATH}/ifft_rel.c + ${IVAS_TRUNK_COM_PATH}/ivas_mdft_imdft.c + ${IVAS_TRUNK_COM_PATH}/rom_com.c + ${IVAS_TRUNK_COM_PATH}/ivas_rom_com.c + ${IVAS_TRUNK_COM_PATH}/tools.c + ${IVAS_TRUNK_COM_PATH}/tns_base.c +) + +set(SOURCE_FILES_H + ${PROJECT_SOURCE_DIR}/ivas_crend_binaural_filter_design.c + ${SOFA_READER_DIR}/src/hrtf/mysofa.h + ${IVAS_TRUNK_REND_PATH}/ivas_stat_rend.h + ${IVAS_TRUNK_DEC_PATH}/ivas_stat_dec.h + ${IVAS_TRUNK_DEC_PATH}/stat_dec.h + ${IVAS_TRUNK_COM_PATH}/options.h + ${IVAS_TRUNK_COM_PATH}/ivas_cnst.h + ${IVAS_TRUNK_COM_PATH}/cnst.h + ${IVAS_TRUNK_COM_PATH}/prot.h + ${IVAS_TRUNK_COM_PATH}/ivas_prot.h + ${IVAS_TRUNK_COM_PATH}/common_api_types.h +) + +add_library(${PROJECT_NAME}_lib STATIC ${SOURCE_FILES_C} ${SOURCE_FILES_H}) + +add_executable(${PROJECT_NAME} generate_crend_ivas_tables_from_sofa.c) +target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib mysofa-static ${zlib}) + +if(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +endif() diff --git a/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_51_Q10_symL_Itrp1_48000.sofa b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_51_Q10_symL_Itrp1_48000.sofa new file mode 100644 index 0000000000000000000000000000000000000000..1ec1c4ce72951395130e871ba9580e97c6467258 Binary files /dev/null and b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_51_Q10_symL_Itrp1_48000.sofa differ diff --git a/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_52_Q10_symL_Itrp1_48000.sofa b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_52_Q10_symL_Itrp1_48000.sofa new file mode 100644 index 0000000000000000000000000000000000000000..187bcae2d743baa1c1f4a9632bd19902bc684bab Binary files /dev/null and b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_52_Q10_symL_Itrp1_48000.sofa differ diff --git a/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_48000.sofa b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_48000.sofa new file mode 100644 index 0000000000000000000000000000000000000000..e210ff2d5e3dec4485fb8ea940f6b2f208584058 Binary files /dev/null and b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_48000.sofa differ diff --git a/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_54_Q10_symL_Itrp1_48000.sofa b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_54_Q10_symL_Itrp1_48000.sofa new file mode 100644 index 0000000000000000000000000000000000000000..c48aacb519df238c1317cb00d0a14ae38ec06f88 Binary files /dev/null and b/scripts/binauralRenderer_interface/HRIRs_sofa/HRIR_128_Meth5_IRC_54_Q10_symL_Itrp1_48000.sofa differ diff --git a/scripts/binauralRenderer_interface/HRIRs_sofa/ORANGE_HRIR_53_HOA3S_48000.sofa b/scripts/binauralRenderer_interface/HRIRs_sofa/ORANGE_HRIR_53_HOA3S_48000.sofa new file mode 100644 index 0000000000000000000000000000000000000000..d0c7fd50f0fc4fdc35da9e5114f5ed8418b09149 Binary files /dev/null and b/scripts/binauralRenderer_interface/HRIRs_sofa/ORANGE_HRIR_53_HOA3S_48000.sofa differ diff --git a/scripts/binauralRenderer_interface/Table_Format_Converter/CMakeLists.txt b/scripts/binauralRenderer_interface/Table_Format_Converter/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..259e3b97b6abc67129aca82147929a3841848e2a --- /dev/null +++ b/scripts/binauralRenderer_interface/Table_Format_Converter/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.6) + +project(tables_format_converter) + +if(WIN32) + # MSVC compiler flags + add_definitions( + -D_CRT_SECURE_NO_WARNINGS + ) + + # CMake sets /W3 by default, until CMake version 3.15. Instead of setting /W4 separately, replace in existing settings + string(REGEX REPLACE "/W3" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +endif() + +set(IVAS_PATH "${PROJECT_SOURCE_DIR}/../../..") +set(IVAS_UTIL_PATH ${IVAS_PATH}/lib_util) +set(IVAS_DEC_PATH ${IVAS_PATH}/lib_dec) +set(IVAS_ENC_PATH ${IVAS_PATH}/lib_enc) +set(IVAS_COM_PATH ${IVAS_PATH}/lib_com) +set(IVAS_REND_PATH ${IVAS_PATH}/lib_rend) +set(IVAS_DEBUG_PATH ${IVAS_PATH}/lib_debug) + +include_directories(${IVAS_UTIL_PATH} ${IVAS_ENC_PATH} ${IVAS_DEC_PATH} ${IVAS_COM_PATH} ${IVAS_REND_PATH} ${IVAS_DEBUG_PATH}) + +set(SOURCE_FILES_C + ${IVAS_REND_PATH}/ivas_rom_binauralRenderer.c + ${IVAS_REND_PATH}/ivas_rom_binaural_crend_head.c) + +set(SOURCE_FILES_H + ${IVAS_REND_PATH}/ivas_rom_binauralRenderer.h + ${IVAS_REND_PATH}/ivas_rom_binaural_crend_head.h) + +add_library(${PROJECT_NAME}_lib STATIC ${SOURCE_FILES_C} ${SOURCE_FILES_H}) + +add_executable(${PROJECT_NAME} generate_tables_from_rom_to_bin.c) +target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib) diff --git a/scripts/binauralRenderer_interface/Table_Format_Converter/generate_tables_from_rom_to_bin.c b/scripts/binauralRenderer_interface/Table_Format_Converter/generate_tables_from_rom_to_bin.c new file mode 100644 index 0000000000000000000000000000000000000000..89a33e1d45cfa5cce857908b87b017e43f23f73c --- /dev/null +++ b/scripts/binauralRenderer_interface/Table_Format_Converter/generate_tables_from_rom_to_bin.c @@ -0,0 +1,2223 @@ +/****************************************************************************************************** + + (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include + +#include "ivas_rom_binauralRenderer.h" +#include "ivas_rom_binaural_crend_head.h" +#include "lib_rend.h" +#include "ivas_stat_dec.h" + +#define FILE_HEADER + +/*------------------------------------------------------------------------------------------* + * Constants + *------------------------------------------------------------------------------------------*/ + +#ifdef WIN32 +#define DEFAULT_PATH ".\\" +#else +#define DEFAULT_PATH "./" +#endif + +#define DEFAULT_INPUT_ROM_FILE "ivas_binaural" +#define DEFAULT_INPUT_TD_BIN_FILE "hrfilter_model" +#define DEFAULT_BIN_FILE_EXT ".bin" + +#define IVAS_NB_RENDERER_TYPE 7 +#define IVAS_NB_AUDIO_CONFIG 2 +#define IVAS_NB_SAMPLERATE 3 + +const RENDERER_TYPE rend_types[IVAS_NB_RENDERER_TYPE] = { + RENDERER_BINAURAL_FASTCONV, + RENDERER_BINAURAL_FASTCONV_ROOM, + RENDERER_BINAURAL_PARAMETRIC, + RENDERER_BINAURAL_PARAMETRIC_ROOM, + RENDERER_BINAURAL_MIXER_CONV, + RENDERER_BINAURAL_MIXER_CONV_ROOM, + RENDERER_BINAURAL_OBJECTS_TD +}; +const BINAURAL_INPUT_AUDIO_CONFIG input_cfgs[IVAS_NB_AUDIO_CONFIG] = { + BINAURAL_INPUT_AUDIO_CONFIG_COMBINED, + BINAURAL_INPUT_AUDIO_CONFIG_HOA +}; +const int32_t sample_rates[IVAS_NB_SAMPLERATE] = { 48000, 32000, 16000 }; /* Hz */ /* 8000 Hz not supported by mdft */ + +#ifdef FILE_HEADER +const char *file_identifier = "IVASHRTF"; // (0x49,0x56,0x41,0x53,0x48,0x52,0x54,0x46) +const int16_t file_identifier_len = 8; +#endif + +/* ------------------------------------------------------------------------------------------ + * Structures declaration + *------------------------------------------------------------------------------------------ */ + +typedef struct _crend_hrtf_tables_dimensions +{ + int16_t max_num_ir; + int16_t max_num_iterations; + int16_t max_num_iterations_diffuse; + uint16_t max_total_num_fsamp_per_iteration; + uint16_t max_total_num_fsamp_per_iteration_diff; + +} crend_hrtf_tables_dimensions; + +typedef struct _crend_hrtf_tables_pointers +{ + float *latency_s; + uint16_t *num_iterations; + uint16_t *pIndex_frequency_max; + uint16_t *num_iterations_diffuse; + uint16_t *pIndex_frequency_max_diffuse; + uint16_t *index_frequency_max_diffuse; + float *inv_diffuse_weight; + float *coeff_re; + float *coeff_im; + float *coeff_diffuse_re; + float *coeff_diffuse_im; + +} crend_hrtf_tables_pointers; + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ + +void usage_tables_format_converter( void ); +int rom2bin_init( int argc, char *argv[] ); +void rom2bin_terminat( void ); +char *to_upper( char *str ); + +char *create_hrtf_crend( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, int32_t *hrtf_size /*OUT*/ ); +char *create_hrtf_fastconv( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, int32_t *hrtf_size ); +char *create_hrtf_parametric( int32_t *hrtf_size ); +char *create_hrtf_tdrend( int32_t frequency, int32_t *hrtf_size /*OUT*/ ); + +int32_t read_hrtf_size( char *hrtf ); +int16_t check_bin_file( FILE *hrtf_bin_file ); +int16_t check_hrtf_data( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, char *hrtf_data_in, int32_t hrtf_size_in ); + +/*---------------------------------------------------------------------*/ + +int16_t get_crend_hrtf_tables( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, crend_hrtf_tables_pointers *hrtf_table_ptrs /*OUT*/, crend_hrtf_tables_dimensions *hrtf_table_dims /*OUT*/ ); +int32_t compute_crend_hrtf_data_size( crend_hrtf_tables_pointers *hrtf_table_ptrs, crend_hrtf_tables_dimensions *hrtf_table_dims ); + +/*---------------------------------------------------------------------* + * usage_gen_crend_tables() + * + * Print the usage of the "generate_crend_ivas_tables" program + *---------------------------------------------------------------------*/ + +void usage_tables_format_converter( void ) +{ + fprintf( stdout, "Usage: tables_format_converter [Options]\n\n" ); + + fprintf( stdout, "Mandatory parameters : \n" ); + fprintf( stdout, "----------------------\n" ); + fprintf( stdout, "\n" ); + + fprintf( stdout, "Options :\n" ); + fprintf( stdout, "---------\n" ); + fprintf( stdout, "-output_file_path : Path where output file will be created (with separator, default = './').\n" ); + fprintf( stdout, "-output_file_name : Name of output file (without extension %s, default = '%s').\n", DEFAULT_BIN_FILE_EXT, DEFAULT_INPUT_ROM_FILE ); + fprintf( stdout, //"-8 : Select 8 kHz sampling frequency (no multiple values, all by default).\n" + "-16 : Select 16 kHz sampling frequency (no multiple values, all frequencies by default).\n" + "-32 : Select 32 kHz sampling frequency (no multiple values, all frequencies by default).\n" + "-48 : Select 48 kHz sampling frequency (no multiple values, all frequencies by default).\n" ); + fprintf( stdout, "-input_td_file_path : Path of binary files for time-domain renderer (with separator, used as flag).\n" ); + fprintf( stdout, "-input_td_file_name : Name of input td file (without extension %s, default = '%s').\n", DEFAULT_BIN_FILE_EXT, DEFAULT_INPUT_TD_BIN_FILE ); + fprintf( stdout, "\n" ); +} + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ + +char *output_path = NULL; +char *output_file_name = NULL; +char *full_out_path = NULL; + +char *input_td_bin_path = NULL; +char *input_td_bin_file_name = NULL; +char *full_in_td_path = NULL; + +int16_t nb_freq = IVAS_NB_SAMPLERATE; +const int32_t *freq_ptr = sample_rates; + +/*------------------------------------------------------------------------------------------* + * Tables converter - from ROM to BIN files + * + *------------------------------------------------------------------------------------------*/ +int main( int argc, char *argv[] ) +{ + int i, j, k, l; + +#ifdef FILE_HEADER + char *file_header, *file_header_wptr; + int32_t file_header_size; +#endif + int32_t fileSize, hrtf_size, hrtf_size_max; + int16_t nbHRTF, nbHRTFMax; + char **setOfHRTF = NULL; + FILE *bin_file = NULL; + + // Initialisation + + if ( rom2bin_init( argc, argv ) != 0 ) + { + return -1; + } + + bin_file = fopen( full_out_path, "wb" ); + if ( bin_file == NULL ) + { + fprintf( stderr, "Creation of binary file failed: %s\n\n", full_out_path ); + rom2bin_terminat(); + return -1; + } + + nbHRTFMax = IVAS_NB_RENDERER_TYPE * IVAS_NB_AUDIO_CONFIG * IVAS_NB_SAMPLERATE; + if ( input_td_bin_path != NULL ) + { + nbHRTFMax += IVAS_NB_SAMPLERATE; + } + setOfHRTF = (char **) malloc( nbHRTFMax * sizeof( char * ) ); + memset( setOfHRTF, 0x00, nbHRTFMax * sizeof( char * ) ); + + // Create the HRTF + + nbHRTF = 0; + hrtf_size_max = 0; + fileSize = 0; + + for ( i = 0; i < IVAS_NB_RENDERER_TYPE; i++ ) + { + hrtf_size = 0; + switch ( rend_types[i] ) + { + case RENDERER_BINAURAL_FASTCONV: + case RENDERER_BINAURAL_FASTCONV_ROOM: + for ( j = 0; j < IVAS_NB_AUDIO_CONFIG; j++ ) + { + /* Only one freq. for fastconv */ + setOfHRTF[nbHRTF] = create_hrtf_fastconv( rend_types[i], input_cfgs[j], freq_ptr[0], &hrtf_size ); + if ( hrtf_size == -1 ) + { + fprintf( stderr, "Creation of HRTF (%d, %d, %d) failed!\n\n", rend_types[i], input_cfgs[j], freq_ptr[0] ); + for ( l = 0; l < nbHRTF; l++ ) + { + free( setOfHRTF[l] ); + } + free( setOfHRTF ); + rom2bin_terminat(); + return -1; + } + else + { + if ( setOfHRTF[nbHRTF] != NULL ) + { + nbHRTF++; + fileSize += hrtf_size; + if ( hrtf_size_max < hrtf_size ) + hrtf_size_max = hrtf_size; + } + } + } + break; + case RENDERER_BINAURAL_PARAMETRIC: + /* Not handled separately. RENDERER_BINAURAL_PARAMETRIC_ROOM will contain the data. */ + break; + case RENDERER_BINAURAL_PARAMETRIC_ROOM: + /* Parametric will always have just one set regardless of input and frequency. */ + setOfHRTF[nbHRTF] = create_hrtf_parametric( &hrtf_size ); + if ( hrtf_size == -1 ) + { + fprintf( stderr, "Creation of HRTF for parametric renderer (%d) failed!\n\n", rend_types[i] ); + for ( l = 0; l < nbHRTF; l++ ) + { + free( setOfHRTF[l] ); + } + free( setOfHRTF ); + rom2bin_terminat(); + return -1; + } + else + { + if ( setOfHRTF[nbHRTF] != NULL ) + { + nbHRTF++; + fileSize += hrtf_size; + if ( hrtf_size_max < hrtf_size ) + hrtf_size_max = hrtf_size; + } + } + break; + case RENDERER_BINAURAL_MIXER_CONV: + case RENDERER_BINAURAL_MIXER_CONV_ROOM: + for ( j = 0; j < IVAS_NB_AUDIO_CONFIG; j++ ) + { + for ( k = 0; k < nb_freq; k++ ) + { + setOfHRTF[nbHRTF] = create_hrtf_crend( rend_types[i], input_cfgs[j], freq_ptr[k], &hrtf_size ); + if ( hrtf_size == -1 ) + { + fprintf( stderr, "Creation of HRTF (%d, %d, %d) failed!\n\n", rend_types[i], input_cfgs[j], freq_ptr[k] ); + for ( l = 0; l < nbHRTF; l++ ) + { + free( setOfHRTF[l] ); + } + free( setOfHRTF ); + rom2bin_terminat(); + return -1; + } + else + { + if ( setOfHRTF[nbHRTF] != NULL ) + { + nbHRTF++; + fileSize += hrtf_size; + if ( hrtf_size_max < hrtf_size ) + hrtf_size_max = hrtf_size; + } + } + } + } + break; + case RENDERER_BINAURAL_OBJECTS_TD: + if ( full_in_td_path != NULL ) + { + for ( k = 0; k < nb_freq; k++ ) + { + setOfHRTF[nbHRTF] = create_hrtf_tdrend( freq_ptr[k], &hrtf_size ); + if ( hrtf_size == -1 ) + { + fprintf( stderr, "Creation of HRTF (%d, %d, %d) failed!\n\n", rend_types[i], input_cfgs[j], freq_ptr[k] ); + for ( l = 0; l < nbHRTF; l++ ) + { + free( setOfHRTF[l] ); + } + free( setOfHRTF ); + rom2bin_terminat(); + return -1; + } + else + { + if ( setOfHRTF[nbHRTF] != NULL ) + { + nbHRTF++; + fileSize += hrtf_size; + if ( hrtf_size_max < hrtf_size ) + hrtf_size_max = hrtf_size; + } + } + } + } + break; + default: + break; + } + } + +#ifdef FILE_HEADER + // Create the file header and write it in the bin file + + // [Declaration of the binary file] + // File Identifier (8 bytes) + // Size of file in bytes (4 bytes) + // Number of HRTF (2 bytes) + // Max length of HRTF data (4 bytes) + + file_header_size = file_identifier_len + sizeof( int32_t ) + sizeof( int16_t ) + sizeof( int32_t ); + file_header = (char *) malloc( file_header_size ); + if ( file_header == NULL ) + { + fprintf( stderr, "Memory allocation for the file header failed!\n\n" ); + for ( l = 0; l < nbHRTF; l++ ) + { + free( setOfHRTF[l] ); + } + free( setOfHRTF ); + rom2bin_terminat(); + return -1; + } + + fileSize += file_header_size; + file_header_wptr = file_header; + + memcpy( file_header_wptr, file_identifier, file_identifier_len ); + file_header_wptr += file_identifier_len; + + memcpy( file_header_wptr, &( fileSize ), sizeof( int32_t ) ); + file_header_wptr += sizeof( int32_t ); + + memcpy( file_header_wptr, &( nbHRTF ), sizeof( int16_t ) ); + file_header_wptr += sizeof( int16_t ); + + hrtf_size_max -= 4 * sizeof( int32_t ); + memcpy( file_header_wptr, &( hrtf_size_max ), sizeof( int32_t ) ); + file_header_wptr += sizeof( int32_t ); + + fwrite( file_header, file_header_size, 1, bin_file ); + free( file_header ); +#endif + + // Write each HRTF in the bin file + + for ( i = 0; i < nbHRTF; i++ ) + { + fwrite( setOfHRTF[i], read_hrtf_size( setOfHRTF[i] ), 1, bin_file ); + free( setOfHRTF[i] ); + setOfHRTF[i] = NULL; + } + free( setOfHRTF ); + setOfHRTF = NULL; + + if ( bin_file != NULL ) + { + fclose( bin_file ); + bin_file = NULL; + } + + // Testing of the generated file + + bin_file = NULL; + bin_file = fopen( full_out_path, "rb" ); + if ( bin_file == NULL ) + { + fprintf( stderr, "Checking : Reading of binary file failed: %s\n\n", full_out_path ); + return -1; + } + + if ( 0 == check_bin_file( bin_file ) ) + { + fprintf( stdout, "Binary file successfully generated.\n\n" ); + } + else + { + fprintf( stderr, "Binary file generation failed!\n\n" ); + } + fclose( bin_file ); + + rom2bin_terminat(); + + return 0; +} + +/*---------------------------------------------------------------------* + * create_hrtf_crend() + * + *---------------------------------------------------------------------*/ +char *create_hrtf_crend( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, int32_t *hrtf_size ) +{ + crend_hrtf_tables_dimensions tabs_dims; + crend_hrtf_tables_pointers tabs_ptrs; + + /* uint16_t max_num_iterations, max_num_iterations_diffuse, index_frequency_max_diffuse; */ + uint16_t iChan, iIR; + uint32_t hrtf_data_size, data_size_tmp; + uint32_t iIter, iIndex; + /* uint32_t total_num_fsamp_per_iteration, iIter, iIndex; + uint32_t total_num_fsamp_per_iteration_diff; */ + float *coeff_rptr; + char *hrtf = NULL, *hrtf_wptr; + + memset( &tabs_dims, 0x00, sizeof( crend_hrtf_tables_dimensions ) ); + memset( &tabs_ptrs, 0x00, sizeof( crend_hrtf_tables_pointers ) ); + hrtf_data_size = 0; + *hrtf_size = 0; + + /* Binary file - block description : + + latency_s => float + + max_num_ir => uint16_t + BINAURAL_CHANNELS => uint16_t (BINAURAL_CHANNELS) + + max_num_iterations => int16_t + num_iterations => uint16_t[max_num_ir][BINAURAL_CHANNELS] + pIndex_frequency_max => uint16_t[max_num_ir][BINAURAL_CHANNELS][max_num_iterations] (Pointer) + + max_num_iterations_diffuse => int16_t + num_iterations_diffuse => uint16_t[BINAURAL_CHANNELS] + pIndex_frequency_max_diffuse => uint16_t[BINAURAL_CHANNELS][max_num_iterations_diffuse] (Pointer) + + index_frequency_max_diffuse => uint16_t + inv_diffuse_weight => float[max_num_ir] + + max_total_num_fsamp_per_iteration => uint16_t + coeff_re => float[max_num_ir][BINAURAL_CHANNELS][max_total_num_fsamp_per_iteration] (Pointer) + coeff_im => float[max_num_ir][BINAURAL_CHANNELS][max_total_num_fsamp_per_iteration] (Pointer) + + max_total_num_fsamp_per_iteration_diff => uint16_t + coeff_diffuse_re => float[BINAURAL_CHANNELS][max_total_num_fsamp_per_iteration] (Pointer) + coeff_diffuse_im => float[BINAURAL_CHANNELS][max_total_num_fsamp_per_iteration] (Pointer) + */ + + // First, get the tables and the relative dimensions + + if ( get_crend_hrtf_tables( rend_type, input_cfg, frequency, &tabs_ptrs, &tabs_dims ) == -1 ) + { + fprintf( stderr, "Get table failed!\n\n" ); + free( hrtf ); + *hrtf_size = -1; + return NULL; + } + + if ( tabs_dims.max_num_ir == 0 ) + { + // Table not found + *hrtf_size = 0; + return NULL; + } + + // Then, determine the block size + + hrtf_data_size = compute_crend_hrtf_data_size( &tabs_ptrs, &tabs_dims ); + + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decodeur output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + *hrtf_size = sizeof( ivas_hrtfs_header_t ) + hrtf_data_size; + hrtf = (char *) malloc( *hrtf_size ); + if ( hrtf == NULL ) + { + fprintf( stderr, "Memory allocation for the block failed!\n\n" ); + *hrtf_size = -1; + return NULL; + } + + memset( hrtf, 0x00, *hrtf_size ); + hrtf_wptr = hrtf; + + // Write the HRTF header + + // Renderer type + memcpy( hrtf_wptr, &( rend_type ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Decoder output format + memcpy( hrtf_wptr, &( input_cfg ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Sampling Frequency + memcpy( hrtf_wptr, &( frequency ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Raw data size + memcpy( hrtf_wptr, &( hrtf_data_size ), sizeof( uint32_t ) ); + hrtf_wptr += sizeof( uint32_t ); + + // Write the HRTF raw data + + memcpy( hrtf_wptr, tabs_ptrs.latency_s, sizeof( float ) ); // latency_s + hrtf_wptr += sizeof( float ); + + memcpy( hrtf_wptr, &( tabs_dims.max_num_ir ), sizeof( uint16_t ) ); // max_num_ir + hrtf_wptr += sizeof( uint16_t ); + + uint16_t nchan_bin = BINAURAL_CHANNELS; + memcpy( hrtf_wptr, &nchan_bin, sizeof( uint16_t ) ); // BINAURAL_CHANNELS + hrtf_wptr += sizeof( uint16_t ); + + memcpy( hrtf_wptr, &( tabs_dims.max_num_iterations ), sizeof( int16_t ) ); // max_num_iterations + hrtf_wptr += sizeof( int16_t ); + + data_size_tmp = tabs_dims.max_num_ir * BINAURAL_CHANNELS * sizeof( uint16_t ); + memcpy( hrtf_wptr, tabs_ptrs.num_iterations, data_size_tmp ); // num_iterations + hrtf_wptr += data_size_tmp; + + data_size_tmp = tabs_dims.max_num_ir * BINAURAL_CHANNELS * tabs_dims.max_num_iterations * sizeof( uint16_t ); + memcpy( hrtf_wptr, tabs_ptrs.pIndex_frequency_max, data_size_tmp ); // pIndex_frequency_max + hrtf_wptr += data_size_tmp; + + memcpy( hrtf_wptr, &( tabs_dims.max_num_iterations_diffuse ), sizeof( int16_t ) ); // max_num_iterations_diffuse + hrtf_wptr += sizeof( int16_t ); + + if ( tabs_dims.max_num_iterations_diffuse != 0 ) + { + data_size_tmp = BINAURAL_CHANNELS * sizeof( uint16_t ); + memcpy( hrtf_wptr, tabs_ptrs.num_iterations_diffuse, data_size_tmp ); // num_iterations_diffuse + hrtf_wptr += data_size_tmp; + + // pIndex_frequency_max_diffuse (the size depends on num_iterations_diffuse) + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + data_size_tmp = tabs_ptrs.num_iterations_diffuse[iChan] * sizeof( uint16_t ); + memcpy( hrtf_wptr, tabs_ptrs.pIndex_frequency_max_diffuse, data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + + memcpy( hrtf_wptr, tabs_ptrs.index_frequency_max_diffuse, sizeof( uint16_t ) ); // index_frequency_max_diffuse + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = tabs_dims.max_num_ir * sizeof( float ); + memcpy( hrtf_wptr, tabs_ptrs.inv_diffuse_weight, data_size_tmp ); // inv_diffuse_weight + hrtf_wptr += data_size_tmp; + + memcpy( hrtf_wptr, &( tabs_dims.max_total_num_fsamp_per_iteration ), sizeof( uint16_t ) ); // max_total_num_fsamp_per_iteration + hrtf_wptr += sizeof( uint16_t ); + + // coeff_re (The size depends on pIndex_frequency_max) + for ( iIR = 0, iIndex = 0; iIR < tabs_dims.max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_re + ( iIR * BINAURAL_CHANNELS + iChan ) * tabs_dims.max_total_num_fsamp_per_iteration; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + data_size_tmp = tabs_ptrs.pIndex_frequency_max[iIndex] * sizeof( float ); + memcpy( hrtf_wptr, coeff_rptr, data_size_tmp ); + hrtf_wptr += data_size_tmp; + coeff_rptr += tabs_ptrs.pIndex_frequency_max[iIndex++]; + } + } + } + + // coeff_im : The size depends on pIndex_frequency_max + for ( iIR = 0, iIndex = 0; iIR < tabs_dims.max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_im + ( iIR * BINAURAL_CHANNELS + iChan ) * tabs_dims.max_total_num_fsamp_per_iteration; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + data_size_tmp = tabs_ptrs.pIndex_frequency_max[iIndex] * sizeof( float ); + memcpy( hrtf_wptr, coeff_rptr, data_size_tmp ); + hrtf_wptr += data_size_tmp; + coeff_rptr += tabs_ptrs.pIndex_frequency_max[iIndex++]; + } + } + } + + memcpy( hrtf_wptr, &( tabs_dims.max_total_num_fsamp_per_iteration_diff ), sizeof( uint16_t ) ); // max_total_num_fsamp_per_iteration_diff + hrtf_wptr += sizeof( uint16_t ); + + if ( tabs_dims.max_total_num_fsamp_per_iteration_diff != 0 ) + { + // coeff_diffuse_re : The size depends on pIndex_frequency_max_diffuse + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_diffuse_re + iChan * tabs_dims.max_total_num_fsamp_per_iteration_diff; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations_diffuse[iChan]; iIter++ ) + { + data_size_tmp = tabs_ptrs.pIndex_frequency_max_diffuse[iIndex] * sizeof( float ); + memcpy( hrtf_wptr, coeff_rptr, data_size_tmp ); + hrtf_wptr += data_size_tmp; + coeff_rptr += tabs_ptrs.pIndex_frequency_max_diffuse[iIndex++]; + } + } + + // coeff_diffuse_im : The size depends on pIndex_frequency_max_diffuse + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_diffuse_im + iChan * tabs_dims.max_total_num_fsamp_per_iteration_diff; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations_diffuse[iChan]; iIter++ ) + { + data_size_tmp = tabs_ptrs.pIndex_frequency_max_diffuse[iIndex] * sizeof( float ); + memcpy( hrtf_wptr, coeff_rptr, data_size_tmp ); + hrtf_wptr += data_size_tmp; + coeff_rptr += tabs_ptrs.pIndex_frequency_max_diffuse[iIndex++]; + } + } + } + + return hrtf; +} + +/*---------------------------------------------------------------------* + * create_hrtf_tdrend() + * + *---------------------------------------------------------------------*/ +char *create_hrtf_tdrend( int32_t frequency, int32_t *hrtf_size ) +{ + + FILE *input_td_bin_file = NULL; + int32_t td_hrtf_header_size, td_hrtf_data_size; + char *td_hrtf = NULL, *td_hrtf_wptr; + + *hrtf_size = 0; + + sprintf( full_in_td_path, "%s%s_%dkHz%s", input_td_bin_path, input_td_bin_file_name, frequency / 1000, DEFAULT_BIN_FILE_EXT ); + input_td_bin_file = fopen( full_in_td_path, "rb" ); + + if ( input_td_bin_file != NULL ) + { + + fseek( input_td_bin_file, 0, SEEK_END ); + td_hrtf_data_size = ftell( input_td_bin_file ); + fseek( input_td_bin_file, 0, SEEK_SET ); + + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decoder output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + td_hrtf_header_size = sizeof( int32_t ) + sizeof( int32_t ) + sizeof( int32_t ) + sizeof( uint32_t ); + *hrtf_size = td_hrtf_header_size + td_hrtf_data_size; + td_hrtf = (char *) malloc( *hrtf_size ); + + if ( td_hrtf == NULL ) + { + fprintf( stderr, "Memory allocation for the block failed!\n\n" ); + fclose( input_td_bin_file ); + *hrtf_size = -1; + return NULL; + } + + memset( td_hrtf, 0x00, *hrtf_size ); + td_hrtf_wptr = td_hrtf; + + // Get the HRTF header + + // Renderer type + *( (int32_t *) ( td_hrtf_wptr ) ) = RENDERER_BINAURAL_OBJECTS_TD; + td_hrtf_wptr += sizeof( int32_t ); + + // Decoder output format + *( (int32_t *) ( td_hrtf_wptr ) ) = BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED; + td_hrtf_wptr += sizeof( int32_t ); + + // Sampling Frequency + memcpy( td_hrtf_wptr, &( frequency ), sizeof( int32_t ) ); + td_hrtf_wptr += sizeof( int32_t ); + + // Raw data size + memcpy( td_hrtf_wptr, &( td_hrtf_data_size ), sizeof( uint32_t ) ); + td_hrtf_wptr += sizeof( uint32_t ); + + // Get the HRTF raw data + + if ( fread( td_hrtf_wptr, td_hrtf_data_size, 1, input_td_bin_file ) != 1 ) + { + + fprintf( stderr, "Reading of the td hrtf failed!\n\n" ); + fclose( input_td_bin_file ); + free( td_hrtf ); + *hrtf_size = -1; + return NULL; + } + + fclose( input_td_bin_file ); + input_td_bin_file = NULL; + } + else + { + fprintf( stderr, "Opening of file %s failed!\n\n", full_in_td_path ); + *hrtf_size = -1; + return NULL; + } + + return td_hrtf; +} + +/*---------------------------------------------------------------------* + * create_hrtf_fastconv() + * + *---------------------------------------------------------------------*/ +char *create_hrtf_fastconv( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, int32_t *hrtf_size ) +{ + char *hrtf = NULL, *hrtf_wptr; + uint32_t hrtf_data_size; + uint32_t data_size_tmp; + + int16_t i, j; + uint16_t binaural_convbands; + uint16_t hrtf_channels; + uint16_t num_taps; + uint16_t cldfb_nchan_max; + float latency_s; + + hrtf_data_size = 0; + + /* Binary file - block description : + + BINAURAL_CONVBANDS => uint16_t + + HRIRs + HRIR_latency_s => float + HRTF_LS_CHANNELS => uint16_t + ntaps => int16_t + leftHRIRReal => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + leftHRIRImag => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + rightHRIRReal => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + rightHRIRImag => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + + HOA3 HRIRs + HRIR_HOA3_latency_s => float + HRTF_SH_CHANNELS => uint16_t + ntaps => int16_t + leftHRIRReal_HOA3 => float[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][num_taps] + leftHRIRImag_HOA3 => float[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][num_taps] + rightHRIRReal_HOA3 => float[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][num_taps] + rightHRIRImag_HOA3 => float[BINAURAL_CONVBANDS][HRTF_SH_CHANNELS][num_taps] + + BRIRs + BRIR_latency_s => float + HRTF_LS_CHANNELS => uint16_t + ntaps => int16_t + leftBRIRReal => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + leftBRIRImag => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + rightBRIRReal => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + rightBRIRImag => float[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][num_taps] + + CLDFB_NO_CHANNELS_MAX => uint16_t + + fastConvReverberationTimes => float[CLDFB_NO_CHANNELS_MAX] + fastConvReverberationEneCorrection => float[CLDFB_NO_CHANNELS_MAX] +*/ + + // Set table sizes + binaural_convbands = BINAURAL_CONVBANDS; + + if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + latency_s = FASTCONV_HRIR_latency_s; + hrtf_channels = HRTF_LS_CHANNELS; + num_taps = BINAURAL_NTAPS; + + if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + latency_s = FASTCONV_BRIR_latency_s; + hrtf_channels = HRTF_LS_CHANNELS; + num_taps = BINAURAL_NTAPS_MAX; + cldfb_nchan_max = CLDFB_NO_CHANNELS_MAX; + } + } + else if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + /* No HOA3 BRIRs */ + return NULL; + } + + latency_s = FASTCONV_HOA3_latency_s; + hrtf_channels = HRTF_SH_CHANNELS; + num_taps = BINAURAL_NTAPS; + } + else + { + fprintf( stderr, "Unsupported renderer type in create_hrtf_fastconv()\n\n" ); + return NULL; + } + + // Compute total size of data to write + hrtf_data_size += sizeof( uint16_t ); // BINAURAL_CONVBANDS + hrtf_data_size += sizeof( float ); // latency_s + hrtf_data_size += sizeof( uint16_t ); // HRTF_{SH,LS}_CHANNELS + hrtf_data_size += sizeof( uint16_t ); // num_taps + hrtf_data_size += 4 * ( BINAURAL_CONVBANDS * hrtf_channels * num_taps * sizeof( float ) ); // HRTF + + if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + hrtf_data_size += sizeof( uint16_t ); // CLDFB_NO_CHANNELS_MAX + hrtf_data_size += CLDFB_NO_CHANNELS_MAX * sizeof( float ); // fastconvReverberationTimes + hrtf_data_size += CLDFB_NO_CHANNELS_MAX * sizeof( float ); // fastconvEneCorrections + } + + // Allocate memory + *hrtf_size = sizeof( ivas_hrtfs_header_t ) + hrtf_data_size; + hrtf = (char *) malloc( *hrtf_size ); + + if ( hrtf == NULL ) + { + fprintf( stderr, "Memory allocation for the block failed!\n\n" ); + *hrtf_size = -1; + return NULL; + } + + // Write + + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decoder output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + memset( hrtf, 0x00, *hrtf_size ); + hrtf_wptr = hrtf; + + // Renderer type + memcpy( hrtf_wptr, &( rend_type ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Decoder output format + memcpy( hrtf_wptr, &( input_cfg ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Sampling Frequency + memcpy( hrtf_wptr, &( frequency ), sizeof( int32_t ) ); + hrtf_wptr += sizeof( int32_t ); + + // Raw data size + memcpy( hrtf_wptr, &( hrtf_data_size ), sizeof( uint32_t ) ); + hrtf_wptr += sizeof( uint32_t ); + + + // Write the HRTF raw data + memcpy( hrtf_wptr, &( binaural_convbands ), sizeof( uint16_t ) ); // nbands_bin => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + + // HRIR + if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + memcpy( hrtf_wptr, &( latency_s ), sizeof( float ) ); // latency_s => float + hrtf_wptr += sizeof( float ); + + memcpy( hrtf_wptr, &( hrtf_channels ), sizeof( uint16_t ) ); // hrtf_channels => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + memcpy( hrtf_wptr, &( num_taps ), sizeof( uint16_t ) ); // num_taps => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = num_taps * sizeof( float ); + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &leftHRIRReal[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &leftHRIRImag[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightHRIRReal[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightHRIRImag[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + } + // HRIR_HOA3 + else if ( rend_type == RENDERER_BINAURAL_FASTCONV && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + memcpy( hrtf_wptr, &( latency_s ), sizeof( float ) ); // latency_s => float + hrtf_wptr += sizeof( float ); + + memcpy( hrtf_wptr, &( hrtf_channels ), sizeof( uint16_t ) ); // hrtf_channels => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + memcpy( hrtf_wptr, &( num_taps ), sizeof( uint16_t ) ); // num_taps => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = num_taps * sizeof( float ); + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &leftHRIRReal_HOA3[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &leftHRIRImag_HOA3[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightHRIRReal_HOA3[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightHRIRImag_HOA3[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + } + // BRIR + else if ( rend_type == RENDERER_BINAURAL_FASTCONV_ROOM && input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + memcpy( hrtf_wptr, &( latency_s ), sizeof( float ) ); // latency_s => float + hrtf_wptr += sizeof( float ); + + memcpy( hrtf_wptr, &( hrtf_channels ), sizeof( uint16_t ) ); // hrtf_channels => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + memcpy( hrtf_wptr, &( num_taps ), sizeof( uint16_t ) ); // num_taps => uint16_t + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = num_taps * sizeof( float ); + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, leftBRIRReal[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &leftBRIRImag[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightBRIRReal[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CONVBANDS; i++ ) + { + for ( j = 0; j < hrtf_channels; j++ ) + { + memcpy( hrtf_wptr, &rightBRIRImag[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + + // Reverb Parameters + memcpy( hrtf_wptr, &( cldfb_nchan_max ), sizeof( uint16_t ) ); // cldfb_ncol => int16_t + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = cldfb_nchan_max * sizeof( float ); + memcpy( hrtf_wptr, &( fastconvReverberationTimes ), data_size_tmp ); // fastconvReverberationTimes + memcpy( hrtf_wptr, &( fastconvReverberationEneCorrections ), data_size_tmp ); // fastconvEneCorrections + } + + return hrtf; +} + +/*---------------------------------------------------------------------* + * create_hrtf_parametric() + * + *---------------------------------------------------------------------*/ +char *create_hrtf_parametric( int32_t *hrtf_size ) +{ + char *hrtf = NULL, *hrtf_wptr; + uint32_t hrtf_data_size; + uint32_t data_size_tmp; + + int16_t i, j; + + hrtf_data_size = 0; + + /* Binary file - block description : + + HRTFs + HRTF_SH_CHANNELS => uint16_t + HRTF_NUM_BINS => uint16_t + hrtfShCoeffsRe => float[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + hrtfShCoeffsIm => float[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]; + + BRIR-based reverb + + CLDFB_NO_CHANNELS_MAX => uint16_t + parametricReverberationTimes => float[CLDFB_NO_CHANNELS_MAX]; + parametricReverberationEneCorrections => float[CLDFB_NO_CHANNELS_MAX]; + parametricEarlyPartEneCorrection => float[CLDFB_NO_CHANNELS_MAX]; +*/ + + // Compute total size of data to write + // CLDFB SH domain HRTF-data + hrtf_data_size += sizeof( uint16_t ); // HRTF_SH_CHANNELS + hrtf_data_size += sizeof( uint16_t ); // HRTF_NUM_BINS + hrtf_data_size += 2 * ( BINAURAL_CHANNELS * HRTF_SH_CHANNELS * HRTF_NUM_BINS * sizeof( float ) ); // HRTF + + // Always write also BRIR reverb data + hrtf_data_size += sizeof( uint16_t ); // CLDFB_NO_CHANNELS_MAX + hrtf_data_size += CLDFB_NO_CHANNELS_MAX * sizeof( float ); // parametricReverberationTimes + hrtf_data_size += CLDFB_NO_CHANNELS_MAX * sizeof( float ); // parametricReverberationEneCorrections + hrtf_data_size += CLDFB_NO_CHANNELS_MAX * sizeof( float ); // parametricEarlyPartEneCorrection + + // Allocate memory + *hrtf_size = sizeof( ivas_hrtfs_header_t ) + hrtf_data_size; + hrtf = (char *) malloc( *hrtf_size ); + + if ( hrtf == NULL ) + { + fprintf( stderr, "Memory allocation for the block failed!\n\n" ); + *hrtf_size = -1; + return NULL; + } + + // Write + + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decoder output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + memset( hrtf, 0x00, *hrtf_size ); + hrtf_wptr = hrtf; + + // Renderer type - we use only parametric room type here to cover both cases + *( (int32_t *) ( hrtf_wptr ) ) = RENDERER_BINAURAL_PARAMETRIC_ROOM; + hrtf_wptr += sizeof( int32_t ); + + // Decoder output format - not relevant parametric binaural renderer + *( (int32_t *) ( hrtf_wptr ) ) = BINAURAL_INPUT_AUDIO_CONFIG_UNDEFINED; + hrtf_wptr += sizeof( int32_t ); + + // Sampling Frequency + *( (int32_t *) ( hrtf_wptr ) ) = 48000; + hrtf_wptr += sizeof( int32_t ); + + // Raw data size + memcpy( hrtf_wptr, &( hrtf_data_size ), sizeof( uint32_t ) ); + hrtf_wptr += sizeof( uint32_t ); + + + // Write the HRTF raw data + *( (uint16_t *) ( hrtf_wptr ) ) = HRTF_SH_CHANNELS; + hrtf_wptr += sizeof( uint16_t ); + + *( (uint16_t *) ( hrtf_wptr ) ) = HRTF_NUM_BINS; + hrtf_wptr += sizeof( uint16_t ); + + + // HRTF + data_size_tmp = HRTF_NUM_BINS * sizeof( float ); + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( hrtf_wptr, &hrtfShCoeffsRe[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + { + memcpy( hrtf_wptr, &hrtfShCoeffsIm[i][j], data_size_tmp ); + hrtf_wptr += data_size_tmp; + } + } + + // Reverb Parameters + *( (uint16_t *) ( hrtf_wptr ) ) = CLDFB_NO_CHANNELS_MAX; + hrtf_wptr += sizeof( uint16_t ); + + data_size_tmp = CLDFB_NO_CHANNELS_MAX * sizeof( float ); + memcpy( hrtf_wptr, &( parametricReverberationTimes ), data_size_tmp ); // parametricReverberationTimes + hrtf_wptr += data_size_tmp; + memcpy( hrtf_wptr, &( parametricReverberationEneCorrections ), data_size_tmp ); // parametricReverberationEneCorrections + hrtf_wptr += data_size_tmp; + memcpy( hrtf_wptr, &( parametricEarlyPartEneCorrection ), data_size_tmp ); // parametricEarlyPartEneCorrection + hrtf_wptr += data_size_tmp; + + return hrtf; +} + +/*---------------------------------------------------------------------* + * get_crend_hrtf_tables() + * + *---------------------------------------------------------------------*/ +int16_t get_crend_hrtf_tables( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, crend_hrtf_tables_pointers *hrtf_table_ptrs /*OUT*/, crend_hrtf_tables_dimensions *hrtf_table_dims /*OUT*/ ) +{ + int16_t result = -1; + uint16_t iChan, iIR, iIter, iIndex, max_num_iterations; + uint16_t total_num_fsamp_per_iteration, total_num_fsamp_per_iteration_diff; + + crend_hrtf_tables_pointers hrtf_table_ptrs_out; + crend_hrtf_tables_dimensions hrtf_table_dims_out; + + memset( &hrtf_table_ptrs_out, 0x00, sizeof( crend_hrtf_tables_pointers ) ); + memset( &hrtf_table_dims_out, 0x00, sizeof( crend_hrtf_tables_dimensions ) ); + + if ( rend_type == RENDERER_BINAURAL_MIXER_CONV ) + { + if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + if ( frequency == 48000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_48kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_diffuse_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_index_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_HRIR_inv_diffuse_weight_48kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_HRIR_coeff_re_48kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_HRIR_coeff_im_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_re_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_im_48kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_48kHz; + + result = 0; + } + else if ( frequency == 32000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_32kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_diffuse_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_index_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_HRIR_inv_diffuse_weight_32kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_HRIR_coeff_re_32kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_HRIR_coeff_im_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_re_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_im_32kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_32kHz; + + result = 0; + } + else if ( frequency == 16000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_16kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_num_iterations_diffuse_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_pIndex_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_HRIR_index_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_HRIR_inv_diffuse_weight_16kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_HRIR_coeff_re_16kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_HRIR_coeff_im_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_re_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_HRIR_coeff_diffuse_im_16kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_HRIR_max_num_iterations_16kHz; + + result = 0; + } + + hrtf_table_dims_out.max_num_ir = 15; + + // Please see below : Next dimensions set according to the tables + /*hrtf_table_dims_out.max_total_num_fsamp_per_iteration = 0; + hrtf_table_dims_out.max_num_iterations_diffuse = 0; + hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff = 0;*/ + } + else if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + if ( frequency == 48000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_HOA3_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_48kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_diffuse_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_index_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_HOA3_HRIR_inv_diffuse_weight_48kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_re_48kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_im_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_re_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_im_48kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_48kHz; + + result = 0; + } + else if ( frequency == 32000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_HOA3_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_32kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_diffuse_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_index_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_HOA3_HRIR_inv_diffuse_weight_32kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_re_32kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_im_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_re_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_im_32kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_32kHz; + + result = 0; + } + else if ( frequency == 16000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_HOA3_HRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_16kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_num_iterations_diffuse_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_pIndex_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_HOA3_HRIR_index_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_HOA3_HRIR_inv_diffuse_weight_16kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_re_16kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_im_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_re_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_HOA3_HRIR_coeff_diffuse_im_16kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_HOA3_HRIR_max_num_iterations_16kHz; + + result = 0; + } + + hrtf_table_dims_out.max_num_ir = 16; + + // Please see below : Next dimensions set according to the tables + /*hrtf_table_dims_out.max_total_num_fsamp_per_iteration = 0; + hrtf_table_dims_out.max_num_iterations_diffuse = 0; + hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff = 0;*/ + } + } + else if ( rend_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_COMBINED ) + { + if ( frequency == 48000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_BRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_48kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_diffuse_48kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_index_frequency_max_diffuse_48kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_BRIR_inv_diffuse_weight_48kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_BRIR_coeff_re_48kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_BRIR_coeff_im_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_re_48kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_im_48kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_48kHz; + + result = 0; + } + else if ( frequency == 32000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_BRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_32kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_diffuse_32kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_index_frequency_max_diffuse_32kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_BRIR_inv_diffuse_weight_32kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_BRIR_coeff_re_32kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_BRIR_coeff_im_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_re_32kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_im_32kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_32kHz; + + result = 0; + } + else if ( frequency == 16000 ) + { + hrtf_table_ptrs_out.latency_s = &CRendBin_Combined_BRIR_latency_s; + hrtf_table_ptrs_out.num_iterations = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_16kHz ); + hrtf_table_ptrs_out.num_iterations_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_num_iterations_diffuse_16kHz ); + hrtf_table_ptrs_out.pIndex_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_pIndex_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.index_frequency_max_diffuse = (uint16_t *) ( &CRendBin_Combined_BRIR_index_frequency_max_diffuse_16kHz ); + hrtf_table_ptrs_out.inv_diffuse_weight = (float *) ( &CRendBin_Combined_BRIR_inv_diffuse_weight_16kHz ); + hrtf_table_ptrs_out.coeff_re = (float *) ( &CRendBin_Combined_BRIR_coeff_re_16kHz ); + hrtf_table_ptrs_out.coeff_im = (float *) ( &CRendBin_Combined_BRIR_coeff_im_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_re = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_re_16kHz ); + hrtf_table_ptrs_out.coeff_diffuse_im = (float *) ( &CRendBin_Combined_BRIR_coeff_diffuse_im_16kHz ); + + hrtf_table_dims_out.max_num_iterations = CRendBin_Combined_BRIR_max_num_iterations_16kHz; + + result = 0; + } + + hrtf_table_dims_out.max_num_ir = 15; + + // Please see below : Next dimensions set according to the tables + /*hrtf_table_dims_out.max_total_num_fsamp_per_iteration = 0; + hrtf_table_dims_out.max_num_iterations_diffuse = 0; + hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff = 0;*/ + } + else if ( input_cfg == BINAURAL_INPUT_AUDIO_CONFIG_HOA ) + { + result = 0; + } + } + + // Dimensions set according to the tables + if ( ( result == 0 ) && ( hrtf_table_dims_out.max_num_ir != 0 ) ) + { + // Check the max_num_iterations + // Please note : The size of the table num_iterations doesn't change (only depends on max_num_ir). + max_num_iterations = 0; + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + for ( iIR = 0; iIR < hrtf_table_dims_out.max_num_ir; iIR++ ) + { + if ( max_num_iterations < hrtf_table_ptrs_out.num_iterations[BINAURAL_CHANNELS * iIR + iChan] ) + { + max_num_iterations = hrtf_table_ptrs_out.num_iterations[BINAURAL_CHANNELS * iIR + iChan]; + } + } + } + if ( max_num_iterations != hrtf_table_dims_out.max_num_iterations ) + { + return -1; + } + + // Get the max_total_num_fsamp_per_iteration + // Please note : The size of the table pIndex_frequency_max doesn't change (only depends on max_num_iterations). + hrtf_table_dims_out.max_total_num_fsamp_per_iteration = 0; + for ( iIR = 0; iIR < hrtf_table_dims_out.max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + total_num_fsamp_per_iteration = 0; + for ( iIter = 0; iIter < hrtf_table_ptrs_out.num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + total_num_fsamp_per_iteration += hrtf_table_ptrs_out.pIndex_frequency_max[iIR * BINAURAL_CHANNELS * hrtf_table_dims_out.max_num_iterations + iChan * hrtf_table_dims_out.max_num_iterations + iIter]; + } + if ( hrtf_table_dims_out.max_total_num_fsamp_per_iteration < total_num_fsamp_per_iteration ) + { + hrtf_table_dims_out.max_total_num_fsamp_per_iteration = total_num_fsamp_per_iteration; + } + } + } + + // Get the max_num_iterations_diffuse + // Please note : The size of the table num_iterations_diffuse doesn't change. + hrtf_table_dims_out.max_num_iterations_diffuse = 0; + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + if ( hrtf_table_dims_out.max_num_iterations_diffuse < hrtf_table_ptrs_out.num_iterations_diffuse[iChan] ) + { + hrtf_table_dims_out.max_num_iterations_diffuse = hrtf_table_ptrs_out.num_iterations_diffuse[iChan]; + } + } + + // Get the max_total_num_fsamp_per_iteration_diff + // Please note : The size of the table pIndex_frequency_max_diffuse depends on the table num_iterations_diffuse). + hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff = 0; + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + total_num_fsamp_per_iteration_diff = 0; + + for ( iIter = 0; iIter < hrtf_table_ptrs_out.num_iterations_diffuse[iChan]; iIter++ ) + { + total_num_fsamp_per_iteration_diff += hrtf_table_ptrs_out.pIndex_frequency_max_diffuse[iIndex++]; + } + + if ( hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff < total_num_fsamp_per_iteration_diff ) + { + hrtf_table_dims_out.max_total_num_fsamp_per_iteration_diff = total_num_fsamp_per_iteration_diff; + } + } + } + + // Copy the results + if ( ( result == 0 ) && ( hrtf_table_ptrs != NULL ) ) + { + memcpy( hrtf_table_ptrs, &hrtf_table_ptrs_out, sizeof( crend_hrtf_tables_pointers ) ); + } + + if ( ( result == 0 ) && ( hrtf_table_dims != NULL ) ) + { + memcpy( hrtf_table_dims, &hrtf_table_dims_out, sizeof( crend_hrtf_tables_dimensions ) ); + } + + return result; +} + +/*---------------------------------------------------------------------* + * compute_crend_hrtf_data_size() + * + *---------------------------------------------------------------------*/ +int32_t compute_crend_hrtf_data_size( crend_hrtf_tables_pointers *hrtf_table_ptrs, crend_hrtf_tables_dimensions *hrtf_table_dims ) +{ + int32_t hrtf_data_size = 0; + int32_t iChan, iIR, iIndex, iIter; + + if ( ( hrtf_table_ptrs == NULL ) || ( hrtf_table_dims == NULL ) ) + { + return 0; + } + + hrtf_data_size += sizeof( float ); // latency_s + hrtf_data_size += sizeof( uint16_t ); // max_num_ir + hrtf_data_size += sizeof( uint16_t ); // BINAURAL_CHANNELS + hrtf_data_size += sizeof( int16_t ); // max_num_iterations + hrtf_data_size += hrtf_table_dims->max_num_ir * BINAURAL_CHANNELS * sizeof( uint16_t ); // num_iterations + hrtf_data_size += hrtf_table_dims->max_num_ir * BINAURAL_CHANNELS * hrtf_table_dims->max_num_iterations * sizeof( uint16_t ); // pIndex_frequency_max + + hrtf_data_size += sizeof( int16_t ); // max_num_iterations_diffuse + if ( hrtf_table_dims->max_num_iterations_diffuse != 0 ) + { + hrtf_data_size += BINAURAL_CHANNELS * sizeof( uint16_t ); // num_iterations_diffuse + // pIndex_frequency_max_diffuse : The size depends on num_iterations_diffuse + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + hrtf_data_size += hrtf_table_ptrs->num_iterations_diffuse[iChan] * sizeof( uint16_t ); + } + } + + hrtf_data_size += sizeof( uint16_t ); // index_frequency_max_diffuse + hrtf_data_size += hrtf_table_dims->max_num_ir * sizeof( float ); // inv_diffuse_weight + + hrtf_data_size += sizeof( uint16_t ); // max_total_num_fsamp_per_iteration + // coeff_re & coeff_im : The size depends on pIndex_frequency_max + for ( iIR = 0, iIndex = 0; iIR < hrtf_table_dims->max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + for ( iIter = 0; iIter < hrtf_table_ptrs->num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + hrtf_data_size += 2 * hrtf_table_ptrs->pIndex_frequency_max[iIndex++] * sizeof( float ); // 2* : re & im + } + } + } + + hrtf_data_size += sizeof( uint16_t ); // max_total_num_fsamp_per_iteration_diff + if ( hrtf_table_dims->max_total_num_fsamp_per_iteration_diff != 0 ) + { + // coeff_diffuse_re & coeff_diffuse_im : The size depends on pIndex_frequency_max + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + for ( iIter = 0; iIter < hrtf_table_ptrs->num_iterations_diffuse[iChan]; iIter++ ) + { + hrtf_data_size += 2 * hrtf_table_ptrs->pIndex_frequency_max_diffuse[iIndex++] * sizeof( float ); // 2* : re & im + } + } + } + + return hrtf_data_size; +} + +/*---------------------------------------------------------------------* + * check_bin_file() + * + *---------------------------------------------------------------------*/ +int16_t check_bin_file( FILE *hrtf_bin_file ) +{ +#ifdef FILE_HEADER + int i; + char *file_header_rptr; + int32_t ctrlFileSize, fileSize, file_header_size; + uint32_t hrtf_data_size_max; + int16_t nbHRTF; +#endif + char *file_header, *hrtf_data, *hrtf_data_rptr; + ivas_hrtfs_header_t hrtf_header; + int16_t result; + + result = 0; + file_header = NULL; + + if ( hrtf_bin_file != NULL ) + { +#ifdef FILE_HEADER + // Get the real size of file + + fseek( hrtf_bin_file, 0, SEEK_END ); + fileSize = ftell( hrtf_bin_file ); + fseek( hrtf_bin_file, 0, SEEK_SET ); + + // Create the file header + + file_header_size = file_identifier_len + sizeof( int32_t ) + sizeof( int16_t ) + sizeof( int32_t ); + file_header = (char *) malloc( file_header_size ); + if ( file_header == NULL ) + { + fprintf( stderr, "Checking : Memory allocation for the file header failed!\n\n" ); + return -1; + } + fread( file_header, file_header_size, 1, hrtf_bin_file ); + file_header_rptr = file_header; + + // Check the file header + + // Check the file control tag "IVASHRTF" + if ( strncmp( file_header_rptr, file_identifier, file_identifier_len ) != 0 ) + { + free( file_header ); + return -1; + } + file_header_rptr += file_identifier_len; + + // Check the size of file + ctrlFileSize = *( (int32_t *) ( file_header_rptr ) ); + if ( ctrlFileSize != fileSize ) + { + free( file_header ); + return -1; + } + file_header_rptr += sizeof( int32_t ); + + // Get the number of stored HRTF + nbHRTF = *( (int16_t *) ( file_header_rptr ) ); + file_header_rptr += sizeof( int16_t ); + + // Get the max size of data + hrtf_data_size_max = *( (int32_t *) ( file_header_rptr ) ); + file_header_rptr += sizeof( int32_t ); + + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decodeur output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + // Get each HRTF from the bin file + for ( i = 0; i < nbHRTF; i++ ) + { + if ( fread( &hrtf_header, sizeof( ivas_hrtfs_header_t ), 1, hrtf_bin_file ) != 1 ) + { + fprintf( stderr, "Reading of binary file failed (bad nb of HRTF in bin file)!\n\n" ); + free( file_header ); + return -1; + } + + if ( hrtf_data_size_max < hrtf_header.data_size ) + { + fprintf( stderr, "Bad header data size!\n\n" ); + free( file_header ); + return -1; + } +#else + // Header [Declaration of the HRTF] + // Renderer type (4 bytes) : See "RENDERER_TYPE" + // Decodeur output format (4 bytes) : See "BINAURAL_INPUT_AUDIO_CONFIG" + // Sampling Frequency (4 bytes) + // Raw data size (4 bytes) + + hrtf_data = NULL; + while ( fread( &hrtf_header, sizeof( ivas_hrtfs_header_t ), 1, hrtf_bin_file ) == 1 ) + { +#endif + hrtf_data = (char *) malloc( hrtf_header.data_size ); + if ( hrtf_data == NULL ) + { + fprintf( stderr, "Memory allocation for the hrtf failed!\n\n" ); + if ( file_header != NULL ) + free( file_header ); + return -1; + } + + if ( fread( hrtf_data, hrtf_header.data_size, 1, hrtf_bin_file ) == 1 ) + { + hrtf_data_rptr = hrtf_data; + if ( check_hrtf_data( hrtf_header.rend_type, hrtf_header.input_cfg, hrtf_header.frequency, hrtf_data_rptr, hrtf_header.data_size ) != 0 ) + { + fprintf( stderr, "HRTF data corrupted!\n\n" ); + if ( file_header != NULL ) + free( file_header ); + free( hrtf_data ); + return -1; + } + free( hrtf_data ); + } + else + { + fprintf( stderr, "Access to HRTF data failed!\n\n" ); + if ( file_header != NULL ) + free( file_header ); + free( hrtf_data ); + return -1; + } + } + + if ( file_header != NULL ) + free( file_header ); + } + else + { + return -1; + } + + return result; +} + +/*---------------------------------------------------------------------* + * check_hrtf_data() + * + *---------------------------------------------------------------------*/ + +int16_t check_hrtf_data( RENDERER_TYPE rend_type, BINAURAL_INPUT_AUDIO_CONFIG input_cfg, int32_t frequency, char *hrtf_data_in, int32_t hrtf_size_in ) +{ + int16_t result; + int32_t hrtf_data_size, ctrl_size, iChan, iIR, iIndex, iIter; + float *coeff_rptr; + char *hrtf_data_in_rptr; + + crend_hrtf_tables_dimensions tabs_dims; + crend_hrtf_tables_pointers tabs_ptrs; + + if ( rend_type == RENDERER_BINAURAL_OBJECTS_TD || + rend_type == RENDERER_BINAURAL_FASTCONV || rend_type == RENDERER_BINAURAL_FASTCONV_ROOM || + rend_type == RENDERER_BINAURAL_PARAMETRIC || rend_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + return 0; + } + + memset( &tabs_dims, 0x00, sizeof( crend_hrtf_tables_dimensions ) ); + memset( &tabs_ptrs, 0x00, sizeof( crend_hrtf_tables_pointers ) ); + + hrtf_data_size = 0; + result = 0; + + // First, determine the block size + + if ( get_crend_hrtf_tables( rend_type, input_cfg, frequency, &tabs_ptrs, &tabs_dims ) == -1 ) + { + fprintf( stderr, "Get table's dimensions failed!\n\n" ); + return -1; + } + + if ( tabs_dims.max_num_ir == 0 ) + { + return -1; + } + + hrtf_data_size = compute_crend_hrtf_data_size( &tabs_ptrs, &tabs_dims ); + + if ( hrtf_data_size != hrtf_size_in ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad hrtf_data_size!\n\n" ); + return -1; + } + + // Then check the HRTF raw data + + hrtf_data_in_rptr = hrtf_data_in; + + // latency_s + if ( *( tabs_ptrs.latency_s ) != *( (float *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad latency_s!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( float ); + + // max_num_ir + if ( tabs_dims.max_num_ir != *( (uint16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad max_num_ir!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( uint16_t ); + + // BINAURAL_CHANNELS + if ( BINAURAL_CHANNELS != *( (int16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad BINAURAL_CHANNELS!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( uint16_t ); + + // max_num_iterations + if ( tabs_dims.max_num_iterations != *( (int16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad max_num_iterations!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( int16_t ); + + // num_iterations + ctrl_size = tabs_dims.max_num_ir * BINAURAL_CHANNELS * sizeof( uint16_t ); + if ( memcmp( tabs_ptrs.num_iterations, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad num_iterations!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + + // pIndex_frequency_max + ctrl_size = tabs_dims.max_num_ir * BINAURAL_CHANNELS * tabs_dims.max_num_iterations * sizeof( uint16_t ); + if ( memcmp( tabs_ptrs.pIndex_frequency_max, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad pIndex_frequency_max!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + + // max_num_iterations_diffuse + if ( tabs_dims.max_num_iterations_diffuse != *( (int16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad max_num_iterations!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( int16_t ); + + if ( tabs_dims.max_num_iterations_diffuse != 0 ) + { + // num_iterations_diffuse + ctrl_size = BINAURAL_CHANNELS * sizeof( uint16_t ); + if ( memcmp( tabs_ptrs.num_iterations_diffuse, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad num_iterations_diffuse!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + + // pIndex_frequency_max_diffuse (the size depends on num_iterations_diffuse) + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + ctrl_size = tabs_ptrs.num_iterations_diffuse[iChan] * sizeof( uint16_t ); + if ( memcmp( tabs_ptrs.pIndex_frequency_max_diffuse, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad pIndex_frequency_max_diffuse!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + } + } + + // index_frequency_max_diffuse + if ( *( tabs_ptrs.index_frequency_max_diffuse ) != *( (uint16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad index_frequency_max_diffuse!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( uint16_t ); + + // inv_diffuse_weight + ctrl_size = tabs_dims.max_num_ir * sizeof( float ); + if ( memcmp( tabs_ptrs.inv_diffuse_weight, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad inv_diffuse_weight!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + + // max_total_num_fsamp_per_iteration + if ( tabs_dims.max_total_num_fsamp_per_iteration != *( (uint16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad max_total_num_fsamp_per_iteration!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( uint16_t ); + + // coeff_re : The size depends on pIndex_frequency_max + for ( iIR = 0, iIndex = 0; iIR < tabs_dims.max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_re + ( iIR * BINAURAL_CHANNELS + iChan ) * tabs_dims.max_total_num_fsamp_per_iteration; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + ctrl_size = tabs_ptrs.pIndex_frequency_max[iIndex] * sizeof( float ); + if ( memcmp( coeff_rptr, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad coeff_re!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + coeff_rptr += tabs_ptrs.pIndex_frequency_max[iIndex++]; + } + } + } + + // coeff_im : The size depends on pIndex_frequency_max + coeff_rptr = tabs_ptrs.coeff_im; + for ( iIR = 0, iIndex = 0; iIR < tabs_dims.max_num_ir; iIR++ ) + { + for ( iChan = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_im + ( iIR * BINAURAL_CHANNELS + iChan ) * tabs_dims.max_total_num_fsamp_per_iteration; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations[iIR * BINAURAL_CHANNELS + iChan]; iIter++ ) + { + ctrl_size = tabs_ptrs.pIndex_frequency_max[iIndex] * sizeof( float ); + if ( memcmp( coeff_rptr, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad coeff_re!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + coeff_rptr += tabs_ptrs.pIndex_frequency_max[iIndex++]; + } + } + } + + // max_total_num_fsamp_per_iteration_diff + if ( tabs_dims.max_total_num_fsamp_per_iteration_diff != *( (uint16_t *) ( hrtf_data_in_rptr ) ) ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad max_total_num_fsamp_per_iteration_diff!\n\n" ); + return -1; + } + hrtf_data_in_rptr += sizeof( uint16_t ); + + if ( tabs_dims.max_total_num_fsamp_per_iteration_diff != 0 ) + { + // coeff_diffuse_re : The size depends on pIndex_frequency_max_diffuse + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_diffuse_re + iChan * tabs_dims.max_total_num_fsamp_per_iteration_diff; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations_diffuse[iChan]; iIter++ ) + { + ctrl_size = tabs_ptrs.pIndex_frequency_max_diffuse[iIndex] * sizeof( float ); + if ( memcmp( coeff_rptr, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad coeff_diffuse_re!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + coeff_rptr += tabs_ptrs.pIndex_frequency_max_diffuse[iIndex++]; + } + } + + // coeff_diffuse_im : The size depends on pIndex_frequency_max_diffuse + for ( iChan = 0, iIndex = 0; iChan < BINAURAL_CHANNELS; iChan++ ) + { + coeff_rptr = tabs_ptrs.coeff_diffuse_im + iChan * tabs_dims.max_total_num_fsamp_per_iteration_diff; + for ( iIter = 0; iIter < tabs_ptrs.num_iterations_diffuse[iChan]; iIter++ ) + { + ctrl_size = tabs_ptrs.pIndex_frequency_max_diffuse[iIndex] * sizeof( float ); + if ( memcmp( coeff_rptr, hrtf_data_in_rptr, ctrl_size ) != 0 ) + { + fprintf( stderr, "check_hrtf_data of binary file failed: bad coeff_diffuse_im!\n\n" ); + return -1; + } + hrtf_data_in_rptr += ctrl_size; + coeff_rptr += tabs_ptrs.pIndex_frequency_max_diffuse[iIndex++]; + } + } + } + + return result; +} + +/*---------------------------------------------------------------------* + * read_hrtf_size() + * + *---------------------------------------------------------------------*/ + +int32_t read_hrtf_size( char *hrtf ) +{ + int32_t hrtf_size = 0; + char *hrtf_rptr = hrtf; + + if ( hrtf != NULL ) + { + hrtf_rptr += sizeof( int32_t ); // RENDERER_TYPE + hrtf_rptr += sizeof( int32_t ); // BINAURAL_INPUT_AUDIO_CONFIG + hrtf_rptr += sizeof( int32_t ); + + memcpy( &( hrtf_size ), hrtf_rptr, sizeof( uint32_t ) ); + hrtf_size += sizeof( int32_t ) + sizeof( int32_t ) + sizeof( int32_t ) + sizeof( int32_t ); // + hrtf header size + // hrtf_rptr += sizeof(uint32_t); + } + + return hrtf_size; +} + +/*---------------------------------------------------------------------* + * rom2bin_init() + * + *---------------------------------------------------------------------*/ + +int rom2bin_init( int argc, char *argv[] ) +{ + + int i; + int32_t selected_frequency = 0; + + if ( ( argc ) == 1 ) + { + fprintf( stderr, "Not enough input arguments!\n\n" ); + usage_tables_format_converter(); + exit( -1 ); + } + + // Optional arguments + + i = 1; + while ( ( i < argc ) && ( argv[i][0] == '-' ) ) + { + if ( strcmp( to_upper( argv[i] ), "-OUTPUT_FILE_PATH" ) == 0 ) + { + i++; + if ( strlen( argv[i] ) == 0 ) + { + fprintf( stderr, "Wrong output file path: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + output_path = malloc( strlen( argv[i] ) + 1 ); + strcpy( output_path, argv[i] ); + i++; + } + else if ( strcmp( to_upper( argv[i] ), "-OUTPUT_FILE_NAME" ) == 0 ) + { + i++; + if ( strlen( argv[i] ) == 0 ) + { + fprintf( stderr, "Wrong output file name: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + output_file_name = malloc( strlen( argv[i] ) + 1 ); + strcpy( output_file_name, argv[i] ); + i++; + } + + else if ( strcmp( argv[i], "-48" ) == 0 ) + { + if ( selected_frequency != 0 ) + { + fprintf( stderr, "Bad configuration: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + selected_frequency = 48000; + i++; + } + else if ( strcmp( argv[i], "-32" ) == 0 ) + { + if ( selected_frequency != 0 ) + { + fprintf( stderr, "Bad configuration: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + selected_frequency = 32000; + i++; + } + else if ( strcmp( argv[i], "-16" ) == 0 ) + { + if ( selected_frequency != 0 ) + { + fprintf( stderr, "Bad configuration: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + selected_frequency = 16000; + i++; + } + else if ( strcmp( to_upper( argv[i] ), "-INPUT_TD_FILE_PATH" ) == 0 ) + { + i++; + if ( strlen( argv[i] ) == 0 ) + { + fprintf( stderr, "Wrong input time-domain file path: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + input_td_bin_path = malloc( strlen( argv[i] ) + 1 ); + strcpy( input_td_bin_path, argv[i] ); + i++; + } + else if ( strcmp( to_upper( argv[i] ), "-INPUT_TD_FILE_NAME" ) == 0 ) + { + i++; + if ( strlen( argv[i] ) == 0 ) + { + fprintf( stderr, "Wrong input time-domain file name: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + input_td_bin_file_name = malloc( strlen( argv[i] ) + 1 ); + strcpy( input_td_bin_file_name, argv[i] ); + i++; + } + else + { + fprintf( stderr, "Unknown option: %s\n\n", argv[i] ); + usage_tables_format_converter(); + return -1; + } + } + + if ( output_path == NULL ) + { + output_path = (char *) malloc( sizeof( char ) * ( strlen( DEFAULT_PATH ) + 1 ) ); + if ( output_path ) + { + strcpy( output_path, DEFAULT_PATH ); + } + else + { + fprintf( stderr, "Memory issue for output path!\n\n" ); + rom2bin_terminat(); + return -1; + } + } + + if ( output_file_name == NULL ) + { + output_file_name = (char *) malloc( sizeof( char ) * ( strlen( DEFAULT_INPUT_ROM_FILE ) + 1 ) ); + if ( output_file_name ) + { + strcpy( output_file_name, DEFAULT_INPUT_ROM_FILE ); + } + else + { + fprintf( stderr, "Memory issue for output file name!\n\n" ); + rom2bin_terminat(); + return -1; + } + } + + if ( selected_frequency == 0 ) + { + + full_out_path = (char *) malloc( sizeof( char ) * ( strlen( output_path ) + strlen( output_file_name ) + strlen( DEFAULT_BIN_FILE_EXT ) + 1 ) ); + sprintf( full_out_path, "%s%s%s", output_path, output_file_name, DEFAULT_BIN_FILE_EXT ); + } + else + { + + nb_freq = 1; + for ( i = 0; i < IVAS_NB_SAMPLERATE; i++ ) + { + if ( sample_rates[i] == selected_frequency ) + { + freq_ptr = &( sample_rates[i] ); + } + } + + full_out_path = (char *) malloc( sizeof( char ) * ( strlen( output_path ) + strlen( output_file_name ) + 6 + strlen( DEFAULT_BIN_FILE_EXT ) + 1 ) ); + if ( full_out_path ) + { + sprintf( full_out_path, "%s%s_%dkHz%s", output_path, output_file_name, selected_frequency / 1000, DEFAULT_BIN_FILE_EXT ); + } + else + { + fprintf( stderr, "Memory issue for full output path!\n\n" ); + rom2bin_terminat(); + return -1; + } + } + + if ( input_td_bin_path != NULL ) + { + + if ( input_td_bin_file_name == NULL ) + { + input_td_bin_file_name = (char *) malloc( sizeof( char ) * ( strlen( DEFAULT_INPUT_TD_BIN_FILE ) + 1 ) ); + if ( input_td_bin_file_name ) + { + strcpy( input_td_bin_file_name, DEFAULT_INPUT_TD_BIN_FILE ); + } + else + { + fprintf( stderr, "Memory issue for input td bin file name!\n\n" ); + rom2bin_terminat(); + return -1; + } + } + + full_in_td_path = (char *) malloc( sizeof( char ) * ( strlen( input_td_bin_path ) + strlen( input_td_bin_file_name ) + 6 + strlen( DEFAULT_BIN_FILE_EXT ) + 1 ) ); + if ( full_in_td_path == NULL ) + { + fprintf( stderr, "Memory issue for full input td path!\n\n" ); + rom2bin_terminat(); + return -1; + } + } + + return 0; +} + +/*---------------------------------------------------------------------* + * rom2bin_terminat() + * + *---------------------------------------------------------------------*/ + +void rom2bin_terminat( void ) +{ + if ( output_path != NULL ) + { + free( output_path ); + } + + if ( output_file_name != NULL ) + { + free( output_file_name ); + } + + if ( full_out_path != NULL ) + { + free( full_out_path ); + } + + if ( input_td_bin_path != NULL ) + { + free( input_td_bin_path ); + } + + if ( input_td_bin_file_name != NULL ) + { + free( input_td_bin_file_name ); + } + + if ( full_in_td_path != NULL ) + { + free( full_in_td_path ); + } +} + +/*---------------------------------------------------------------------* + * to_upper() + * + * Capitalize all letters of a string. + * (normally to_upper() function would be used but it does not work in Unix) + *---------------------------------------------------------------------*/ +char *to_upper( + char *str ) +{ + int16_t i; + char *p = str; + + i = 0; + while ( str[i] != 0 ) + { + if ( str[i] >= 'a' && str[i] <= 'z' ) + { + str[i] -= 0x20; + } + i++; + } + + return p; +} diff --git a/scripts/binauralRenderer_interface/Table_Format_Converter/table_format_converter_readme.txt b/scripts/binauralRenderer_interface/Table_Format_Converter/table_format_converter_readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..391ad644e942c007d498b7ac5fa1eb234d9c752b --- /dev/null +++ b/scripts/binauralRenderer_interface/Table_Format_Converter/table_format_converter_readme.txt @@ -0,0 +1,60 @@ +/****************************************************************************************************** + + (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +Table Format Converter program +------------------------------ + +The table format converter is used to generate the file containing the binary representation of the binaural +filters for renderers (dynamic loading of generated file using –hrtf argument). +This tool is able : + - to generate binary file for MIXER_CONV, MIXER_CONV_ROOM (tables conversion from ROM); + - to aggregate the binary HR filter of OBJECTS_TD (to be done : FASTCONV and PARAMETRIC binaural) + +First, build the converter under scripts/binauralRenderer_interface/Table_Format_Converter/ in VSCode (using CMakeList). + +Usage: +------ +tables_format_converter [Options] + +Mandatory parameters : + +Options : +-output_file_path : Path where output file will be created (with separator, default = './'). +-output_file_name : Name of output file (without extension .bin, default = 'ivas_binaural'). +-16 : Select 16 kHz sampling frequency (no multiple values, all frequencies by default). +-32 : Select 32 kHz sampling frequency (no multiple values, all frequencies by default). +-48 : Select 48 kHz sampling frequency (no multiple values, all frequencies by default). +-input_td_file_path : Path of binary files for time-domain renderer (with separator, used as flag). +-input_td_file_name : Name of input td file (without extension .bin, default = 'hrfilter_model'). + +For example : +table_format_converter(.exe) -output_file_path './' -48 -input_td_file_path './../../../td_object_renderer/hrtf_data/Orange_53/' -input_td_file_name 'hrfilter_model_v002' \ No newline at end of file diff --git a/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin new file mode 100644 index 0000000000000000000000000000000000000000..e099563d59c8d1ca05b0131e06ba2c61482b6c6d --- /dev/null +++ b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44a59257b01a2f8dde378958c4539e80ccd50157e2766dd08c2f9858275d2f2c +size 2074172 diff --git a/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin new file mode 100644 index 0000000000000000000000000000000000000000..2137f267a11d8da905480aa3e32e4a3d81cad678 --- /dev/null +++ b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be4a11053ec5f265f33fdc36c6a68762b7e9974b9ff23af85dcca8ffaf62aef0 +size 2578384 diff --git a/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin new file mode 100644 index 0000000000000000000000000000000000000000..1532a923a1c1e3861d1a79c78fe0e5a2346fb21f --- /dev/null +++ b/scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcaeb7604af344e2ab4d4bafb9fa05cd06fb0989320ea4343e6a9328233e199d +size 2860960 diff --git a/scripts/binauralRenderer_interface/generate_crend_ivas_tables_from_sofa.c b/scripts/binauralRenderer_interface/generate_crend_ivas_tables_from_sofa.c new file mode 100644 index 0000000000000000000000000000000000000000..73d99d76a7f6e7ebb1d1bb14242d5484117e0c3c --- /dev/null +++ b/scripts/binauralRenderer_interface/generate_crend_ivas_tables_from_sofa.c @@ -0,0 +1,1454 @@ +/****************************************************************************************************** + + (C) 2022 Baseline Development Group with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The Baseline Development Group consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., and VoiceAge Corporation retain full ownership + rights in their respective contributions in the software. No license of any kind, including but not + limited to patent license, of any foregoing parties is hereby granted by implication, estoppel or + otherwise. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and/or fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_stat_dec.h" +#include "lib_dec.h" +#include "ivas_rom_com.h" +#include "cmdl_tools.h" +#include "ivas_crend_binaural_filter_design.h" +#ifdef M +#undef M +#endif + +#include "hrtf/mysofa.h" + + +/*------------------------------------------------------------------------------------------* + * Constants + *------------------------------------------------------------------------------------------*/ + +#define MAX_DIFF_AZI 1 /* angle in degree */ +#define MAX_DIFF_ELE 10 /* angle in degree */ +#define DEFAULT_SAMPLERATE 48000 /* Hz */ +#define TEMPLTATE_C_ROM_FILE_NAME "ivas_rom_binaural_crend_head.template" +#define FORCE_COPY_TO_LIB_DEC +#define ROM_FILE_NAME "ivas_rom_binaural_crend_head" +#define FORMAT_FLOAT "%8.6f" +#define NUM_SAMPLES_PER_LINES 96 +#define DECLARATION_NAME "CRendBin" + +int32_t sample_rates[3] = { DEFAULT_SAMPLERATE, 32000, 16000 }; /* Hz */ /* 8000 Hz not supported by mdft */ + +/* ------------------------------------------------------------------------------------------ + * Struct + *------------------------------------------------------------------------------------------ */ + +struct ivas_layout_config +{ + char name[32]; + int nb_channel; + float azi[MAX_CICP_CHANNELS]; + float ele[MAX_CICP_CHANNELS]; + int16_t isloudspeaker; + int16_t sba_order; + int16_t num_lfe; + int16_t lfe_index[2]; + float gain_lfe; +}; + + +/*---------------------------------------------------------------------* + * Local function prototypes + *---------------------------------------------------------------------*/ +char *to_upper( char *str ); +void usage_gen_crend_tables( void ); +void get_ls_layout_config( IVAS_DEC_AUDIO_CONFIG ls_layout_config, struct ivas_layout_config *ls_struct ); +int generate_crend_ivas_tables_from_sofa( const char *sofa_file_path, bool no_optim ); +void update_h_file( HRTFS_DATA *hrtf, struct ivas_layout_config lscfg, const int32_t samplerate, const int16_t frame_len ); +void update_c_file( HRTFS_DATA *hrtf, struct ivas_layout_config lscfg, const int32_t samplerate, const int16_t frame_len ); + + +/*---------------------------------------------------------------------* + * + * Avoid compiling all decoder create a false get_next_indice function + *---------------------------------------------------------------------*/ + +#ifdef DEBUG_BS_READ_WRITE +uint16_t get_next_indice_( +#else +uint16_t get_next_indice( +#endif + Decoder_State *st, /* i/o: decoder state structure */ + int16_t nb_bits /* i : number of bits that were used to quantize the indice */ +#ifdef DEBUG_BS_READ_WRITE + , + int16_t line, + const char *func +#endif +) +{ + return 0; +} + + +/*---------------------------------------------------------------------* + * usage_gen_crend_tables() + * + * Print the usage of the "generate_crend_ivas_tables" program + *---------------------------------------------------------------------*/ + +void usage_gen_crend_tables( void ) +{ + fprintf( stdout, "Usage: generate_crend_ivas_tables.exe [Options] sofa_file_path1 sofa_file_path2 ... \n\n" ); + + fprintf( stdout, "Mandatory parameters:\n" ); + fprintf( stdout, "---------------------\n" ); + fprintf( stdout, "sofa_file_path1 sofa_file_path2 ... : paths of the sofa files to process %ld Hz sample rate mandatory\n", (long) DEFAULT_SAMPLERATE ); + fprintf( stdout, "frame_length_ms : path where header and c files will be created (lib_dec forlder for example, default = './')\n" ); + + fprintf( stdout, "Options:\n" ); + fprintf( stdout, "--------\n" ); + fprintf( stdout, "-lib_dec_path path : path where header and c files will be created (lib_dec forlder for example, default = './')\n" ); + fprintf( stdout, "-no_optim : if present no BRIR optimisation is perfromed \n" ); + fprintf( stdout, "\n" ); +} + + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ + +int32_t frame = 0; /* Counter of frames */ +char *c_file_path = NULL; +char *h_file_path = NULL; +char *rom_file_name = NULL; +uint16_t frame_len_ms = 5; + +/*------------------------------------------------------------------------------------------* + * Standalone Renderer program + * + * + *------------------------------------------------------------------------------------------*/ +int main( int argc, char *argv[] ) +{ + if ( ( argc ) == 1 ) + { + fprintf( stderr, "Not enough input arguments!\n\n" ); + usage_gen_crend_tables(); + exit( -1 ); + } + + FILE *fp = NULL; + + char *lib_dec_path = NULL; + bool no_optim = false; + int notEndingWithSeparator = 0; + + int i = 1; + /* Optional arguments */ + while ( argv[i][0] == '-' ) + { + if ( strcmp( to_upper( argv[i] ), "-LIB_DEC_PATH" ) == 0 ) + { + i++; + if ( strlen( argv[i] ) == 0 ) + { + fprintf( stderr, "Wrong lib_dec path: %s\n\n", argv[i] ); + usage_gen_crend_tables(); + return -1; + } + lib_dec_path = malloc( strlen( argv[i] ) + 1 ); + strcpy( lib_dec_path, argv[i] ); + notEndingWithSeparator = ( ( argv[i][strlen( argv[i] ) - 1] == '\\' ) || ( ( argv[i][strlen( argv[i] ) - 1] == '/' ) ) ) ? 0 : 1; + i++; + } + else if ( strcmp( to_upper( argv[i] ), "-NO_OPTIM" ) == 0 ) + { + no_optim = true; + i++; + } + else + { + fprintf( stderr, "Unknown option: %s\n\n", argv[i] ); + usage_gen_crend_tables(); + return -1; + } + } + + if ( ( strlen( argv[i] ) != 1 ) && ( strlen( argv[i] ) != 2 ) ) + { + fprintf( stderr, "Unknown option: %s need to specify frame length in ms\n\n", argv[i] ); + usage_gen_crend_tables(); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + frame_len_ms = atoi( argv[i] ); + i++; + + if ( ( frame_len_ms != 5 ) && ( frame_len_ms != 20 ) ) + { + fprintf( stderr, "Unknown option: %s need to specify frame length in ms 5 or 20\n\n", argv[i] ); + usage_gen_crend_tables(); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + + rom_file_name = (char *) malloc( sizeof( char ) * strlen( ROM_FILE_NAME ) + 1 ); + if ( rom_file_name ) + { + strncpy( rom_file_name, ROM_FILE_NAME, strlen( ROM_FILE_NAME ) ); + rom_file_name[strlen( ROM_FILE_NAME )] = '\0'; + } + else + { + fprintf( stderr, "Memory issue for rom file temporary name\n\n" ); + usage_gen_crend_tables(); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + + if ( lib_dec_path ) + { + c_file_path = (char *) malloc( sizeof( char ) * ( strlen( lib_dec_path ) + strlen( ROM_FILE_NAME ) + 2 + 1 + notEndingWithSeparator ) ); + if ( c_file_path ) + { + if ( notEndingWithSeparator ) + { +#ifdef WIN32 + sprintf( c_file_path, "%s\\%s.c", lib_dec_path, ROM_FILE_NAME ); +#else + sprintf( c_file_path, "%s/%s.c", lib_dec_path, ROM_FILE_NAME ); +#endif + } + else + { +#ifdef WIN32 + sprintf( c_file_path, "%s%s.c", lib_dec_path, ROM_FILE_NAME ); +#else + sprintf( c_file_path, "%s%s.c", lib_dec_path, ROM_FILE_NAME ); +#endif + } + } + else + { + fprintf( stderr, "Memory issue for c file path\n\n" ); + usage_gen_crend_tables(); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + fp = fopen( c_file_path, "w" ); + if ( fp == NULL ) + { + fprintf( stderr, "Wrong lib_dec path: %s\n\n", lib_dec_path ); + usage_gen_crend_tables(); + if ( c_file_path ) + free( c_file_path ); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + fclose( fp ); + + h_file_path = (char *) malloc( sizeof( char ) * ( strlen( lib_dec_path ) + strlen( ROM_FILE_NAME ) + 2 + 1 + notEndingWithSeparator ) ); + if ( h_file_path ) + { + if ( notEndingWithSeparator ) + { +#ifdef WIN32 + sprintf( h_file_path, "%s\\%s.h", lib_dec_path, ROM_FILE_NAME ); +#else + sprintf( h_file_path, "%s/%s.h", lib_dec_path, ROM_FILE_NAME ); +#endif + } + else + { +#ifdef WIN32 + sprintf( h_file_path, "%s\\%s.h", lib_dec_path, ROM_FILE_NAME ); +#else + sprintf( h_file_path, "%s/%s.h", lib_dec_path, ROM_FILE_NAME ); +#endif + } + } + else + { + fprintf( stderr, "Memory issue: for header file path\n\n" ); + usage_gen_crend_tables(); + if ( c_file_path ) + free( c_file_path ); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + fp = fopen( h_file_path, "w" ); + if ( fp == NULL ) + { + fprintf( stderr, "Wrong lib_dec path: %s\n\n", lib_dec_path ); + usage_gen_crend_tables(); + if ( h_file_path ) + free( h_file_path ); + if ( c_file_path ) + free( c_file_path ); + if ( lib_dec_path ) + free( lib_dec_path ); + return -1; + } + fclose( fp ); + } + + if ( c_file_path == NULL ) + { + size_t len = ( strlen( ROM_FILE_NAME ) + 5 + ( no_optim ? strlen( "_no_optim" ) : 0 ) + 2 + 1); + c_file_path = (char *) malloc( sizeof( char ) * len ); + sprintf( c_file_path, "%s_%02dms%s.c", ROM_FILE_NAME, frame_len_ms, ( no_optim ? "_no_optim" : "" ) ); + c_file_path[len-1] = '\0'; + } + if ( h_file_path == NULL ) + { + size_t len = ( strlen( ROM_FILE_NAME ) + 5 + ( no_optim ? strlen( "_no_optim" ) : 0 ) + 2 + 1); + h_file_path = (char *) malloc( sizeof( char ) * len ); + sprintf( h_file_path, "%s_%02dms%s.h", ROM_FILE_NAME, frame_len_ms, ( no_optim ? "_no_optim" : "" ) ); + h_file_path[len-1] = '\0'; + } + + FILE *fpt = fopen( TEMPLTATE_C_ROM_FILE_NAME, "rb" ); + + if ( fpt ) + { + fseek( fpt, 0, SEEK_END ); + size_t fsize = ftell( fpt ); + fseek( fpt, 0, SEEK_SET ); + char *tmpc = (char *) malloc( fsize + 1 ); + size_t ret = fread( tmpc, fsize, 1, fpt ); + tmpc[fsize] = '\0'; + if ( ret * fsize == fsize ) + { + fp = fopen( c_file_path, "wb" ); + if ( fp ) + { + fwrite( tmpc, fsize, 1, fp ); + fclose( fp ); + } + + fp = fopen( h_file_path, "wb" ); + if ( fp ) + { + fwrite( tmpc, fsize, 1, fp ); + fclose( fp ); + } + } + + fclose( fpt ); + } + fp = fopen( h_file_path, "a" ); + if ( fp ) + { + fprintf( fp, "\n#ifndef _%s_\n", to_upper( rom_file_name ) ); + fprintf( fp, "#define _%s_\n", to_upper( rom_file_name ) ); + fprintf( fp, "\n#include \n#include \"cnst.h\"\n#include \"ivas_cnst.h\"\n" ); + fclose( fp ); + } + + fp = fopen( c_file_path, "a" ); + if ( fp ) + { + fprintf( fp, "\n#include \n#include \n#include \"cnst.h\"\n#include \"ivas_cnst.h\"\n" ); + fclose( fp ); + } + + int err = 0; + for ( ; i < argc; i++ ) + { + err = generate_crend_ivas_tables_from_sofa( argv[i], no_optim ); + if ( err != 0 ) + return err; + } + fp = fopen( h_file_path, "a" ); + if ( fp ) + { + fprintf( fp, "\n#endif /* _%s_ */\n", to_upper( rom_file_name ) ); + fclose( fp ); + } + + fp = fopen( c_file_path, "a" ); + if ( fp ) + { + fprintf( fp, "\n\n" ); + fclose( fp ); + } + + if ( c_file_path ) + free( c_file_path ); + if ( h_file_path ) + free( h_file_path ); + if ( rom_file_name ) + free( rom_file_name ); + return err; +} + +struct MYSOFA_ARRAY *mysofa_getVariable( struct MYSOFA_VARIABLE *attr, char *name ) +{ + while ( attr ) + { + if ( attr->name && !strcmp( name, attr->name ) ) + { + return attr->value; + } + attr = attr->next; + } + return NULL; +} + +int generate_crend_ivas_tables_from_sofa( const char *file_path, bool no_optim ) +{ + char *sofa_file_path = NULL; + int err; + int i, indSR; + unsigned ui; + + struct MYSOFA_EASY *hrtf = (struct MYSOFA_EASY *) malloc( sizeof( struct MYSOFA_EASY ) ); + if ( !hrtf ) + return 1234; + memset( hrtf, 0, sizeof( struct MYSOFA_EASY ) ); + + /*------------------------------------------------------------------------------------------* + * Parse command line and initialize renderer + *------------------------------------------------------------------------------------------*/ + /* Optional arguments */ + sofa_file_path = (char *) malloc( sizeof( char ) * ( strlen( file_path ) + 1 ) ); + if ( sofa_file_path == NULL ) + { + fprintf( stderr, "Cannot alloc sofa_file_path !\n\n" ); + return -1; + } + strcpy( sofa_file_path, file_path ); + + hrtf->hrtf = mysofa_load( sofa_file_path, &err ); + if ( !hrtf->hrtf ) + { + mysofa_close( hrtf ); + fprintf( stderr, "Cannot open file %s!\n\n", sofa_file_path ); + usage_gen_crend_tables(); + free( sofa_file_path ); + + return err; + } + hrtf->lookup = NULL; + hrtf->neighborhood = NULL; + hrtf->fir = NULL; + + + if ( hrtf->hrtf->DataDelay.elements == hrtf->hrtf->M * hrtf->hrtf->R ) + { + mysofa_close( hrtf ); + fprintf( stderr, "Wrong file unsupported format delay metadata %s!\n\n", sofa_file_path ); + usage_gen_crend_tables(); + free( sofa_file_path ); + + return -1; + } + + if ( hrtf->hrtf->DataSamplingRate.elements > 0 ) + { + int hasWantedSampleRate = 0; + for ( ui = 0; ui < hrtf->hrtf->DataSamplingRate.elements; ui++ ) + { + if ( hrtf->hrtf->DataSamplingRate.values[ui] == DEFAULT_SAMPLERATE ) + { + hasWantedSampleRate = 1; + break; + } + } + if ( hasWantedSampleRate == 0 ) + { + mysofa_close( hrtf ); + fprintf( stderr, "Wrong file with wrong sample rate %s!\n\n", sofa_file_path ); + usage_gen_crend_tables(); + free( sofa_file_path ); + + return -1; + } + } + else + { + mysofa_close( hrtf ); + fprintf( stderr, "Wrong file with wrong sample rate %s!\n\n", sofa_file_path ); + usage_gen_crend_tables(); + free( sofa_file_path ); + + return -1; + } + + /* err = mysofa_check( hrtf->hrtf ); + if ( err != MYSOFA_OK ) + { + mysofa_close( hrtf ); + return err; + }*/ + + struct ivas_layout_config lscfg; + + if ( hrtf->hrtf->M == 4 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_FOA, &lscfg ); + else if ( hrtf->hrtf->M == 9 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_HOA2, &lscfg ); + else if ( hrtf->hrtf->M == 16 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_HOA3, &lscfg ); + else if ( hrtf->hrtf->M == 6 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_5_1, &lscfg ); + else if ( ( hrtf->hrtf->M == 8 ) && ( strstr( sofa_file_path, "710" ) != 0 ) ) + get_ls_layout_config( IVAS_DEC_OUTPUT_7_1, &lscfg ); + else if ( ( hrtf->hrtf->M == 8 ) && ( strstr( sofa_file_path, "512" ) != 0 ) ) + get_ls_layout_config( IVAS_DEC_OUTPUT_5_1_2, &lscfg ); + else if ( hrtf->hrtf->M == 10 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_5_1_4, &lscfg ); + else if ( hrtf->hrtf->M == 12 ) + get_ls_layout_config( IVAS_DEC_OUTPUT_7_1_4, &lscfg ); + else + get_ls_layout_config( IVAS_DEC_OUTPUT_EXT, &lscfg ); + + /* general information about the loaded HRTF set */ + fprintf( stderr, "Number of HRTFs: %d\n", hrtf->hrtf->M ); + fprintf( stderr, "Filter length: %d samples\n", hrtf->hrtf->N ); + fprintf( stderr, "Database: %s\n", mysofa_getAttribute( hrtf->hrtf->attributes, "DatabaseName" ) ); + fprintf( stderr, "Listener: %s\n", mysofa_getAttribute( hrtf->hrtf->attributes, "ListenerShortName" ) ); + + struct MYSOFA_ARRAY *latency_s = mysofa_getVariable( hrtf->hrtf->variables, "latencys" ); + + if ( lscfg.isloudspeaker && ( lscfg.nb_channel > 11 ) ) + { + mysofa_tocartesian( hrtf->hrtf ); + + hrtf->lookup = mysofa_lookup_init( hrtf->hrtf ); + if ( hrtf->lookup == NULL ) + { + err = MYSOFA_INTERNAL_ERROR; + mysofa_close( hrtf ); + free( sofa_file_path ); + + return err; + } + hrtf->neighborhood = mysofa_neighborhood_init( hrtf->hrtf, hrtf->lookup ); + fprintf( stderr, "Radius min: %f, max: %f\n", hrtf->lookup->radius_min, hrtf->lookup->radius_max ); + } + /* get index to a position given in t (in spherical) */ + int *index_pos = (int *) malloc( sizeof( int ) * lscfg.nb_channel ); + uint32_t maxDel48kHz = 0; + if ( index_pos == NULL ) + { + mysofa_close( hrtf ); + free( sofa_file_path ); + fprintf( stderr, "Cannot alloc sofa_file_path !\n\n" ); + return -1; + } + for ( i = 0; i < lscfg.nb_channel; i++ ) + { + if ( lscfg.isloudspeaker && ( lscfg.nb_channel > 11 ) ) + { + float t[3], a[3]; + t[0] = lscfg.azi[i]; /* azimuth in deg */ + t[1] = lscfg.ele[i]; /* elevation in deg */ + t[2] = hrtf->lookup->radius_min; /* radius in m */ + fprintf( stderr, "Wanted Position: %f, %f, %f\n", t[0], t[1], t[2] ); + mysofa_s2c( t ); + int nearest = mysofa_lookup( hrtf->lookup, t ); + a[0] = hrtf->hrtf->SourcePosition.values[3 * nearest]; + a[1] = hrtf->hrtf->SourcePosition.values[3 * nearest + 1]; + a[2] = hrtf->hrtf->SourcePosition.values[3 * nearest + 2]; + if ( fabs( t[0] - a[0] ) > MAX_DIFF_AZI ) + { + mysofa_close( hrtf ); + fprintf( stderr, "Nearest position to far from target incomplete sofa file\n" ); + free( sofa_file_path ); + free( index_pos ); + return -1; + } + if ( fabs( t[1] - a[1] ) > MAX_DIFF_ELE ) + { + mysofa_close( hrtf ); + fprintf( stderr, "Nearest position to far from target incomplete sofa file\n" ); + free( sofa_file_path ); + return -1; + } + mysofa_c2s( a ); + if ( a[0] > 180 ) + a[0] -= 360; + if ( a[0] < -180 ) + a[0] += 360; + fprintf( stderr, "Nearest Position: %f, %f, %f\n", a[0], a[1], a[2] ); + fprintf( stderr, "Nearest position found at: %d\n", nearest ); + index_pos[i] = nearest; + } + else + { + index_pos[i] = i; + } + /* get the HRIR for the position given in t */ + uint32_t size = (uint32_t) hrtf->hrtf->R; + uint32_t delL = 0, delR = 0; + if ( hrtf->hrtf->DataDelay.elements == ( hrtf->hrtf->M * hrtf->hrtf->R ) ) + { + size = hrtf->hrtf->R; + delL = (uint32_t) roundf( hrtf->hrtf->DataDelay.values[index_pos[i] * size] * DEFAULT_SAMPLERATE ); + if ( maxDel48kHz < delL ) + maxDel48kHz = delL; + delR = (uint32_t) roundf( hrtf->hrtf->DataDelay.values[index_pos[i] * size + 1] * DEFAULT_SAMPLERATE ); + if ( maxDel48kHz < delR ) + maxDel48kHz = delR; + } + } + + size_t len_ls_cfg_name = strlen( lscfg.name ); + + double latency_48k = 0; + float latency_48k_optim = 0; + + for ( indSR = 0; indSR < sizeof( sample_rates ) / sizeof( float ); indSR++ ) + { + + uint16_t frame_len = L_FRAME48k; + int32_t maxDel = maxDel48kHz * DEFAULT_SAMPLERATE / sample_rates[indSR]; + switch ( sample_rates[indSR] ) + { + case 8000: + frame_len = L_FRAME8k; + break; + case 16000: + frame_len = L_FRAME16k; + break; + case 32000: + frame_len = L_FRAME32k; + break; + case 48000: + default: + frame_len = L_FRAME48k; + break; + } + if ( frame_len_ms == 5 ) + frame_len = frame_len >> 2; + + if ( sample_rates[indSR] != DEFAULT_SAMPLERATE ) + { + char *file_path = (char *) malloc( sizeof( char ) * ( strlen( sofa_file_path ) + 1 ) ); + strcpy( file_path, sofa_file_path ); + char *fstr = strstr( file_path, "48000" ); + if ( fstr ) + { + switch ( sample_rates[indSR] ) + { + case 32000: + strncpy( fstr, "32000", 5 ); + break; + case 16000: + strncpy( fstr, "16000", 5 ); + break; + default: + break; + } + } + else + { + strcpy( file_path, "" ); + } + FILE *fp = fopen( file_path, "rb" ); + if ( fp ) + { + fclose( fp ); + + mysofa_close( hrtf ); + hrtf = (struct MYSOFA_EASY *) malloc( sizeof( struct MYSOFA_EASY ) ); + if ( !hrtf ) + return 1234; + memset( hrtf, 0, sizeof( struct MYSOFA_EASY ) ); + hrtf->hrtf = mysofa_load( file_path, &err ); + } + else + { + mysofa_close( hrtf ); + hrtf = (struct MYSOFA_EASY *) malloc( sizeof( struct MYSOFA_EASY ) ); + if ( !hrtf ) + return 1234; + memset( hrtf, 0, sizeof( struct MYSOFA_EASY ) ); + hrtf->hrtf = mysofa_load( sofa_file_path, &err ); + mysofa_resample( hrtf->hrtf, (float) sample_rates[indSR] ); + } + latency_s = mysofa_getVariable( hrtf->hrtf->variables, "latencys" ); + if ( file_path ) + free( file_path ); + } + + struct ivas_hrtf_t *ivas_hrtf = NULL; + ivas_hrtf = malloc( sizeof( ivas_hrtf_t ) ); + memset( ivas_hrtf, 0, sizeof( ivas_hrtf_t ) ); + ivas_hrtf->I = hrtf->hrtf->I; + ivas_hrtf->m = lscfg.nb_channel; + ivas_hrtf->N = hrtf->hrtf->N + maxDel; + ivas_hrtf->R = hrtf->hrtf->R; + ivas_hrtf->sampling_rate = sample_rates[indSR]; + + int32_t ind_max_ir = hrtf->hrtf->N; + uint32_t delL = 0, delR = 0; + unsigned size = hrtf->hrtf->R; + double max_ir_l = 0; + double max_ir_r = 0; + int32_t ind_max_l = hrtf->hrtf->N; + int32_t ind_max_r = hrtf->hrtf->N; + double tmpf; + size = (uint32_t) hrtf->hrtf->N * hrtf->hrtf->R; + + for ( i = 0; i < lscfg.nb_channel; i++ ) + { + max_ir_l = 0; + max_ir_r = 0; + ind_max_l = hrtf->hrtf->N; + ind_max_r = hrtf->hrtf->N; + + if ( hrtf->hrtf->DataDelay.elements == hrtf->hrtf->M * hrtf->hrtf->R ) + { + delL = (uint32_t) roundf( hrtf->hrtf->DataDelay.values[index_pos[i] * size] * DEFAULT_SAMPLERATE ); + delR = (uint32_t) roundf( hrtf->hrtf->DataDelay.values[index_pos[i] * size + 1] * DEFAULT_SAMPLERATE ); + } + + ivas_hrtf->data_ir[i][0] = (double *) malloc( sizeof( double ) * ( ivas_hrtf->N ) ); + memset( ivas_hrtf->data_ir[i][0], 0, sizeof( double ) * ivas_hrtf->N ); + for ( unsigned n = 0; n < hrtf->hrtf->N; n++ ) + { + ivas_hrtf->data_ir[i][0][n + delL] = hrtf->hrtf->DataIR.values[size * index_pos[i] + n]; + tmpf = fabs( hrtf->hrtf->DataIR.values[index_pos[i] * size + n] ); + if ( tmpf > max_ir_l ) + { + max_ir_l = tmpf; + ind_max_l = n + delL; + } + } + ivas_hrtf->data_ir[i][1] = (double *) malloc( sizeof( double ) * ( ivas_hrtf->N ) ); + memset( ivas_hrtf->data_ir[i][1], 0, sizeof( double ) * ivas_hrtf->N ); + for ( unsigned n = 0; n < hrtf->hrtf->N; n++ ) + { + ivas_hrtf->data_ir[i][1][n + delR] = hrtf->hrtf->DataIR.values[size * index_pos[i] + hrtf->hrtf->N + n]; + tmpf = fabs( hrtf->hrtf->DataIR.values[size * index_pos[i] + hrtf->hrtf->N + n] ); + if ( tmpf > max_ir_r ) + { + max_ir_r = tmpf; + ind_max_r = n + delR; + } + } + if ( ind_max_ir > ind_max_l ) + { + ind_max_ir = ind_max_l; + } + if ( ind_max_ir > ind_max_r ) + { + ind_max_ir = ind_max_r; + } + } + + if ( sample_rates[indSR] == DEFAULT_SAMPLERATE ) + { + latency_48k = (double) ind_max_ir / (double) sample_rates[indSR]; + } + ivas_hrtf->latency_s[0] = (double *) malloc( sizeof( double ) ); + if ( latency_s == NULL ) + { + ivas_hrtf->latency_s[0][0] = latency_48k; + } + else + { + if ( fabs( latency_s->values[0] - (float) latency_48k ) > 1e-6f ) + { + fprintf( stderr, "Warning : At sample rate %ld latency in sofa file and computed are different sofa = %f, computed = %lf\n", (long) sample_rates[indSR], latency_s->values[0], latency_48k ); + } + ivas_hrtf->latency_s[0][0] = latency_s->values[0]; + } + + HRTFS_DATA hrtf_data = { 0 }; + int32_t index_start, index_end, max_ir_len; + + hrtf_data.max_num_ir = ivas_hrtf->m; + + ivas_get_hrtf_lens( ivas_hrtf, &hrtf_data, frame_len ); + if ( sample_rates[indSR] != DEFAULT_SAMPLERATE ) + { + hrtf_data.latency_s = latency_48k_optim; + } + + if ( ( hrtf_data.num_iterations[0][0] > 2 ) && ( no_optim == false ) ) + { + ivas_crend_binaural_filter_design_compute_filters_params( ivas_hrtf, frame_len, &hrtf_data, &index_start, &index_end, &max_ir_len ); + ivas_crend_binaural_filter_design_set_hrtf_fr( ivas_hrtf, frame_len, &hrtf_data, index_start, index_end, &max_ir_len ); + } + else + { + ivas_set_hrtf_fr( &hrtf_data, ivas_hrtf, frame_len ); + } + + if ( ( hrtf_data.num_iterations[0][0] > 2 ) ) + { + strcpy( &lscfg.name[len_ls_cfg_name], "_BRIR" ); + } + else + { + strcpy( &lscfg.name[len_ls_cfg_name], "_HRIR" ); + } + + if ( sample_rates[indSR] == DEFAULT_SAMPLERATE ) + { + latency_48k_optim = hrtf_data.latency_s; + } + + update_h_file( &hrtf_data, lscfg, sample_rates[indSR], frame_len ); + update_c_file( &hrtf_data, lscfg, sample_rates[indSR], frame_len ); + + if ( ivas_hrtf->latency_s[0] ) + { + free( ivas_hrtf->latency_s[0] ); + ivas_hrtf->latency_s[0] = NULL; + } + for ( int i = 0; i < lscfg.nb_channel; i++ ) + { + if ( ivas_hrtf->data_ir[i][0] ) + { + free( ivas_hrtf->data_ir[i][0] ); + ivas_hrtf->data_ir[i][0] = NULL; + } + if ( ivas_hrtf->data_ir[i][1] ) + { + free( ivas_hrtf->data_ir[i][1] ); + ivas_hrtf->data_ir[i][1] = NULL; + } + } + free( ivas_hrtf ); + ivas_hrtf_close( &hrtf_data ); + } + /* close the file */ + mysofa_close( hrtf ); + if ( sofa_file_path ) + free( sofa_file_path ); + if ( index_pos ) + free( index_pos ); + + return 0; +} + +/*---------------------------------------------------------------------* + *write_array_float_to_file(); + *---------------------------------------------------------------------*/ +void write_array_float_to_file( FILE *fp, float *vec, int32_t size_vec, int32_t sample_per_ligne, const char *format, const int num_tab ) +{ + int32_t k, l, num_iter, remaining_samples; + int16_t i; + + num_iter = size_vec / sample_per_ligne; + remaining_samples = size_vec % sample_per_ligne; + if ( remaining_samples == 0 ) + { + num_iter--; + remaining_samples = sample_per_ligne; + } + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + fprintf( fp, "{" ); + + for ( k = 0; k < num_iter; k++ ) + { + if ( k != 0 ) + { + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + } + for ( l = 0; l < sample_per_ligne; l++ ) + { + fprintf( fp, format, vec[k * sample_per_ligne + l] ); + fprintf( fp, "f, " ); + } + fprintf( fp, "\n" ); + } + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + for ( l = 0; l < remaining_samples - 1; l++ ) + { + fprintf( fp, format, vec[k * sample_per_ligne + l] ); + fprintf( fp, "f, " ); + } + fprintf( fp, format, vec[k * sample_per_ligne + l] ); + fprintf( fp, "f}" ); +} + +/*---------------------------------------------------------------------* + *write_array_float_to_file(); + *---------------------------------------------------------------------*/ +void write_array_uint16_to_file( FILE *fp, uint16_t *vec, int32_t size_vec, int32_t sample_per_ligne, const int num_tab ) +{ + int32_t k, l, num_iter, remaining_samples; + int16_t i; + + num_iter = size_vec / sample_per_ligne; + remaining_samples = size_vec % sample_per_ligne; + if ( remaining_samples == 0 ) + { + num_iter--; + remaining_samples = sample_per_ligne; + } + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + + fprintf( fp, "{" ); + for ( k = 0; k < num_iter; k++ ) + { + if ( k != 0 ) + { + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + } + for ( l = 0; l < sample_per_ligne; l++ ) + { + fprintf( fp, "%u", vec[k * sample_per_ligne + l] ); + fprintf( fp, ", " ); + } + fprintf( fp, "\n" ); + } + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + for ( l = 0; l < remaining_samples - 1; l++ ) + { + fprintf( fp, "%u", vec[k * sample_per_ligne + l] ); + fprintf( fp, ", " ); + } + fprintf( fp, "%u", vec[k * sample_per_ligne + l] ); + for ( i = 0; i < num_tab; i++ ) + { + fprintf( fp, "\t" ); + } + fprintf( fp, "}" ); +} + + +/*---------------------------------------------------------------------* + *update_c_file(); + *---------------------------------------------------------------------*/ +void update_c_file( HRTFS_DATA *hrtf, struct ivas_layout_config lscfg, const int32_t samplerate, const int16_t frame_len ) +{ + + FILE *fp = fopen( c_file_path, "a" ); + int16_t i, j; + uint32_t *pTotalNumFreqSampPerIterations[2], maxTotalNumFreqSampPerIterations; + uint32_t pTotalNumFreqSampPerIterationsDiffuse[2], maxTotalNumFreqSampPerIterationsDiffuse; + + pTotalNumFreqSampPerIterations[0] = malloc( sizeof( float ) * hrtf->max_num_ir ); + pTotalNumFreqSampPerIterations[1] = malloc( sizeof( float ) * hrtf->max_num_ir ); + + if ( fp == NULL ) + return; + if ( hrtf == NULL ) + return; + + if ( samplerate == DEFAULT_SAMPLERATE ) + { + /* float latency_s; */ + fprintf( fp, "\n\n/********************** %s_%s **********************/\n", DECLARATION_NAME, lscfg.name ); + fprintf( fp, "\nconst float %s_%s_latency_s = %16.15ff;", DECLARATION_NAME, lscfg.name, hrtf->latency_s ); + } + + fprintf( fp, "\n\n/* Sample Rate = %ld */\n", (long) samplerate ); + + /* int16_t max_num_iterations; */ + fprintf( fp, "\nconst int16_t %s_%s_max_num_iterations_%2dkHz = %d;", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_iterations ); + /* uint16_t num_iterations[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS];*/ + fprintf( fp, "\nconst uint16_t %s_%s_num_iterations_%2dkHz[%d][BINAURAL_CHANNELS]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir ); + for ( i = 0; i < hrtf->max_num_ir - 1; i++ ) + { + fprintf( fp, "{%u, %u}, ", hrtf->num_iterations[i][0], hrtf->num_iterations[i][1] ); + } + fprintf( fp, "{%u, %u} ", hrtf->num_iterations[i][0], hrtf->num_iterations[i][1] ); + fprintf( fp, "};" ); + + /* uint16_t num_iterations_diffuse[BINAURAL_CHANNELS];*/ + fprintf( fp, "\nconst uint16_t %s_%s_num_iterations_diffuse_%2dkHz[BINAURAL_CHANNELS] = {%u, %u};", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->num_iterations_diffuse[0], hrtf->num_iterations_diffuse[1] ); + + maxTotalNumFreqSampPerIterations = 0; + for ( i = 0; i < hrtf->max_num_ir; i++ ) + { + pTotalNumFreqSampPerIterations[0][i] = 0; + pTotalNumFreqSampPerIterations[1][i] = 0; + for ( j = 0; j < hrtf->num_iterations[i][0]; j++ ) + { + pTotalNumFreqSampPerIterations[0][i] += hrtf->pIndex_frequency_max[i][0][j]; + } + if ( maxTotalNumFreqSampPerIterations < pTotalNumFreqSampPerIterations[0][i] ) + { + maxTotalNumFreqSampPerIterations = pTotalNumFreqSampPerIterations[0][i]; + } + for ( j = 0; j < hrtf->num_iterations[i][1]; j++ ) + { + pTotalNumFreqSampPerIterations[1][i] += hrtf->pIndex_frequency_max[i][1][j]; + } + if ( maxTotalNumFreqSampPerIterations < pTotalNumFreqSampPerIterations[1][i] ) + { + maxTotalNumFreqSampPerIterations = pTotalNumFreqSampPerIterations[1][i]; + } + } + + pTotalNumFreqSampPerIterationsDiffuse[0] = 0; + pTotalNumFreqSampPerIterationsDiffuse[1] = 0; + maxTotalNumFreqSampPerIterationsDiffuse = 0; + for ( j = 0; j < hrtf->num_iterations_diffuse[0]; j++ ) + { + pTotalNumFreqSampPerIterationsDiffuse[0] += hrtf->pIndex_frequency_max_diffuse[0][j]; + } + if ( maxTotalNumFreqSampPerIterationsDiffuse < pTotalNumFreqSampPerIterationsDiffuse[0] ) + { + maxTotalNumFreqSampPerIterationsDiffuse = pTotalNumFreqSampPerIterationsDiffuse[0]; + } + for ( j = 0; j < hrtf->num_iterations_diffuse[1]; j++ ) + { + pTotalNumFreqSampPerIterationsDiffuse[1] += hrtf->pIndex_frequency_max_diffuse[1][j]; + } + if ( maxTotalNumFreqSampPerIterationsDiffuse < pTotalNumFreqSampPerIterationsDiffuse[1] ) + { + maxTotalNumFreqSampPerIterationsDiffuse = pTotalNumFreqSampPerIterationsDiffuse[1]; + } + + /*uint16_t *pIndex_frequency_max[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; */ + fprintf( fp, "\nconst uint16_t %s_%s_pIndex_frequency_max_%2dkHz[%d][BINAURAL_CHANNELS][%d]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, hrtf->max_num_iterations ); + for ( i = 0; i < hrtf->max_num_ir - 1; i++ ) + { + fprintf( fp, "{" ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max[i][0], hrtf->max_num_iterations, hrtf->max_num_iterations, 0 ); + fprintf( fp, "," ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max[i][1], hrtf->max_num_iterations, hrtf->max_num_iterations, 0 ); + fprintf( fp, "}," ); + } + fprintf( fp, "{" ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max[i][0], hrtf->max_num_iterations, hrtf->max_num_iterations, 0 ); + fprintf( fp, "," ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max[i][1], hrtf->max_num_iterations, hrtf->max_num_iterations, 0 ); + fprintf( fp, "}" ); + fprintf( fp, "};" ); + + /* uint16_t index_frequency_max_diffuse; */ + fprintf( fp, "\nconst uint16_t %s_%s_index_frequency_max_diffuse_%2dkHz = %d;", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->index_frequency_max_diffuse ); + + /* float inv_diffuse_weight[MAX_INTERN_CHANNELS]; */ + fprintf( fp, "\nconst float %s_%s_inv_diffuse_weight_%2dkHz[%u]=", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir ); + write_array_float_to_file( fp, hrtf->inv_diffuse_weight, hrtf->max_num_ir, hrtf->max_num_ir, FORMAT_FLOAT, 0 ); + fprintf( fp, ";" ); + + /* uint16_t *pIndex_frequency_max_diffuse[BINAURAL_CHANNELS];*/ + if ( hrtf->pIndex_frequency_max_diffuse[0] == NULL ) + { + fprintf( fp, "\nconst uint16_t *%s_%s_pIndex_frequency_max_diffuse_%2dkHz[BINAURAL_CHANNELS]={NULL,NULL};", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nconst uint16_t %s_%s_pIndex_frequency_max_diffuse_%2dkHz[BINAURAL_CHANNELS][%u]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, ( hrtf->num_iterations_diffuse[0] > hrtf->num_iterations_diffuse[1] ) ? hrtf->num_iterations_diffuse[0] : hrtf->num_iterations_diffuse[1] ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max_diffuse[0], hrtf->num_iterations_diffuse[0], hrtf->num_iterations_diffuse[0], 0 ); + fprintf( fp, "," ); + write_array_uint16_to_file( fp, hrtf->pIndex_frequency_max_diffuse[1], hrtf->num_iterations_diffuse[1], hrtf->num_iterations_diffuse[1], 0 ); + fprintf( fp, "};" ); + } + + /* float *pOut_to_bin[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS];*/ + fprintf( fp, "\nconst float %s_%s_coeff_re_%2dkHz[%d][BINAURAL_CHANNELS][%u]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, maxTotalNumFreqSampPerIterations ); + for ( i = 0; i < hrtf->max_num_ir - 1; i++ ) + { + fprintf( fp, "\n\t{\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_re[i][0], pTotalNumFreqSampPerIterations[0][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_re[i][1], pTotalNumFreqSampPerIterations[1][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n\t}," ); + } + fprintf( fp, "\n\t{\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_re[i][0], pTotalNumFreqSampPerIterations[0][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_re[i][1], pTotalNumFreqSampPerIterations[1][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n\t}" ); + fprintf( fp, "\n};" ); + + fprintf( fp, "\nconst float %s_%s_coeff_im_%2dkHz[%d][BINAURAL_CHANNELS][%u]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, maxTotalNumFreqSampPerIterations ); + for ( i = 0; i < hrtf->max_num_ir - 1; i++ ) + { + fprintf( fp, "\n\t{\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_im[i][0], pTotalNumFreqSampPerIterations[0][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_im[i][1], pTotalNumFreqSampPerIterations[1][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n\t}," ); + } + fprintf( fp, "\n\t{\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_im[i][0], pTotalNumFreqSampPerIterations[0][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_im[i][1], pTotalNumFreqSampPerIterations[1][i], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n\t}" ); + fprintf( fp, "\n};" ); + + /* float *pOut_to_bin_diffuse_re[BINAURAL_CHANNELS];*/ + if ( hrtf->pOut_to_bin_diffuse_re[0] == NULL ) + { + fprintf( fp, "\nconst float *%s_%s_coeff_diffuse_re_%2dkHz[BINAURAL_CHANNELS]={NULL,NULL};", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nconst float %s_%s_coeff_diffuse_re_%2dkHz[BINAURAL_CHANNELS][%u]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, maxTotalNumFreqSampPerIterationsDiffuse ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_diffuse_re[0], pTotalNumFreqSampPerIterationsDiffuse[0], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_diffuse_re[1], pTotalNumFreqSampPerIterationsDiffuse[1], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n};" ); + } + + /* float *pOut_to_bin_diffuse_im[BINAURAL_CHANNELS];*/ + if ( hrtf->pOut_to_bin_diffuse_im[0] == NULL ) + { + fprintf( fp, "\nconst float *%s_%s_coeff_diffuse_im_%2dkHz[BINAURAL_CHANNELS]={NULL,NULL};", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nconst float %s_%s_coeff_diffuse_im_%2dkHz[BINAURAL_CHANNELS][%u]={", DECLARATION_NAME, lscfg.name, samplerate / 1000, maxTotalNumFreqSampPerIterationsDiffuse ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_diffuse_im[0], pTotalNumFreqSampPerIterationsDiffuse[0], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, ",\n" ); + write_array_float_to_file( fp, hrtf->pOut_to_bin_diffuse_im[1], pTotalNumFreqSampPerIterationsDiffuse[1], NUM_SAMPLES_PER_LINES, FORMAT_FLOAT, 2 ); + fprintf( fp, "\n};" ); + } + + if ( fp ) + fclose( fp ); + + if ( pTotalNumFreqSampPerIterations[0] ) + { + free( pTotalNumFreqSampPerIterations[0] ); + } + if ( pTotalNumFreqSampPerIterations[1] ) + { + free( pTotalNumFreqSampPerIterations[1] ); + } + + return; +} + +/*---------------------------------------------------------------------* + *update_h_file(); + *---------------------------------------------------------------------*/ +void update_h_file( HRTFS_DATA *hrtf, struct ivas_layout_config lscfg, const int32_t samplerate, const int16_t frame_len ) +{ + uint16_t i, j; + uint32_t *pTotalNumFreqSampPerIterations[2], maxTotalNumFreqSampPerIterations; + uint32_t pTotalNumFreqSampPerIterationsDiffuse[2], maxTotalNumFreqSampPerIterationsDiffuse; + + pTotalNumFreqSampPerIterations[0] = malloc( sizeof( float ) * hrtf->max_num_ir ); + pTotalNumFreqSampPerIterations[1] = malloc( sizeof( float ) * hrtf->max_num_ir ); + FILE *fp = fopen( h_file_path, "a" ); + + if ( fp == NULL ) + return; + if ( hrtf == NULL ) + return; + + maxTotalNumFreqSampPerIterations = 0; + for ( i = 0; i < hrtf->max_num_ir; i++ ) + { + pTotalNumFreqSampPerIterations[0][i] = 0; + pTotalNumFreqSampPerIterations[1][i] = 0; + for ( j = 0; j < hrtf->num_iterations[i][0]; j++ ) + { + pTotalNumFreqSampPerIterations[0][i] += hrtf->pIndex_frequency_max[i][0][j]; + } + if ( maxTotalNumFreqSampPerIterations < pTotalNumFreqSampPerIterations[0][i] ) + { + maxTotalNumFreqSampPerIterations = pTotalNumFreqSampPerIterations[0][i]; + } + for ( j = 0; j < hrtf->num_iterations[i][1]; j++ ) + { + pTotalNumFreqSampPerIterations[1][i] += hrtf->pIndex_frequency_max[i][1][j]; + } + if ( maxTotalNumFreqSampPerIterations < pTotalNumFreqSampPerIterations[1][i] ) + { + maxTotalNumFreqSampPerIterations = pTotalNumFreqSampPerIterations[1][i]; + } + } + + pTotalNumFreqSampPerIterationsDiffuse[0] = 0; + pTotalNumFreqSampPerIterationsDiffuse[1] = 0; + maxTotalNumFreqSampPerIterationsDiffuse = 0; + for ( j = 0; j < hrtf->num_iterations_diffuse[0]; j++ ) + { + pTotalNumFreqSampPerIterationsDiffuse[0] += hrtf->pIndex_frequency_max_diffuse[0][j]; + } + if ( maxTotalNumFreqSampPerIterationsDiffuse < pTotalNumFreqSampPerIterationsDiffuse[0] ) + { + maxTotalNumFreqSampPerIterationsDiffuse = pTotalNumFreqSampPerIterationsDiffuse[0]; + } + for ( j = 0; j < hrtf->num_iterations_diffuse[1]; j++ ) + { + pTotalNumFreqSampPerIterationsDiffuse[1] += hrtf->pIndex_frequency_max_diffuse[1][j]; + } + if ( maxTotalNumFreqSampPerIterationsDiffuse < pTotalNumFreqSampPerIterationsDiffuse[1] ) + { + maxTotalNumFreqSampPerIterationsDiffuse = pTotalNumFreqSampPerIterationsDiffuse[1]; + } + + if ( samplerate == DEFAULT_SAMPLERATE ) + { + /* float latency_s; */ + fprintf( fp, "\n\n/********************** %s_%s **********************/\n", DECLARATION_NAME, lscfg.name ); + fprintf( fp, "\nextern float %s_%s_latency_s;", DECLARATION_NAME, lscfg.name ); + } + + fprintf( fp, "\n\n/* Sample Rate = %ld */\n", (long) samplerate ); + + /* int16_t max_num_iterations; */ + fprintf( fp, "\nextern int16_t %s_%s_max_num_iterations_%2dkHz;", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + /* uint16_t num_iterations[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS];*/ + fprintf( fp, "\nextern uint16_t %s_%s_num_iterations_%2dkHz[%d][BINAURAL_CHANNELS];", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir ); + + /* uint16_t num_iterations_diffuse[BINAURAL_CHANNELS];*/ + fprintf( fp, "\nextern uint16_t %s_%s_num_iterations_diffuse_%2dkHz[BINAURAL_CHANNELS];", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + + /*uint16_t *pIndex_frequency_max[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS]; */ + fprintf( fp, "\nextern uint16_t %s_%s_pIndex_frequency_max_%2dkHz[%d][BINAURAL_CHANNELS][%d];", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, hrtf->max_num_iterations ); + + /* uint16_t index_frequency_max_diffuse; */ + fprintf( fp, "\nextern uint16_t %s_%s_index_frequency_max_diffuse_%2dkHz;", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + + /* float inv_diffuse_weight[MAX_INTERN_CHANNELS]; */ + fprintf( fp, "\nextern float %s_%s_inv_diffuse_weight_%2dkHz[%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir ); + + /* uint16_t *pIndex_frequency_max_diffuse[BINAURAL_CHANNELS];*/ + if ( hrtf->pIndex_frequency_max_diffuse[0] == NULL ) + { + fprintf( fp, "\nextern uint16_t *%s_%s_pIndex_frequency_max_diffuse_%2dkHz[BINAURAL_CHANNELS];", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nextern uint16_t %s_%s_pIndex_frequency_max_diffuse_%2dkHz[BINAURAL_CHANNELS][%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, ( hrtf->num_iterations_diffuse[0] > hrtf->num_iterations_diffuse[1] ) ? hrtf->num_iterations_diffuse[0] : hrtf->num_iterations_diffuse[1] ); + } + + /* float *pOut_to_bin[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS];*/ + fprintf( fp, "\nextern float %s_%s_coeff_re_%2dkHz[%d][BINAURAL_CHANNELS][%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, maxTotalNumFreqSampPerIterations ); + fprintf( fp, "\nextern float %s_%s_coeff_im_%2dkHz[%d][BINAURAL_CHANNELS][%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, hrtf->max_num_ir, maxTotalNumFreqSampPerIterations ); + + /* float *pOut_to_bin_diffuse_re[BINAURAL_CHANNELS];*/ + if ( hrtf->pOut_to_bin_diffuse_re[0] == NULL ) + { + fprintf( fp, "\nextern float *%s_%s_coeff_diffuse_re_%2dkHz[BINAURAL_CHANNELS];", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nextern float %s_%s_coeff_diffuse_re_%2dkHz[BINAURAL_CHANNELS][%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, maxTotalNumFreqSampPerIterationsDiffuse ); + } + + /* float *pOut_to_bin_diffuse_im[BINAURAL_CHANNELS];*/ + if ( hrtf->pOut_to_bin_diffuse_im[0] == NULL ) + { + fprintf( fp, "\nextern float *%s_%s_coeff_diffuse_im_%2dkHz[BINAURAL_CHANNELS];", DECLARATION_NAME, lscfg.name, samplerate / 1000 ); + } + else + { + fprintf( fp, "\nextern float %s_%s_coeff_diffuse_im_%2dkHz[BINAURAL_CHANNELS][%u];", DECLARATION_NAME, lscfg.name, samplerate / 1000, maxTotalNumFreqSampPerIterationsDiffuse ); + } + + if ( fp ) + fclose( fp ); + + if ( pTotalNumFreqSampPerIterations[0] ) + { + free( pTotalNumFreqSampPerIterations[0] ); + } + if ( pTotalNumFreqSampPerIterations[1] ) + { + free( pTotalNumFreqSampPerIterations[1] ); + } + return; +} + + +/*---------------------------------------------------------------------* + * to_upper() + * + * Capitalize all letters of a string. + * (normally to_upper() function would be used but it does not work in Unix) + *---------------------------------------------------------------------*/ +char *to_upper( + char *str ) +{ + int16_t i; + char *p = str; + + i = 0; + while ( str[i] != 0 ) + { + if ( str[i] >= 'a' && str[i] <= 'z' ) + { + str[i] -= 0x20; + } + i++; + } + + return p; +} + +/*---------------------------------------------------------------------* + *get_ls_layout_config( IVAS_DEC_OUTPUT_CONFIG ls_layout_config, struct ivas_layout_config *ls_struct ) + * fill ls_struct with proper values depending on ls_layout_config + *---------------------------------------------------------------------*/ +void get_ls_layout_config( IVAS_DEC_AUDIO_CONFIG ls_layout_config, struct ivas_layout_config *ls_struct ) +{ + + memset( ls_struct, 0, sizeof( struct ivas_layout_config ) ); + + switch ( ls_layout_config ) + { + case IVAS_DEC_OUTPUT_FOA: + strcpy( ls_struct->name, "FOA" ); + ls_struct->nb_channel = 4; + ls_struct->isloudspeaker = 0; + ls_struct->sba_order = 1; + ls_struct->num_lfe = 0; + memset( ls_struct->lfe_index, -1, sizeof( int16_t ) * 2 ); + break; + case IVAS_DEC_OUTPUT_HOA2: + strcpy( ls_struct->name, "HOA2" ); + ls_struct->nb_channel = 9; + ls_struct->isloudspeaker = 0; + ls_struct->sba_order = 2; + ls_struct->num_lfe = 0; + memset( ls_struct->lfe_index, -1, sizeof( int16_t ) * 2 ); + break; + case IVAS_DEC_OUTPUT_HOA3: + strcpy( ls_struct->name, "HOA3" ); + ls_struct->nb_channel = 16; + ls_struct->isloudspeaker = 0; + ls_struct->sba_order = 3; + ls_struct->num_lfe = 0; + memset( ls_struct->lfe_index, -1, sizeof( int16_t ) * 2 ); + break; + case IVAS_DEC_OUTPUT_MONO: + strcpy( ls_struct->name, "MONO" ); + ls_struct->nb_channel = 1; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 0; + memset( ls_struct->lfe_index, -1, sizeof( int16_t ) * 2 ); + break; + case IVAS_DEC_OUTPUT_STEREO: + strcpy( ls_struct->name, "STEREO" ); + ls_struct->nb_channel = 2; + memcpy( ls_struct->azi, ls_azimuth_CICP2, sizeof( float ) * ls_struct->nb_channel ); + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 0; + memset( ls_struct->lfe_index, -1, sizeof( int16_t ) * 2 ); + break; + case IVAS_DEC_OUTPUT_5_1: + strcpy( ls_struct->name, "5_1" ); + ls_struct->nb_channel = 5; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[0] = 3; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + memcpy( ls_struct->azi, ls_azimuth_CICP6, sizeof( float ) * ls_struct->nb_channel ); + break; + case IVAS_DEC_OUTPUT_7_1: + strcpy( ls_struct->name, "7_1" ); + ls_struct->nb_channel = 7; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[0] = 3; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + memcpy( ls_struct->azi, ls_azimuth_CICP12, sizeof( float ) * ls_struct->nb_channel ); + break; + case IVAS_DEC_OUTPUT_5_1_2: + strcpy( ls_struct->name, "5_1_2" ); + ls_struct->nb_channel = 7; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + memcpy( ls_struct->azi, ls_azimuth_CICP14, sizeof( float ) * ls_struct->nb_channel ); + break; + case IVAS_DEC_OUTPUT_5_1_4: + strcpy( ls_struct->name, "5_1_4" ); + ls_struct->nb_channel = 9; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[0] = 3; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + memcpy( ls_struct->azi, ls_azimuth_CICP16, sizeof( float ) * ls_struct->nb_channel ); + break; + case IVAS_DEC_OUTPUT_7_1_4: + strcpy( ls_struct->name, "7_1_4" ); + ls_struct->nb_channel = 11; + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[0] = 3; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + memcpy( ls_struct->azi, ls_azimuth_CICP19, sizeof( float ) * ls_struct->nb_channel ); + break; + case IVAS_DEC_OUTPUT_EXT: + default: + { + const float tmp_azi[15] = { 30, -30, 0, 135, -135, 110, -110, 90, -90, 30, -30, 110, -110, 135, -135 }; + const float tmp_ele[15] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 35, 35, 35, 35, 35 }; + strcpy( ls_struct->name, "Combined" ); + ls_struct->nb_channel = 15; + memcpy( ls_struct->azi, tmp_azi, sizeof( float ) * ls_struct->nb_channel ); + memcpy( ls_struct->ele, tmp_ele, sizeof( float ) * ls_struct->nb_channel ); + ls_struct->isloudspeaker = 1; + ls_struct->sba_order = -1; + ls_struct->num_lfe = 1; + ls_struct->lfe_index[0] = 3; + ls_struct->lfe_index[1] = -1; + ls_struct->gain_lfe = GAIN_LFE; + } + break; + } + + return; +} diff --git a/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.c b/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.c new file mode 100644 index 0000000000000000000000000000000000000000..456997b5a1202344911e0313c17343458439f17f --- /dev/null +++ b/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.c @@ -0,0 +1,1389 @@ +/****************************************************************************************************** + + (C) 2022 Baseline Development Group with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The Baseline Development Group consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., and VoiceAge Corporation retain full ownership + rights in their respective contributions in the software. No license of any kind, including but not + limited to patent license, of any foregoing parties is hereby granted by implication, estoppel or + otherwise. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and/or fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include "ivas_crend_binaural_filter_design.h" +#include "prot.h" +#include "ivas_prot.h" +#include +#include /* for powf() and sqrtf() */ +#include +#include + +#define DEBUG_BINAURAL_FILTER_DESIGN + +#ifdef DEBUG_BINAURAL_FILTER_DESIGN +/*------------------------------ Debug utilities ---------------------------------------------- */ +static void printBuf_float32( float *buf, uint32_t size1 ) +{ + uint32_t ii; + for ( ii = 0; ii < size1; ++ii ) + { + printf( "%4.2f ", buf[ii] ); + } + + return; +} + +static void printBuf_uint16( uint16_t *buf, uint16_t size1 ) +{ + uint16_t ii; + for ( ii = 0; ii < size1; ++ii ) + { + printf( "%u ", (uint32_t) buf[ii] ); + } + + return; +} + +/* +static void printBuf_int16( int16_t *buf, uint16_t size1 ) +{ + int16_t ii; + for ( ii = 0; ii < size1; ++ii ) + { + printf( "%d ", buf[ii] ); + } + + return; +} + +static void printBuf_uint32( uint32_t *buf, int32_t size1 ) +{ + int32_t ii; + for ( ii = 0; ii < size1; ++ii ) + { + printf( "%lu ", (unsigned long) buf[ii] ); + } + + return; +} + +static void printBuf_int32( int32_t *buf, int32_t size1 ) +{ + int32_t ii; + for ( ii = 0; ii < size1; ++ii ) + { + printf( "%ld ", (long) buf[ii] ); + } + + return; +} + +static void printMatrix_float32(float** buf, uint32_t size1, uint32_t size2) +{ + uint32_t ii, jj; + for (ii = 0; ii < size1; ++ii) + { + for (jj = 0; jj < size2; ++jj) + { + printf("%4.2f ", buf[ii][jj]); + } + } +} + + +static void printMatrix_uint32(uint32_t** buf, uint32_t size1, uint32_t size2) +{ + uint32_t ii, jj; + for (ii = 0; ii < size1; ++ii) + { + for (jj = 0; jj < size2; ++jj) + { + printf("%u ", buf[ii][jj]); + } + } +} +*/ + + +static void printfAudioBufferOutFilterParams( + HRTFS_DATA *pParam, + uint32_t index_start, + uint32_t index_end ) +{ + printf( "\nFilter Params" ); + printf( "\nNum Channels : %u", pParam->max_num_ir ); + printf( "\nBegin delay : %u", index_start ); + printf( "\nEnd delay : %u", index_end ); + printf( "\nNum Direct Blocks : %u", pParam->max_num_iterations ); + printf( "\nNum Diffuse Blocks : %u", pParam->num_iterations_diffuse[0] ); + + printf( "\n" ); + printf( "\nDirect Fc : " ); + printBuf_uint16( pParam->pIndex_frequency_max[0][0], pParam->num_iterations[0][0] ); + printf( "\n" ); + printf( "\nDiffuse Fc : " ); + printBuf_uint16( pParam->pIndex_frequency_max_diffuse[0], pParam->num_iterations_diffuse[0] ); + printf( "\nmax Diffuse Fc : %u", pParam->index_frequency_max_diffuse ); + printf( "\n" ); + printf( "\nInverse Diffuse Weights :" ); + printBuf_float32( pParam->inv_diffuse_weight, pParam->max_num_ir ); + printf( "\n" ); + + /*if (pParam->numDiffuseBlock > 0) + { + + printf("\nDiffuse Fc Left : "); + printBuf(pParam->ppDiffuseFc[0], pParam->numDiffuseBlock); + printf("\n"); + printf("\nDiffuse Fc Right : "); + printBuf(pParam->ppDiffuseFc[1], pParam->numDiffuseBlock); + + } + else + { + printf("\nDiffuse Fc : None"); + } + */ + printf( "\n" ); + + return; +} +#endif + + +ivas_error ivas_hrtf_close( + HRTFS_HANDLE hHRTF /* i/o: HRTF handle */ +) +{ + int16_t i, j; + if ( hHRTF == NULL ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + for ( i = 0; i < MAX_INTERN_CHANNELS; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( hHRTF->pIndex_frequency_max[i][j] != NULL ) + { + free( hHRTF->pIndex_frequency_max[i][j] ); + hHRTF->pIndex_frequency_max[i][j] = NULL; + } + if ( hHRTF->pOut_to_bin_re[i][j] != NULL ) + { + free( hHRTF->pOut_to_bin_re[i][j] ); + hHRTF->pOut_to_bin_re[i][j] = NULL; + } + if ( hHRTF->pOut_to_bin_im[i][j] != NULL ) + { + free( hHRTF->pOut_to_bin_im[i][j] ); + hHRTF->pOut_to_bin_im[i][j] = NULL; + } + } + } + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + if ( hHRTF->pIndex_frequency_max_diffuse[j] != NULL ) + { + free( hHRTF->pIndex_frequency_max_diffuse[j] ); + hHRTF->pIndex_frequency_max_diffuse[j] = NULL; + } + if ( hHRTF->pOut_to_bin_diffuse_re[j] != NULL ) + { + free( hHRTF->pOut_to_bin_diffuse_re[j] ); + hHRTF->pOut_to_bin_diffuse_re[j] = NULL; + } + if ( hHRTF->pOut_to_bin_diffuse_im[j] != NULL ) + { + free( hHRTF->pOut_to_bin_diffuse_im[j] ); + hHRTF->pOut_to_bin_diffuse_im[j] = NULL; + } + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------- FFT Utils --------------------------------------------*/ +static void FFT_Complex_to_Mag( + float *pXr_32f, + float *pXi_32f, + float *pMag_32f, + const int16_t FFTsize_32s ) +{ + int16_t ind_32s; + + for ( ind_32s = 0; ind_32s < FFTsize_32s; ++ind_32s ) + { + pMag_32f[ind_32s] = sqrtf( pXr_32f[ind_32s] * pXr_32f[ind_32s] + pXi_32f[ind_32s] * pXi_32f[ind_32s] ); + } + + return; +} + + +/*------------------------------------ Binaural Filter Design Functions ----------------------------------------*/ + + +/** + * Compute number of direct blocks and diffuse blocks for a given BRIR + * + * @param pFirData : source ptr to ivas_hrtf_t struct + * @param framelen : size of the blocks linked to sample rate and fft size + * @param framelen : index of channel LFE if any. if no LFE channel set the value to -1 + * @param pParam : dest ptr to a HRTFS_DATA struct for storing computed params + * + * @return 0 if no error, 1 otherwise + */ + +ivas_error ivas_crend_binaural_filter_design_compute_filters_params( + ivas_hrtf_t *pFirData, + const int16_t framelen, + HRTFS_DATA *pParam, + int32_t *index_start, + int32_t *index_end, + int32_t *max_ir_len ) +{ + /* Parameters */ + float BeginEnergyThld = -50; + float EndEnergyThld = -120; + + float DirectEnergyThld = -25; + float DiffuseEnergyThld = -25; + + /* Vars for loop indices etc. */ + int32_t i_ear, i_chan, i_tap; + + int32_t indBegin, indBeginMini, indDirect, indDirectMaxi[MAX_INTERN_CHANNELS], indDiffuse, + indDiffuseMaxi, diffuseMinLength, numDiffuseBlock, indMax[IVAS_SOFA_MAX_VAL_M]; + + float energy, energyL, energyR, energyMaxi, threshold, CSEinst, CSEinstInv; + double valMax[IVAS_SOFA_MAX_VAL_M]; + // float mdft_scale_fact = ((float)L_FRAME48k) / framelen; + + memset( indDirectMaxi, 0, sizeof( int32_t ) * MAX_INTERN_CHANNELS ); + + /* number of channels */ + pParam->max_num_ir = (int16_t) pFirData->m; + + pParam->gain_lfe = (float) GAIN_LFE; + + if ( pParam->latency_s == 0 ) + { + pParam->latency_s = (float) pFirData->latency_s[0][0]; + + i_tap = (int32_t) ( pParam->latency_s * pFirData->sampling_rate + 0.5f ); + + /* Find maximum energy */ + energyMaxi = 0; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + indMax[i_chan] = 0; + valMax[i_chan] = 0; + energyL = 0; + for ( i_tap = 0; i_tap < pFirData->N; ++i_tap ) + { + if ( valMax[i_chan] < fabs( pFirData->data_ir[i_chan][0][i_tap] ) ) + { + valMax[i_chan] = fabs( pFirData->data_ir[i_chan][0][i_tap] ); + indMax[i_chan] = i_tap; + } + energyL += (float) pFirData->data_ir[i_chan][0][i_tap] * (float) pFirData->data_ir[i_chan][0][i_tap]; + } + energyR = 0; + for ( i_tap = 0; i_tap < pFirData->N; ++i_tap ) + { + if ( valMax[i_chan] < fabs( pFirData->data_ir[i_chan][1][i_tap] ) ) + { + valMax[i_chan] = fabs( pFirData->data_ir[i_chan][1][i_tap] ); + indMax[i_chan] = i_tap; + } + energyR += (float) pFirData->data_ir[i_chan][1][i_tap] * (float) pFirData->data_ir[i_chan][1][i_tap]; + } + if ( energyL > energyMaxi ) + { + energyMaxi = energyL; + } + if ( energyR > energyMaxi ) + { + energyMaxi = energyR; + } + } + + /* Find minimum indBegin */ + indBeginMini = (int32_t) pFirData->N - 1; + threshold = powf( 10.f, BeginEnergyThld * 0.1f ); + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + indBegin = 0; + CSEinst = 0; + + while ( indBegin < pFirData->N ) + { + CSEinst += (float) pFirData->data_ir[i_chan][i_ear][indBegin] * (float) pFirData->data_ir[i_chan][i_ear][indBegin]; + + if ( CSEinst / energyMaxi > threshold ) + { + indBegin--; + if ( indBegin < 0 ) + { + indBegin = 0; + } + break; + } + ++indBegin; + } + + if ( indBegin < indBeginMini ) + { + indBeginMini = indBegin; + } + } + } + + /* indBeginMini = (int32_t) pFirData->N - 1; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + if ( indMax[i_chan] < indBeginMini ) + { + indBeginMini = indMax[i_chan]; + } + } + + indBeginMini = indBeginMini - (int32_t) roundf( 5.f * 48000.f / pFirData->sampling_rate );*/ + + *index_start = indBeginMini = (int32_t) ( (float) indBeginMini / 3.f ) * 3; + + i_tap = (uint32_t) ( pParam->latency_s * (double) pFirData->sampling_rate ) - indBeginMini; + + pParam->latency_s = (float) i_tap / (float) pFirData->sampling_rate; + } + else + { + indBeginMini = *index_start = (uint32_t) round( ( pFirData->latency_s[0][0] - (double) pParam->latency_s ) * (double) pFirData->sampling_rate ); + } + + + /************************************************************************/ + /* Case HRIR (len <= 1024) -> fill FilterParam struct and quit function */ + /************************************************************************/ + + if ( pFirData->N <= framelen ) + { + /* Find end of direct part */ + *index_end = 0; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + indDirectMaxi[i_chan] = 0; + + /* Recompute filter energy from indBeginMini */ + energyL = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyL += (float) pFirData->data_ir[i_chan][0][i_tap] * (float) pFirData->data_ir[i_chan][0][i_tap]; + } + energyR = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyR += (float) pFirData->data_ir[i_chan][1][i_tap] * (float) pFirData->data_ir[i_chan][1][i_tap]; + } + energy = max( energyL, energyR ); + indDirectMaxi[i_chan] = 0; + if ( energy > 0 ) + { + /* set threshold */ + threshold = powf( 10.f, EndEnergyThld * 0.1f ) * energy; + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + indDirect = pFirData->N - 1; + CSEinstInv = 0; + while ( indDirect >= 0 ) + { + CSEinstInv += (float) pFirData->data_ir[i_chan][i_ear][indDirect] * (float) pFirData->data_ir[i_chan][i_ear][indDirect]; + + if ( CSEinstInv >= threshold ) + { + indDirect++; + + if ( indDirect >= pFirData->N ) + { + indDirect = pFirData->N - 1; + } + break; + } + --indDirect; + } + + if ( indDirectMaxi[i_chan] < indDirect ) + { + indDirectMaxi[i_chan] = indDirect; + } + } + } + + if ( *index_end < indDirectMaxi[i_chan] ) + { + *index_end = indDirectMaxi[i_chan]; + } + } + + /* directFc: set to 1 */ + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + pParam->num_iterations_diffuse[i_ear] = 0; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + pParam->num_iterations[i_chan][i_ear] = 1; + } + } + + /* not used now because we use imdft thus set back value to initial value FOR test vector */ + *index_start = 0; + *index_end = pFirData->N - 1; + + *max_ir_len = *index_end - *index_start + 1; + + pParam->max_num_iterations = 1; + + return IVAS_ERR_OK; + } + + /***********************************************************************/ + /* Case BRIR (len > 1024) -> design direct and diffuse filters */ + /***********************************************************************/ + /* Find end of direct part */ + *index_end = 0; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + indDirectMaxi[i_chan] = 0; + + /* Recompute filter energy from indBeginMini */ + energyL = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyL += (float) pFirData->data_ir[i_chan][0][i_tap] * (float) pFirData->data_ir[i_chan][0][i_tap]; + } + energyR = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyR += (float) pFirData->data_ir[i_chan][1][i_tap] * (float) pFirData->data_ir[i_chan][1][i_tap]; + } + energy = max( energyL, energyR ); + indDirectMaxi[i_chan] = 0; + + if ( energy > 0 ) + { + /* set threshold */ + threshold = powf( 10.f, DirectEnergyThld * 0.1f ) * energy; + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + indDirect = pFirData->N - 1; + CSEinstInv = 0; + while ( indDirect >= 0 ) + { + CSEinstInv += (float) pFirData->data_ir[i_chan][i_ear][indDirect] * (float) pFirData->data_ir[i_chan][i_ear][indDirect]; + + if ( CSEinstInv >= threshold ) + { + indDirect++; + + if ( indDirect >= pFirData->N ) + { + indDirect = pFirData->N - 1; + } + break; + } + --indDirect; + } + + if ( indDirectMaxi[i_chan] < indDirect ) + { + indDirectMaxi[i_chan] = indDirect; + } + } + } + + if ( *index_end < indDirectMaxi[i_chan] ) + { + *index_end = indDirectMaxi[i_chan]; + } + } + + + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + pParam->num_iterations[i_chan][0] = 1; + + /* remove indBeginMini */ + indDirectMaxi[i_chan] -= indBeginMini; + + /* Direct length calculation */ + while ( pParam->num_iterations[i_chan][0] * framelen < indDirectMaxi[i_chan] ) + { + pParam->num_iterations[i_chan][0]++; + } + pParam->num_iterations[i_chan][1] = pParam->num_iterations[i_chan][0]; + /* max MAX_LENGTH_DIRECT_FILTER */ + if ( pParam->num_iterations[i_chan][0] > IVAS_MAX_NUM_DIRECT_BLOCKS ) + { + pParam->num_iterations[i_chan][0] = IVAS_MAX_NUM_DIRECT_BLOCKS; + } + } + + pParam->max_num_iterations = 0; + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + if ( pParam->max_num_iterations < pParam->num_iterations[i_chan][0] ) + { + pParam->max_num_iterations = pParam->num_iterations[i_chan][0]; + } + + if ( pParam->max_num_iterations < pParam->num_iterations[i_chan][1] ) + { + pParam->max_num_iterations = pParam->num_iterations[i_chan][1]; + } + } + + /* Find end of diffuse part */ + indDiffuseMaxi = 0; + indBeginMini = indBeginMini + pParam->max_num_iterations * framelen; + + if ( indBeginMini < pFirData->N ) + { + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + + energyL = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyL += (float) pFirData->data_ir[i_chan][0][i_tap] * (float) pFirData->data_ir[i_chan][0][i_tap]; + } + energyR = 0; + for ( i_tap = indBeginMini; i_tap < pFirData->N; ++i_tap ) + { + energyR += (float) pFirData->data_ir[i_chan][1][i_tap] * (float) pFirData->data_ir[i_chan][1][i_tap]; + } + energy = max( energyL, energyR ); + + indDiffuseMaxi = 0; + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + /* set threshold */ + threshold = powf( 10.f, DiffuseEnergyThld * 0.1f ) * energy; + + indDiffuse = pFirData->N - 1; + CSEinstInv = 0; + while ( indDiffuse >= 0 ) + { + CSEinstInv += (float) pFirData->data_ir[i_chan][i_ear][indDiffuse] * (float) pFirData->data_ir[i_chan][i_ear][indDiffuse]; + + if ( CSEinstInv >= threshold ) + { + indDiffuse++; + + if ( indDiffuse >= pFirData->N ) + { + indDiffuse = pFirData->N - 1; + } + break; + } + + --indDiffuse; + } + + if ( indDiffuse > indDiffuseMaxi ) + { + indDiffuseMaxi = indDiffuse; + } + } + } + } + + if ( indDiffuseMaxi ) + { + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + pParam->num_iterations[i_chan][0] = pParam->max_num_iterations; + pParam->num_iterations[i_chan][1] = pParam->max_num_iterations; + } + + /* Calculate number of diffuse blocks */ + diffuseMinLength = indDiffuseMaxi - indBeginMini - 1; + numDiffuseBlock = 0; + + while ( numDiffuseBlock * framelen < diffuseMinLength ) + { + ++numDiffuseBlock; + } + + /* max MAX_NUM_DIFFUSE_BLOCKS */ + if ( numDiffuseBlock > IVAS_MAX_NUM_DIFFUSE_BLOCKS ) + { + numDiffuseBlock = IVAS_MAX_NUM_DIFFUSE_BLOCKS; + } + + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + pParam->num_iterations_diffuse[i_ear] = (int16_t) numDiffuseBlock; + } + } + + *max_ir_len = ( pParam->max_num_iterations + pParam->num_iterations_diffuse[0] ) * framelen; + + return IVAS_ERR_OK; +} + + +/* Compute parameters for a given BRIR + * + * @param pFirData : source ptr to ivas_hrtf_t struct + * @param framelen : size of the blocks linked to sample rate and fft size + * @param pParam : dest ptr to a HRTFS_DATA struct for storing computed params + * + * @return 0 if no error, 1 otherwise + */ +ivas_error ivas_crend_binaural_filter_design_set_hrtf_fr( + ivas_hrtf_t *pFirData, + const int16_t frame_len, + HRTFS_DATA *pParam, + int32_t index_start, + int32_t index_end, + int32_t *max_ir_len ) +{ + /* Parameters */ + float DiffuseFcThld = -20; + + /* Vars FOR loop indices etc. */ + int16_t i_ear, i_chan; + int32_t i_tap, i_block, lenDiffus, indStart, totSizeFreq[MAX_INTERN_CHANNELS], offset, totSizeFreqDiffuse; + + int16_t indFreq, indFreqMaxi; + float energy, threshold, CSEinstInvFreq; + + float DirectFcThld = -20; + float pBlock[L_FRAME48k] = { 0 }; + float pBlockSpectrum_r[L_FRAME48k]; + float pBlockSpectrum_i[L_FRAME48k]; + float pBlockSpectrum_Mag[L_FRAME48k] = { 0 }; + + float *pDiffuseFilter; /* diffuse filter (containing all blocks) ( pDiffuseFilter[tap] ) */ + float **ppDiffuseFilterWMC; /* diffuse filters WMC (containing all blocks) ( ppDiffuseFilterWMC[ear][tap] ) */ + float ppEnergyDiffuseFilter[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS] = { { 0 } }; /* diffuse filter energies ( ppEnergyDiffuseFilter[ear][channel] ) */ + float ppDiffuseWeight[MAX_INTERN_CHANNELS][BINAURAL_CHANNELS] = { { 0 } }; /* diffuse weights ( ppDiffuseWeight[ear][channel] ) */ + float delayf; + float mdft_scale_fact = ( (float) L_FRAME48k * 0.25f ) / frame_len; + + if ( pFirData->N <= frame_len ) + { + *max_ir_len = ( index_end - index_start + 1 ); + } + else + { + *max_ir_len = ( pParam->max_num_iterations + pParam->num_iterations_diffuse[0] ) * frame_len; + } + + for ( i_chan = 0; i_chan < pParam->max_num_ir; i_chan++ ) + { + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; i_ear++ ) + { + pParam->pIndex_frequency_max[i_chan][i_ear] = (uint16_t *) malloc( pParam->num_iterations[i_chan][i_ear] * sizeof( uint16_t ) ); + } + } + + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; i_ear++ ) + { + if ( pParam->num_iterations_diffuse[i_ear] > 0 ) + { + pParam->pIndex_frequency_max_diffuse[i_ear] = (uint16_t *) malloc( pParam->num_iterations_diffuse[i_ear] * sizeof( uint16_t ) ); + } + else + { + pParam->pIndex_frequency_max_diffuse[i_ear] = NULL; + } + } + + /* Direct Fc calculation */ + if ( pParam->max_num_iterations == 1 && pParam->num_iterations_diffuse[0] == 0 ) + { + for ( i_chan = 0; i_chan < pParam->max_num_ir; i_chan++ ) + { + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; i_ear++ ) + { + pParam->pOut_to_bin_re[i_chan][i_ear] = (float *) malloc( ( ( pParam->num_iterations[i_chan][i_ear] * frame_len ) ) * sizeof( float ) ); + pParam->pOut_to_bin_im[i_chan][i_ear] = (float *) malloc( ( ( pParam->num_iterations[i_chan][i_ear] * frame_len ) ) * sizeof( float ) ); + } + } + + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; ++i_ear ) + { + /* Get block */ + lenDiffus = *max_ir_len > frame_len ? frame_len : *max_ir_len; + int32_t indSt = index_start; + + if ( indSt + lenDiffus - 1 < pFirData->N ) /* full block is available */ + { + for ( i_tap = 0; i_tap < lenDiffus; i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + for ( ; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = 0; + } + } + else /* exceed BRIR size -> zero-pad the block */ + { + for ( i_tap = 0; i_tap < ( pFirData->N - indSt ); i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + for ( ; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = 0; + } + } + + /* Compute block spectrum and take magnitude */ + + ivas_mdft( pBlock, pParam->pOut_to_bin_re[i_chan][i_ear], pParam->pOut_to_bin_im[i_chan][i_ear], frame_len, frame_len ); + + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pParam->pOut_to_bin_re[i_chan][i_ear][i_tap] = mdft_scale_fact * pParam->pOut_to_bin_re[i_chan][i_ear][i_tap]; + pParam->pOut_to_bin_im[i_chan][i_ear][i_tap] = mdft_scale_fact * pParam->pOut_to_bin_im[i_chan][i_ear][i_tap]; + } + + FFT_Complex_to_Mag( pParam->pOut_to_bin_re[i_chan][i_ear], pBlockSpectrum_i, pBlockSpectrum_Mag, frame_len ); /* compute Magnitude */ + + /* Recompute filter energy (to Nyquist freq only) */ + pParam->pIndex_frequency_max[i_chan][i_ear][0] = frame_len; + } + } + } + else + { + /* For each chan, find the index from which cumulative spectral power (end to begin) is under the threshold */ + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; ++i_ear ) + { + for ( i_block = 0; i_block < pParam->num_iterations[i_chan][i_ear]; ++i_block ) + { + /* Get block */ + int32_t indSt = index_start + ( pParam->num_iterations[i_chan][i_ear] - 1 - i_block ) * frame_len; + + if ( indSt + frame_len - 1 < pFirData->N ) /* full block is available */ + { + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + } + else /* exceed BRIR size -> zero-pad the block */ + { + for ( i_tap = 0; i_tap < ( pFirData->N - indSt ); i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + for ( ; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = 0; + } + } + + /* Compute block spectrum and take magnitude */ + ivas_mdft( pBlock, pBlockSpectrum_r, pBlockSpectrum_i, frame_len, frame_len ); + + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlockSpectrum_r[i_tap] = mdft_scale_fact * pBlockSpectrum_r[i_tap]; + pBlockSpectrum_i[i_tap] = mdft_scale_fact * pBlockSpectrum_i[i_tap]; + } + + FFT_Complex_to_Mag( pBlockSpectrum_r, pBlockSpectrum_i, pBlockSpectrum_Mag, frame_len ); /* compute Magnitude */ + + /* Recompute filter energy (to Nyquist freq only) */ + if ( i_block < pParam->num_iterations[i_chan][i_ear] - 1 ) + { + energy = 0; + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + energy += pBlockSpectrum_Mag[i_tap] * pBlockSpectrum_Mag[i_tap]; + } + if ( energy > 0 ) + { + /* set threshold */ + threshold = powf( 10.f, DirectFcThld * 0.1f ) * energy; + indFreq = frame_len - 1; + CSEinstInvFreq = 0; + while ( indFreq >= 0 ) + { + CSEinstInvFreq += pBlockSpectrum_Mag[indFreq] * pBlockSpectrum_Mag[indFreq]; + + if ( CSEinstInvFreq >= threshold ) + { + break; + } + --indFreq; + } + } + else + { + indFreq = 0; + } + } + else + { + indFreq = frame_len; + } + pParam->pIndex_frequency_max[i_chan][i_ear][i_block] = indFreq; + // pParam->pIndex_frequency_max[i_chan][i_ear][i_block] = framelen; + } + } + } + + /* for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + for ( i_block = pParam->num_iterations[i_chan][0] - 1; i_block > 0; --i_block ) + { + if ( pParam->pIndex_frequency_max[i_chan][0][i_block - 1] > pParam->pIndex_frequency_max[i_chan][0][i_block] ) + { + pParam->pIndex_frequency_max[i_chan][1][i_block - 1] = pParam->pIndex_frequency_max[i_chan][0][i_block - 1] = pParam->pIndex_frequency_max[i_chan][0][i_block]; + } + } + }*/ + + /* set same FC FOR both ears */ + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + totSizeFreq[i_chan] = 0; + for ( i_block = 0; i_block < pParam->num_iterations[i_chan][0]; ++i_block ) + { + indFreqMaxi = max( pParam->pIndex_frequency_max[i_chan][0][i_block], pParam->pIndex_frequency_max[i_chan][1][i_block] ); + pParam->pIndex_frequency_max[i_chan][0][i_block] = indFreqMaxi; + pParam->pIndex_frequency_max[i_chan][1][i_block] = indFreqMaxi; + totSizeFreq[i_chan] = totSizeFreq[i_chan] + indFreqMaxi; + } + } + + /* For each chan, find the index from which cumulative spectral power (end to begin) is under the threshold */ + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; ++i_ear ) + { + pParam->pOut_to_bin_re[i_chan][i_ear] = (float *) malloc( ( totSizeFreq[i_chan] ) * sizeof( float ) ); + pParam->pOut_to_bin_im[i_chan][i_ear] = (float *) malloc( ( totSizeFreq[i_chan] ) * sizeof( float ) ); + offset = 0; + for ( i_block = 0; i_block < pParam->num_iterations[i_chan][i_ear]; ++i_block ) + { + /* Get block */ + int32_t indSt = index_start + ( pParam->num_iterations[i_chan][i_ear] - 1 - i_block ) * frame_len; + + if ( indSt + frame_len - 1 < pFirData->N ) /* full block is available */ + { + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + } + else /* exceed BRIR size -> zero-pad the block */ + { + for ( i_tap = 0; i_tap < ( pFirData->N - indSt ); i_tap++ ) + { + pBlock[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + for ( ; i_tap < frame_len; i_tap++ ) + { + pBlock[i_tap] = 0; + } + } + + /* Compute block spectrum and take magnitude */ + ivas_mdft( pBlock, pBlockSpectrum_r, pBlockSpectrum_i, frame_len, frame_len ); + + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlockSpectrum_r[i_tap] = mdft_scale_fact * pBlockSpectrum_r[i_tap]; + pBlockSpectrum_i[i_tap] = mdft_scale_fact * pBlockSpectrum_i[i_tap]; + } + + for ( i_tap = 0; i_tap < pParam->pIndex_frequency_max[i_chan][i_ear][i_block]; i_tap++ ) + { + pParam->pOut_to_bin_re[i_chan][i_ear][offset + i_tap] = pBlockSpectrum_r[i_tap]; + pParam->pOut_to_bin_im[i_chan][i_ear][offset + i_tap] = pBlockSpectrum_i[i_tap]; + } + offset = offset + pParam->pIndex_frequency_max[i_chan][i_ear][i_block]; + } + } + } + + for ( i_ear = 0; i_ear < BINAURAL_CHANNELS; i_ear++ ) + { + if ( pParam->num_iterations_diffuse[i_ear] == 0 ) + { + pParam->pOut_to_bin_diffuse_re[i_ear] = NULL; + pParam->pOut_to_bin_diffuse_im[i_ear] = NULL; + } + } + + if ( pParam->num_iterations_diffuse[0] > 0 ) + { + /* size of diffuse filters (containing all blocks) */ + lenDiffus = pParam->num_iterations_diffuse[0] * frame_len; + + /* mallocs */ + pDiffuseFilter = (float *) malloc( lenDiffus * sizeof( float ) ); + ppDiffuseFilterWMC = (float **) malloc( 2 * sizeof( float * ) ); + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + ppDiffuseFilterWMC[i_ear] = (float *) malloc( lenDiffus * sizeof( float ) ); + for ( i_tap = 0; i_tap < lenDiffus; i_tap++ ) + { + ppDiffuseFilterWMC[i_ear][i_tap] = 0; + } + } + + /* compute diffusFilterWMC */ + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + /* Get diffuse filter */ + int32_t indSt = index_start + pParam->max_num_iterations * frame_len; + + if ( indSt + lenDiffus - 1 < pFirData->N ) /* full diffuse filter is available */ + { + for ( i_tap = 0; i_tap < lenDiffus; i_tap++ ) + { + pDiffuseFilter[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + } + else /* exceed BRIR size -> zero-pad the diffuse filter */ + { + for ( i_tap = 0; i_tap < pFirData->N - indSt; i_tap++ ) + { + pDiffuseFilter[i_tap] = (float) pFirData->data_ir[i_chan][i_ear][indSt + i_tap]; + } + for ( ; i_tap < lenDiffus; i_tap++ ) + { + pDiffuseFilter[i_tap] = 0; + } + } + // Apply cos window to last 512 samples of the diffuse filter + /* lenWin = framelen >> 1; + for (i_tap = 0; i_tap < lenWin; ++i_tap) + { + pDiffuseFilter[i_tap + lenDiffus - lenWin] *= cos(M_PI_2*((float)(i_tap + 1.0) / (float)lenWin)); + }*/ + + /* Compute diffuse filter energy and store it */ + energy = 0; + for ( i_tap = 0; i_tap < lenDiffus; ++i_tap ) + { + energy += pDiffuseFilter[i_tap] * pDiffuseFilter[i_tap]; + } + ppEnergyDiffuseFilter[i_chan][i_ear] = energy; + + if ( ppEnergyDiffuseFilter[i_chan][i_ear] > 0 ) + { + /* compute diffusFilterWMC */ + for ( i_tap = 0; i_tap < lenDiffus; ++i_tap ) + { + ppDiffuseFilterWMC[i_ear][i_tap] += pDiffuseFilter[i_tap]; + } + } + } + } + + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + /* Compute diffuse ppDiffuseFilterWMC energy */ + energy = 0; + for ( i_tap = 0; i_tap < lenDiffus; ++i_tap ) + { + energy += ppDiffuseFilterWMC[i_ear][i_tap] * ppDiffuseFilterWMC[i_ear][i_tap]; + } + + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + if ( ppEnergyDiffuseFilter[i_chan][i_ear] > 0 ) + { + ppDiffuseWeight[i_chan][i_ear] = sqrtf( energy / ppEnergyDiffuseFilter[i_chan][i_ear] ); + } + else + { + ppDiffuseWeight[i_chan][i_ear] = -1; /* avoid div by 0 when ppEnergyDiffuseFilter[i_ear][i_chan]=0 */ + } + } + } + + /* set pInvDiffuseWeight (inverse of mean weights per channel) */ + for ( i_chan = 0; i_chan < pParam->max_num_ir; ++i_chan ) + { + if ( ppDiffuseWeight[i_chan][0] != -1 && ppDiffuseWeight[i_chan][1] != -1 ) + { + pParam->inv_diffuse_weight[i_chan] = 2.f / ( ppDiffuseWeight[i_chan][0] + ppDiffuseWeight[i_chan][1] ); + } + else + { + pParam->inv_diffuse_weight[i_chan] = 0; /* pathological case ppEnergyDiffuseFilter[i_ear][i_chan]=0 */ + } + } + + free( pDiffuseFilter ); + + /**************************/ + /* Diffuse Fc calculation */ + /* For each block, find the index from which cumulative spectral power (end to begin) is under the threshold */ + for ( i_block = 0; i_block < pParam->num_iterations_diffuse[0]; ++i_block ) + { + /* reset indFreqMaxi */ + indFreqMaxi = 0; + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + /* Get block */ + indStart = ( pParam->num_iterations_diffuse[0] - 1 - i_block ) * frame_len; + + if ( indStart + frame_len - 1 < pFirData->N ) /* full block is available */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlock[i_tap] = ppDiffuseFilterWMC[i_ear][indStart + i_tap]; + } + } + else /* exceed BRIR size -> zero-pad the block -> cannot append */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlock[i_tap] = 0; + } + for ( i_tap = 0; i_tap < pFirData->N - indStart; ++i_tap ) + { + pBlock[i_tap] = ppDiffuseFilterWMC[i_ear][indStart + i_tap]; + } + } + + /* Compute block spectrum and take magnitude */ + ivas_mdft( pBlock, pBlockSpectrum_r, pBlockSpectrum_i, frame_len, frame_len ); + + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlockSpectrum_r[i_tap] = mdft_scale_fact * pBlockSpectrum_r[i_tap]; + pBlockSpectrum_i[i_tap] = mdft_scale_fact * pBlockSpectrum_i[i_tap]; + } + + delayf = (float) EVS_PI * ( (float) frame_len - 1.f ) / (float) frame_len; + + if ( i_block == 0 ) /* FOR last block of diffusion delay of the block to avoid reconstruction windows from cut off frequency at the end of the block */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlockSpectrum_r[i_tap] *= 1.414f * cosf( delayf * ( (float) i_tap + 0.5f ) ); + pBlockSpectrum_i[i_tap] *= -1.414f * sinf( delayf * ( (float) i_tap + 0.5f ) ); + } + } + + FFT_Complex_to_Mag( pBlockSpectrum_r, pBlockSpectrum_i, pBlockSpectrum_Mag, frame_len ); /* compute Magnitude */ + + /* Recompute filter energy (to Nyquist freq only) */ + energy = 0; + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + energy += pBlockSpectrum_Mag[i_tap] * pBlockSpectrum_Mag[i_tap]; + } + if ( energy > 0 ) + { + /* set threshold */ + threshold = powf( 10.f, DiffuseFcThld * 0.1f ) * energy; + indFreq = frame_len - 1; + CSEinstInvFreq = 0; + while ( indFreq >= 0 ) + { + CSEinstInvFreq += pBlockSpectrum_Mag[indFreq] * pBlockSpectrum_Mag[indFreq]; + + if ( CSEinstInvFreq >= threshold ) + { + break; + } + --indFreq; + } + } + else + { + indFreq = 0; + } + + if ( indFreq > indFreqMaxi ) + { + indFreqMaxi = indFreq; + } + } + + /* Set the frequency value(in Hz) in the output parameter "diffuseFc" */ + pParam->pIndex_frequency_max_diffuse[1][i_block] = pParam->pIndex_frequency_max_diffuse[0][i_block] = indFreqMaxi; + // pParam->pIndex_frequency_max_diffuse[1][i_block] = pParam->pIndex_frequency_max_diffuse[0][i_block] = framelen; + // reset indFreqMaxi + } + + for ( i_block = pParam->num_iterations_diffuse[0] - 1; i_block > 0; --i_block ) + { + if ( pParam->pIndex_frequency_max_diffuse[0][i_block - 1] > pParam->pIndex_frequency_max_diffuse[0][i_block] ) + { + pParam->pIndex_frequency_max_diffuse[1][i_block - 1] = pParam->pIndex_frequency_max_diffuse[0][i_block - 1] = pParam->pIndex_frequency_max_diffuse[0][i_block]; + } + } + + pParam->index_frequency_max_diffuse = 0; + totSizeFreqDiffuse = 0; + for ( i_block = 0; i_block < pParam->num_iterations_diffuse[0]; ++i_block ) + { + if ( pParam->index_frequency_max_diffuse < pParam->pIndex_frequency_max_diffuse[0][i_block] ) + { + pParam->index_frequency_max_diffuse = pParam->pIndex_frequency_max_diffuse[0][i_block]; + } + totSizeFreqDiffuse = totSizeFreqDiffuse + pParam->pIndex_frequency_max_diffuse[0][i_block]; + } + + /**************************/ + /* Diffuse Fc calculation */ + /* For each block, find the index from which cumulative spectral power (end to begin) is under the threshold */ + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + pParam->pOut_to_bin_diffuse_re[i_ear] = (float *) malloc( totSizeFreqDiffuse * sizeof( float ) ); + pParam->pOut_to_bin_diffuse_im[i_ear] = (float *) malloc( totSizeFreqDiffuse * sizeof( float ) ); + offset = 0; + for ( i_block = 0; i_block < pParam->num_iterations_diffuse[0]; ++i_block ) + { + /* Get block */ + indStart = ( pParam->num_iterations_diffuse[0] - 1 - i_block ) * frame_len; + + if ( indStart + frame_len - 1 < pFirData->N ) /* full block is available */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlock[i_tap] = ppDiffuseFilterWMC[i_ear][indStart + i_tap]; + } + } + else /* exceed BRIR size -> zero-pad the block -> cannot append */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlock[i_tap] = 0; + } + for ( i_tap = 0; i_tap < pFirData->N - indStart; ++i_tap ) + { + pBlock[i_tap] = ppDiffuseFilterWMC[i_ear][indStart + i_tap]; + } + } + + /* Compute block spectrum and take magnitude */ + ivas_mdft( pBlock, pBlockSpectrum_r, pBlockSpectrum_i, frame_len, frame_len ); + + for ( i_tap = 0; i_tap < frame_len; i_tap++ ) + { + pBlockSpectrum_r[i_tap] = mdft_scale_fact * pBlockSpectrum_r[i_tap]; + pBlockSpectrum_i[i_tap] = mdft_scale_fact * pBlockSpectrum_i[i_tap]; + } + + delayf = (float) EVS_PI * ( (float) frame_len - 1.f ) / (float) frame_len; + + if ( i_block == 0 ) /* FOR last block of diffusion delay of the block to avoid reconstruction windows from cut off frequency at the end of the block */ + { + for ( i_tap = 0; i_tap < frame_len; ++i_tap ) + { + pBlockSpectrum_r[i_tap] *= 1.414f * cosf( delayf * ( (float) i_tap + 0.5f ) ); + pBlockSpectrum_i[i_tap] *= -1.414f * sinf( delayf * ( (float) i_tap + 0.5f ) ); + } + } + for ( i_tap = 0; i_tap < pParam->pIndex_frequency_max_diffuse[i_ear][i_block]; i_tap++ ) + { + pParam->pOut_to_bin_diffuse_re[i_ear][offset + i_tap] = pBlockSpectrum_r[i_tap]; + pParam->pOut_to_bin_diffuse_im[i_ear][offset + i_tap] = pBlockSpectrum_i[i_tap]; + } + offset = offset + pParam->pIndex_frequency_max_diffuse[i_ear][i_block]; + } + } + + for ( i_ear = 0; i_ear < 2; ++i_ear ) + { + free( ppDiffuseFilterWMC[i_ear] ); + } + free( ppDiffuseFilterWMC ); + } + } + +#ifdef DEBUG_BINAURAL_FILTER_DESIGN + printfAudioBufferOutFilterParams( pParam, (uint32_t) index_start, (uint32_t) index_end ); +#endif + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function description - + * set the memory for hrtf pointers and do mdft + * + * Inputs - + * float *pStatic_memory + * ivas_hrtf_t **hrtf + * + * Outputs - + * HRTFS_DATA *crend_hrtf + * + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_set_hrtf_fr( + HRTFS_DATA *crend_hrtf, + ivas_hrtf_t *hrtf, + const int16_t output_frame ) +{ + int32_t i, j, m, n; + float data_ir_flt[L_FRAME48k] = { 0.0f }; + int32_t tmp_ir_len, in_len, k; + float mdft_scale_fact; + + mdft_scale_fact = ( (float) L_FRAME48k * 0.25f ) / output_frame; + + crend_hrtf->max_num_ir = (int16_t) hrtf->m; + + crend_hrtf->latency_s = (float) hrtf->latency_s[0][0]; + + for ( i = 0; i < crend_hrtf->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + crend_hrtf->pOut_to_bin_re[i][j] = (float *) malloc( ( ( crend_hrtf->num_iterations[i][j] * output_frame ) ) * sizeof( float ) ); + if ( crend_hrtf->pOut_to_bin_re[i][j] == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + crend_hrtf->pOut_to_bin_im[i][j] = (float *) malloc( ( ( crend_hrtf->num_iterations[i][j] * output_frame ) ) * sizeof( float ) ); + if ( crend_hrtf->pOut_to_bin_im[i][j] == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + n = 0; + tmp_ir_len = 0; + + for ( k = 0; k < hrtf->N; k++ ) + { + if ( hrtf->data_ir[i][j][k] != 0 ) + { + tmp_ir_len = k + 1; + } + } + for ( m = 0; m < crend_hrtf->num_iterations[i][j]; m++ ) + { + in_len = ( tmp_ir_len >= output_frame ) ? output_frame : tmp_ir_len; + for ( k = 0; k < in_len; k++, n++ ) + { + data_ir_flt[k] = (float) hrtf->data_ir[i][j][n]; + } + for ( k = tmp_ir_len; k < output_frame; k++, n++ ) + { + data_ir_flt[k] = 0; + } + tmp_ir_len -= in_len; + + ivas_mdft( data_ir_flt, &crend_hrtf->pOut_to_bin_re[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], + &crend_hrtf->pOut_to_bin_im[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], output_frame, output_frame ); + + v_multc( &crend_hrtf->pOut_to_bin_re[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], mdft_scale_fact, + &crend_hrtf->pOut_to_bin_re[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], output_frame ); + v_multc( &crend_hrtf->pOut_to_bin_im[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], mdft_scale_fact, + &crend_hrtf->pOut_to_bin_im[i][j][( crend_hrtf->num_iterations[i][j] - 1 - m ) * output_frame], output_frame ); + } + } + } + + for ( i = 0; i < crend_hrtf->max_num_ir; i++ ) + { + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + crend_hrtf->pIndex_frequency_max[i][j] = (uint16_t *) malloc( crend_hrtf->num_iterations[i][j] * sizeof( uint16_t ) ); + if ( crend_hrtf->pIndex_frequency_max[i][j] == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + for ( m = 0; m < crend_hrtf->num_iterations[i][j]; m++ ) + { + crend_hrtf->pIndex_frequency_max[i][j][m] = output_frame; + } + } + } + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------------------------* + * Function description - + * Get HRTF lengths for all input formats + * + * Inputs - + * int16_t frame_len + * ivas_hrtf_t **hrtf + * + * Outputs - + * HRTFS_DATA *crend_hrtf + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_get_hrtf_lens( + ivas_hrtf_t *hrtf, + HRTFS_DATA *crend_hrtf, + const int16_t frame_len ) +{ + int32_t i, j, k, tmp_ir_len; + + crend_hrtf->max_num_iterations = 0; + crend_hrtf->max_num_ir = (int16_t) hrtf->m; + for ( i = 0; i < hrtf->m; i++ ) + { + for ( j = 0; j < hrtf->R; j++ ) + { + tmp_ir_len = 0; + for ( k = 0; k < hrtf->N; k++ ) + { + if ( hrtf->data_ir[i][j][k] != 0 ) + { + tmp_ir_len = k + 1; + } + } + crend_hrtf->num_iterations[i][j] = (uint16_t) ceilf( (float) tmp_ir_len / frame_len ); + if ( crend_hrtf->max_num_iterations < crend_hrtf->num_iterations[i][j] ) + { + crend_hrtf->max_num_iterations = crend_hrtf->num_iterations[i][j]; + } + } + } + + for ( i = crend_hrtf->max_num_ir; i < MAX_INTERN_CHANNELS; i++ ) + { + for ( j = 0; j < hrtf->R; j++ ) + { + crend_hrtf->num_iterations[i][j] = 0; + } + } + + return IVAS_ERR_OK; +} diff --git a/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.h b/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.h new file mode 100644 index 0000000000000000000000000000000000000000..9b8fdbcde916440319990b039e1a141d21c79cee --- /dev/null +++ b/scripts/binauralRenderer_interface/ivas_crend_binaural_filter_design.h @@ -0,0 +1,67 @@ +/****************************************************************************************************** + + (C) 2022 Baseline Development Group with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The Baseline Development Group consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., and VoiceAge Corporation retain full ownership + rights in their respective contributions in the software. No license of any kind, including but not + limited to patent license, of any foregoing parties is hereby granted by implication, estoppel or + otherwise. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and/or fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ +#ifndef IVAS_CREND_BIBAURAL_FILTER_DESIGN_H_ +#define IVAS_CREND_BIBAURAL_FILTER_DESIGN_H_ + +#include +#include + +#include "ivas_stat_dec.h" +#define IVAS_SOFA_MAX_VAL_M ( 30 ) +#define IVAS_SOFA_MAX_VAL_R ( 2 ) +#define IVAS_SOFA_MAX_VAL_N ( 48000 ) +#define IVAS_SOFA_MAX_VAL_I ( 1 ) +#define IVAS_MAX_NUM_DIRECT_BLOCKS ( 40 ) /* max number of direct blocks */ +#define IVAS_MAX_NUM_DIFFUSE_BLOCKS ( 40 ) /* max number of diffuse blocks */ +#define IVAS_MAX_HRTF_LATENCY_MS ( 0.1 ) /* max hrtf latency */ + +typedef struct ivas_hrtf_t +{ + double *latency_s[IVAS_SOFA_MAX_VAL_I]; + double *data_ir[IVAS_SOFA_MAX_VAL_M][IVAS_SOFA_MAX_VAL_M]; + int8_t *p_hrtf_data; + int32_t I; + int32_t R; + int32_t N; + int32_t m; + int32_t sampling_rate; +} ivas_hrtf_t; + +/*------------------------------------------------------------------------------------------* + * function declarations + *------------------------------------------------------------------------------------------*/ + +ivas_error ivas_get_hrtf_lens( ivas_hrtf_t *hrtf, HRTFS_DATA *crend_hrtf, const int16_t frame_len ); +ivas_error ivas_set_hrtf_fr( HRTFS_DATA *crend_hrtf, ivas_hrtf_t *hrtf, const int16_t frame_len ); + +ivas_error ivas_crend_binaural_filter_design_compute_filters_params( ivas_hrtf_t *pFirData, const int16_t framelen, HRTFS_DATA *pParam, int32_t *index_start, int32_t *index_end, int32_t *max_ir_len ); +ivas_error ivas_crend_binaural_filter_design_set_hrtf_fr( ivas_hrtf_t *pFirData, const int16_t frame_len, HRTFS_DATA *pParam, int32_t index_start, int32_t index_end, int32_t *max_ir_len ); + +ivas_error ivas_hrtf_close( HRTFS_HANDLE hHRTF ); + +#endif /* IVAS_SOFA_PARSER_H_ */ diff --git a/scripts/binauralRenderer_interface/resolve_build_dep.py b/scripts/binauralRenderer_interface/resolve_build_dep.py new file mode 100644 index 0000000000000000000000000000000000000000..5a1a823033b5bbc9480bbc4d0da0c8e55b2f86a2 --- /dev/null +++ b/scripts/binauralRenderer_interface/resolve_build_dep.py @@ -0,0 +1,130 @@ +""" + (C) 2022 Baseline Development Group with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The Baseline Development Group consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies OY, Orange, + Panasonic Corporation, Qualcomm Technologies, Inc., and VoiceAge Corporation retain full ownership + rights in their respective contributions in the software. No license of any kind, including but not + limited to patent license, of any foregoing parties is hereby granted by implication, estoppel or + otherwise. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and/or fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import os +import sys +import subprocess +import urllib.request +import shutil +import zipfile +import errno +import fileinput + + +def main(): + zlib_src_dir = './Externals/zlib' + extracted_zlib_dir = get_zlib(zlib_src_dir) + #extracted_zlib_dir = 'zlib_dir/zlib-1.2.12' + # delete_files(zlib_src_dir) + print(extracted_zlib_dir) + return extracted_zlib_dir + + +def check_rm_and_makedir(dir_path): + if not os.path.exists(dir_path): + try: + os.makedirs(dir_path) + except OSError as e: + if e.errno != errno.EEXIST: + raise # raises the error again + else: + shutil.rmtree(dir_path, ignore_errors=True) + check_rm_and_makedir(dir_path) + + +def extract_files(file_name, extract_path): + check_rm_and_makedir(extract_path) + with zipfile.ZipFile(file_name, 'r') as zip_ref: + zip_ref.extractall(extract_path) + + +def get_zlib(zlib_dir): + url = 'https://github.com/madler/zlib/archive/refs/tags/v1.2.12.zip' + file_name = 'zlib1212.zip' + if os.path.isfile(file_name): + os.remove(file_name) + # Download the file from `url` and save it locally under `file_name`: + with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file: + shutil.copyfileobj(response, out_file) + + if os.path.isfile(file_name): + extract_files(file_name, zlib_dir) + extracted_zlib_dir = zlib_dir + '/zlib-1.2.12' + os.remove(file_name) + else: + extracted_zlib_dir = '' + assert False + + return extracted_zlib_dir + + +def find_config(file, search_text): + f = open(file, 'r') + empty_line = '' + for line in f: + if search_text in line: + return line + return empty_line + + +def add_config(file, tag, prop): + for line in fileinput.FileInput(file, inplace=1): + if tag in line: + line = line.replace(line, line+prop) + sys.stdout.write(line) + + +def replace_config(file, search_text, replace_text): + for line in fileinput.input(file, inplace=1): + if search_text in line: + line = line.replace(search_text, replace_text) + sys.stdout.write(line) + + +def scr_fun(tag, src_file, dest_file): + new_config = find_config(src_file, tag) + if len(new_config) == 0: + print('property not found in IVAS project file, update IVAS project file first') + assert False + old_config = find_config(dest_file, tag) + replace_config(dest_file, old_config, new_config) + + +def scr_fun2(tag, src_file, dest_file, tag2): + new_config = find_config(src_file, tag) + if len(new_config) == 0: + print('property not found in IVAS project file, update IVAS project file first') + assert False + add_config(dest_file, tag2, new_config) + + +def delete_files(extracted_zlib_dir): + if os.path.exists(extracted_zlib_dir): + shutil.rmtree(extracted_zlib_dir, ignore_errors=True) + + +if __name__ == "__main__": + main()