From f74034064ed3fd350d09d52176676e9e5fbd7a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hauke=20Kr=C3=BCger?= Date: Fri, 3 May 2024 07:54:08 +0200 Subject: [PATCH] Extended binaural HRTF dispenser to support multiple slots for different HRTFs in different modules --- .../src/CjvxAuNBinauralRender.cpp | 8 +- .../src/CjvxAuNBinauralRender.h | 4 +- .../src/CjvxAuNBinauralRender_props.cpp | 52 ++--- .../ayf-hrtf-dispenser/include/ayf-hrtf.h | 30 +-- .../ayf-hrtf-dispenser/src/ayf-hrtf.cpp | 191 +++++++++++------- .../IjvxPropertyExtenderHrtfDispenser.h | 10 +- 6 files changed, 175 insertions(+), 120 deletions(-) diff --git a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.cpp b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.cpp index 7047b5f6..96a552d2 100644 --- a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.cpp +++ b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.cpp @@ -149,7 +149,7 @@ CjvxAuNBinauralRender::prepare_connect_icon(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) // _common_set_icon.theData_in->con_params jvxSize samplerate = _common_set_icon.theData_in->con_params.rate; - theHrtfDispenser->init(&samplerate); // Check result in the future + theHrtfDispenser->init(&samplerate, 1); // Check result in the future - number of slots provided here! // Allocate renderer render_pri = allocate_renderer(_common_set_icon.theData_in->con_params.buffersize, @@ -280,12 +280,12 @@ CjvxAuNBinauralRender::update_hrirs(jvxOneRenderCore* renderer, jvxData azimuth_ this->source_direction_angles_deg_inuse[1] = inclination_deg; jvxSize length_hrir; - this->theHrtfDispenser->get_length_hrir(length_hrir, &loadId); + this->theHrtfDispenser->get_length_hrir(length_hrir, &loadId, slotIdHrtfs); if (renderer->loadId == loadId) { jvxErrorType res = this->theHrtfDispenser->copy_closest_hrir_pair(azimuth_deg, inclination_deg, renderer->buffer_hrir_left, renderer->buffer_hrir_right, renderer->length_buffer_hrir, - renderer->loadId); + renderer->loadId, slotIdHrtfs); if (res != JVX_NO_ERROR) { std::cout << __FUNCTION__ << " Warning: on update of position, the request to return hrir buffers failed with error <" << @@ -409,7 +409,7 @@ CjvxAuNBinauralRender::allocate_renderer(jvxSize bsize, jvxData startAz, jvxData jvxOneRenderCore* render_inst = nullptr; JVX_SAFE_ALLOCATE_OBJECT(render_inst, jvxOneRenderCore); - jvxErrorType res = theHrtfDispenser->get_length_hrir(render_inst->length_buffer_hrir, &render_inst->loadId); + jvxErrorType res = theHrtfDispenser->get_length_hrir(render_inst->length_buffer_hrir, &render_inst->loadId, slotIdHrtfs); assert(res == JVX_NO_ERROR); // Allocate the hrir buffers diff --git a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.h b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.h index 7016bb4a..57d8a996 100644 --- a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.h +++ b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender.h @@ -67,7 +67,7 @@ class CjvxAuNBinauralRender : public CjvxBareNode1ioRearrange, jvxRenderingUpdateStatus updateDBase = jvxRenderingUpdateStatus::JVX_RENDERING_UPDATE_OFF; jvxSize missedUpdatesPosition = 0; - + jvxSize slotIdHrtfs = 0; public: @@ -123,7 +123,7 @@ class CjvxAuNBinauralRender : public CjvxBareNode1ioRearrange, // ========================================================================================================= // IjvxPropertyExtenderHrtfDispenser_report - virtual jvxErrorType report_database_changed() override; + virtual jvxErrorType report_database_changed(jvxSize slotId) override; // ========================================================================================================= jvxErrorType supports_prop_extender_type(jvxPropertyExtenderType tp) override; jvxErrorType prop_extender_specialization(jvxHandle** prop_extender, jvxPropertyExtenderType tp)override; diff --git a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender_props.cpp b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender_props.cpp index fc42fd15..cb90e7fa 100644 --- a/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender_props.cpp +++ b/sources/jvxComponents/jvxAudioNodes/jvxAuNBinauralRender/src/CjvxAuNBinauralRender_props.cpp @@ -54,37 +54,39 @@ JVX_PROPERTIES_FORWARD_C_CALLBACK_EXECUTE_FULL(CjvxAuNBinauralRender, set_extend } jvxErrorType -CjvxAuNBinauralRender::report_database_changed() +CjvxAuNBinauralRender::report_database_changed(jvxSize slotId) { - // Here, we need to be careful: the fftw does not allow threaded creation of plans, - // - // https://www.fftw.org/fftw3_doc/Thread-safety.html - // - // The consequence is that we are not allowed to allocate fftws in parallel threads. - // Therefore, all fftw allocation must be in the main thread. - // The update of the position, in contrast, is relocated into another thread since this - // update may occur in the main thread but also in the processing thread for high speed - // modification. + // Only if our slot is in use + if (slotId == slotIdHrtfs) + { + // Here, we need to be careful: the fftw does not allow threaded creation of plans, + // + // https://www.fftw.org/fftw3_doc/Thread-safety.html + // + // The consequence is that we are not allowed to allocate fftws in parallel threads. + // Therefore, all fftw allocation must be in the main thread. + // The update of the position, in contrast, is relocated into another thread since this + // update may occur in the main thread but also in the processing thread for high speed + // modification. + jvxBool triggerThread = false; + JVX_LOCK_MUTEX(safeAccessUpdateBgrd); - jvxBool triggerThread = false; - JVX_LOCK_MUTEX(safeAccessUpdateBgrd); + // Cancel all current position updates + updateHRir = jvxRenderingUpdateStatus::JVX_RENDERING_UPDATE_OFF; - // Cancel all current position updates - updateHRir = jvxRenderingUpdateStatus::JVX_RENDERING_UPDATE_OFF; + // jvxOneRenderCore* removedThis = render_sec; - // jvxOneRenderCore* removedThis = render_sec; + if (render_sec) + { + deallocate_renderer(render_sec); + } - if (render_sec) - { - deallocate_renderer(render_sec); + // Allocate new renderer but as "secondary" renderer for now + render_sec = allocate_renderer(_common_set_icon.theData_in->con_params.buffersize, + this->source_direction_angles_deg_inuse[0], this->source_direction_angles_deg_inuse[1]); + updateDBase = jvxRenderingUpdateStatus::JVX_RENDERING_UPDATE_READY; + JVX_UNLOCK_MUTEX(safeAccessUpdateBgrd); } - - // Allocate new renderer but as "secondary" renderer for now - render_sec = allocate_renderer(_common_set_icon.theData_in->con_params.buffersize, - this->source_direction_angles_deg_inuse[0], this->source_direction_angles_deg_inuse[1]); - updateDBase = jvxRenderingUpdateStatus::JVX_RENDERING_UPDATE_READY; - JVX_UNLOCK_MUTEX(safeAccessUpdateBgrd); - return JVX_NO_ERROR; } diff --git a/sources/jvxLibraries/ayf-hrtf-dispenser/include/ayf-hrtf.h b/sources/jvxLibraries/ayf-hrtf-dispenser/include/ayf-hrtf.h index 38ce7370..7e74bda8 100644 --- a/sources/jvxLibraries/ayf-hrtf-dispenser/include/ayf-hrtf.h +++ b/sources/jvxLibraries/ayf-hrtf-dispenser/include/ayf-hrtf.h @@ -37,6 +37,14 @@ class oneSofaDataBase jvxErrorType close(); }; +struct oneDBaslot +{ + oneSofaDataBase* activeDatabase = nullptr; + float* buffer_hrir_left = nullptr; + float* buffer_hrir_right = nullptr; + jvxSize length_buffer_hrir = JVX_SIZE_UNSELECTED; + jvxSize idx = JVX_SIZE_UNSELECTED; +}; class ayfHrtfDispenser : public IjvxPropertyExtender, public IjvxPropertyExtenderHrtfDispenser { @@ -50,15 +58,11 @@ class ayfHrtfDispenser : public IjvxPropertyExtender, public IjvxPropertyExtende std::string pathName = "./"; std::list sofaDataBases; - oneSofaDataBase* activeDatabase = nullptr; jvxSize samplerate = JVX_SIZE_UNSELECTED; JVX_MUTEX_HANDLE safeAccess; - float *buffer_hrir_left = nullptr; - float *buffer_hrir_right = nullptr; - jvxSize length_buffer_hrir = JVX_SIZE_UNSELECTED; - std::list registeredListeners; + std::vector dataBaseSlots; public: ayfHrtfDispenser(); @@ -71,11 +75,11 @@ class ayfHrtfDispenser : public IjvxPropertyExtender, public IjvxPropertyExtende // ============================================================================== - virtual jvxErrorType JVX_CALLINGCONVENTION init(jvxSize* samplerate) override; - virtual jvxErrorType JVX_CALLINGCONVENTION get_length_hrir(jvxSize& length_hrir, jvxSize* loadId) override; + virtual jvxErrorType JVX_CALLINGCONVENTION init(jvxSize* samplerate, jvxSize numSlots) override; + virtual jvxErrorType JVX_CALLINGCONVENTION get_length_hrir(jvxSize& length_hrir, jvxSize* loadId, jvxSize slotId) override; virtual jvxErrorType JVX_CALLINGCONVENTION copy_closest_hrir_pair(jvxData azimuth_deg, jvxData inclination_deg, - jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId) override; - virtual jvxErrorType JVX_CALLINGCONVENTION get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg) override; + jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId, jvxSize slotId) override; + virtual jvxErrorType JVX_CALLINGCONVENTION get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg, jvxSize slotId) override; // ============================================================================== @@ -93,15 +97,15 @@ class ayfHrtfDispenser : public IjvxPropertyExtender, public IjvxPropertyExtende jvxErrorType name_sofa_file(jvxSize idx, std::string& name); // Select SOFA database without loading it. - jvxErrorType select_database(jvxSize idx_database); + jvxErrorType select_database(jvxSize idx_database, jvxSize slotId); // Load the selected SOFA database. - jvxErrorType load_selected_database(oneSofaDataBase* dbase); + jvxErrorType load_selected_database(oneSofaDataBase* dbase, jvxSize slotId); // Return list index of selected SOFA database. - jvxSize selected_database(); + jvxSize selected_database(jvxSize slotId); - void allocate_hrir_buffers(oneSofaDataBase* dbase); + void allocate_hrir_buffers(oneSofaDataBase* dbase, jvxSize slotId); }; diff --git a/sources/jvxLibraries/ayf-hrtf-dispenser/src/ayf-hrtf.cpp b/sources/jvxLibraries/ayf-hrtf-dispenser/src/ayf-hrtf.cpp index 4a632144..e9b4b02c 100644 --- a/sources/jvxLibraries/ayf-hrtf-dispenser/src/ayf-hrtf.cpp +++ b/sources/jvxLibraries/ayf-hrtf-dispenser/src/ayf-hrtf.cpp @@ -44,32 +44,39 @@ ayfHrtfDispenser::prop_extender_specialization(jvxHandle** prop_extender, jvxPro jvxErrorType -ayfHrtfDispenser::get_length_hrir(jvxSize& length_hrir, jvxSize* loadIdArg) +ayfHrtfDispenser::get_length_hrir(jvxSize& length_hrir, jvxSize* loadIdArg, jvxSize slotId) { jvxErrorType res = JVX_NO_ERROR; - if (this->activeDatabase) + if (slotId < dataBaseSlots.size()) { - length_hrir = this->activeDatabase->length_hrir; - if (loadIdArg) + if (dataBaseSlots[slotId].activeDatabase) { - *loadIdArg = this->activeDatabase->loadId; + length_hrir = dataBaseSlots[slotId].activeDatabase->length_hrir; + if (loadIdArg) + { + *loadIdArg = dataBaseSlots[slotId].activeDatabase->loadId; + } } - } - else - { - length_hrir = JVX_SIZE_UNSELECTED; - if (loadIdArg) + else { - *loadIdArg = JVX_SIZE_UNSELECTED; + length_hrir = JVX_SIZE_UNSELECTED; + if (loadIdArg) + { + *loadIdArg = JVX_SIZE_UNSELECTED; + } + res = JVX_ERROR_NOT_READY; } - res = JVX_ERROR_NOT_READY; + } + else + { + res = JVX_ERROR_ID_OUT_OF_BOUNDS; } return res; } jvxErrorType -ayfHrtfDispenser::init(jvxSize* samplerateArg) +ayfHrtfDispenser::init(jvxSize* samplerateArg, jvxSize numSlots) { if (this->is_initialized) { @@ -88,8 +95,16 @@ ayfHrtfDispenser::init(jvxSize* samplerateArg) if (!samplerateArg) return JVX_ERROR_INVALID_ARGUMENT; this->samplerate = *samplerateArg; - jvxErrorType res = this->load_selected_database(activeDatabase); - assert(res == JVX_NO_ERROR); + dataBaseSlots.resize(numSlots); + jvxSize cnt = 0; + + jvxErrorType res = JVX_NO_ERROR; + for (auto& elm : dataBaseSlots) + { + elm.idx = cnt++; + jvxErrorType resL = this->load_selected_database(elm.activeDatabase, elm.idx); + assert(res == JVX_NO_ERROR); + } this->is_initialized = true; return res; @@ -97,7 +112,7 @@ ayfHrtfDispenser::init(jvxSize* samplerateArg) jvxErrorType ayfHrtfDispenser::copy_closest_hrir_pair(jvxData azimuth_deg, jvxData inclination_deg, - jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId) + jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId, jvxSize slotId) { jvxErrorType res = JVX_NO_ERROR; @@ -107,37 +122,46 @@ ayfHrtfDispenser::copy_closest_hrir_pair(jvxData azimuth_deg, jvxData inclinatio if (resW == JVX_TRY_LOCK_MUTEX_SUCCESS) { - if (dataBaseId == this->activeDatabase->loadId) + if (slotId < dataBaseSlots.size()) { - if (hrir_left && hrir_right) + if (dataBaseId == dataBaseSlots[slotId].activeDatabase->loadId) { - assert(length_hrir == this->activeDatabase->length_hrir); - assert(length_hrir == this->length_buffer_hrir); - float hrir_delay_left = 0; // unit is samples - float hrir_delay_right = 0; // unit is samples - float const elevation_deg = -inclination_deg + 90.0; - float source_coordinates[3] = { static_cast(azimuth_deg) , static_cast(elevation_deg), (jvxData)2 }; - mysofa_s2c(source_coordinates); - mysofa_getfilter_float_nointerp(this->activeDatabase->mysofa_db, source_coordinates[0], source_coordinates[1], source_coordinates[2], this->buffer_hrir_left, this->buffer_hrir_right, &hrir_delay_left, &hrir_delay_right); - - // Databases which return delayed HRIRs are not supported. - if (hrir_delay_left != 0.0 || hrir_delay_right != 0.0) - { - res = JVX_ERROR_UNSUPPORTED; - } - else + if (hrir_left && hrir_right) { - for (int idx_sample = 0; idx_sample < this->activeDatabase->length_hrir; idx_sample++) + assert(length_hrir == dataBaseSlots[slotId].activeDatabase->length_hrir); + assert(length_hrir == dataBaseSlots[slotId].length_buffer_hrir); + float hrir_delay_left = 0; // unit is samples + float hrir_delay_right = 0; // unit is samples + float const elevation_deg = -inclination_deg + 90.0; + float source_coordinates[3] = { static_cast(azimuth_deg) , static_cast(elevation_deg), (jvxData)2 }; + mysofa_s2c(source_coordinates); + mysofa_getfilter_float_nointerp(dataBaseSlots[slotId].activeDatabase->mysofa_db, source_coordinates[0], + source_coordinates[1], source_coordinates[2], dataBaseSlots[slotId].buffer_hrir_left, + dataBaseSlots[slotId].buffer_hrir_right, &hrir_delay_left, &hrir_delay_right); + + // Databases which return delayed HRIRs are not supported. + if (hrir_delay_left != 0.0 || hrir_delay_right != 0.0) + { + res = JVX_ERROR_UNSUPPORTED; + } + else { - hrir_left[idx_sample] = (jvxData)this->buffer_hrir_left[idx_sample]; - hrir_right[idx_sample] = (jvxData)this->buffer_hrir_right[idx_sample]; + for (int idx_sample = 0; idx_sample < dataBaseSlots[slotId].activeDatabase->length_hrir; idx_sample++) + { + hrir_left[idx_sample] = (jvxData)dataBaseSlots[slotId].buffer_hrir_left[idx_sample]; + hrir_right[idx_sample] = (jvxData)dataBaseSlots[slotId].buffer_hrir_right[idx_sample]; + } } } } + else + { + res = JVX_ERROR_INVALID_SETTING; + } } else { - res = JVX_ERROR_INVALID_SETTING; + res = JVX_ERROR_ID_OUT_OF_BOUNDS; } JVX_UNLOCK_MUTEX(safeAccess); } @@ -150,7 +174,7 @@ ayfHrtfDispenser::copy_closest_hrir_pair(jvxData azimuth_deg, jvxData inclinatio } jvxErrorType -ayfHrtfDispenser::get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg) +ayfHrtfDispenser::get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg, jvxSize slotId) { jvxErrorType res = JVX_ERROR_INVALID_ARGUMENT; JVX_TRY_LOCK_MUTEX_RESULT_TYPE resW = JVX_TRY_LOCK_MUTEX_NO_SUCCESS; @@ -225,7 +249,10 @@ ayfHrtfDispenser::start(const std::string& directory) auto elm = sofaDataBases.begin(); if (elm != sofaDataBases.end()) { - select_database(0); + for (auto& elm : dataBaseSlots) + { + select_database(0, elm.idx); + } } started = true; return JVX_NO_ERROR; @@ -240,14 +267,17 @@ ayfHrtfDispenser::stop() { JVX_LOCK_MUTEX(safeAccess); - for (auto sofa_database : sofaDataBases) + for (auto& sofa_database : sofaDataBases) { - if (activeDatabase->is_open) { + if (sofa_database->is_open) { sofa_database->close(); } } - activeDatabase = nullptr; + for (auto& elm : dataBaseSlots) + { + elm.activeDatabase = nullptr; + } JVX_UNLOCK_MUTEX(safeAccess); for (auto sofa_database : sofaDataBases) @@ -256,8 +286,11 @@ ayfHrtfDispenser::stop() } sofaDataBases.clear(); - JVX_SAFE_DELETE_FIELD(this->buffer_hrir_left); - JVX_SAFE_DELETE_FIELD(this->buffer_hrir_right); + for (auto& elm : dataBaseSlots) + { + JVX_SAFE_DELETE_FIELD(elm.buffer_hrir_left); + JVX_SAFE_DELETE_FIELD(elm.buffer_hrir_right); + } started = false; } @@ -289,7 +322,7 @@ ayfHrtfDispenser::name_sofa_file(jvxSize idx, std::string& name) jvxErrorType -ayfHrtfDispenser::load_selected_database(oneSofaDataBase* dbase) +ayfHrtfDispenser::load_selected_database(oneSofaDataBase* dbase, jvxSize slotId) { jvxErrorType res = JVX_NO_ERROR; @@ -304,7 +337,7 @@ ayfHrtfDispenser::load_selected_database(oneSofaDataBase* dbase) assert(res == JVX_NO_ERROR); } - this->allocate_hrir_buffers(dbase); + this->allocate_hrir_buffers(dbase, slotId); JVX_UNLOCK_MUTEX(safeAccess); @@ -312,26 +345,28 @@ ayfHrtfDispenser::load_selected_database(oneSofaDataBase* dbase) } void -ayfHrtfDispenser::allocate_hrir_buffers(oneSofaDataBase* dbase) +ayfHrtfDispenser::allocate_hrir_buffers(oneSofaDataBase* dbase, jvxSize slotId) { - JVX_SAFE_DELETE_FIELD(this->buffer_hrir_left); - JVX_SAFE_DELETE_FIELD(this->buffer_hrir_right); - this->length_buffer_hrir = 0; - - this->length_buffer_hrir = dbase->length_hrir; - JVX_SAFE_ALLOCATE_FIELD_CPP_Z(this->buffer_hrir_left, float, this->length_buffer_hrir); - JVX_SAFE_ALLOCATE_FIELD_CPP_Z(this->buffer_hrir_right, float, this->length_buffer_hrir); + assert(slotId < dataBaseSlots.size()); + JVX_SAFE_DELETE_FIELD(dataBaseSlots[slotId].buffer_hrir_left); + JVX_SAFE_DELETE_FIELD(dataBaseSlots[slotId].buffer_hrir_right); + dataBaseSlots[slotId].length_buffer_hrir = 0; + + dataBaseSlots[slotId].length_buffer_hrir = dbase->length_hrir; + JVX_SAFE_ALLOCATE_FIELD_CPP_Z(dataBaseSlots[slotId].buffer_hrir_left, float, dataBaseSlots[slotId].length_buffer_hrir); + JVX_SAFE_ALLOCATE_FIELD_CPP_Z(dataBaseSlots[slotId].buffer_hrir_right, float, dataBaseSlots[slotId].length_buffer_hrir); } jvxErrorType -ayfHrtfDispenser::select_database(jvxSize idx_database) +ayfHrtfDispenser::select_database(jvxSize idx_database, jvxSize slotId) { + assert(slotId < dataBaseSlots.size()); if (idx_database >= sofaDataBases.size()) return JVX_ERROR_ID_OUT_OF_BOUNDS; auto sofa_database = sofaDataBases.begin(); std::advance(sofa_database, idx_database); - if (*sofa_database != this->activeDatabase) + if (*sofa_database != dataBaseSlots[slotId].activeDatabase) { JVX_LOCK_MUTEX(safeAccess); @@ -342,21 +377,21 @@ ayfHrtfDispenser::select_database(jvxSize idx_database) if (!selectMe->is_open) { if (this->samplerate != JVX_SIZE_UNSELECTED) { - this->load_selected_database(selectMe); + this->load_selected_database(selectMe, slotId); } } // Here, the database is updated - if (this->length_buffer_hrir != selectMe->length_hrir) { - this->allocate_hrir_buffers(selectMe); + if (dataBaseSlots[slotId].length_buffer_hrir != selectMe->length_hrir) { + this->allocate_hrir_buffers(selectMe, slotId); } - this->activeDatabase = selectMe; - std::cout << __FUNCTION__ << ": Sofa database " << activeDatabase->fName << " selected." << std::endl; + dataBaseSlots[slotId].activeDatabase = selectMe; + std::cout << __FUNCTION__ << ": Sofa database " << dataBaseSlots[slotId].activeDatabase->fName << " selected." << std::endl; // inform BinauralRender modules for (auto elm : this->registeredListeners) { - elm->report_database_changed(); + elm->report_database_changed(slotId); } JVX_UNLOCK_MUTEX(safeAccess); @@ -366,12 +401,13 @@ ayfHrtfDispenser::select_database(jvxSize idx_database) jvxSize -ayfHrtfDispenser::selected_database() +ayfHrtfDispenser::selected_database(jvxSize slotId) { jvxSize cnt = 0; + assert(slotId < dataBaseSlots.size()); for (auto sofa_database : sofaDataBases) { - if (sofa_database == activeDatabase) + if (sofa_database == dataBaseSlots[slotId].activeDatabase) { return cnt; } @@ -456,16 +492,29 @@ ayfHrtfDispenser::unregister_change_listener(IjvxPropertyExtenderHrtfDispenser_r jvxErrorType ayfHrtfDispenser::is_ready(jvxBool* isReady, jvxApiString* reason) { - if (activeDatabase == nullptr) + jvxBool isReadyLocal = true; + std::string errDescr; + + if (dataBaseSlots.size() == 0) { - if (isReady) - { - *isReady = false; - } - if (reason) + isReadyLocal = false; + errDescr = "No slots declared for HRTF dispenser."; + } + else + { + if (dataBaseSlots[0].activeDatabase == nullptr) { - *reason = "No active HRTF database in folder <" + curWorkingDir + ">."; + isReadyLocal = false; + errDescr = "No active HRTF database in folder <" + curWorkingDir + ">."; } } + if (isReady) + { + *isReady = isReadyLocal; + } + if (reason) + { + *reason = errDescr; + } return JVX_NO_ERROR; } \ No newline at end of file diff --git a/sources/jvxLibraries/jvx-system-product/include/interfaces/property-extender/IjvxPropertyExtenderHrtfDispenser.h b/sources/jvxLibraries/jvx-system-product/include/interfaces/property-extender/IjvxPropertyExtenderHrtfDispenser.h index 2206cc8f..ee412a8a 100644 --- a/sources/jvxLibraries/jvx-system-product/include/interfaces/property-extender/IjvxPropertyExtenderHrtfDispenser.h +++ b/sources/jvxLibraries/jvx-system-product/include/interfaces/property-extender/IjvxPropertyExtenderHrtfDispenser.h @@ -5,15 +5,15 @@ JVX_INTERFACE IjvxPropertyExtenderHrtfDispenser_report { public: virtual ~IjvxPropertyExtenderHrtfDispenser_report() {}; - virtual jvxErrorType report_database_changed() = 0; + virtual jvxErrorType report_database_changed(jvxSize slotId) = 0; }; JVX_INTERFACE IjvxPropertyExtenderHrtfDispenser { public: virtual ~IjvxPropertyExtenderHrtfDispenser() {}; - virtual jvxErrorType JVX_CALLINGCONVENTION init(jvxSize* samplerate) = 0; - virtual jvxErrorType JVX_CALLINGCONVENTION get_length_hrir(jvxSize& length_hrir, jvxSize* loadId) = 0; + virtual jvxErrorType JVX_CALLINGCONVENTION init(jvxSize* samplerate, jvxSize numSlots) = 0; + virtual jvxErrorType JVX_CALLINGCONVENTION get_length_hrir(jvxSize& length_hrir, jvxSize* loadId, jvxSize slotId) = 0; /* Get HRIR pair from SOFA database. * @param inclination_deg: inclination angle of source direction in degree. * @param azimuth_deg: azimuth angle of source direction in degree. @@ -21,8 +21,8 @@ JVX_INTERFACE IjvxPropertyExtenderHrtfDispenser * @param hrir_left: pointer to array of length received by get_length_hrir(jvxSize& length_hrir). Returns the HRIR for the right ear. */ virtual jvxErrorType JVX_CALLINGCONVENTION copy_closest_hrir_pair(jvxData azimuth_deg, jvxData inclination_deg, - jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId) = 0; - virtual jvxErrorType JVX_CALLINGCONVENTION get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg) = 0; + jvxData* hrir_left, jvxData* hrir_right, jvxSize length_hrir, jvxSize dataBaseId, jvxSize slotId) = 0; + virtual jvxErrorType JVX_CALLINGCONVENTION get_closest_direction(jvxData& azimuth_deg, jvxData& inclination_deg, jvxSize slotId) = 0; virtual jvxErrorType JVX_CALLINGCONVENTION register_change_listener(IjvxPropertyExtenderHrtfDispenser_report* ref) = 0; virtual jvxErrorType JVX_CALLINGCONVENTION unregister_change_listener(IjvxPropertyExtenderHrtfDispenser_report* ref) = 0;