From d9500d6c32747f469bad8da79a46dddd90b16089 Mon Sep 17 00:00:00 2001
From: abscisys <vincent_gauche@hotmail.com>
Date: Wed, 25 Jan 2023 23:34:38 +0100
Subject: [PATCH] Adding debugging features to the MixingConsole

---
 src/fx_engine.hpp                | 12 ++++----
 src/mixing_console.hpp           | 47 +++++++++++++++++++++++++++++
 src/test/test_mixing_console.cpp | 51 ++++++++++++++++++++++++++++----
 3 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/src/fx_engine.hpp b/src/fx_engine.hpp
index 0595ede..132fa61 100644
--- a/src/fx_engine.hpp
+++ b/src/fx_engine.hpp
@@ -235,7 +235,7 @@ public:
         template <typename D>
         inline void write(D& d, int32_t offset, float32_t scale)
         {
-            assert(D::base + D::length <= size);
+            assert((D::base + D::length) <= size);
             T w = DataType<format>::compress(this->accumulator_);
             if(offset == -1)
             {
@@ -270,7 +270,7 @@ public:
         template <typename D>
         inline void read(D& d, int32_t offset, float32_t scale)
         {
-            assert(D::base + D::length <= size);
+            assert((D::base + D::length) <= size);
             T r;
             if(offset == -1)
             {
@@ -306,7 +306,7 @@ public:
         template <typename D>
         inline void interpolate(D& d, float32_t offset, float32_t scale)
         {
-            assert(D::base + D::length <= size);
+            assert((D::base + D::length) <= size);
             MAKE_INTEGRAL_FRACTIONAL(offset);
             float32_t a = DataType<format>::decompress(this->buffer_[(this->write_ptr_ + offset_integral + D::base) & MASK]);
             float32_t b = DataType<format>::decompress(this->buffer_[(this->write_ptr_ + offset_integral + D::base + 1) & MASK]);
@@ -318,7 +318,7 @@ public:
         template <typename D>
         inline void interpolate(D& d, float32_t offset, LFOIndex index, float32_t amplitude, float32_t scale)
         {
-            assert(D::base + D::length <= size);
+            assert((D::base + D::length) <= size);
             assert(index < LFOIndex::kLFOCount);
             offset += amplitude * this->lfo_value_[index];
             MAKE_INTEGRAL_FRACTIONAL(offset);
@@ -364,8 +364,8 @@ public:
         }
         c->accumulator_ = 0.0f;
         c->previous_read_ = 0.0f;
-        c->buffer_ = buffer_;
-        c->write_ptr_ = write_ptr_;
+        c->buffer_ = this->buffer_;
+        c->write_ptr_ = this->write_ptr_;
         if(enable_lfo)
         {
             for(unsigned i = 0; i < LFOIndex::kLFOCount; ++i) 
diff --git a/src/mixing_console.hpp b/src/mixing_console.hpp
index be0c67f..03896a5 100644
--- a/src/mixing_console.hpp
+++ b/src/mixing_console.hpp
@@ -33,6 +33,10 @@
 #include "fx_dry.h"
 #include "fx_unit2.hpp"
 
+#if defined(DEBUG)
+typedef void (*ValueInpector)(const std::string&, size_t, const float32_t);
+#endif
+
 template<size_t nb_inputs>
 class MixingConsole : public FXBase
 {
@@ -101,6 +105,7 @@ private:
 #if defined(DEBUG)
 public:
     void dump(std::ostream& out, const std::string& key = "") const;
+    void inspect(ValueInpector inspector, bool checkInputBuffer = false) const;
 #endif
 };
 
@@ -602,9 +607,51 @@ void MixingConsole<nb_inputs>::dump(std::ostream& out, const std::string& key) c
 #define DUMP1(mixer, out) mixer->dump(cout)
 #define DUMP2(mixer, out, tag) mixer->dump(cout, tag)
 
+template<size_t nb_inputs>
+void MixingConsole<nb_inputs>::inspect(ValueInpector inspector, bool checkInputBuffer) const
+{
+    for(size_t i = 0; i < nb_inputs; ++i)
+    {
+        inspector("Level  ", i, this->channel_level_[i]);
+        inspector("Pan L  ", i, this->pan_[StereoChannels::Left][i]);
+        inspector("Pan R  ", i, this->pan_[StereoChannels::Right][i]);
+        inspector("Pan    ", i, this->pan_[StereoChannels::kNumChannels][i]);
+    }
+
+    for(size_t i = 0; i < (nb_inputs + MixerOutput::kFXCount - 1); ++i)
+    {
+        inspector("Input L", i, this->input_samples_[StereoChannels::Left ][i]);
+        inspector("Input R", i, this->input_samples_[StereoChannels::Right][i]);
+    }
+
+    for(size_t c = 0; c < MixerOutput::kFXCount; ++c)
+    {
+        for(size_t i = 0; i < (nb_inputs + MixerOutput::kFXCount - 1); ++i)
+        {
+            inspector("Levels ", c * 100 + i, this->levels_[c][i]);
+        }
+    }
+
+    if(checkInputBuffer)
+    {
+        for(size_t i = 0; i < nb_inputs; ++i)
+        {
+            for(size_t k = 0; k < this->BufferSize; ++k)
+            {
+                inspector("Buffer ", k * 100 + i, this->input_sample_buffer_[StereoChannels::Left ][i][k]);
+                inspector("Buffer ", k * 100 + i, this->input_sample_buffer_[StereoChannels::Right][i][k]);
+            }
+        }
+    }
+}
+
+#define INSPECT(mixer, inspector) mixer->inspect(inspector, true);
+
 #else
 
 #define DUMP1(mixer, out)
 #define DUMP2(mixer, out, tag)
 
+#define INSPECT(mixer, inspector)
+
 #endif
diff --git a/src/test/test_mixing_console.cpp b/src/test/test_mixing_console.cpp
index bb42d0c..8526d94 100644
--- a/src/test/test_mixing_console.cpp
+++ b/src/test/test_mixing_console.cpp
@@ -1,10 +1,23 @@
 #include <gtest/gtest.h>
+#include <cmath>
 
 #include "test_fx_helper.h"
 #include "wave.h"
 
 #include "../mixing_console.hpp"
 
+void normalizedValueInspector(const std::string& el, size_t idx, const float32_t value)
+{
+    if(std::isnan(value))
+    {
+        std::cout << "NAN - " << el << " " << idx << " = " << value  << std::endl;
+    }
+    else if(value != constrain(value, -1.0f, 1.0f))
+    {
+        std::cout << "OoB - " << el << " " << idx << " = " << value  << std::endl;
+    }
+}
+
 TEST(MixerOutputTest, toStringForTube)
 {
     auto v = toString(MixerOutput::FX_Tube);
@@ -203,33 +216,27 @@ TEST(MixingConsole, ShimmerProcessing)
     mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
     mixer->setChannelLevel(0, 1.0f);
     mixer->setPan(0, 0.5f);
-    DUMP2(mixer, std::cout, "Post setup");
 
     float32_t in[length] = {0.1, 0.2};
     float32_t out1[StereoChannels::kNumChannels][length];
     for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out1[i], 0, length * sizeof(float32_t));
 
     mixer->setInputSampleBuffer(0, in);
-    DUMP2(mixer, std::cout, "Post input injection #1");
 
     mixer->process(
         out1[StereoChannels::Left ],
         out1[StereoChannels::Right]
     );
-    DUMP2(mixer, std::cout, "Post processing #1");
 
     mixer->reset();
-    DUMP2(mixer, std::cout, "Post reset");
 
     float32_t out2[StereoChannels::kNumChannels][length];
     mixer->setInputSampleBuffer(0, in);
-    DUMP2(mixer, std::cout, "Post input injection #2");
 
     mixer->process(
         out2[StereoChannels::Left ],
         out2[StereoChannels::Right]
     );
-    DUMP2(mixer, std::cout, "Post processing #2");
 
     EXPECT_EQ(out1[StereoChannels::Left ][0], out2[StereoChannels::Left ][0]);
     EXPECT_EQ(out1[StereoChannels::Right][0], out2[StereoChannels::Right][0]);
@@ -239,6 +246,38 @@ TEST(MixingConsole, ShimmerProcessing)
     delete mixer;
 }
 
+TEST(MixingConsole, ShimmerNoiseProcessing)
+{
+    constexpr size_t length = 1024;
+
+    Mixer* mixer = new Mixer(SAMPLING_FREQUENCY, length);
+    mixer->reset();
+
+    mixer->setSendLevel(0, MixerOutput::MainOutput, 0.0f);
+    mixer->setSendLevel(0, MixerOutput::FX_ShimmerReverb, 1.0f);
+    mixer->setReturnLevel(MixerOutput::FX_ShimmerReverb, MixerOutput::MainOutput, 1.0f);
+    mixer->setChannelLevel(0, 1.0f);
+    mixer->setPan(0, 0.5f);
+    INSPECT(mixer, normalizedValueInspector);
+
+    float32_t in[length];
+    for(size_t i = 0; i < length; ++i) in[i] = getRandomValue();
+    
+    float32_t out[StereoChannels::kNumChannels][length];
+    for(size_t i = 0; i < StereoChannels::kNumChannels; ++i) memset(out[i], 0, length * sizeof(float32_t));
+
+    mixer->setInputSampleBuffer(0, in);
+    INSPECT(mixer, normalizedValueInspector);
+
+    mixer->process(
+        out[StereoChannels::Left ],
+        out[StereoChannels::Right]
+    );
+    INSPECT(mixer, normalizedValueInspector);
+
+    delete mixer;
+}
+
 TEST(MixingConsole, SimpleProcessing)
 {
     const unsigned nbRepeats = 4;