diff --git a/NAM/convnet.cpp b/NAM/convnet.cpp
index ef63121..76d3baa 100644
--- a/NAM/convnet.cpp
+++ b/NAM/convnet.cpp
@@ -109,9 +109,9 @@ nam::convnet::ConvNet::ConvNet(const int channels, const std::vector<int>& dilat
   if (it != weights.end())
     throw std::runtime_error("Didn't touch all the weights when initializing ConvNet");
 
-  _prewarm_samples = 1;
+  mPrewarmSamples = 1;
   for (size_t i = 0; i < dilations.size(); i++)
-    _prewarm_samples += dilations[i];
+    mPrewarmSamples += dilations[i];
 }
 
 
diff --git a/NAM/convnet.h b/NAM/convnet.h
index 310a1e5..b1fa142 100644
--- a/NAM/convnet.h
+++ b/NAM/convnet.h
@@ -71,6 +71,8 @@ class ConvNet : public Buffer
           std::vector<float>& weights, const double expected_sample_rate = -1.0);
   ~ConvNet() = default;
 
+  void process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) override;
+
 protected:
   std::vector<ConvNetBlock> _blocks;
   std::vector<Eigen::MatrixXf> _block_vals;
@@ -81,7 +83,8 @@ class ConvNet : public Buffer
   void _update_buffers_(NAM_SAMPLE* input, const int num_frames) override;
   void _rewind_buffers_() override;
 
-  void process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) override;
+  int mPrewarmSamples = 0; // Pre-compute during initialization
+  int PrewarmSamples() override { return mPrewarmSamples; };
 };
 }; // namespace convnet
 }; // namespace nam
