From 42d9d8b4c37e8d44a861bd43044f172a7b343ecf Mon Sep 17 00:00:00 2001 From: Mike Oliphant Date: Mon, 10 Nov 2025 10:45:29 -0800 Subject: [PATCH 1/4] Smart bypass on silence --- deps/NeuralAudio | 2 +- src/nam_plugin.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/nam_plugin.h | 3 +++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/deps/NeuralAudio b/deps/NeuralAudio index 162c804..6177d02 160000 --- a/deps/NeuralAudio +++ b/deps/NeuralAudio @@ -1 +1 @@ -Subproject commit 162c80403f95ea0b1a10038887f1ad6265fc20df +Subproject commit 6177d02f4a36c4b13e9a4e1c0f76128156b74138 diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index 1c13c1b..2dc2a8e 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -7,12 +7,18 @@ #define SMOOTH_EPSILON .0001f +#ifndef BYPASS_DB_THRESHOLD +#define BYPASS_DB_THRESHOLD -100 +#endif + namespace NAM { Plugin::Plugin() { // prevent allocations on the audio thread currentModelPath.reserve(MAX_FILE_NAME + 1); + bypassThresholdLinear = powf(10, BYPASS_DB_THRESHOLD * 0.05f); + // NeuralAudio::NeuralModel::SetLSTMLoadMode( //#ifdef LSTM_PREFER_NAM // NeuralAudio::PreferNAMCore @@ -181,6 +187,9 @@ namespace NAM { nam->currentModelPath = msg->path; assert(nam->currentModelPath.capacity() >= MAX_FILE_NAME + 1); + nam->silentSamples = 0; + nam->smartBypassed = false; + // send reply nam->schedule->schedule_work(nam->schedule->handle, sizeof(reply), &reply); @@ -241,6 +250,42 @@ namespace NAM { if (currentModel != nullptr) { modelInputAdjustmentDB = currentModel->GetRecommendedInputDBAdjustment(); + +#ifdef SMART_BYPASS_ENABLED + int receptiveFieldSamples = currentModel->GetReceptiveFieldSize(); + + if (receptiveFieldSamples > -1) + { + for (unsigned int i = 0; i < n_samples; i++) + { + if (abs(ports.audio_in[i]) <= bypassThresholdLinear) + { + silentSamples++; + } + else + { + silentSamples = 0; + } + } + + if (silentSamples > (uint32_t)receptiveFieldSamples) + { + if (smartBypassed) + { + for (unsigned int i = 0; i < n_samples; i++) + { + ports.audio_out[i] = ports.audio_in[i]; + } + + return; + } + + smartBypassed = true; // If we aren't already, we'll be bypassed on the next process call + } + else + smartBypassed = false; + } +#endif } // convert input level from db diff --git a/src/nam_plugin.h b/src/nam_plugin.h index 15a03a4..686b495 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -120,5 +120,8 @@ namespace NAM { float inputLevel = 0; float outputLevel = 0; int32_t maxBufferSize = 512; + float bypassThresholdLinear = 0; + uint32_t silentSamples = 0; + bool smartBypassed = false; }; } From d998b95e4521ec1ade99fa7463975b90e4c572dc Mon Sep 17 00:00:00 2001 From: Mike Oliphant Date: Mon, 10 Nov 2025 10:52:26 -0800 Subject: [PATCH 2/4] Added cmake option for smart bypass --- src/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7566523..ec9ce38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,6 +54,12 @@ if (DISABLE_DENORMALS) add_definitions(-DDISABLE_DENORMALS) endif (DISABLE_DENORMALS) +option(SMART_BYPASS_ENABLED "Enable auto-bypass on silence" OFF) + +if (SMART_BYPASS_ENABLED) + add_definitions(-DSMART_BYPASS_ENABLED) +endif (SMART_BYPASS_ENABLED) + set_target_properties(neural_amp_modeler PROPERTIES CXX_VISIBILITY_PRESET hidden From 0fd82dc816280208179ec667953edf5fa699c014 Mon Sep 17 00:00:00 2001 From: Mike Oliphant Date: Mon, 10 Nov 2025 10:56:01 -0800 Subject: [PATCH 3/4] Document SMART_BYPASS_ENABLED CMake option --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ce2cff5..3b70d35 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,6 @@ After building, the plugin will be in **build/neural_amp_modeler.lv2**. ```-DUSE_NATIVE_ARCH=ON```: If you have a relatively modern x64 processor, you can pass ```-DUSE_NATIVE_ARCH=ON``` on your cmake command line to enable certain processor-specific optimizations. +```-DSMART_BYPASS_ENABLED=ON```: If enabled, this will bypass model processing if input has been silent (below -100 dB by default) for a sufficient number of samples (determined by the model's receptive field size). + Also see the [NeuralAudio CMake options](https://github.com/mikeoliphant/NeuralAudio#cmake-options) - adding these to your neural-amp-modeler-lv2 cmake will pass them to the NeuralAudio build. From eeaeeecf24cea63cbebf2d7d712ab8fd44045748 Mon Sep 17 00:00:00 2001 From: Mike Oliphant Date: Tue, 11 Nov 2025 07:23:47 -0800 Subject: [PATCH 4/4] Start new models bypassed. Prevent silentSamples from overflowing. --- src/nam_plugin.cpp | 17 ++++++++++++++--- src/nam_plugin.h | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/nam_plugin.cpp b/src/nam_plugin.cpp index 2dc2a8e..df825fb 100644 --- a/src/nam_plugin.cpp +++ b/src/nam_plugin.cpp @@ -187,8 +187,17 @@ namespace NAM { nam->currentModelPath = msg->path; assert(nam->currentModelPath.capacity() >= MAX_FILE_NAME + 1); - nam->silentSamples = 0; - nam->smartBypassed = false; + if (nam->currentModel != nullptr) + { + int receptiveFieldSize = nam->currentModel->GetReceptiveFieldSize(); + + if (receptiveFieldSize > -1) + { + // A newly loaded model is prewarmed to have a silent sample history + nam->silentSamples = receptiveFieldSize; + nam->smartBypassed = true; + } + } // send reply nam->schedule->schedule_work(nam->schedule->handle, sizeof(reply), &reply); @@ -268,8 +277,10 @@ namespace NAM { } } - if (silentSamples > (uint32_t)receptiveFieldSamples) + if (silentSamples >= (uint32_t)receptiveFieldSamples) { + silentSamples = (uint32_t)receptiveFieldSamples; // Prevent silentSamples growing and eventually overflowing uint32 + if (smartBypassed) { for (unsigned int i = 0; i < n_samples; i++) diff --git a/src/nam_plugin.h b/src/nam_plugin.h index 686b495..b47ab9e 100644 --- a/src/nam_plugin.h +++ b/src/nam_plugin.h @@ -80,6 +80,7 @@ namespace NAM { bool initialize(double rate, const LV2_Feature* const* features) noexcept; void set_max_buffer_size(int size) noexcept; + void activate() noexcept; void process(uint32_t n_samples) noexcept; void write_current_path(); @@ -122,6 +123,6 @@ namespace NAM { int32_t maxBufferSize = 512; float bypassThresholdLinear = 0; uint32_t silentSamples = 0; - bool smartBypassed = false; + bool smartBypassed = true; }; }