From 3710dda8393f624b4aaa0e211d12dada5384326d Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 16:36:31 +0200 Subject: [PATCH 1/7] Move fast tanh enable call to static plugin init Signed-off-by: falkTX --- src/nam_lv2.cpp | 9 ++++++++- src/nam_plugin.cpp | 3 --- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/nam_lv2.cpp b/src/nam_lv2.cpp index 2468801..771440d 100644 --- a/src/nam_lv2.cpp +++ b/src/nam_lv2.cpp @@ -90,5 +90,12 @@ static const LV2_Descriptor descriptor = LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) { - return index == 0 ? &descriptor : nullptr; + if (index == 0) { + // Turn on fast tanh approximation + activations::Activation::enable_fast_tanh(); + + return &descriptor; + } + + return nullptr; } diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index 05f1624..c3ac658 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -11,9 +11,6 @@ namespace NAM { Plugin::Plugin() { - // Turn on fast tanh approximation - activations::Activation::enable_fast_tanh(); - // prevent allocations on the audio thread currentModelPath.reserve(MAX_FILE_NAME+1); } From 0d7954cf2ae5aadaa1b8c76e9aad010f86170f3e Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 16:42:45 +0200 Subject: [PATCH 2/7] General cleanup, no functional changes Signed-off-by: falkTX --- resources/neural_amp_modeler.ttl.in | 6 +++--- src/nam_lv2.cpp | 4 +--- src/nam_plugin.cpp | 25 +++++++++++-------------- src/nam_plugin.h | 11 +++++------ 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/resources/neural_amp_modeler.ttl.in b/resources/neural_amp_modeler.ttl.in index b7b4eff..701cec4 100644 --- a/resources/neural_amp_modeler.ttl.in +++ b/resources/neural_amp_modeler.ttl.in @@ -14,10 +14,10 @@ @prefix mod: . <@NAM_LV2_ID@#model> - a lv2:Parameter; + a lv2:Parameter; mod:fileTypes "nam,nammodel"; - rdfs:label "Neural Model"; - rdfs:range atom:Path. + rdfs:label "Neural Model"; + rdfs:range atom:Path. <@NAM_LV2_ID@> a lv2:Plugin, lv2:SimulatorPlugin; diff --git a/src/nam_lv2.cpp b/src/nam_lv2.cpp index 771440d..553dcf9 100644 --- a/src/nam_lv2.cpp +++ b/src/nam_lv2.cpp @@ -66,10 +66,8 @@ static const void* extension_data(const char* uri) static const LV2_State_Interface state = {NAM::Plugin::save, NAM::Plugin::restore}; static const LV2_Worker_Interface worker = { NAM::Plugin::work, NAM::Plugin::work_response, NULL }; - if (!strcmp(uri, LV2_STATE__interface)) { + if (!strcmp(uri, LV2_STATE__interface)) return &state; - } - if (!strcmp(uri, LV2_WORKER__interface)) return &worker; diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index c3ac658..e2c7530 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -17,8 +17,6 @@ namespace NAM { bool Plugin::initialize(double rate, const LV2_Feature* const* features) noexcept { - logger.log = nullptr; - for (size_t i = 0; features[i]; ++i) { if (std::string(features[i]->URI) == std::string(LV2_URID__map)) map = static_cast(features[i]->data); @@ -146,8 +144,8 @@ namespace NAM { void Plugin::process(uint32_t n_samples) noexcept { - lv2_atom_forge_set_buffer(&atom_forge,(uint8_t*)ports.notify,ports.notify->atom.size); - lv2_atom_forge_sequence_head(&atom_forge,&sequence_frame,uris.units_frame); + lv2_atom_forge_set_buffer(&atom_forge, (uint8_t*)ports.notify, ports.notify->atom.size); + lv2_atom_forge_sequence_head(&atom_forge, &sequence_frame, uris.units_frame); LV2_ATOM_SEQUENCE_FOREACH(ports.control, event) { @@ -173,7 +171,7 @@ namespace NAM { { lv2_atom_object_get(obj, uris.patch_value, &file_path, 0); - if (file_path && (file_path->size > 0) && (file_path->size < 1024)) + if (file_path && (file_path->size > 0) && (file_path->size < MAX_FILE_NAME)) { LV2LoadModelMsg msg = { kWorkTypeLoad, {} }; @@ -210,10 +208,7 @@ namespace NAM { } } - if (currentModel == nullptr) - { - } - else + if (currentModel != nullptr) { currentModel->process(&ports.audio_out, &ports.audio_out, 1, n_samples, 1.0, 1.0, mNAMParams); currentModel->finalize_(n_samples); @@ -286,7 +281,7 @@ namespace NAM { } else { -#ifndef _WIN32 // Can't free library allocated memory on Windows +#ifndef _WIN32 // Can't free host-allocated memory on plugin side under Windows free(apath); #endif } @@ -335,7 +330,7 @@ namespace NAM { LV2_State_Status result = LV2_STATE_SUCCESS; - if (pathLen < 1024) + if (pathLen < MAX_FILE_NAME) { // Schedule model to be loaded by the provided worker NAM::LV2LoadModelMsg msg = { NAM::kWorkTypeLoad, {} }; @@ -345,7 +340,7 @@ namespace NAM { } else { - lv2_log_error(&nam->logger, "Model path is too long (max 1024 chars)\n"); + lv2_log_error(&nam->logger, "Model path is too long (max %u chars)\n", MAX_FILE_NAME); result = LV2_STATE_ERR_UNKNOWN; } @@ -358,7 +353,7 @@ namespace NAM { } else { -#ifndef _WIN32 // Can't free library allocated memory on Windows +#ifndef _WIN32 // Can't free host-allocated memory on plugin side under Windows free(path); #endif } @@ -385,7 +380,9 @@ namespace NAM { LV2_Atom_Forge_Frame frame; lv2_atom_forge_object(&atom_forge, &frame, 0, uris.state_StateChanged); - /* object with no properties */ + + /* object with no properties */ + lv2_atom_forge_pop(&atom_forge, &frame); } diff --git a/src/nam_plugin.h b/src/nam_plugin.h index 038c843..ddd4a59 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -25,6 +25,7 @@ #define MODEL_URI PlUGIN_URI "#model" namespace NAM { + static constexpr unsigned int MAX_FILE_NAME = 1024; enum LV2WorkType { kWorkTypeLoad, @@ -33,7 +34,7 @@ namespace NAM { struct LV2LoadModelMsg { LV2WorkType type; - char path[1024]; + char path[MAX_FILE_NAME]; }; class Plugin { @@ -49,9 +50,9 @@ namespace NAM { Ports ports = {}; - LV2_URID_Map* map; - LV2_Log_Logger logger; - LV2_Worker_Schedule* schedule; + LV2_URID_Map* map = nullptr; + LV2_Log_Logger logger = {}; + LV2_Worker_Schedule* schedule = nullptr; std::unique_ptr<::DSP> currentModel; std::unique_ptr<::DSP> stagedModel; @@ -82,8 +83,6 @@ namespace NAM { const LV2_Feature* const* features); private: - static constexpr size_t MAX_FILE_NAME = 1024; - struct URIs { LV2_URID atom_Object; LV2_URID atom_Float; From 4e9b7d6b4970c0b436762dd196ae157e9ee554f7 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 17:00:02 +0200 Subject: [PATCH 3/7] rework worker implementation, dont rely on class variables previous implementation was racy and bound to issues when more than 1 file change request happened before worker was triggered. using C++ move assignment is nice, but LV2 worker is a C API that does not fit non-POD types very well, leading to awkward implementations alike before with current + staged + deleted models. let us "downgrade" to raw pointers, which are C compatible. since LV2 worker rules are well defined, any crashes or racy behaviour can be considered host-side bugs. Signed-off-by: falkTX --- src/nam_plugin.cpp | 138 ++++++++++++++++++++++----------------------- src/nam_plugin.h | 27 +++++---- 2 files changed, 86 insertions(+), 79 deletions(-) diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index e2c7530..6a2f3bf 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -15,6 +15,11 @@ namespace NAM { currentModelPath.reserve(MAX_FILE_NAME+1); } + Plugin::~Plugin() + { + delete currentModel; + } + bool Plugin::initialize(double rate, const LV2_Feature* const* features) noexcept { for (size_t i = 0; features[i]; ++i) { @@ -61,41 +66,41 @@ namespace NAM { return true; } + // runs on non-RT, can block or use [de]allocations LV2_Worker_Status Plugin::work(LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) { - switch (*((const uint32_t*)data)) + switch (*(const LV2WorkType*)data) { case kWorkTypeLoad: - auto msg = reinterpret_cast(data); + { + auto msg = static_cast(data); auto nam = static_cast(instance); try { - // If we had a previous model, delete it - if (nam->deleteModel) - { - nam->deleteModel.reset(); - } + // load model from path + const size_t pathlen = strlen(msg->path); + ::DSP* model; - if (strlen(msg->path) == 0) - { + if (pathlen == 0 || pathlen >= MAX_FILE_NAME) + { // avoid logging an error on an empty path. // but do clear the model. - nam->stagedModel = nullptr; - nam->stagedModelPath = msg->path; - } else + model = nullptr; + } + else { lv2_log_trace(&nam->logger, "Staging model change: `%s`\n", msg->path); - nam->stagedModel = get_dsp(msg->path); - nam->stagedModelPath = msg->path; + model = get_dsp(msg->path).release(); // Enable model loudness normalization - nam->stagedModel->SetNormalize(true); + model->SetNormalize(true); } - LV2WorkType response = kWorkTypeSwitch; + LV2SwitchModelMsg response = { kWorkTypeSwitch, {}, model }; + memcpy(response.path, msg->path, pathlen); respond(handle, sizeof(response), &response); return LV2_WORKER_SUCCESS; @@ -105,43 +110,51 @@ namespace NAM { lv2_log_error(&nam->logger, "Unable to load model from: '%s'\n", msg->path); } + break; + } + + case kWorkTypeFree: + { + auto msg = static_cast(data); + delete msg->model; + return LV2_WORKER_SUCCESS; + } + + case kWorkTypeSwitch: + // should not happen! break; } return LV2_WORKER_ERR_UNKNOWN; } + // runs on RT, right after process(), must not block or [de]allocate memory LV2_Worker_Status Plugin::work_response(LV2_Handle instance, uint32_t size, const void* data) { - switch (*((const uint32_t*)data)) - { - case kWorkTypeSwitch: - try - { - auto nam = static_cast(instance); + if (*(const LV2WorkType*)data != kWorkTypeSwitch) + return LV2_WORKER_ERR_UNKNOWN; - std::swap(nam->currentModel, nam->stagedModel); - nam->currentModelPath = nam->stagedModelPath; - assert(nam->currentModelPath.capacity() >= MAX_FILE_NAME + 1); - nam->stateChanged = true; + auto msg = static_cast(data); + auto nam = static_cast(instance); - nam->deleteModel = std::move(nam->stagedModel); + // prepare reply for deleting old model + LV2FreeModelMsg reply = { kWorkTypeFree, nam->currentModel }; - nam->write_set_patch(nam->currentModelPath); + // swap current model with new one + nam->currentModel = msg->model; + nam->currentModelPath = msg->path; + assert(nam->currentModelPath.capacity() >= MAX_FILE_NAME + 1); - return LV2_WORKER_SUCCESS; - } - catch (std::exception& e) - { - } + // send reply + nam->schedule->schedule_work(nam->schedule->handle, sizeof(reply), &reply); - break; - } + // report change to host/ui + nam->write_current_path(); + nam->write_state_changed(); - return LV2_WORKER_ERR_UNKNOWN; + return LV2_WORKER_SUCCESS; } - void Plugin::process(uint32_t n_samples) noexcept { lv2_atom_forge_set_buffer(&atom_forge, (uint8_t*)ports.notify, ports.notify->atom.size); @@ -152,34 +165,28 @@ namespace NAM { if (event->body.type == uris.atom_Object) { const auto obj = reinterpret_cast(&event->body); - if (obj->body.otype == uris.patch_Get) { - lv2_atom_forge_frame_time(&atom_forge, 0); - write_set_patch(currentModelPath); + if (obj->body.otype == uris.patch_Get) + { + write_current_path(); } - - if (obj->body.otype == uris.patch_Set) + else if (obj->body.otype == uris.patch_Set) { const LV2_Atom* property = NULL; const LV2_Atom* file_path = NULL; - lv2_atom_object_get(obj, uris.patch_property, &property, 0); - + lv2_atom_object_get(obj, + uris.patch_property, &property, + uris.patch_value, &file_path, + 0); - if (property && (property->type == uris.atom_URID)) + if (property && property->type == uris.atom_URID && + ((const LV2_Atom_URID*)property)->body == uris.model_Path && + file_path && file_path->type == uris.atom_Path && + file_path->size > 0 && file_path->size < MAX_FILE_NAME) { - if (((const LV2_Atom_URID*)property)->body == uris.model_Path) - { - lv2_atom_object_get(obj, uris.patch_value, &file_path, 0); - - if (file_path && (file_path->size > 0) && (file_path->size < MAX_FILE_NAME)) - { - LV2LoadModelMsg msg = { kWorkTypeLoad, {} }; - - memcpy(msg.path, (const char*)LV2_ATOM_BODY_CONST(file_path), file_path->size); - - schedule->schedule_work(schedule->handle, sizeof(msg), &msg); - } - } + LV2LoadModelMsg msg = { kWorkTypeLoad, {} }; + memcpy(msg.path, file_path + 1, file_path->size); + schedule->schedule_work(schedule->handle, sizeof(msg), &msg); } } } @@ -236,15 +243,6 @@ namespace NAM { ports.audio_out[i] *= outputLevel; } } - - if (stateChanged) - { - stateChanged = false; - lv2_atom_forge_frame_time(&atom_forge, 0); - write_state_changed(); - } - - lv2_atom_forge_pop(&atom_forge,&sequence_frame); } LV2_State_Status Plugin::save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, @@ -361,16 +359,17 @@ namespace NAM { return result; } - void Plugin::write_set_patch( std::string filename) + void Plugin::write_current_path() { LV2_Atom_Forge_Frame frame; + lv2_atom_forge_frame_time(&atom_forge, 0); lv2_atom_forge_object(&atom_forge, &frame, 0, uris.patch_Set); lv2_atom_forge_key(&atom_forge, uris.patch_property); lv2_atom_forge_urid(&atom_forge, uris.model_Path); lv2_atom_forge_key(&atom_forge, uris.patch_value); - lv2_atom_forge_path(&atom_forge, filename.c_str(), filename.length()); + lv2_atom_forge_path(&atom_forge, currentModelPath.c_str(), currentModelPath.length() + 1); lv2_atom_forge_pop(&atom_forge, &frame); } @@ -379,6 +378,7 @@ namespace NAM { { LV2_Atom_Forge_Frame frame; + lv2_atom_forge_frame_time(&atom_forge, 0); lv2_atom_forge_object(&atom_forge, &frame, 0, uris.state_StateChanged); /* object with no properties */ diff --git a/src/nam_plugin.h b/src/nam_plugin.h index ddd4a59..d48700f 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -29,7 +29,8 @@ namespace NAM { enum LV2WorkType { kWorkTypeLoad, - kWorkTypeSwitch + kWorkTypeSwitch, + kWorkTypeFree }; struct LV2LoadModelMsg { @@ -37,6 +38,17 @@ namespace NAM { char path[MAX_FILE_NAME]; }; + struct LV2SwitchModelMsg { + LV2WorkType type; + char path[MAX_FILE_NAME]; + ::DSP* model; + }; + + struct LV2FreeModelMsg { + LV2WorkType type; + ::DSP* model; + }; + class Plugin { public: struct Ports { @@ -54,23 +66,18 @@ namespace NAM { LV2_Log_Logger logger = {}; LV2_Worker_Schedule* schedule = nullptr; - std::unique_ptr<::DSP> currentModel; - std::unique_ptr<::DSP> stagedModel; - std::unique_ptr<::DSP> deleteModel; - bool stateChanged = false; - + ::DSP* currentModel = nullptr; std::string currentModelPath; - std::string stagedModelPath; std::unordered_map mNAMParams = {}; Plugin(); - ~Plugin() = default; + ~Plugin(); bool initialize(double rate, const LV2_Feature* const* features) noexcept; void process(uint32_t n_samples) noexcept; - - void write_set_patch(std::string filename); + + void write_current_path(); void write_state_changed(); static LV2_Worker_Status work(LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, From eb352607890679976c57a7cd2de5fb9e3fac10d5 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 17:06:32 +0200 Subject: [PATCH 4/7] Pre-run model to ensure all needed buffers are allocated in advance Signed-off-by: falkTX --- resources/neural_amp_modeler.ttl.in | 6 ++-- src/nam_lv2.cpp | 7 +++-- src/nam_plugin.cpp | 44 ++++++++++++++++++++++++++++- src/nam_plugin.h | 7 +++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/resources/neural_amp_modeler.ttl.in b/resources/neural_amp_modeler.ttl.in index 701cec4..977b204 100644 --- a/resources/neural_amp_modeler.ttl.in +++ b/resources/neural_amp_modeler.ttl.in @@ -7,6 +7,7 @@ @prefix ui: . @prefix units: . @prefix urid: . +@prefix opts: . @prefix param: . @prefix patch: . @prefix state: . @@ -33,8 +34,9 @@ ]; lv2:requiredFeature urid:map, work:schedule; - lv2:optionalFeature lv2:hardRTCapable; - lv2:extensionData work:interface, state:interface; + lv2:optionalFeature lv2:hardRTCapable, opts:options, state:threadSafeRestore; + lv2:extensionData work:interface, state:interface, options:interface; + opts:supportedOption ; rdfs:comment """ An LV2 implementation of Neural Amp Modeler. diff --git a/src/nam_lv2.cpp b/src/nam_lv2.cpp index 553dcf9..b836438 100644 --- a/src/nam_lv2.cpp +++ b/src/nam_lv2.cpp @@ -63,9 +63,12 @@ static void cleanup(LV2_Handle instance) static const void* extension_data(const char* uri) { - static const LV2_State_Interface state = {NAM::Plugin::save, NAM::Plugin::restore}; - static const LV2_Worker_Interface worker = { NAM::Plugin::work, NAM::Plugin::work_response, NULL }; + static const LV2_Options_Interface options = { NAM::Plugin::options_get, NAM::Plugin::options_set }; + static const LV2_State_Interface state = { NAM::Plugin::save, NAM::Plugin::restore}; + static const LV2_Worker_Interface worker = { NAM::Plugin::work, NAM::Plugin::work_response, NULL }; + if (!strcmp(uri, LV2_OPTIONS__interface)) + return &options; if (!strcmp(uri, LV2_STATE__interface)) return &state; if (!strcmp(uri, LV2_WORKER__interface)) diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index 6a2f3bf..79ac529 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -22,6 +22,9 @@ namespace NAM { bool Plugin::initialize(double rate, const LV2_Feature* const* features) noexcept { + // for fetching initial options, can be null + LV2_Options_Option* options = nullptr; + for (size_t i = 0; features[i]; ++i) { if (std::string(features[i]->URI) == std::string(LV2_URID__map)) map = static_cast(features[i]->data); @@ -29,6 +32,8 @@ namespace NAM { schedule = static_cast(features[i]->data); else if (std::string(features[i]->URI) == std::string(LV2_LOG__log)) logger.log = static_cast(features[i]->data); + else if (std::string(features[i]->URI) == std::string(LV2_OPTIONS__options)) + options = static_cast(features[i]->data); } lv2_log_logger_set_map(&logger, map); @@ -54,6 +59,7 @@ namespace NAM { uris.atom_Int = map->map(map->handle, LV2_ATOM__Int); uris.atom_Path = map->map(map->handle, LV2_ATOM__Path); uris.atom_URID = map->map(map->handle, LV2_ATOM__URID); + uris.bufSize_maxBlockLength = map->map(map->handle, LV2_BUF_SIZE__maxBlockLength); uris.patch_Set = map->map(map->handle, LV2_PATCH__Set); uris.patch_Get = map->map(map->handle, LV2_PATCH__Get); uris.patch_property = map->map(map->handle, LV2_PATCH__property); @@ -63,6 +69,9 @@ namespace NAM { uris.model_Path = map->map(map->handle, MODEL_URI); + if (options != nullptr) + options_set(this, options); + return true; } @@ -97,6 +106,18 @@ namespace NAM { // Enable model loudness normalization model->SetNormalize(true); + + // Pre-run model to ensure all needed buffers are allocated in advance + if (const int32_t numSamples = nam->maxBufferSize) + { + float* buffer = new float[numSamples]; + + std::unordered_map params = {}; + model->process(&buffer, &buffer, 1, numSamples, 1.0, 1.0, params); + model->finalize_(numSamples); + + delete[] buffer; + } } LV2SwitchModelMsg response = { kWorkTypeSwitch, {}, model }; @@ -245,6 +266,28 @@ namespace NAM { } } + uint32_t Plugin::options_get(LV2_Handle, LV2_Options_Option*) + { + // currently unused + return LV2_OPTIONS_ERR_UNKNOWN; + } + + uint32_t Plugin::options_set(LV2_Handle instance, const LV2_Options_Option* options) + { + auto nam = static_cast(instance); + + for (int i=0; options[i].key && options[i].type; ++i) + { + if (options[i].key == nam->uris.bufSize_maxBlockLength && options[i].type == nam->uris.atom_Int) + { + nam->maxBufferSize = *(const int32_t*)options[i].value; + break; + } + } + + return LV2_OPTIONS_SUCCESS; + } + LV2_State_Status Plugin::save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features) { @@ -385,5 +428,4 @@ namespace NAM { lv2_atom_forge_pop(&atom_forge, &frame); } - } diff --git a/src/nam_plugin.h b/src/nam_plugin.h index d48700f..9e83046 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -80,6 +82,9 @@ namespace NAM { void write_current_path(); void write_state_changed(); + static uint32_t options_get(LV2_Handle instance, LV2_Options_Option* options); + static uint32_t options_set(LV2_Handle instance, const LV2_Options_Option* options); + static LV2_Worker_Status work(LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, uint32_t size, const void* data); static LV2_Worker_Status work_response(LV2_Handle instance, uint32_t size, const void* data); @@ -96,6 +101,7 @@ namespace NAM { LV2_URID atom_Int; LV2_URID atom_Path; LV2_URID atom_URID; + LV2_URID bufSize_maxBlockLength; LV2_URID patch_Set; LV2_URID patch_Get; LV2_URID patch_property; @@ -113,5 +119,6 @@ namespace NAM { float m_rate; float inputLevel = 0; float outputLevel = 0; + int32_t maxBufferSize = 0; }; } From 9c9b795579b102349ad87667c499f77efdffbb57 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 17:06:44 +0200 Subject: [PATCH 5/7] Add doap:Project as type, making ttl validators happy Signed-off-by: falkTX --- resources/neural_amp_modeler.ttl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/neural_amp_modeler.ttl.in b/resources/neural_amp_modeler.ttl.in index 977b204..b852142 100644 --- a/resources/neural_amp_modeler.ttl.in +++ b/resources/neural_amp_modeler.ttl.in @@ -21,7 +21,7 @@ rdfs:range atom:Path. <@NAM_LV2_ID@> - a lv2:Plugin, lv2:SimulatorPlugin; + a lv2:Plugin, lv2:SimulatorPlugin, doap:Project; doap:name "Neural Amp Modeler"; lv2:project <@NAM_LV2_ID@>; lv2:minorVersion @PROJECT_VERSION_MINOR@; From 27ac59f9b4e394aab653162946b115a573f4fd21 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 19:00:56 +0200 Subject: [PATCH 6/7] Fix typo Signed-off-by: falkTX --- resources/neural_amp_modeler.ttl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/neural_amp_modeler.ttl.in b/resources/neural_amp_modeler.ttl.in index b852142..356b625 100644 --- a/resources/neural_amp_modeler.ttl.in +++ b/resources/neural_amp_modeler.ttl.in @@ -35,7 +35,7 @@ lv2:requiredFeature urid:map, work:schedule; lv2:optionalFeature lv2:hardRTCapable, opts:options, state:threadSafeRestore; - lv2:extensionData work:interface, state:interface, options:interface; + lv2:extensionData work:interface, state:interface, opts:interface; opts:supportedOption ; rdfs:comment """ From 739f43b15131e46f9f1e502e58a465532201fdc4 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 15 Jun 2023 19:13:55 +0200 Subject: [PATCH 7/7] state changed is no longer needed Signed-off-by: falkTX --- src/nam_plugin.cpp | 14 -------------- src/nam_plugin.h | 2 -- 2 files changed, 16 deletions(-) diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index 79ac529..27e151f 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -65,7 +65,6 @@ namespace NAM { uris.patch_property = map->map(map->handle, LV2_PATCH__property); uris.patch_value = map->map(map->handle, LV2_PATCH__value); uris.units_frame = map->map(map->handle, LV2_UNITS__frame); - uris.state_StateChanged = map->map(map->handle, LV2_STATE__StateChanged); uris.model_Path = map->map(map->handle, MODEL_URI); @@ -171,7 +170,6 @@ namespace NAM { // report change to host/ui nam->write_current_path(); - nam->write_state_changed(); return LV2_WORKER_SUCCESS; } @@ -416,16 +414,4 @@ namespace NAM { lv2_atom_forge_pop(&atom_forge, &frame); } - - void Plugin::write_state_changed() - { - LV2_Atom_Forge_Frame frame; - - lv2_atom_forge_frame_time(&atom_forge, 0); - lv2_atom_forge_object(&atom_forge, &frame, 0, uris.state_StateChanged); - - /* object with no properties */ - - lv2_atom_forge_pop(&atom_forge, &frame); - } } diff --git a/src/nam_plugin.h b/src/nam_plugin.h index 9e83046..7968670 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -80,7 +80,6 @@ namespace NAM { void process(uint32_t n_samples) noexcept; void write_current_path(); - void write_state_changed(); static uint32_t options_get(LV2_Handle instance, LV2_Options_Option* options); static uint32_t options_set(LV2_Handle instance, const LV2_Options_Option* options); @@ -106,7 +105,6 @@ namespace NAM { LV2_URID patch_Get; LV2_URID patch_property; LV2_URID patch_value; - LV2_URID state_StateChanged; LV2_URID units_frame; LV2_URID model_Path; };