diff --git a/NAM/convnet.cpp b/NAM/convnet.cpp index 975b4fc..d99d7c9 100644 --- a/NAM/convnet.cpp +++ b/NAM/convnet.cpp @@ -109,8 +109,13 @@ convnet::ConvNet::ConvNet(const int channels, const std::vector& dilations, this->_head = _Head(channels, it); if (it != params.end()) throw std::runtime_error("Didn't touch all the params when initializing ConvNet"); + + _prewarm_samples = 1; + for (size_t i = 0; i < dilations.size(); i++) + _prewarm_samples += dilations[i]; } + void convnet::ConvNet::process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) { diff --git a/NAM/dsp.cpp b/NAM/dsp.cpp index 4ce110e..09f0663 100644 --- a/NAM/dsp.cpp +++ b/NAM/dsp.cpp @@ -21,6 +21,23 @@ DSP::DSP(const double expected_sample_rate) { } +void DSP::prewarm() +{ + if (_prewarm_samples == 0) + return; + + NAM_SAMPLE sample = 0; + NAM_SAMPLE* sample_ptr = &sample; + + // pre-warm the model for a model-specific number of samples + for (long i = 0; i < _prewarm_samples; i++) + { + this->process(sample_ptr, sample_ptr, 1); + this->finalize_(1); + sample = 0; + } +} + void DSP::process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) { // Default implementation is the null operation diff --git a/NAM/dsp.h b/NAM/dsp.h index af2ad75..209821d 100644 --- a/NAM/dsp.h +++ b/NAM/dsp.h @@ -50,6 +50,9 @@ class DSP // We may choose to have the models figure out for themselves how loud they are in here in the future. DSP(const double expected_sample_rate); virtual ~DSP() = default; + // prewarm() does any required intial work required to "settle" model initial conditions + // it can be somewhat expensive, so should not be called during realtime audio processing + virtual void prewarm(); // process() does all of the processing requried to take `input` array and // fill in the required values on `output`. // To do this: @@ -87,6 +90,7 @@ class DSP std::unordered_map _params; // If the params have changed since the last buffer was processed: bool _stale_params = true; + int _prewarm_samples = 0; // Methods diff --git a/NAM/get_dsp.cpp b/NAM/get_dsp.cpp index 0f84772..3c71c86 100644 --- a/NAM/get_dsp.cpp +++ b/NAM/get_dsp.cpp @@ -211,5 +211,9 @@ std::unique_ptr get_dsp(dspData& conf) { out->SetLoudness(loudness); } + + // "pre-warm" the model to settle initial conditions + out->prewarm(); + return out; } diff --git a/NAM/wavenet.cpp b/NAM/wavenet.cpp index 84fcad7..bbdbcfe 100644 --- a/NAM/wavenet.cpp +++ b/NAM/wavenet.cpp @@ -263,20 +263,9 @@ wavenet::WaveNet::WaveNet(const std::vector& layer_ar this->_head_output.resize(1, 0); // Mono output! this->set_params_(params); - long receptive_field = 1; + _prewarm_samples = 1; for (size_t i = 0; i < this->_layer_arrays.size(); i++) - receptive_field += this->_layer_arrays[i].get_receptive_field(); - - NAM_SAMPLE sample = 0; - NAM_SAMPLE* sample_ptr = &sample; - - // pre-warm the model over the size of the receptive field - for (long i = 0; i < receptive_field; i++) - { - this->process(sample_ptr, sample_ptr, 1); - this->finalize_(1); - sample = 0; - } + _prewarm_samples += this->_layer_arrays[i].get_receptive_field(); } void wavenet::WaveNet::finalize_(const int num_frames) diff --git a/NAM/wavenet.h b/NAM/wavenet.h index f3eda79..981acb2 100644 --- a/NAM/wavenet.h +++ b/NAM/wavenet.h @@ -199,7 +199,6 @@ class WaveNet : public DSP // Get the info from the parametric config void _init_parametric_(nlohmann::json& parametric); void _prepare_for_frames_(const long num_frames); - // Reminder: From ._input_post_gain to ._core_dsp_output void process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) override; // Ensure that all buffer arrays are the right size for this num_frames