diff --git a/NAM/dsp.cpp b/NAM/dsp.cpp
index c94cb73..b945789 100644
--- a/NAM/dsp.cpp
+++ b/NAM/dsp.cpp
@@ -21,14 +21,15 @@ nam::DSP::DSP(const double expected_sample_rate)
 
 void nam::DSP::prewarm()
 {
-  if (_prewarm_samples == 0)
+  const int prewarmSamples = PrewarmSamples();
+  if (prewarmSamples == 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++)
+  for (long i = 0; i < prewarmSamples; i++)
   {
     this->process(sample_ptr, sample_ptr, 1);
     sample = 0;
@@ -51,6 +52,17 @@ double nam::DSP::GetLoudness() const
   return mLoudness;
 }
 
+void nam::DSP::Reset(const double sampleRate, const int maxBufferSize)
+{
+  // Some subclasses might want to throw an exception if the sample rate is "wrong".
+  // This could be under a debugging flag potentially.
+  mExternalSampleRate = sampleRate;
+  mHaveExternalSampleRate = true;
+  mMaxBufferSize = maxBufferSize;
+
+  // Subclasses might also want to pre-warm, but let them call that themselves in case
+  // they want to e.g. do some allocations first.
+}
 void nam::DSP::SetLoudness(const double loudness)
 {
   mLoudness = loudness;
diff --git a/NAM/dsp.h b/NAM/dsp.h
index fd176da..35bd3bc 100644
--- a/NAM/dsp.h
+++ b/NAM/dsp.h
@@ -44,6 +44,9 @@ class DSP
   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
+  // Important: don't expect the model to be outputting zeroes after this. Neural networks
+  // Don't know that there's anything special about "zero", and forcing this gets rid of
+  // some possibilities that I dont' want to rule out (e.g. models that "are noisy").
   virtual void prewarm();
   // process() does all of the processing requried to take `input` array and
   // fill in the required values on `output`.
@@ -60,6 +63,16 @@ class DSP
   double GetLoudness() const;
   // Get whether the model knows how loud it is.
   bool HasLoudness() const { return mHasLoudness; };
+  // General function for resetting the DSP unit.
+  // This doesn't call prewarm(). If you want to do that, then you might want to use ResetAndPrewarm().
+  // See https://github.com/sdatkinson/NeuralAmpModelerCore/issues/96 for the reasoning.
+  virtual void Reset(const double sampleRate, const int maxBufferSize);
+  // Reset(), then prewarm()
+  void ResetAndPrewarm(const double sampleRate, const int maxBufferSize)
+  {
+    Reset(sampleRate, maxBufferSize);
+    prewarm();
+  }
   // Set the loudness, in dB.
   // This is usually defined to be the loudness to a standardized input. The trainer has its own, but you can always
   // use this to define it a different way if you like yours better.
@@ -71,8 +84,14 @@ class DSP
   double mLoudness = 0.0;
   // What sample rate does the model expect?
   double mExpectedSampleRate;
-  // How many samples should be processed during "pre-warming"
-  int _prewarm_samples = 0;
+  // Have we been told what the external sample rate is? If so, what is it?
+  bool mHaveExternalSampleRate = false;
+  double mExternalSampleRate = -1.0;
+  // The largest buffer I expect to be told to process:
+  int mMaxBufferSize;
+
+  // How many samples should be processed for me to be considered "warmed up"?
+  virtual int PrewarmSamples() { return 0; };
 };
 
 // Class where an input buffer is kept so that long-time effects can be
@@ -116,6 +135,7 @@ class Linear : public Buffer
 
 // NN modules =================================================================
 
+// TODO conv could take care of its own ring buffer.
 class Conv1D
 {
 public:
diff --git a/NAM/lstm.cpp b/NAM/lstm.cpp
index 38ff494..437ce81 100644
--- a/NAM/lstm.cpp
+++ b/NAM/lstm.cpp
@@ -84,6 +84,14 @@ void nam::lstm::LSTM::process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int n
     output[i] = this->_process_sample(input[i]);
 }
 
+int nam::lstm::LSTM::PrewarmSamples()
+{
+  int result = (int)(0.5 * mExpectedSampleRate);
+  // If the expected sample rate wasn't provided, it'll be -1.
+  // Make sure something still happens.
+  return result <= 0 ? 1 : result;
+}
+
 float nam::lstm::LSTM::_process_sample(const float x)
 {
   if (this->_layers.size() == 0)
diff --git a/NAM/lstm.h b/NAM/lstm.h
index 6b02b18..7ee38e0 100644
--- a/NAM/lstm.h
+++ b/NAM/lstm.h
@@ -55,6 +55,9 @@ class LSTM : public DSP
   ~LSTM() = default;
 
 protected:
+  // Hacky, but a half-second seems to work for most models.
+  int PrewarmSamples() override;
+
   Eigen::VectorXf _head_weight;
   float _head_bias;
   void process(NAM_SAMPLE* input, NAM_SAMPLE* output, const int num_frames) override;
diff --git a/NAM/wavenet.cpp b/NAM/wavenet.cpp
index 6941f81..2104c4c 100644
--- a/NAM/wavenet.cpp
+++ b/NAM/wavenet.cpp
@@ -267,9 +267,9 @@ nam::wavenet::WaveNet::WaveNet(const std::vector<nam::wavenet::LayerArrayParams>
   this->_head_output.resize(1, 0); // Mono output!
   this->set_weights_(weights);
 
-  _prewarm_samples = 1;
+  mPrewarmSamples = 1;
   for (size_t i = 0; i < this->_layer_arrays.size(); i++)
-    _prewarm_samples += this->_layer_arrays[i].get_receptive_field();
+    mPrewarmSamples += this->_layer_arrays[i].get_receptive_field();
 }
 
 void nam::wavenet::WaveNet::set_weights_(std::vector<float>& weights)
diff --git a/NAM/wavenet.h b/NAM/wavenet.h
index 745b3e7..a2ad2fc 100644
--- a/NAM/wavenet.h
+++ b/NAM/wavenet.h
@@ -196,6 +196,9 @@ class WaveNet : public DSP
   virtual void _set_condition_array(NAM_SAMPLE* input, const int num_frames);
   // Ensure that all buffer arrays are the right size for this num_frames
   void _set_num_frames_(const long num_frames);
+
+  int mPrewarmSamples = 0; // Pre-compute during initialization
+  int PrewarmSamples() override { return mPrewarmSamples; };
 };
 }; // namespace wavenet
 }; // namespace nam
diff --git a/tools/benchmodel.cpp b/tools/benchmodel.cpp
index 4b1c3e3..99f3923 100644
--- a/tools/benchmodel.cpp
+++ b/tools/benchmodel.cpp
@@ -11,7 +11,8 @@ using std::chrono::milliseconds;
 
 #define AUDIO_BUFFER_SIZE 64
 
-double buffer[AUDIO_BUFFER_SIZE];
+double inputBuffer[AUDIO_BUFFER_SIZE];
+double outputBuffer[AUDIO_BUFFER_SIZE];
 
 int main(int argc, char* argv[])
 {
@@ -38,14 +39,22 @@ int main(int argc, char* argv[])
 
     auto t1 = high_resolution_clock::now();
 
-    size_t bufferSize = 64;
-    size_t numBuffers = (48000 / 64) * 2;
+    size_t bufferSize = AUDIO_BUFFER_SIZE;
+    model->Reset(model->GetExpectedSampleRate(), bufferSize);
+    size_t numBuffers = (48000 / bufferSize) * 2;
+
+    // Fill input buffer with zeroes.
+    // Output buffer doesn't matter.
+    for (int i = 0; i < AUDIO_BUFFER_SIZE; i++)
+    {
+      inputBuffer[i] = 0.0;
+    }
 
     std::cout << "Running benchmark\n";
 
     for (size_t i = 0; i < numBuffers; i++)
     {
-      model->process(buffer, buffer, AUDIO_BUFFER_SIZE);
+      model->process(inputBuffer, outputBuffer, AUDIO_BUFFER_SIZE);
     }
 
     std::cout << "Finished\n";
