Loading scripts/binauralRenderer_interface/CMakeLists.txt +38 −4 Original line number Diff line number Diff line Loading @@ -11,6 +11,28 @@ 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) option(USE_PYTHON "Use SOFA python reader" OFF) option(USE_MATLAB "Use SOFA matlab reader" ON) if (USE_MATLAB) find_package(Matlab REQUIRED) message("Matlab_VERSION = ${Matlab_VERSION}") message("Matlab_ROOT_DIR = ${Matlab_ROOT_DIR}") message("Matlab_INCLUDE_DIRS = ${Matlab_INCLUDE_DIRS}") if (NOT Matlab_MAT_LIBRARY) string(REPLACE "mex" "mat" Matlab_MAT_LIBRARY ${Matlab_MEX_LIBRARY}) endif() message("Matlab_MAT_LIBRARY = ${Matlab_MAT_LIBRARY}") message("Matlab_LIBRARIES = ${Matlab_LIBRARIES}") message("Matlab_MX_LIBRARY = ${Matlab_MX_LIBRARY}") message("Matlab_MEX_LIBRARY = ${Matlab_MEX_LIBRARY}") message("Matlab_ENGINE_LIBRARY = ${Matlab_ENGINE_LIBRARY}") message("Matlab_DATAARRAY_LIBRARY = ${Matlab_DATAARRAY_LIBRARY}") add_definitions(-DUSE_MATLAB) include_directories(${Matlab_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}) endif() if (USE_PYTHON) find_package(Python REQUIRED COMPONENTS Development Interpreter NumPy) message("Python_EXECUTABLE = ${Python_EXECUTABLE}") Loading @@ -37,6 +59,7 @@ endif() add_definitions(-DNPY_NO_DEPRECATED_API) include_directories(${Python_INCLUDE_DIRS} ${Python_NumPy_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}) endif() set(SOURCE_FILES_C ${PROJECT_SOURCE_DIR}/ivas_crend_binaural_filter_design.c Loading Loading @@ -77,11 +100,22 @@ add_library(${PROJECT_NAME}_lib STATIC ${SOURCE_FILES_C} ${SOURCE_FILES_H}) add_executable(${PROJECT_NAME} generate_crend_ivas_tables_from_sofa.c) if (USE_MATLAB) if(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Matlab_MAT_LIBRARY} -lm -ldl) else() message("Matlab_MX_LIBRARY = ${Matlab_MX_LIBRARY}") target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Matlab_MAT_LIBRARY} ${Matlab_LIBRARIES} ) endif() endif() if (USE_PYTHON) if(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Python_LIBRARIES} -lm -ldl) else() target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Python_LIBRARIES}) endif() endif() if(WIN32) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) Loading scripts/binauralRenderer_interface/generate_crend_ivas_tables_from_sofa.c +214 −24 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ #include <unistd.h> #define MAX_PATH PATH_MAX #endif #ifdef _WIN32 #define _USE_MATH_DEFINES #endif #include <math.h> #include "options.h" #include "ivas_cnst.h" Loading @@ -56,10 +59,14 @@ #undef M #endif #ifdef USE_MATLAB #include "mat.h" #else #include <Python.h> #include "numpy/utils.h" // Include any other Numpy headers, UFuncs for example. #include "numpy/numpyconfig.h" // Include any other Numpy headers, UFuncs for example. #include "numpy/arrayobject.h" // Include any other Numpy headers, UFuncs for example. #endif /*------------------------------------------------------------------------------------------* * Constants Loading Loading @@ -222,6 +229,7 @@ char *h_file_path = NULL; char *rom_file_name = NULL; uint16_t frame_len_ms = 5; #ifndef USE_MATLAB PyObject *sofa_load_func = NULL; PyObject *sofa_find_dir_func = NULL; Loading Loading @@ -252,6 +260,7 @@ int numpy_import_array( int ret ) return 0; } #endif /*------------------------------------------------------------------------------------------* * Standalone Renderer program * Loading Loading @@ -638,6 +647,9 @@ int main( int argc, char *argv[] ) char *tmpstr = strstr( ivas_path, "/binauralRenderer_interface" ); #endif tmpstr[0] = '\0'; #ifndef USE_MATLAB Py_Initialize(); PyObject *sysPath = PySys_GetObject( (char *) "path" ); Loading Loading @@ -749,7 +761,7 @@ int main( int argc, char *argv[] ) free( binary_common_file_name ); return -1; } #endif int err = 0; for ( ; i < argc; i++ ) { Loading Loading @@ -849,16 +861,39 @@ int main( int argc, char *argv[] ) if ( binary_file_path ) free( binary_file_path ); #ifndef USE_MATLAB Py_DECREF( sofa_find_dir_func ); Py_DECREF( sofa_load_func ); Py_Finalize(); #endif return err; } int32_t find_pos_spheric( const double *Source_Position_Cartesian, int32_t numPos, const double dir_spheric[3] ) { double valmax = 0; int32_t indmax = -1; int32_t ind; double dir_cart[3]; double tmp; dir_cart[0] = ( dir_spheric[2] * cos( dir_spheric[0] * M_PI / 180. ) * cos( dir_spheric[1] * M_PI / 180. ) ); dir_cart[1] = ( dir_spheric[2] * sin( dir_spheric[0] * M_PI / 180. ) * cos( dir_spheric[1] * M_PI / 180. ) ); dir_cart[2] = dir_spheric[2] * sin( dir_spheric[1] * M_PI / 180. ); for ( ind = 0; ind < numPos; ind++ ) { tmp = Source_Position_Cartesian[ind * 3] * dir_cart[0] + Source_Position_Cartesian[ind * 3 + 1] * dir_cart[1] + Source_Position_Cartesian[ind * 3 + 2] * dir_cart[2]; if ( tmp > valmax ) { valmax = tmp; indmax = ind; } } return indmax; } int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *cfgReader ) { char *sofa_file_path = NULL; Loading @@ -867,7 +902,6 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c const char *sofaDataBaseName = ""; const char *sofaListenerName = ""; double *data_IR_current = NULL; double *sofa_data_IR_val = NULL; double *sofa_data_IR_val_48k = NULL; double *sofa_data_IR_val_32k = NULL; double *sofa_data_IR_val_16k = NULL; Loading @@ -875,6 +909,12 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c double *sofa_delay_val = NULL; double *sofa_src_pos_val = NULL; double *sofa_src_pos_cart_val = NULL; long sofa_sample_rate = 0; double a[3] = { 0 }; double t[3] = { 0 }; long nearest; #ifndef USE_MATLAB PyObject *args = NULL; PyObject *kwargs = NULL; Loading @@ -882,12 +922,9 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c PyArrayObject *sofa_data_IR = NULL; PyArrayObject *sofa_data_IR_48k = NULL; PyArrayObject *sofa_delay = NULL; long sofa_sample_rate = 0; PyArrayObject *sofa_src_pos_cart = NULL; PyArrayObject *dir_t = NULL; double a[3] = { 0 }; double t[3] = { 0 }; long nearest; #endif /*------------------------------------------------------------------------------------------* * Parse command line and initialize renderer *------------------------------------------------------------------------------------------*/ Loading @@ -900,6 +937,148 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } strcpy( sofa_file_path, file_path ); #ifdef USE_MATLAB MATFile *mat_fp = matOpen( sofa_file_path, "r" ); if ( mat_fp == NULL ) { printf( "Error reading existing matrix LocalDouble\n" ); usage_gen_crend_tables(); free( sofa_file_path ); return -1; } mxArray *sofa = matGetVariable( mat_fp, "Sofa" ); if ( sofa == NULL ) { printf( "Error reading existing matrix LocalDouble\n" ); usage_gen_crend_tables(); free( sofa_file_path ); matClose( mat_fp ); return -1; } mwSize total_num_of_elements; mwIndex index = 0; int number_of_fields, field_index; const char *field_name; const mxArray *data; const double *sampleRate; // total_num_of_elements = mxGetNumberOfElements( sofa ); number_of_fields = mxGetNumberOfFields( sofa ); /* For the given index, walk through each field. */ for ( field_index = 0; field_index < number_of_fields; field_index++ ) { // display_subscript( structure_array_ptr, index ); field_name = mxGetFieldNameByNumber( sofa, field_index ); if ( strcmp( field_name, "DatabaseName" ) == 0 ) { sofaDataBaseName = mxArrayToUTF8String( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofaDataBaseName == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "ListenerShortName" ) == 0 ) { sofaListenerName = mxArrayToUTF8String( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofaListenerName == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "latencys" ) == 0 ) { sofa_latencys = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_latencys == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "DataResampled" ) == 0 ) { data = mxGetFieldByNumber( sofa, index, field_index ); if ( data == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } total_num_of_elements = mxGetNumberOfElements( data ); for ( indSR = 0; indSR < total_num_of_elements; indSR++ ) { sampleRate = mxGetPr( mxGetFieldByNumber( data, indSR, 1 ) ); if ( *sampleRate == 48000 ) { const mwSize *dims = mxGetDimensions( mxGetFieldByNumber( data, indSR, 0 ) ); sofa_N = sofa_N_48k = (int32_t) dims[0]; sofa_R = (int32_t) dims[1]; sofa_M = (int32_t) dims[2]; sofa_data_IR_val_48k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } if ( *sampleRate == 32000 ) { sofa_data_IR_val_32k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } if ( *sampleRate == 16000 ) { sofa_data_IR_val_16k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } } } if ( strcmp( field_name, "PosCartesian" ) == 0 ) { sofa_src_pos_cart_val = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_src_pos_cart_val == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } } if ( strcmp( field_name, "PosSpherical" ) == 0 ) { sofa_src_pos_val = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_src_pos_val == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } } } // } #else int ret = PyCallable_Check( sofa_load_func ); if ( ret ) { Loading Loading @@ -963,6 +1142,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } } } #endif struct ivas_layout_config lscfg; Loading Loading @@ -996,6 +1176,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c long nearest = 0; // int nd = 1; // int64_t n = 3; #ifndef USE_MATLAB npy_intp dim[1] = { 3 }; dir_t = (PyArrayObject *) PyArray_SimpleNewFromData( 1, dim, NPY_DOUBLE, t ); Loading @@ -1007,13 +1188,16 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c return -1; } #endif } /* 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 ) { #ifndef USE_MATLAB Py_DECREF( py_results ); #endif free( sofa_file_path ); fprintf( stderr, "Cannot alloc sofa_file_path !\n\n" ); return -1; Loading @@ -1035,16 +1219,20 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c // tmp[2] = t[2]; // fprintf( stderr, "Wanted Position: %lf, %lf, %lf\n", t[0], t[1], t[2] ); // fprintf( stderr, "Wanted Position: %lf, %lf, %lf\n", tmp[0], tmp[1], tmp[2] ); #ifdef USE_MATLAB nearest = find_pos_spheric( sofa_src_pos_cart_val, sofa_M, t ); #else py_results = PyObject_CallFunction( sofa_find_dir_func, "OO", (PyObject *) sofa_src_pos_cart, (PyObject *) dir_t ); nearest = PyLong_AsLong( py_results ); #endif if ( ( nearest >= 0 ) && ( nearest < sofa_M ) ) { a[0] = sofa_src_pos_val[nearest * 3]; a[0] = sofa_src_pos_val[nearest * 3] * 180. / M_PI; if ( a[0] < 0 ) { a[0] += 360.; } a[1] = sofa_src_pos_val[nearest * 3 + 1]; a[1] = sofa_src_pos_val[nearest * 3 + 1] * 180. / M_PI; a[2] = sofa_src_pos_val[nearest * 3 + 2]; } Loading @@ -1061,10 +1249,10 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c free( sofa_file_path ); return -1; } if ( a[0] > 180 ) a[0] -= 360; if ( a[0] < -180 ) a[0] += 360; 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: %ld\n", nearest ); index_pos[i] = nearest; Loading @@ -1077,7 +1265,6 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c uint32_t size = (uint32_t) sofa_R; uint32_t delL = 0, delR = 0; } size_t len_ls_cfg_name = strlen( lscfg.name ); double latency_48k = 0; Loading Loading @@ -1261,8 +1448,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } else { ivas_set_hrtf_fr( &hrtf_data, ivas_hrtf, frame_len ); ivas_set_hrtf_fr( &hrtf_data, ivas_hrtf, frame_len ); } hrtf_data.latency_s += 0.000000001f; Loading Loading @@ -1313,8 +1499,12 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c ivas_hrtf_close( &hrtf_data ); } #ifdef USE_MATLAB matClose( mat_fp ); #else Py_DECREF( args ); Py_DECREF( py_results ); #endif if ( sofa_file_path ) free( sofa_file_path ); Loading scripts/binauralRenderer_interface/generate_ivas_binauralizer_tables_from_sofa.m +8 −5 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ dataSpec.romOutDir = rom_path; Mod_Hrf_Itd_Main(dataSpec); %% generate crend rom or binary values SOFA_save_to_mat(hrir_file); SOFA_save_to_mat(brir_file); convert_SD2SHD_HRIRs(hrir_path,hrir_file_name,128); command = ['.' filesep() 'generate_crend_ivas_tables']; Loading @@ -99,11 +102,11 @@ end command = [command ... ' 5 ' ... hrir_file ' ' ... erase(hrir_file,'.sofa') '_FOA.sofa ' ... erase(hrir_file,'.sofa') '_HOA2.sofa ' ... erase(hrir_file,'.sofa') '_HOA3.sofa ' ... brir_file ]; erase(hrir_file,'.sofa') '.mat ' ... erase(hrir_file,'.sofa') '_FOA.mat ' ... erase(hrir_file,'.sofa') '_HOA2.mat ' ... erase(hrir_file,'.sofa') '_HOA3.mat ' ... erase(brir_file,'.sofa') '.mat ' ]; %display(command); Loading scripts/binauralRenderer_interface/matlab_hrir_generation_scripts/SOFA_save_to_mat.m 0 → 100644 +113 −0 Original line number Diff line number Diff line %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % (C) 2022-2023 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. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function SOFA_save_to_mat(Lib_Name,outputSofaPath,sampleRates) %UNTITLED Summary of this function goes here % Detailed explanation goes here if nargin == 1 outputSofaPath = [erase(Lib_Name,'.sofa') '.mat']; sampleRates = [48000 32000 16000]; end if nargin == 2 sampleRates = [48000 32000 16000]; end if isfile(Lib_Name) if isfile(outputSofaPath) delete(outputSofaPath); end Sofa = struct('Sofa',struct()); sofa_data = ncinfo(Lib_Name); for indVar = 1:length(sofa_data.Variables) if (strcmp(sofa_data.Variables(indVar).Name, 'latencys')) Sofa.latencys = ncread(Lib_Name,'latencys'); end end Sofa.Pos = ncread(Lib_Name, 'SourcePosition'); Sofa.Units = strtrim(strsplit(ncreadatt(Lib_Name, 'SourcePosition', 'Units'), ',')); assert( any(strcmpi(Sofa.Units{1}, {'degree','radian'})), 'Unknown units'); if strcmpi(Sofa.Units{1},'degree'), Sofa.Pos(1,:)=Sofa.Pos(1,:)*pi/180; end assert( any(strcmpi(Sofa.Units{2}, {'degree','radian'})), 'Unknown units'); if strcmpi(Sofa.Units{2},'degree'), Sofa.Pos(2,:)=Sofa.Pos(2,:)*pi/180; end assert( any(strcmpi(Sofa.Units{3}, {'metre','meter','inch'})), 'Unknown units'); if strcmpi(Sofa.Units{3},'inch' ), Sofa.Pos(3,:)=Sofa.Pos(3,:)*0.0254; end Sofa.PosSpherical = Sofa.Pos; Sofa.Pos = Sofa.Pos(3,:) .* ... [cos(Sofa.Pos(2,:)).*[cos(Sofa.Pos(1,:));sin(Sofa.Pos(1,:))];sin(Sofa.Pos(2,:))]; Sofa.PosCartesian = make_unit_vectors(Sofa.Pos); NumLoc = size(Sofa.PosCartesian,2); % Now, get the impulse repsonses: Sofa.DataType = ncreadatt(Lib_Name, '/', 'DataType'); Sofa.Data.IR = ncread(Lib_Name, 'Data.IR'); Sofa.Data.SamplingRate = ncread(Lib_Name, 'Data.SamplingRate'); Sofa.Data.SamplingRate_Units = ncreadatt(Lib_Name, 'Data.SamplingRate', 'Units'); Sofa.Data.Delay = permute(ncread(Lib_Name, 'Data.Delay'), [2, 1]); switch lower(Sofa.DataType) case 'fir' assert( size(Sofa.Data.IR,2)>=2, 'Expecting 2 receivers (ears)'); if size(Sofa.Data.IR,2)>2 Sofa.Data.IR = Sofa.Data.IR(:,1:2,:); Sofa.Data.Delay = Sofa.Data.Delay(:,1:2); end assert( size(Sofa.Data.IR,3)==NumLoc, 'IR is incorrect size'); assert( all(diff(Sofa.Data.Delay,1,2)==0), ... 'Non-zero inter-aural delay offset not (yet) implemented'); assert(strcmp(Sofa.Data.SamplingRate_Units,'hertz'), 'unknown samplerate units'); otherwise error(['unknown GLOBAL_DataType = ', hrtf.GLOBAL_DataType]); end for ind = 1:length(sampleRates) if sampleRates(ind) == Sofa.Data.SamplingRate Sofa.DataResampled(ind).IR = Sofa.Data.IR; else Sofa.DataResampled(ind).IR = resample(Sofa.Data.IR, sampleRates(ind),Sofa.Data.SamplingRate, Dimension=3); end Sofa.DataResampled(ind).SamplingRate = sampleRates(ind); end Sofa.License = ncreadatt(Lib_Name,'/','License'); Sofa.ListenerShortName = ncreadatt(Lib_Name,'/','ListenerShortName'); Sofa.DatabaseName = ncreadatt(Lib_Name,'/','DatabaseName'); Sofa.Title = ncreadatt(Lib_Name,'/','Title'); Sofa.SOFAConventions = ncreadatt(Lib_Name,'/','SOFAConventions'); save(outputSofaPath, 'Sofa'); end No newline at end of file Loading
scripts/binauralRenderer_interface/CMakeLists.txt +38 −4 Original line number Diff line number Diff line Loading @@ -11,6 +11,28 @@ 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) option(USE_PYTHON "Use SOFA python reader" OFF) option(USE_MATLAB "Use SOFA matlab reader" ON) if (USE_MATLAB) find_package(Matlab REQUIRED) message("Matlab_VERSION = ${Matlab_VERSION}") message("Matlab_ROOT_DIR = ${Matlab_ROOT_DIR}") message("Matlab_INCLUDE_DIRS = ${Matlab_INCLUDE_DIRS}") if (NOT Matlab_MAT_LIBRARY) string(REPLACE "mex" "mat" Matlab_MAT_LIBRARY ${Matlab_MEX_LIBRARY}) endif() message("Matlab_MAT_LIBRARY = ${Matlab_MAT_LIBRARY}") message("Matlab_LIBRARIES = ${Matlab_LIBRARIES}") message("Matlab_MX_LIBRARY = ${Matlab_MX_LIBRARY}") message("Matlab_MEX_LIBRARY = ${Matlab_MEX_LIBRARY}") message("Matlab_ENGINE_LIBRARY = ${Matlab_ENGINE_LIBRARY}") message("Matlab_DATAARRAY_LIBRARY = ${Matlab_DATAARRAY_LIBRARY}") add_definitions(-DUSE_MATLAB) include_directories(${Matlab_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}) endif() if (USE_PYTHON) find_package(Python REQUIRED COMPONENTS Development Interpreter NumPy) message("Python_EXECUTABLE = ${Python_EXECUTABLE}") Loading @@ -37,6 +59,7 @@ endif() add_definitions(-DNPY_NO_DEPRECATED_API) include_directories(${Python_INCLUDE_DIRS} ${Python_NumPy_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}) endif() set(SOURCE_FILES_C ${PROJECT_SOURCE_DIR}/ivas_crend_binaural_filter_design.c Loading Loading @@ -77,11 +100,22 @@ add_library(${PROJECT_NAME}_lib STATIC ${SOURCE_FILES_C} ${SOURCE_FILES_H}) add_executable(${PROJECT_NAME} generate_crend_ivas_tables_from_sofa.c) if (USE_MATLAB) if(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Matlab_MAT_LIBRARY} -lm -ldl) else() message("Matlab_MX_LIBRARY = ${Matlab_MX_LIBRARY}") target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Matlab_MAT_LIBRARY} ${Matlab_LIBRARIES} ) endif() endif() if (USE_PYTHON) if(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Python_LIBRARIES} -lm -ldl) else() target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_lib ${Python_LIBRARIES}) endif() endif() if(WIN32) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) Loading
scripts/binauralRenderer_interface/generate_crend_ivas_tables_from_sofa.c +214 −24 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ #include <unistd.h> #define MAX_PATH PATH_MAX #endif #ifdef _WIN32 #define _USE_MATH_DEFINES #endif #include <math.h> #include "options.h" #include "ivas_cnst.h" Loading @@ -56,10 +59,14 @@ #undef M #endif #ifdef USE_MATLAB #include "mat.h" #else #include <Python.h> #include "numpy/utils.h" // Include any other Numpy headers, UFuncs for example. #include "numpy/numpyconfig.h" // Include any other Numpy headers, UFuncs for example. #include "numpy/arrayobject.h" // Include any other Numpy headers, UFuncs for example. #endif /*------------------------------------------------------------------------------------------* * Constants Loading Loading @@ -222,6 +229,7 @@ char *h_file_path = NULL; char *rom_file_name = NULL; uint16_t frame_len_ms = 5; #ifndef USE_MATLAB PyObject *sofa_load_func = NULL; PyObject *sofa_find_dir_func = NULL; Loading Loading @@ -252,6 +260,7 @@ int numpy_import_array( int ret ) return 0; } #endif /*------------------------------------------------------------------------------------------* * Standalone Renderer program * Loading Loading @@ -638,6 +647,9 @@ int main( int argc, char *argv[] ) char *tmpstr = strstr( ivas_path, "/binauralRenderer_interface" ); #endif tmpstr[0] = '\0'; #ifndef USE_MATLAB Py_Initialize(); PyObject *sysPath = PySys_GetObject( (char *) "path" ); Loading Loading @@ -749,7 +761,7 @@ int main( int argc, char *argv[] ) free( binary_common_file_name ); return -1; } #endif int err = 0; for ( ; i < argc; i++ ) { Loading Loading @@ -849,16 +861,39 @@ int main( int argc, char *argv[] ) if ( binary_file_path ) free( binary_file_path ); #ifndef USE_MATLAB Py_DECREF( sofa_find_dir_func ); Py_DECREF( sofa_load_func ); Py_Finalize(); #endif return err; } int32_t find_pos_spheric( const double *Source_Position_Cartesian, int32_t numPos, const double dir_spheric[3] ) { double valmax = 0; int32_t indmax = -1; int32_t ind; double dir_cart[3]; double tmp; dir_cart[0] = ( dir_spheric[2] * cos( dir_spheric[0] * M_PI / 180. ) * cos( dir_spheric[1] * M_PI / 180. ) ); dir_cart[1] = ( dir_spheric[2] * sin( dir_spheric[0] * M_PI / 180. ) * cos( dir_spheric[1] * M_PI / 180. ) ); dir_cart[2] = dir_spheric[2] * sin( dir_spheric[1] * M_PI / 180. ); for ( ind = 0; ind < numPos; ind++ ) { tmp = Source_Position_Cartesian[ind * 3] * dir_cart[0] + Source_Position_Cartesian[ind * 3 + 1] * dir_cart[1] + Source_Position_Cartesian[ind * 3 + 2] * dir_cart[2]; if ( tmp > valmax ) { valmax = tmp; indmax = ind; } } return indmax; } int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *cfgReader ) { char *sofa_file_path = NULL; Loading @@ -867,7 +902,6 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c const char *sofaDataBaseName = ""; const char *sofaListenerName = ""; double *data_IR_current = NULL; double *sofa_data_IR_val = NULL; double *sofa_data_IR_val_48k = NULL; double *sofa_data_IR_val_32k = NULL; double *sofa_data_IR_val_16k = NULL; Loading @@ -875,6 +909,12 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c double *sofa_delay_val = NULL; double *sofa_src_pos_val = NULL; double *sofa_src_pos_cart_val = NULL; long sofa_sample_rate = 0; double a[3] = { 0 }; double t[3] = { 0 }; long nearest; #ifndef USE_MATLAB PyObject *args = NULL; PyObject *kwargs = NULL; Loading @@ -882,12 +922,9 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c PyArrayObject *sofa_data_IR = NULL; PyArrayObject *sofa_data_IR_48k = NULL; PyArrayObject *sofa_delay = NULL; long sofa_sample_rate = 0; PyArrayObject *sofa_src_pos_cart = NULL; PyArrayObject *dir_t = NULL; double a[3] = { 0 }; double t[3] = { 0 }; long nearest; #endif /*------------------------------------------------------------------------------------------* * Parse command line and initialize renderer *------------------------------------------------------------------------------------------*/ Loading @@ -900,6 +937,148 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } strcpy( sofa_file_path, file_path ); #ifdef USE_MATLAB MATFile *mat_fp = matOpen( sofa_file_path, "r" ); if ( mat_fp == NULL ) { printf( "Error reading existing matrix LocalDouble\n" ); usage_gen_crend_tables(); free( sofa_file_path ); return -1; } mxArray *sofa = matGetVariable( mat_fp, "Sofa" ); if ( sofa == NULL ) { printf( "Error reading existing matrix LocalDouble\n" ); usage_gen_crend_tables(); free( sofa_file_path ); matClose( mat_fp ); return -1; } mwSize total_num_of_elements; mwIndex index = 0; int number_of_fields, field_index; const char *field_name; const mxArray *data; const double *sampleRate; // total_num_of_elements = mxGetNumberOfElements( sofa ); number_of_fields = mxGetNumberOfFields( sofa ); /* For the given index, walk through each field. */ for ( field_index = 0; field_index < number_of_fields; field_index++ ) { // display_subscript( structure_array_ptr, index ); field_name = mxGetFieldNameByNumber( sofa, field_index ); if ( strcmp( field_name, "DatabaseName" ) == 0 ) { sofaDataBaseName = mxArrayToUTF8String( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofaDataBaseName == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "ListenerShortName" ) == 0 ) { sofaListenerName = mxArrayToUTF8String( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofaListenerName == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "latencys" ) == 0 ) { sofa_latencys = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_latencys == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); } } if ( strcmp( field_name, "DataResampled" ) == 0 ) { data = mxGetFieldByNumber( sofa, index, field_index ); if ( data == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } total_num_of_elements = mxGetNumberOfElements( data ); for ( indSR = 0; indSR < total_num_of_elements; indSR++ ) { sampleRate = mxGetPr( mxGetFieldByNumber( data, indSR, 1 ) ); if ( *sampleRate == 48000 ) { const mwSize *dims = mxGetDimensions( mxGetFieldByNumber( data, indSR, 0 ) ); sofa_N = sofa_N_48k = (int32_t) dims[0]; sofa_R = (int32_t) dims[1]; sofa_M = (int32_t) dims[2]; sofa_data_IR_val_48k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } if ( *sampleRate == 32000 ) { sofa_data_IR_val_32k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } if ( *sampleRate == 16000 ) { sofa_data_IR_val_16k = mxGetPr( mxGetFieldByNumber( data, indSR, 0 ) ); } } } if ( strcmp( field_name, "PosCartesian" ) == 0 ) { sofa_src_pos_cart_val = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_src_pos_cart_val == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } } if ( strcmp( field_name, "PosSpherical" ) == 0 ) { sofa_src_pos_val = mxGetPr( mxGetFieldByNumber( sofa, index, field_index ) ); if ( sofa_src_pos_val == NULL ) { printf( "\tEmpty Field for %s\n", field_name ); free( sofa_file_path ); matClose( mat_fp ); return -1; } } } // } #else int ret = PyCallable_Check( sofa_load_func ); if ( ret ) { Loading Loading @@ -963,6 +1142,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } } } #endif struct ivas_layout_config lscfg; Loading Loading @@ -996,6 +1176,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c long nearest = 0; // int nd = 1; // int64_t n = 3; #ifndef USE_MATLAB npy_intp dim[1] = { 3 }; dir_t = (PyArrayObject *) PyArray_SimpleNewFromData( 1, dim, NPY_DOUBLE, t ); Loading @@ -1007,13 +1188,16 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c return -1; } #endif } /* 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 ) { #ifndef USE_MATLAB Py_DECREF( py_results ); #endif free( sofa_file_path ); fprintf( stderr, "Cannot alloc sofa_file_path !\n\n" ); return -1; Loading @@ -1035,16 +1219,20 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c // tmp[2] = t[2]; // fprintf( stderr, "Wanted Position: %lf, %lf, %lf\n", t[0], t[1], t[2] ); // fprintf( stderr, "Wanted Position: %lf, %lf, %lf\n", tmp[0], tmp[1], tmp[2] ); #ifdef USE_MATLAB nearest = find_pos_spheric( sofa_src_pos_cart_val, sofa_M, t ); #else py_results = PyObject_CallFunction( sofa_find_dir_func, "OO", (PyObject *) sofa_src_pos_cart, (PyObject *) dir_t ); nearest = PyLong_AsLong( py_results ); #endif if ( ( nearest >= 0 ) && ( nearest < sofa_M ) ) { a[0] = sofa_src_pos_val[nearest * 3]; a[0] = sofa_src_pos_val[nearest * 3] * 180. / M_PI; if ( a[0] < 0 ) { a[0] += 360.; } a[1] = sofa_src_pos_val[nearest * 3 + 1]; a[1] = sofa_src_pos_val[nearest * 3 + 1] * 180. / M_PI; a[2] = sofa_src_pos_val[nearest * 3 + 2]; } Loading @@ -1061,10 +1249,10 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c free( sofa_file_path ); return -1; } if ( a[0] > 180 ) a[0] -= 360; if ( a[0] < -180 ) a[0] += 360; 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: %ld\n", nearest ); index_pos[i] = nearest; Loading @@ -1077,7 +1265,6 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c uint32_t size = (uint32_t) sofa_R; uint32_t delL = 0, delR = 0; } size_t len_ls_cfg_name = strlen( lscfg.name ); double latency_48k = 0; Loading Loading @@ -1261,8 +1448,7 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c } else { ivas_set_hrtf_fr( &hrtf_data, ivas_hrtf, frame_len ); ivas_set_hrtf_fr( &hrtf_data, ivas_hrtf, frame_len ); } hrtf_data.latency_s += 0.000000001f; Loading Loading @@ -1313,8 +1499,12 @@ int generate_crend_ivas_tables_from_sofa( const char *file_path, ConfigReader *c ivas_hrtf_close( &hrtf_data ); } #ifdef USE_MATLAB matClose( mat_fp ); #else Py_DECREF( args ); Py_DECREF( py_results ); #endif if ( sofa_file_path ) free( sofa_file_path ); Loading
scripts/binauralRenderer_interface/generate_ivas_binauralizer_tables_from_sofa.m +8 −5 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ dataSpec.romOutDir = rom_path; Mod_Hrf_Itd_Main(dataSpec); %% generate crend rom or binary values SOFA_save_to_mat(hrir_file); SOFA_save_to_mat(brir_file); convert_SD2SHD_HRIRs(hrir_path,hrir_file_name,128); command = ['.' filesep() 'generate_crend_ivas_tables']; Loading @@ -99,11 +102,11 @@ end command = [command ... ' 5 ' ... hrir_file ' ' ... erase(hrir_file,'.sofa') '_FOA.sofa ' ... erase(hrir_file,'.sofa') '_HOA2.sofa ' ... erase(hrir_file,'.sofa') '_HOA3.sofa ' ... brir_file ]; erase(hrir_file,'.sofa') '.mat ' ... erase(hrir_file,'.sofa') '_FOA.mat ' ... erase(hrir_file,'.sofa') '_HOA2.mat ' ... erase(hrir_file,'.sofa') '_HOA3.mat ' ... erase(brir_file,'.sofa') '.mat ' ]; %display(command); Loading
scripts/binauralRenderer_interface/matlab_hrir_generation_scripts/SOFA_save_to_mat.m 0 → 100644 +113 −0 Original line number Diff line number Diff line %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % (C) 2022-2023 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. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function SOFA_save_to_mat(Lib_Name,outputSofaPath,sampleRates) %UNTITLED Summary of this function goes here % Detailed explanation goes here if nargin == 1 outputSofaPath = [erase(Lib_Name,'.sofa') '.mat']; sampleRates = [48000 32000 16000]; end if nargin == 2 sampleRates = [48000 32000 16000]; end if isfile(Lib_Name) if isfile(outputSofaPath) delete(outputSofaPath); end Sofa = struct('Sofa',struct()); sofa_data = ncinfo(Lib_Name); for indVar = 1:length(sofa_data.Variables) if (strcmp(sofa_data.Variables(indVar).Name, 'latencys')) Sofa.latencys = ncread(Lib_Name,'latencys'); end end Sofa.Pos = ncread(Lib_Name, 'SourcePosition'); Sofa.Units = strtrim(strsplit(ncreadatt(Lib_Name, 'SourcePosition', 'Units'), ',')); assert( any(strcmpi(Sofa.Units{1}, {'degree','radian'})), 'Unknown units'); if strcmpi(Sofa.Units{1},'degree'), Sofa.Pos(1,:)=Sofa.Pos(1,:)*pi/180; end assert( any(strcmpi(Sofa.Units{2}, {'degree','radian'})), 'Unknown units'); if strcmpi(Sofa.Units{2},'degree'), Sofa.Pos(2,:)=Sofa.Pos(2,:)*pi/180; end assert( any(strcmpi(Sofa.Units{3}, {'metre','meter','inch'})), 'Unknown units'); if strcmpi(Sofa.Units{3},'inch' ), Sofa.Pos(3,:)=Sofa.Pos(3,:)*0.0254; end Sofa.PosSpherical = Sofa.Pos; Sofa.Pos = Sofa.Pos(3,:) .* ... [cos(Sofa.Pos(2,:)).*[cos(Sofa.Pos(1,:));sin(Sofa.Pos(1,:))];sin(Sofa.Pos(2,:))]; Sofa.PosCartesian = make_unit_vectors(Sofa.Pos); NumLoc = size(Sofa.PosCartesian,2); % Now, get the impulse repsonses: Sofa.DataType = ncreadatt(Lib_Name, '/', 'DataType'); Sofa.Data.IR = ncread(Lib_Name, 'Data.IR'); Sofa.Data.SamplingRate = ncread(Lib_Name, 'Data.SamplingRate'); Sofa.Data.SamplingRate_Units = ncreadatt(Lib_Name, 'Data.SamplingRate', 'Units'); Sofa.Data.Delay = permute(ncread(Lib_Name, 'Data.Delay'), [2, 1]); switch lower(Sofa.DataType) case 'fir' assert( size(Sofa.Data.IR,2)>=2, 'Expecting 2 receivers (ears)'); if size(Sofa.Data.IR,2)>2 Sofa.Data.IR = Sofa.Data.IR(:,1:2,:); Sofa.Data.Delay = Sofa.Data.Delay(:,1:2); end assert( size(Sofa.Data.IR,3)==NumLoc, 'IR is incorrect size'); assert( all(diff(Sofa.Data.Delay,1,2)==0), ... 'Non-zero inter-aural delay offset not (yet) implemented'); assert(strcmp(Sofa.Data.SamplingRate_Units,'hertz'), 'unknown samplerate units'); otherwise error(['unknown GLOBAL_DataType = ', hrtf.GLOBAL_DataType]); end for ind = 1:length(sampleRates) if sampleRates(ind) == Sofa.Data.SamplingRate Sofa.DataResampled(ind).IR = Sofa.Data.IR; else Sofa.DataResampled(ind).IR = resample(Sofa.Data.IR, sampleRates(ind),Sofa.Data.SamplingRate, Dimension=3); end Sofa.DataResampled(ind).SamplingRate = sampleRates(ind); end Sofa.License = ncreadatt(Lib_Name,'/','License'); Sofa.ListenerShortName = ncreadatt(Lib_Name,'/','ListenerShortName'); Sofa.DatabaseName = ncreadatt(Lib_Name,'/','DatabaseName'); Sofa.Title = ncreadatt(Lib_Name,'/','Title'); Sofa.SOFAConventions = ncreadatt(Lib_Name,'/','SOFAConventions'); save(outputSofaPath, 'Sofa'); end No newline at end of file