From 3959664a0f37cde2f95e09f9b3bb0f1ae79b7c36 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Thu, 18 Sep 2025 19:39:17 -0500 Subject: [PATCH 1/7] Fix multiplicative impl --- src/utilities/smoothed_value.h | 112 +++++++- tests/utilities/smoothed_value_test.cpp | 326 +++++++++++++++++++++--- 2 files changed, 400 insertions(+), 38 deletions(-) diff --git a/src/utilities/smoothed_value.h b/src/utilities/smoothed_value.h index bbc2b1b..338660c 100644 --- a/src/utilities/smoothed_value.h +++ b/src/utilities/smoothed_value.h @@ -1,9 +1,19 @@ #pragma once +#include #include "arithmetic.h" namespace neuron { - class SmoothedValue { + enum SmoothingType { + Linear, + Multiplicative, + }; + + template + class SmoothedValue; + + template<> + class SmoothedValue { public: SmoothedValue() : m_currentValue(0.0f), m_targetValue(0.0f) { @@ -15,8 +25,6 @@ namespace neuron { UpdateIncrement(); } - ~SmoothedValue() = default; - void Reset(double sampleRate, double rampLengthMillis) { if (sampleRate > 0.0 && rampLengthMillis >= 0.0) { @@ -37,13 +45,14 @@ namespace neuron { if (isApproximatelyEqual(m_currentValue, m_targetValue)) { m_currentValue = m_targetValue; return m_currentValue; - } else { - m_currentValue += m_increment; - if ((m_increment > 0.0f && m_currentValue > m_targetValue) || (m_increment < 0.0f && m_currentValue < m_targetValue)) { - m_currentValue = m_targetValue; - } - return m_currentValue; } + + m_currentValue += m_increment; + if ((m_increment > 0.0f && m_currentValue > m_targetValue) || (m_increment < 0.0f && m_currentValue < m_targetValue)) { + m_currentValue = m_targetValue; + } + + return m_currentValue; } void Skip(int numSamples) @@ -81,7 +90,92 @@ namespace neuron { float m_currentValue; float m_targetValue; + + float m_increment = 0.0f; + }; + + template<> + class SmoothedValue { + public: + SmoothedValue() : m_currentValue(1.0f), m_targetValue(1.0f) + { + UpdateIncrement(); + } + + SmoothedValue(float initialValue) : m_currentValue(initialValue), m_targetValue(initialValue) + { + UpdateIncrement(); + } + + void Reset(double sampleRate, double rampLengthMillis) + { + if (sampleRate > 0.0 && rampLengthMillis >= 0.0) { + m_sampleRate = sampleRate; + m_rampLengthMillis = rampLengthMillis; + UpdateIncrement(); + } + } + + void SetTargetValue(float value) noexcept + { + m_targetValue = value; + UpdateIncrement(); + } + + float GetNextValue() noexcept + { + if (isApproximatelyEqual(m_currentValue, m_targetValue)) { + m_currentValue = m_targetValue; + return m_currentValue; + } + + m_currentValue *= std::exp(m_increment); + if ((m_increment > 0.0f && m_currentValue > m_targetValue) || + (m_increment < 0.0f && m_currentValue < m_targetValue)) { + m_currentValue = m_targetValue; + } + + return m_currentValue; + } + + void Skip(int numSamples) + { + if (isApproximatelyEqual(m_currentValue, m_targetValue)) { + m_currentValue = m_targetValue; + return; + } + + m_currentValue *= std::exp(m_increment * numSamples); + } + + private: + static constexpr float INV_1000 = 1.0f / 1000.0f; + + void UpdateIncrement() noexcept + { + if (m_rampLengthMillis <= 0.0) { + m_currentValue = m_targetValue; + m_increment = 0.0f; + return; + } + + float numSamplesBetweenValues = static_cast(m_rampLengthMillis * m_sampleRate) * INV_1000; + if (m_currentValue > 0.0f && m_targetValue > 0.0f) { + m_increment = std::log(m_targetValue / m_currentValue) / numSamplesBetweenValues; + } else { + m_increment = 0.0f; + } + } + + double m_sampleRate = 44100.0; + double m_rampLengthMillis = 50; + + float m_currentValue; + float m_targetValue; + float m_increment = 0.0f; }; + using LinearSmoothedValue = SmoothedValue; + using MultiplicativeSmoothedValue = SmoothedValue; } diff --git a/tests/utilities/smoothed_value_test.cpp b/tests/utilities/smoothed_value_test.cpp index e9624c8..3743774 100644 --- a/tests/utilities/smoothed_value_test.cpp +++ b/tests/utilities/smoothed_value_test.cpp @@ -4,7 +4,7 @@ using namespace neuron; -class SmoothedValueTest : public ::testing::Test { +class LinearSmoothedValueTest : public ::testing::Test { protected: void SetUp() override { // Default test parameters @@ -21,22 +21,41 @@ class SmoothedValueTest : public ::testing::Test { double rampLengthMs; }; +class MultiplicativeSmoothedValueTest : public ::testing::Test { +protected: + void SetUp() override { + // Default test parameters + sampleRate = 44100.0; + rampLengthMs = 100.0; // 100ms ramp + } + + // Helper function for floating point comparisons + bool IsApproximatelyEqual(float a, float b, float tolerance = 1e-6f) { + return std::abs(a - b) < tolerance; + } + + double sampleRate; + double rampLengthMs; +}; + +// LINEAR ============================================================================================================= + // Test default constructor -TEST_F(SmoothedValueTest, DefaultConstructor) { - SmoothedValue sv; +TEST_F(LinearSmoothedValueTest, DefaultConstructor) { + LinearSmoothedValue sv; EXPECT_FLOAT_EQ(sv.GetNextValue(), 0.0f); } // Test constructor with initial value -TEST_F(SmoothedValueTest, ConstructorWithInitialValue) { +TEST_F(LinearSmoothedValueTest, ConstructorWithInitialValue) { const float initialValue = 5.0f; - SmoothedValue sv(initialValue); + LinearSmoothedValue sv(initialValue); EXPECT_FLOAT_EQ(sv.GetNextValue(), initialValue); } // Test Reset with valid parameters -TEST_F(SmoothedValueTest, ResetWithValidParameters) { - SmoothedValue sv(1.0f); +TEST_F(LinearSmoothedValueTest, ResetWithValidParameters) { + LinearSmoothedValue sv(1.0f); sv.Reset(sampleRate, rampLengthMs); EXPECT_FLOAT_EQ(sv.GetNextValue(), 1.0f); @@ -48,8 +67,8 @@ TEST_F(SmoothedValueTest, ResetWithValidParameters) { } // Test Reset with invalid parameters -TEST_F(SmoothedValueTest, ResetWithInvalidParameters) { - SmoothedValue sv(1.0f); +TEST_F(LinearSmoothedValueTest, ResetWithInvalidParameters) { + LinearSmoothedValue sv(1.0f); sv.SetTargetValue(2.0f); // Store the state before any reset attempts @@ -69,8 +88,8 @@ TEST_F(SmoothedValueTest, ResetWithInvalidParameters) { } // Test SetTargetValue -TEST_F(SmoothedValueTest, SetTargetValue) { - SmoothedValue sv(0.0f); +TEST_F(LinearSmoothedValueTest, SetTargetValue) { + LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(10.0f); @@ -84,8 +103,8 @@ TEST_F(SmoothedValueTest, SetTargetValue) { } // Test GetNextValue reaches target eventually -TEST_F(SmoothedValueTest, GetNextValueReachesTarget) { - SmoothedValue sv(0.0f); +TEST_F(LinearSmoothedValueTest, GetNextValueReachesTarget) { + LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 50.0); sv.SetTargetValue(1.0f); @@ -100,8 +119,8 @@ TEST_F(SmoothedValueTest, GetNextValueReachesTarget) { } // Test smoothing with negative values -TEST_F(SmoothedValueTest, SmoothingWithNegativeValues) { - SmoothedValue sv(5.0f); +TEST_F(LinearSmoothedValueTest, SmoothingWithNegativeValues) { + LinearSmoothedValue sv(5.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(-5.0f); @@ -114,9 +133,9 @@ TEST_F(SmoothedValueTest, SmoothingWithNegativeValues) { } // Test Skip functionality -TEST_F(SmoothedValueTest, SkipSamples) { - SmoothedValue sv1(0.0f); - SmoothedValue sv2(0.0f); +TEST_F(LinearSmoothedValueTest, SkipSamples) { + LinearSmoothedValue sv1(0.0f); + LinearSmoothedValue sv2(0.0f); sv1.Reset(sampleRate, rampLengthMs); sv2.Reset(sampleRate, rampLengthMs); @@ -137,8 +156,8 @@ TEST_F(SmoothedValueTest, SkipSamples) { } // Test when ramp length is zero -TEST_F(SmoothedValueTest, ZeroRampLength) { - SmoothedValue sv(1.0f); +TEST_F(LinearSmoothedValueTest, ZeroRampLength) { + LinearSmoothedValue sv(1.0f); sv.Reset(sampleRate, 0.0); sv.SetTargetValue(5.0f); @@ -146,8 +165,8 @@ TEST_F(SmoothedValueTest, ZeroRampLength) { } // Test very short ramp length -TEST_F(SmoothedValueTest, VeryShortRampLength) { - SmoothedValue sv(0.0f); +TEST_F(LinearSmoothedValueTest, VeryShortRampLength) { + LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 0.1); sv.SetTargetValue(1.0f); @@ -160,8 +179,8 @@ TEST_F(SmoothedValueTest, VeryShortRampLength) { } // Test multiple target changes -TEST_F(SmoothedValueTest, MultipleTargetChanges) { - SmoothedValue sv(0.0f); +TEST_F(LinearSmoothedValueTest, MultipleTargetChanges) { + LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 50.0); sv.SetTargetValue(10.0f); @@ -182,8 +201,8 @@ TEST_F(SmoothedValueTest, MultipleTargetChanges) { } // Test same target value -TEST_F(SmoothedValueTest, SameTargetValue) { - SmoothedValue sv(5.0f); +TEST_F(LinearSmoothedValueTest, SameTargetValue) { + LinearSmoothedValue sv(5.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(5.0f); @@ -192,8 +211,8 @@ TEST_F(SmoothedValueTest, SameTargetValue) { } // Test large sample rate -TEST_F(SmoothedValueTest, LargeSampleRate) { - SmoothedValue sv(0.0f); +TEST_F(LinearSmoothedValueTest, LargeSampleRate) { + LinearSmoothedValue sv(0.0f); sv.Reset(192000.0, 100.0); sv.SetTargetValue(1.0f); @@ -203,4 +222,253 @@ TEST_F(SmoothedValueTest, LargeSampleRate) { EXPECT_GT(value1, 0.0f); EXPECT_GT(value2, value1); EXPECT_LT(value1, 0.1f); -} \ No newline at end of file +} + +// MULTIPLICATIVE ===================================================================================================== + +// Test constructor with initial value (multiplicative can't start from zero) +TEST_F(MultiplicativeSmoothedValueTest, ConstructorWithInitialValue) { + const float initialValue = 5.0f; + MultiplicativeSmoothedValue sv(initialValue); + EXPECT_FLOAT_EQ(sv.GetNextValue(), initialValue); +} + +// Test basic multiplicative behavior - exponential curve +TEST_F(MultiplicativeSmoothedValueTest, ExponentialCurve) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(sampleRate, 100.0); // 100ms ramp + sv.SetTargetValue(8.0f); // 3 octaves (2^3 = 8) + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + float value3 = sv.GetNextValue(); + + // For multiplicative smoothing, the ratio between consecutive values should be approximately constant + float ratio1 = value2 / value1; + float ratio2 = value3 / value2; + + EXPECT_GT(value1, 1.0f); + EXPECT_GT(value2, value1); + EXPECT_GT(value3, value2); + EXPECT_TRUE(IsApproximatelyEqual(ratio1, ratio2, 1e-4f)); +} + +// Test frequency doubling (octave) - with more realistic tolerance +TEST_F(MultiplicativeSmoothedValueTest, FrequencyOctave) { + MultiplicativeSmoothedValue sv(440.0f); // A4 + sv.Reset(sampleRate, 50.0); + sv.SetTargetValue(880.0f); // A5 (one octave up) + + // Check that we get exponential progression + float prevValue = 440.0f; + for (int i = 0; i < 10; ++i) { + float currentValue = sv.GetNextValue(); + EXPECT_GT(currentValue, prevValue); + EXPECT_LT(currentValue, 880.0f); + prevValue = currentValue; + } + + // Eventually gets close to target - use more relaxed tolerance + for (int i = 0; i < 5000; ++i) { // More samples to ensure convergence + sv.GetNextValue(); + } + float finalValue = sv.GetNextValue(); + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 0.01f)); // 1% tolerance +} + +// Test dB conversion - another common audio use case +TEST_F(MultiplicativeSmoothedValueTest, DecibelConversion) { + MultiplicativeSmoothedValue sv(1.0f); // 0 dB + sv.Reset(sampleRate, 100.0); + sv.SetTargetValue(3.16228f); // Approximately 10 dB (10^(10/20)) + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + EXPECT_GT(value1, 1.0f); + EXPECT_GT(value2, value1); + EXPECT_LT(value2, 3.16228f); +} + +// Test zero handling - multiplicative can't reach zero +TEST_F(MultiplicativeSmoothedValueTest, ZeroHandling) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(sampleRate, rampLengthMs); + sv.SetTargetValue(0.0f); // Invalid target for multiplicative + + // Should not progress since target is zero + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + EXPECT_FLOAT_EQ(value1, 1.0f); // Should remain at current value + EXPECT_FLOAT_EQ(value2, 1.0f); +} + +// Test starting from zero - should handle gracefully +TEST_F(MultiplicativeSmoothedValueTest, StartingFromZero) { + MultiplicativeSmoothedValue sv(0.0f); + sv.Reset(sampleRate, rampLengthMs); + sv.SetTargetValue(10.0f); + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + // Should not progress since current value is zero + EXPECT_FLOAT_EQ(value1, 0.0f); + EXPECT_FLOAT_EQ(value2, 0.0f); +} + +// Test SetTargetValue +TEST_F(MultiplicativeSmoothedValueTest, SetTargetValue) { + MultiplicativeSmoothedValue sv(2.0f); + sv.Reset(sampleRate, rampLengthMs); + sv.SetTargetValue(32.0f); // 4 octaves (2^4 * 2 = 32) + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + EXPECT_GT(value1, 2.0f); + EXPECT_GT(value2, value1); + EXPECT_LT(value2, 32.0f); +} + +// Test GetNextValue gets close to target +TEST_F(MultiplicativeSmoothedValueTest, GetNextValueReachesTarget) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(sampleRate, 50.0); + sv.SetTargetValue(4.0f); + + float lastValue = 1.0f; + for (int i = 0; i < 5000; ++i) { // More samples + lastValue = sv.GetNextValue(); + } + + // Use percentage-based tolerance for multiplicative + EXPECT_TRUE(IsApproximatelyEqual(lastValue, 4.0f, 0.01f)); // 1% tolerance +} + +// Test Skip functionality +TEST_F(MultiplicativeSmoothedValueTest, SkipSamples) { + MultiplicativeSmoothedValue sv1(1.0f); + MultiplicativeSmoothedValue sv2(1.0f); + + sv1.Reset(sampleRate, rampLengthMs); + sv2.Reset(sampleRate, rampLengthMs); + + sv1.SetTargetValue(16.0f); + sv2.SetTargetValue(16.0f); + + for (int i = 0; i < 100; ++i) { + sv1.GetNextValue(); + } + + sv2.Skip(100); + + float value1 = sv1.GetNextValue(); + float value2 = sv2.GetNextValue(); + + EXPECT_TRUE(IsApproximatelyEqual(value1, value2, 1e-4f)); +} + +// Test when ramp length is zero +TEST_F(MultiplicativeSmoothedValueTest, ZeroRampLength) { + MultiplicativeSmoothedValue sv(2.0f); + sv.Reset(sampleRate, 0.0); + sv.SetTargetValue(8.0f); + + EXPECT_FLOAT_EQ(sv.GetNextValue(), 8.0f); +} + +// Test very short ramp length - adjust expectations +TEST_F(MultiplicativeSmoothedValueTest, VeryShortRampLength) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(sampleRate, 0.1); // Very short ramp + sv.SetTargetValue(2.0f); + + float value = 1.0f; + for (int i = 0; i < 20; ++i) { // More iterations for very short ramp + value = sv.GetNextValue(); + } + + // For very short ramps, expect to get reasonably close + EXPECT_TRUE(IsApproximatelyEqual(value, 2.0f, 0.05f)); // 5% tolerance +} + +// Test multiple target changes - with realistic tolerances +TEST_F(MultiplicativeSmoothedValueTest, MultipleTargetChanges) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(sampleRate, 50.0); + + sv.SetTargetValue(4.0f); + for (int i = 0; i < 100; ++i) { + sv.GetNextValue(); + } + + float valueBeforeChange = sv.GetNextValue(); + sv.SetTargetValue(0.5f); // Going down + float valueAfterChange = sv.GetNextValue(); + + EXPECT_LT(valueAfterChange, valueBeforeChange); // Should start decreasing + + for (int i = 0; i < 5000; ++i) { + sv.GetNextValue(); + } + float finalValue = sv.GetNextValue(); + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 0.5f, 0.01f)); // 1% tolerance +} + +// Test same target value +TEST_F(MultiplicativeSmoothedValueTest, SameTargetValue) { + MultiplicativeSmoothedValue sv(5.0f); + sv.Reset(sampleRate, rampLengthMs); + sv.SetTargetValue(5.0f); + + EXPECT_FLOAT_EQ(sv.GetNextValue(), 5.0f); + EXPECT_FLOAT_EQ(sv.GetNextValue(), 5.0f); +} + +// Test decreasing values (important for multiplicative) +TEST_F(MultiplicativeSmoothedValueTest, DecreasingValues) { + MultiplicativeSmoothedValue sv(8.0f); + sv.Reset(sampleRate, rampLengthMs); + sv.SetTargetValue(2.0f); // Decreasing + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + EXPECT_LT(value1, 8.0f); + EXPECT_LT(value2, value1); + EXPECT_GT(value2, 2.0f); +} + +// Test large sample rate +TEST_F(MultiplicativeSmoothedValueTest, LargeSampleRate) { + MultiplicativeSmoothedValue sv(1.0f); + sv.Reset(192000.0, 100.0); + sv.SetTargetValue(2.0f); + + float value1 = sv.GetNextValue(); + float value2 = sv.GetNextValue(); + + EXPECT_GT(value1, 1.0f); + EXPECT_GT(value2, value1); + EXPECT_LT(value1, 1.01f); // Should be a very small increment +} + +// Test musical interval - with more realistic expectations +TEST_F(MultiplicativeSmoothedValueTest, MusicalInterval) { + MultiplicativeSmoothedValue sv(440.0f); // A4 + sv.Reset(sampleRate, 120.0); // 120ms for 12 steps + sv.SetTargetValue(880.0f); // A5 + + // Just run for the expected duration plus some buffer + int totalSamples = static_cast((150.0 / 1000.0) * sampleRate); // 150ms buffer + for (int i = 0; i < totalSamples; ++i) { + sv.GetNextValue(); + } + + float finalValue = sv.GetNextValue(); + + // Check that we get reasonably close to 880Hz (within 1%) + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 8.8f)); // ~1% tolerance +} From 0de2ab071df7aae1bc1e36c9065a79c3ad0c5dee Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Thu, 18 Sep 2025 20:10:05 -0500 Subject: [PATCH 2/7] Update makefile for Daisy --- Makefile | 2 -- vendor/googletest | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 19613f5..deee4f0 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ filter \ UTILITY_MOD_DIR = utilities UTILITY_MODULES = \ -logger ###################################### # source @@ -41,7 +40,6 @@ CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(GENERATOR_MOD_DIR)/$(GENERATOR_ CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(MODULATOR_MOD_DIR)/$(MODULATOR_MODULES)) CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(PROCESSOR_EFFECTS_MOD_DIR)/$(PROCESSOR_EFFECTS_MODULES)) CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(PROCESSOR_FILTERS_MOD_DIR)/$(PROCESS_FILTERS_MODULES)) -CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(UTILITY_MOD_DIR)/$(UTILITY_MODULES)) ###################################### # building variables diff --git a/vendor/googletest b/vendor/googletest index 35d0c36..df1544b 160000 --- a/vendor/googletest +++ b/vendor/googletest @@ -1 +1 @@ -Subproject commit 35d0c365609296fa4730d62057c487e3cfa030ff +Subproject commit df1544bcee0c7ce35cd5ea0b3eb8cc81855a4140 From 44822b5be2530f6c3915bec987c34d5d25e3c979 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Sun, 21 Sep 2025 16:51:14 -0500 Subject: [PATCH 3/7] Use proper include dir --- CMakeLists.txt | 14 ++++--- .../neuron.h => include/neuron/core/base.h | 0 {src/audio => include/neuron/core}/context.h | 0 .../neuron/core}/parameter.h | 0 {src/audio => include/neuron/core}/sample.h | 0 .../neuron/dsp/generators}/generator.h | 2 +- .../neuron/dsp}/generators/oscillator.h | 12 +++--- {src => include/neuron/dsp}/modulators/adsr.h | 8 ++-- .../neuron/dsp/modulators}/modulator.h | 0 .../neuron/dsp/processors}/filter.h | 10 ++--- .../neuron/dsp/processors}/processor.h | 2 +- .../neuron/dsp/processors}/saturator.h | 8 ++-- .../neuron/dsp/processors}/wavefolder.h | 6 +-- include/neuron/neuron.h | 34 +++++++++++++++ .../neuron/utils}/arithmetic.h | 0 .../utilities => include/neuron/utils}/midi.h | 2 +- .../neuron/utils}/smoothed_value.h | 3 +- .../audio => include/neuron/utils}/waveform.h | 4 +- scripts/format.sh | 7 ++++ src/{ => dsp}/generators/oscillator.cpp | 4 +- src/{ => dsp}/modulators/adsr.cpp | 2 +- .../filters => dsp/processors}/filter.cpp | 4 +- .../effects => dsp/processors}/saturator.cpp | 4 +- .../effects => dsp/processors}/wavefolder.cpp | 4 +- src/neuron.h | 41 ------------------- 25 files changed, 87 insertions(+), 84 deletions(-) rename src/abstractions/neuron.h => include/neuron/core/base.h (100%) rename {src/audio => include/neuron/core}/context.h (100%) rename {src/abstractions => include/neuron/core}/parameter.h (100%) rename {src/audio => include/neuron/core}/sample.h (100%) rename {src/abstractions => include/neuron/dsp/generators}/generator.h (94%) rename {src => include/neuron/dsp}/generators/oscillator.h (91%) rename {src => include/neuron/dsp}/modulators/adsr.h (95%) rename {src/abstractions => include/neuron/dsp/modulators}/modulator.h (100%) rename {src/processors/filters => include/neuron/dsp/processors}/filter.h (89%) rename {src/abstractions => include/neuron/dsp/processors}/processor.h (94%) rename {src/processors/effects => include/neuron/dsp/processors}/saturator.h (92%) rename {src/processors/effects => include/neuron/dsp/processors}/wavefolder.h (94%) create mode 100644 include/neuron/neuron.h rename {src/utilities => include/neuron/utils}/arithmetic.h (100%) rename {src/utilities => include/neuron/utils}/midi.h (91%) rename {src/utilities => include/neuron/utils}/smoothed_value.h (99%) rename {src/audio => include/neuron/utils}/waveform.h (93%) rename src/{ => dsp}/generators/oscillator.cpp (98%) rename src/{ => dsp}/modulators/adsr.cpp (98%) rename src/{processors/filters => dsp/processors}/filter.cpp (93%) rename src/{processors/effects => dsp/processors}/saturator.cpp (92%) rename src/{processors/effects => dsp/processors}/wavefolder.cpp (94%) delete mode 100644 src/neuron.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fb84f5..813cea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,6 @@ option(NEO_BUILD_TESTS "Build unit tests" OFF) project(neuron VERSION 0.1.0 LANGUAGES CXX) -file(GLOB_RECURSE LIST_DIRECTORIES INCLUDE_DIRS "src/*") file(GLOB_RECURSE SRC_FILES "src/*.cpp") add_library(neuron STATIC ${SRC_FILES}) @@ -25,12 +24,17 @@ else() CXX_STANDARD_REQUIRED) endif () +target_include_directories(neuron + PUBLIC + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src) + if (NEO_BUILD_TESTS) function(add_neuron_test name src) add_executable("${name}_test_exe" ${src}) - target_include_directories("${name}_test_exe" PRIVATE ${INCLUDE_DIRS}) - target_link_libraries("${name}_test_exe" neuron) - target_link_libraries("${name}_test_exe" gtest gtest_main) + target_link_libraries("${name}_test_exe" PRIVATE neuron gtest gtest_main) add_test(NAME "${name}_test" COMMAND "${name}_test_exe") endfunction() @@ -53,5 +57,3 @@ if (NEO_BUILD_TESTS) enable_testing() endif () - -target_include_directories(neuron PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src PRIVATE ${INCLUDE_DIRS}) diff --git a/src/abstractions/neuron.h b/include/neuron/core/base.h similarity index 100% rename from src/abstractions/neuron.h rename to include/neuron/core/base.h diff --git a/src/audio/context.h b/include/neuron/core/context.h similarity index 100% rename from src/audio/context.h rename to include/neuron/core/context.h diff --git a/src/abstractions/parameter.h b/include/neuron/core/parameter.h similarity index 100% rename from src/abstractions/parameter.h rename to include/neuron/core/parameter.h diff --git a/src/audio/sample.h b/include/neuron/core/sample.h similarity index 100% rename from src/audio/sample.h rename to include/neuron/core/sample.h diff --git a/src/abstractions/generator.h b/include/neuron/dsp/generators/generator.h similarity index 94% rename from src/abstractions/generator.h rename to include/neuron/dsp/generators/generator.h index e0629a3..aa6b9c7 100644 --- a/src/abstractions/generator.h +++ b/include/neuron/dsp/generators/generator.h @@ -1,6 +1,6 @@ #pragma once -#include "audio/sample.h" +#include "neuron/core/sample.h" namespace neuron { diff --git a/src/generators/oscillator.h b/include/neuron/dsp/generators/oscillator.h similarity index 91% rename from src/generators/oscillator.h rename to include/neuron/dsp/generators/oscillator.h index 02d13c6..0307e26 100644 --- a/src/generators/oscillator.h +++ b/include/neuron/dsp/generators/oscillator.h @@ -1,11 +1,11 @@ #pragma once -#include "abstractions/generator.h" -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "audio/context.h" -#include "audio/waveform.h" -#include "utilities/arithmetic.h" +#include "neuron/core/base.h" +#include "neuron/core/context.h" +#include "neuron/core/parameter.h" +#include "neuron/dsp/generators/generator.h" +#include "neuron/utils/arithmetic.h" +#include "neuron/utils/waveform.h" namespace neuron { diff --git a/src/modulators/adsr.h b/include/neuron/dsp/modulators/adsr.h similarity index 95% rename from src/modulators/adsr.h rename to include/neuron/dsp/modulators/adsr.h index 9a52455..1cc7493 100644 --- a/src/modulators/adsr.h +++ b/include/neuron/dsp/modulators/adsr.h @@ -1,9 +1,9 @@ #pragma once -#include "abstractions/modulator.h" -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "audio/context.h" +#include "neuron/core/base.h" +#include "neuron/core/context.h" +#include "neuron/core/parameter.h" +#include "neuron/dsp/modulators/modulator.h" namespace neuron { diff --git a/src/abstractions/modulator.h b/include/neuron/dsp/modulators/modulator.h similarity index 100% rename from src/abstractions/modulator.h rename to include/neuron/dsp/modulators/modulator.h diff --git a/src/processors/filters/filter.h b/include/neuron/dsp/processors/filter.h similarity index 89% rename from src/processors/filters/filter.h rename to include/neuron/dsp/processors/filter.h index 6e8d00c..ac61a77 100644 --- a/src/processors/filters/filter.h +++ b/include/neuron/dsp/processors/filter.h @@ -1,10 +1,10 @@ #pragma once -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "abstractions/processor.h" -#include "audio/context.h" -#include "audio/sample.h" +#include "neuron/core/base.h" +#include "neuron/core/context.h" +#include "neuron/core/parameter.h" +#include "neuron/core/sample.h" +#include "neuron/dsp/processors/processor.h" namespace neuron { diff --git a/src/abstractions/processor.h b/include/neuron/dsp/processors/processor.h similarity index 94% rename from src/abstractions/processor.h rename to include/neuron/dsp/processors/processor.h index 45dab46..6596c24 100644 --- a/src/abstractions/processor.h +++ b/include/neuron/dsp/processors/processor.h @@ -1,6 +1,6 @@ #pragma once -#include "audio/sample.h" +#include "neuron/core/sample.h" namespace neuron { diff --git a/src/processors/effects/saturator.h b/include/neuron/dsp/processors/saturator.h similarity index 92% rename from src/processors/effects/saturator.h rename to include/neuron/dsp/processors/saturator.h index 2adfb07..cd5f5fc 100644 --- a/src/processors/effects/saturator.h +++ b/include/neuron/dsp/processors/saturator.h @@ -1,9 +1,9 @@ #pragma once -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "abstractions/processor.h" -#include "audio/sample.h" +#include "neuron/core/base.h" +#include "neuron/core/parameter.h" +#include "neuron/core/sample.h" +#include "neuron/dsp/processors/processor.h" namespace neuron { diff --git a/src/processors/effects/wavefolder.h b/include/neuron/dsp/processors/wavefolder.h similarity index 94% rename from src/processors/effects/wavefolder.h rename to include/neuron/dsp/processors/wavefolder.h index 5069728..d9cb0bd 100644 --- a/src/processors/effects/wavefolder.h +++ b/include/neuron/dsp/processors/wavefolder.h @@ -1,8 +1,8 @@ #pragma once -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "abstractions/processor.h" +#include "neuron/core/base.h" +#include "neuron/core/parameter.h" +#include "neuron/dsp/processors/processor.h" namespace neuron { diff --git a/include/neuron/neuron.h b/include/neuron/neuron.h new file mode 100644 index 0000000..5ba5bc7 --- /dev/null +++ b/include/neuron/neuron.h @@ -0,0 +1,34 @@ +/** +* Neuron is a lightweight audio DSP library intended for use + * in any relevant application e.g. Electrosmith Daisy patches, + * JUCE plugins, VCV Rack modules. + * + * Author: Matthew Maxwell, 2024 + */ +#pragma once + +#ifndef NEURON_LIB_H +#define NEURON_LIB_H + +// CORE +#include "neuron/core/base.h" +#include "neuron/core/context.h" +#include "neuron/core/parameter.h" +#include "neuron/core/sample.h" + +// DSP (Generators) +#include "neuron/dsp/generators/generator.h" + +// DSP (Modulators) +#include "neuron/dsp/modulators/modulator.h" + +// DSP (Processors) +#include "neuron/dsp/processors/processor.h" + +// UTILS +#include "neuron/utils/arithmetic.h" +#include "neuron/utils/midi.h" +#include "neuron/utils/smoothed_value.h" +#include "neuron/utils/waveform.h" + +#endif diff --git a/src/utilities/arithmetic.h b/include/neuron/utils/arithmetic.h similarity index 100% rename from src/utilities/arithmetic.h rename to include/neuron/utils/arithmetic.h diff --git a/src/utilities/midi.h b/include/neuron/utils/midi.h similarity index 91% rename from src/utilities/midi.h rename to include/neuron/utils/midi.h index c798590..82004c1 100644 --- a/src/utilities/midi.h +++ b/include/neuron/utils/midi.h @@ -1,6 +1,6 @@ #pragma once -#include "utilities/arithmetic.h" +#include "neuron/utils/arithmetic.h" namespace neuron { diff --git a/src/utilities/smoothed_value.h b/include/neuron/utils/smoothed_value.h similarity index 99% rename from src/utilities/smoothed_value.h rename to include/neuron/utils/smoothed_value.h index 338660c..dd9b715 100644 --- a/src/utilities/smoothed_value.h +++ b/include/neuron/utils/smoothed_value.h @@ -1,7 +1,8 @@ #pragma once +#include "neuron/utils/arithmetic.h" + #include -#include "arithmetic.h" namespace neuron { enum SmoothingType { diff --git a/src/audio/waveform.h b/include/neuron/utils/waveform.h similarity index 93% rename from src/audio/waveform.h rename to include/neuron/utils/waveform.h index f0cf428..2177c2f 100644 --- a/src/audio/waveform.h +++ b/include/neuron/utils/waveform.h @@ -1,7 +1,7 @@ #pragma once -#include "audio/sample.h" -#include "utilities/arithmetic.h" +#include "neuron/utils/arithmetic.h" +#include "neuron/core/sample.h" namespace neuron { diff --git a/scripts/format.sh b/scripts/format.sh index d5b4338..d518e56 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -1,6 +1,13 @@ #!/bin/bash printf "Formatting code...\n" + +find include/ -iname '*.h' -o | xargs clang-format -i -style=file +if [ $? -ne 0 ]; then + printf "Failed to format source code\n" + exit 1 +fi + find src/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i -style=file if [ $? -ne 0 ]; then printf "Failed to format source code\n" diff --git a/src/generators/oscillator.cpp b/src/dsp/generators/oscillator.cpp similarity index 98% rename from src/generators/oscillator.cpp rename to src/dsp/generators/oscillator.cpp index d5769e2..25f1d04 100644 --- a/src/generators/oscillator.cpp +++ b/src/dsp/generators/oscillator.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/dsp/generators/oscillator.h" -#include "generators/oscillator.h" +#include using namespace neuron; diff --git a/src/modulators/adsr.cpp b/src/dsp/modulators/adsr.cpp similarity index 98% rename from src/modulators/adsr.cpp rename to src/dsp/modulators/adsr.cpp index 6adb3b5..9921aab 100644 --- a/src/modulators/adsr.cpp +++ b/src/dsp/modulators/adsr.cpp @@ -1,4 +1,4 @@ -#include "modulators/adsr.h" +#include "neuron/dsp/modulators/adsr.h" using namespace neuron; diff --git a/src/processors/filters/filter.cpp b/src/dsp/processors/filter.cpp similarity index 93% rename from src/processors/filters/filter.cpp rename to src/dsp/processors/filter.cpp index 4859c09..5d7a3db 100644 --- a/src/processors/filters/filter.cpp +++ b/src/dsp/processors/filter.cpp @@ -1,5 +1,5 @@ -#include "processors/filters/filter.h" -#include "utilities/arithmetic.h" +#include "neuron/dsp/processors/filter.h" +#include "neuron/utils/arithmetic.h" using namespace neuron; diff --git a/src/processors/effects/saturator.cpp b/src/dsp/processors/saturator.cpp similarity index 92% rename from src/processors/effects/saturator.cpp rename to src/dsp/processors/saturator.cpp index a3b8ed3..57ee3c1 100644 --- a/src/processors/effects/saturator.cpp +++ b/src/dsp/processors/saturator.cpp @@ -1,5 +1,5 @@ -#include "processors/effects/saturator.h" -#include "utilities/arithmetic.h" +#include "neuron/dsp/processors/saturator.h" +#include "neuron/utils/arithmetic.h" using namespace neuron; diff --git a/src/processors/effects/wavefolder.cpp b/src/dsp/processors/wavefolder.cpp similarity index 94% rename from src/processors/effects/wavefolder.cpp rename to src/dsp/processors/wavefolder.cpp index 1046417..88ae1d7 100644 --- a/src/processors/effects/wavefolder.cpp +++ b/src/dsp/processors/wavefolder.cpp @@ -1,5 +1,5 @@ -#include "processors/effects/wavefolder.h" -#include "utilities/arithmetic.h" +#include "neuron/dsp/processors/wavefolder.h" +#include "neuron/utils/arithmetic.h" using namespace neuron; diff --git a/src/neuron.h b/src/neuron.h deleted file mode 100644 index b53261c..0000000 --- a/src/neuron.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Neuron is a lightweight audio DSP library intended for use - * in any relevant application e.g. Electrosmith Daisy patches, - * JUCE plugins, VCV Rack modules. - * - * Author: Matthew Maxwell, 2024 - */ -#pragma once - -#ifndef NEURON_LIB_H -#define NEURON_LIB_H - -// ABSTRACTIONS -#include "abstractions/generator.h" -#include "abstractions/modulator.h" -#include "abstractions/neuron.h" -#include "abstractions/parameter.h" -#include "abstractions/processor.h" - -// AUDIO -#include "audio/context.h" -#include "audio/sample.h" -#include "audio/waveform.h" - -// GENERATORS -#include "generators/oscillator.h" - -// MODULATORS -#include "modulators/adsr.h" - -// PROCESSORS -#include "processors/effects/saturator.h" -#include "processors/effects/wavefolder.h" -#include "processors/filters/filter.h" - -// UTILITIES -#include "utilities/arithmetic.h" -#include "utilities/midi.h" -#include "utilities/smoothed_value.h" - -#endif From dad1e61c965e50ff4cd0cdf0355381e0e8ed714c Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Sun, 21 Sep 2025 16:51:33 -0500 Subject: [PATCH 4/7] Format code --- include/neuron/utils/arithmetic.h | 2 +- include/neuron/utils/smoothed_value.h | 21 ++-- include/neuron/utils/waveform.h | 2 +- scripts/format.sh | 2 +- tests/utilities/arithmetic_test.cpp | 40 +++--- tests/utilities/smoothed_value_test.cpp | 159 ++++++++++++++---------- 6 files changed, 133 insertions(+), 93 deletions(-) diff --git a/include/neuron/utils/arithmetic.h b/include/neuron/utils/arithmetic.h index 7415fc3..bb0cbb9 100644 --- a/include/neuron/utils/arithmetic.h +++ b/include/neuron/utils/arithmetic.h @@ -39,7 +39,7 @@ namespace neuron { template struct Epsilon { - static constexpr T value = T{1e-5}; + static constexpr T value = T { 1e-5 }; }; template<> diff --git a/include/neuron/utils/smoothed_value.h b/include/neuron/utils/smoothed_value.h index dd9b715..2e9d55e 100644 --- a/include/neuron/utils/smoothed_value.h +++ b/include/neuron/utils/smoothed_value.h @@ -16,12 +16,16 @@ namespace neuron { template<> class SmoothedValue { public: - SmoothedValue() : m_currentValue(0.0f), m_targetValue(0.0f) + SmoothedValue() + : m_currentValue(0.0f) + , m_targetValue(0.0f) { UpdateIncrement(); } - SmoothedValue(float initialValue) : m_currentValue(initialValue), m_targetValue(initialValue) + SmoothedValue(float initialValue) + : m_currentValue(initialValue) + , m_targetValue(initialValue) { UpdateIncrement(); } @@ -98,12 +102,16 @@ namespace neuron { template<> class SmoothedValue { public: - SmoothedValue() : m_currentValue(1.0f), m_targetValue(1.0f) + SmoothedValue() + : m_currentValue(1.0f) + , m_targetValue(1.0f) { UpdateIncrement(); } - SmoothedValue(float initialValue) : m_currentValue(initialValue), m_targetValue(initialValue) + SmoothedValue(float initialValue) + : m_currentValue(initialValue) + , m_targetValue(initialValue) { UpdateIncrement(); } @@ -131,9 +139,8 @@ namespace neuron { } m_currentValue *= std::exp(m_increment); - if ((m_increment > 0.0f && m_currentValue > m_targetValue) || - (m_increment < 0.0f && m_currentValue < m_targetValue)) { - m_currentValue = m_targetValue; + if ((m_increment > 0.0f && m_currentValue > m_targetValue) || (m_increment < 0.0f && m_currentValue < m_targetValue)) { + m_currentValue = m_targetValue; } return m_currentValue; diff --git a/include/neuron/utils/waveform.h b/include/neuron/utils/waveform.h index 2177c2f..5d76e3d 100644 --- a/include/neuron/utils/waveform.h +++ b/include/neuron/utils/waveform.h @@ -1,7 +1,7 @@ #pragma once -#include "neuron/utils/arithmetic.h" #include "neuron/core/sample.h" +#include "neuron/utils/arithmetic.h" namespace neuron { diff --git a/scripts/format.sh b/scripts/format.sh index d518e56..244c151 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -2,7 +2,7 @@ printf "Formatting code...\n" -find include/ -iname '*.h' -o | xargs clang-format -i -style=file +find include/ -iname '*.h' | xargs clang-format -i -style=file if [ $? -ne 0 ]; then printf "Failed to format source code\n" exit 1 diff --git a/tests/utilities/arithmetic_test.cpp b/tests/utilities/arithmetic_test.cpp index 24154db..db1157d 100644 --- a/tests/utilities/arithmetic_test.cpp +++ b/tests/utilities/arithmetic_test.cpp @@ -77,23 +77,23 @@ TEST(arithmetic_suite, isApproximatelyEqual_test) EXPECT_TRUE(isApproximatelyEqual(-3, -3)); // Test values well within default relative epsilon for float (1e-5f) - EXPECT_TRUE(isApproximatelyEqual(1.0f, 1.0f + 1e-6f)); // Well within 1e-5f * 1.0f + EXPECT_TRUE(isApproximatelyEqual(1.0f, 1.0f + 1e-6f)); // Well within 1e-5f * 1.0f EXPECT_TRUE(isApproximatelyEqual(1.0f, 1.0f - 1e-6f)); - EXPECT_TRUE(isApproximatelyEqual(10.0f, 10.0f + 5e-5f)); // Well within 1e-5f * 10.0f = 1e-4f + EXPECT_TRUE(isApproximatelyEqual(10.0f, 10.0f + 5e-5f)); // Well within 1e-5f * 10.0f = 1e-4f EXPECT_TRUE(isApproximatelyEqual(-1.0f, -1.0f + 1e-6f)); // Test values well within default relative epsilon for double (1e-9) - EXPECT_TRUE(isApproximatelyEqual(1.0, 1.0 + 1e-10)); // Well within 1e-9 * 1.0 + EXPECT_TRUE(isApproximatelyEqual(1.0, 1.0 + 1e-10)); // Well within 1e-9 * 1.0 EXPECT_TRUE(isApproximatelyEqual(1.0, 1.0 - 1e-10)); - EXPECT_TRUE(isApproximatelyEqual(100.0, 100.0 + 5e-8)); // Well within 1e-9 * 100.0 = 1e-7 + EXPECT_TRUE(isApproximatelyEqual(100.0, 100.0 + 5e-8)); // Well within 1e-9 * 100.0 = 1e-7 // Test values outside default relative epsilon for float - EXPECT_FALSE(isApproximatelyEqual(1.0f, 1.0f + 2e-5f)); // Exceeds 1e-5f * 1.0f + EXPECT_FALSE(isApproximatelyEqual(1.0f, 1.0f + 2e-5f)); // Exceeds 1e-5f * 1.0f EXPECT_FALSE(isApproximatelyEqual(1.0f, 1.0f - 2e-5f)); EXPECT_FALSE(isApproximatelyEqual(10.0f, 10.0f + 2e-4f)); // Exceeds 1e-5f * 10.0f // Test values outside default relative epsilon for double - EXPECT_FALSE(isApproximatelyEqual(1.0, 1.0 + 2e-9)); // Exceeds 1e-9 * 1.0 + EXPECT_FALSE(isApproximatelyEqual(1.0, 1.0 + 2e-9)); // Exceeds 1e-9 * 1.0 EXPECT_FALSE(isApproximatelyEqual(1.0, 1.0 - 2e-9)); EXPECT_FALSE(isApproximatelyEqual(100.0, 100.0 + 2e-7)); // Exceeds 1e-9 * 100.0 @@ -113,8 +113,8 @@ TEST(arithmetic_suite, isApproximatelyEqual_test) EXPECT_FALSE(isApproximatelyEqual(0, 1)); // Test with custom epsilon values - EXPECT_TRUE(isApproximatelyEqual(1.0f, 1.0f + 1e-7f, 1e-6f)); // Custom epsilon - EXPECT_FALSE(isApproximatelyEqual(1.0f, 1.0f + 1e-5f, 1e-6f)); // Exceeds custom epsilon + EXPECT_TRUE(isApproximatelyEqual(1.0f, 1.0f + 1e-7f, 1e-6f)); // Custom epsilon + EXPECT_FALSE(isApproximatelyEqual(1.0f, 1.0f + 1e-5f, 1e-6f)); // Exceeds custom epsilon // Test edge cases near zero - demonstrate relative epsilon limitations EXPECT_TRUE(isApproximatelyEqual(0.0f, 0.0f)); @@ -129,25 +129,25 @@ TEST(arithmetic_suite, isApproximatelyEqual_test) EXPECT_TRUE(std::abs(0.0f - tiny_val) <= 1e-8f); // Direct absolute comparison works // Test with small values where relative epsilon works well - float small_val = 1e-3f; // 0.001f + float small_val = 1e-3f; // 0.001f EXPECT_TRUE(isApproximatelyEqual(small_val, small_val)); - EXPECT_TRUE(isApproximatelyEqual(small_val, small_val + 5e-9f)); // Well within 1e-5f * 1e-3f = 1e-8f + EXPECT_TRUE(isApproximatelyEqual(small_val, small_val + 5e-9f)); // Well within 1e-5f * 1e-3f = 1e-8f EXPECT_FALSE(isApproximatelyEqual(small_val, small_val + 2e-8f)); // Exceeds 1e-8f // Test with large values where relative epsilon scales appropriately - float large_val = 1e6f; // 1,000,000 + float large_val = 1e6f; // 1,000,000 EXPECT_TRUE(isApproximatelyEqual(large_val, large_val)); - EXPECT_TRUE(isApproximatelyEqual(large_val, large_val + 5.0f)); // Well within 1e-5f * 1e6f = 10.0f + EXPECT_TRUE(isApproximatelyEqual(large_val, large_val + 5.0f)); // Well within 1e-5f * 1e6f = 10.0f EXPECT_FALSE(isApproximatelyEqual(large_val, large_val + 20.0f)); // Exceeds 10.0f threshold // Test audio-relevant ranges // Frequency range: 20Hz - 20kHz - EXPECT_TRUE(isApproximatelyEqual(440.0f, 440.0f + 0.002f)); // Well within 1e-5f * 440 ≈ 0.0044f - EXPECT_FALSE(isApproximatelyEqual(440.0f, 440.0f + 0.01f)); // Exceeds threshold + EXPECT_TRUE(isApproximatelyEqual(440.0f, 440.0f + 0.002f)); // Well within 1e-5f * 440 ≈ 0.0044f + EXPECT_FALSE(isApproximatelyEqual(440.0f, 440.0f + 0.01f)); // Exceeds threshold // Gain range: 0.0 - 1.0 - EXPECT_TRUE(isApproximatelyEqual(0.5f, 0.5f + 1e-6f)); // Well within 1e-5f * 0.5 = 5e-6f - EXPECT_FALSE(isApproximatelyEqual(0.5f, 0.5f + 1e-5f)); // Exceeds 5e-6f + EXPECT_TRUE(isApproximatelyEqual(0.5f, 0.5f + 1e-6f)); // Well within 1e-5f * 0.5 = 5e-6f + EXPECT_FALSE(isApproximatelyEqual(0.5f, 0.5f + 1e-5f)); // Exceeds 5e-6f // Test sign differences EXPECT_FALSE(isApproximatelyEqual(1.0f, -1.0f)); @@ -155,10 +155,10 @@ TEST(arithmetic_suite, isApproximatelyEqual_test) // Test boundary behavior around typical audio values // MIDI note velocity (0-127) - EXPECT_TRUE(isApproximatelyEqual(64.0f, 64.0f + 0.0005f)); // Well within tolerance - EXPECT_FALSE(isApproximatelyEqual(64.0f, 64.0f + 0.001f)); // Outside tolerance + EXPECT_TRUE(isApproximatelyEqual(64.0f, 64.0f + 0.0005f)); // Well within tolerance + EXPECT_FALSE(isApproximatelyEqual(64.0f, 64.0f + 0.001f)); // Outside tolerance // Sample values (-1.0 to 1.0 range) - EXPECT_TRUE(isApproximatelyEqual(0.8f, 0.8f + 5e-6f)); // Well within tolerance - EXPECT_FALSE(isApproximatelyEqual(0.8f, 0.8f + 1e-5f)); // At/outside tolerance + EXPECT_TRUE(isApproximatelyEqual(0.8f, 0.8f + 5e-6f)); // Well within tolerance + EXPECT_FALSE(isApproximatelyEqual(0.8f, 0.8f + 1e-5f)); // At/outside tolerance } diff --git a/tests/utilities/smoothed_value_test.cpp b/tests/utilities/smoothed_value_test.cpp index 3743774..e7bda7a 100644 --- a/tests/utilities/smoothed_value_test.cpp +++ b/tests/utilities/smoothed_value_test.cpp @@ -1,19 +1,21 @@ -#include #include "neuron.h" #include +#include using namespace neuron; class LinearSmoothedValueTest : public ::testing::Test { protected: - void SetUp() override { + void SetUp() override + { // Default test parameters sampleRate = 44100.0; rampLengthMs = 100.0; // 100ms ramp } // Helper function for floating point comparisons - bool IsApproximatelyEqual(float a, float b, float tolerance = 1e-6f) { + bool IsApproximatelyEqual(float a, float b, float tolerance = 1e-6f) + { return std::abs(a - b) < tolerance; } @@ -23,14 +25,16 @@ class LinearSmoothedValueTest : public ::testing::Test { class MultiplicativeSmoothedValueTest : public ::testing::Test { protected: - void SetUp() override { + void SetUp() override + { // Default test parameters sampleRate = 44100.0; rampLengthMs = 100.0; // 100ms ramp } // Helper function for floating point comparisons - bool IsApproximatelyEqual(float a, float b, float tolerance = 1e-6f) { + bool IsApproximatelyEqual(float a, float b, float tolerance = 1e-6f) + { return std::abs(a - b) < tolerance; } @@ -41,20 +45,23 @@ class MultiplicativeSmoothedValueTest : public ::testing::Test { // LINEAR ============================================================================================================= // Test default constructor -TEST_F(LinearSmoothedValueTest, DefaultConstructor) { +TEST_F(LinearSmoothedValueTest, DefaultConstructor) +{ LinearSmoothedValue sv; EXPECT_FLOAT_EQ(sv.GetNextValue(), 0.0f); } // Test constructor with initial value -TEST_F(LinearSmoothedValueTest, ConstructorWithInitialValue) { +TEST_F(LinearSmoothedValueTest, ConstructorWithInitialValue) +{ const float initialValue = 5.0f; LinearSmoothedValue sv(initialValue); EXPECT_FLOAT_EQ(sv.GetNextValue(), initialValue); } // Test Reset with valid parameters -TEST_F(LinearSmoothedValueTest, ResetWithValidParameters) { +TEST_F(LinearSmoothedValueTest, ResetWithValidParameters) +{ LinearSmoothedValue sv(1.0f); sv.Reset(sampleRate, rampLengthMs); @@ -67,7 +74,8 @@ TEST_F(LinearSmoothedValueTest, ResetWithValidParameters) { } // Test Reset with invalid parameters -TEST_F(LinearSmoothedValueTest, ResetWithInvalidParameters) { +TEST_F(LinearSmoothedValueTest, ResetWithInvalidParameters) +{ LinearSmoothedValue sv(1.0f); sv.SetTargetValue(2.0f); @@ -82,13 +90,14 @@ TEST_F(LinearSmoothedValueTest, ResetWithInvalidParameters) { float valueAfter2 = sv.GetNextValue(); // Values should continue progressing toward target - EXPECT_GT(valueAfter1, valueBefore); // Still progressing - EXPECT_GT(valueAfter2, valueAfter1); // Still progressing - EXPECT_LT(valueAfter2, 2.0f); // Haven't reached target yet + EXPECT_GT(valueAfter1, valueBefore); // Still progressing + EXPECT_GT(valueAfter2, valueAfter1); // Still progressing + EXPECT_LT(valueAfter2, 2.0f); // Haven't reached target yet } // Test SetTargetValue -TEST_F(LinearSmoothedValueTest, SetTargetValue) { +TEST_F(LinearSmoothedValueTest, SetTargetValue) +{ LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, rampLengthMs); @@ -103,7 +112,8 @@ TEST_F(LinearSmoothedValueTest, SetTargetValue) { } // Test GetNextValue reaches target eventually -TEST_F(LinearSmoothedValueTest, GetNextValueReachesTarget) { +TEST_F(LinearSmoothedValueTest, GetNextValueReachesTarget) +{ LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 50.0); sv.SetTargetValue(1.0f); @@ -119,7 +129,8 @@ TEST_F(LinearSmoothedValueTest, GetNextValueReachesTarget) { } // Test smoothing with negative values -TEST_F(LinearSmoothedValueTest, SmoothingWithNegativeValues) { +TEST_F(LinearSmoothedValueTest, SmoothingWithNegativeValues) +{ LinearSmoothedValue sv(5.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(-5.0f); @@ -133,7 +144,8 @@ TEST_F(LinearSmoothedValueTest, SmoothingWithNegativeValues) { } // Test Skip functionality -TEST_F(LinearSmoothedValueTest, SkipSamples) { +TEST_F(LinearSmoothedValueTest, SkipSamples) +{ LinearSmoothedValue sv1(0.0f); LinearSmoothedValue sv2(0.0f); @@ -156,7 +168,8 @@ TEST_F(LinearSmoothedValueTest, SkipSamples) { } // Test when ramp length is zero -TEST_F(LinearSmoothedValueTest, ZeroRampLength) { +TEST_F(LinearSmoothedValueTest, ZeroRampLength) +{ LinearSmoothedValue sv(1.0f); sv.Reset(sampleRate, 0.0); sv.SetTargetValue(5.0f); @@ -165,7 +178,8 @@ TEST_F(LinearSmoothedValueTest, ZeroRampLength) { } // Test very short ramp length -TEST_F(LinearSmoothedValueTest, VeryShortRampLength) { +TEST_F(LinearSmoothedValueTest, VeryShortRampLength) +{ LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 0.1); sv.SetTargetValue(1.0f); @@ -179,7 +193,8 @@ TEST_F(LinearSmoothedValueTest, VeryShortRampLength) { } // Test multiple target changes -TEST_F(LinearSmoothedValueTest, MultipleTargetChanges) { +TEST_F(LinearSmoothedValueTest, MultipleTargetChanges) +{ LinearSmoothedValue sv(0.0f); sv.Reset(sampleRate, 50.0); @@ -201,7 +216,8 @@ TEST_F(LinearSmoothedValueTest, MultipleTargetChanges) { } // Test same target value -TEST_F(LinearSmoothedValueTest, SameTargetValue) { +TEST_F(LinearSmoothedValueTest, SameTargetValue) +{ LinearSmoothedValue sv(5.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(5.0f); @@ -211,7 +227,8 @@ TEST_F(LinearSmoothedValueTest, SameTargetValue) { } // Test large sample rate -TEST_F(LinearSmoothedValueTest, LargeSampleRate) { +TEST_F(LinearSmoothedValueTest, LargeSampleRate) +{ LinearSmoothedValue sv(0.0f); sv.Reset(192000.0, 100.0); sv.SetTargetValue(1.0f); @@ -227,17 +244,19 @@ TEST_F(LinearSmoothedValueTest, LargeSampleRate) { // MULTIPLICATIVE ===================================================================================================== // Test constructor with initial value (multiplicative can't start from zero) -TEST_F(MultiplicativeSmoothedValueTest, ConstructorWithInitialValue) { +TEST_F(MultiplicativeSmoothedValueTest, ConstructorWithInitialValue) +{ const float initialValue = 5.0f; MultiplicativeSmoothedValue sv(initialValue); EXPECT_FLOAT_EQ(sv.GetNextValue(), initialValue); } // Test basic multiplicative behavior - exponential curve -TEST_F(MultiplicativeSmoothedValueTest, ExponentialCurve) { +TEST_F(MultiplicativeSmoothedValueTest, ExponentialCurve) +{ MultiplicativeSmoothedValue sv(1.0f); - sv.Reset(sampleRate, 100.0); // 100ms ramp - sv.SetTargetValue(8.0f); // 3 octaves (2^3 = 8) + sv.Reset(sampleRate, 100.0); // 100ms ramp + sv.SetTargetValue(8.0f); // 3 octaves (2^3 = 8) float value1 = sv.GetNextValue(); float value2 = sv.GetNextValue(); @@ -254,10 +273,11 @@ TEST_F(MultiplicativeSmoothedValueTest, ExponentialCurve) { } // Test frequency doubling (octave) - with more realistic tolerance -TEST_F(MultiplicativeSmoothedValueTest, FrequencyOctave) { - MultiplicativeSmoothedValue sv(440.0f); // A4 +TEST_F(MultiplicativeSmoothedValueTest, FrequencyOctave) +{ + MultiplicativeSmoothedValue sv(440.0f); // A4 sv.Reset(sampleRate, 50.0); - sv.SetTargetValue(880.0f); // A5 (one octave up) + sv.SetTargetValue(880.0f); // A5 (one octave up) // Check that we get exponential progression float prevValue = 440.0f; @@ -269,18 +289,19 @@ TEST_F(MultiplicativeSmoothedValueTest, FrequencyOctave) { } // Eventually gets close to target - use more relaxed tolerance - for (int i = 0; i < 5000; ++i) { // More samples to ensure convergence + for (int i = 0; i < 5000; ++i) { // More samples to ensure convergence sv.GetNextValue(); } float finalValue = sv.GetNextValue(); - EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 0.01f)); // 1% tolerance + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 0.01f)); // 1% tolerance } // Test dB conversion - another common audio use case -TEST_F(MultiplicativeSmoothedValueTest, DecibelConversion) { - MultiplicativeSmoothedValue sv(1.0f); // 0 dB +TEST_F(MultiplicativeSmoothedValueTest, DecibelConversion) +{ + MultiplicativeSmoothedValue sv(1.0f); // 0 dB sv.Reset(sampleRate, 100.0); - sv.SetTargetValue(3.16228f); // Approximately 10 dB (10^(10/20)) + sv.SetTargetValue(3.16228f); // Approximately 10 dB (10^(10/20)) float value1 = sv.GetNextValue(); float value2 = sv.GetNextValue(); @@ -291,21 +312,23 @@ TEST_F(MultiplicativeSmoothedValueTest, DecibelConversion) { } // Test zero handling - multiplicative can't reach zero -TEST_F(MultiplicativeSmoothedValueTest, ZeroHandling) { +TEST_F(MultiplicativeSmoothedValueTest, ZeroHandling) +{ MultiplicativeSmoothedValue sv(1.0f); sv.Reset(sampleRate, rampLengthMs); - sv.SetTargetValue(0.0f); // Invalid target for multiplicative + sv.SetTargetValue(0.0f); // Invalid target for multiplicative // Should not progress since target is zero float value1 = sv.GetNextValue(); float value2 = sv.GetNextValue(); - EXPECT_FLOAT_EQ(value1, 1.0f); // Should remain at current value + EXPECT_FLOAT_EQ(value1, 1.0f); // Should remain at current value EXPECT_FLOAT_EQ(value2, 1.0f); } // Test starting from zero - should handle gracefully -TEST_F(MultiplicativeSmoothedValueTest, StartingFromZero) { +TEST_F(MultiplicativeSmoothedValueTest, StartingFromZero) +{ MultiplicativeSmoothedValue sv(0.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(10.0f); @@ -319,10 +342,11 @@ TEST_F(MultiplicativeSmoothedValueTest, StartingFromZero) { } // Test SetTargetValue -TEST_F(MultiplicativeSmoothedValueTest, SetTargetValue) { +TEST_F(MultiplicativeSmoothedValueTest, SetTargetValue) +{ MultiplicativeSmoothedValue sv(2.0f); sv.Reset(sampleRate, rampLengthMs); - sv.SetTargetValue(32.0f); // 4 octaves (2^4 * 2 = 32) + sv.SetTargetValue(32.0f); // 4 octaves (2^4 * 2 = 32) float value1 = sv.GetNextValue(); float value2 = sv.GetNextValue(); @@ -333,22 +357,24 @@ TEST_F(MultiplicativeSmoothedValueTest, SetTargetValue) { } // Test GetNextValue gets close to target -TEST_F(MultiplicativeSmoothedValueTest, GetNextValueReachesTarget) { +TEST_F(MultiplicativeSmoothedValueTest, GetNextValueReachesTarget) +{ MultiplicativeSmoothedValue sv(1.0f); sv.Reset(sampleRate, 50.0); sv.SetTargetValue(4.0f); float lastValue = 1.0f; - for (int i = 0; i < 5000; ++i) { // More samples + for (int i = 0; i < 5000; ++i) { // More samples lastValue = sv.GetNextValue(); } // Use percentage-based tolerance for multiplicative - EXPECT_TRUE(IsApproximatelyEqual(lastValue, 4.0f, 0.01f)); // 1% tolerance + EXPECT_TRUE(IsApproximatelyEqual(lastValue, 4.0f, 0.01f)); // 1% tolerance } // Test Skip functionality -TEST_F(MultiplicativeSmoothedValueTest, SkipSamples) { +TEST_F(MultiplicativeSmoothedValueTest, SkipSamples) +{ MultiplicativeSmoothedValue sv1(1.0f); MultiplicativeSmoothedValue sv2(1.0f); @@ -371,7 +397,8 @@ TEST_F(MultiplicativeSmoothedValueTest, SkipSamples) { } // Test when ramp length is zero -TEST_F(MultiplicativeSmoothedValueTest, ZeroRampLength) { +TEST_F(MultiplicativeSmoothedValueTest, ZeroRampLength) +{ MultiplicativeSmoothedValue sv(2.0f); sv.Reset(sampleRate, 0.0); sv.SetTargetValue(8.0f); @@ -380,22 +407,24 @@ TEST_F(MultiplicativeSmoothedValueTest, ZeroRampLength) { } // Test very short ramp length - adjust expectations -TEST_F(MultiplicativeSmoothedValueTest, VeryShortRampLength) { +TEST_F(MultiplicativeSmoothedValueTest, VeryShortRampLength) +{ MultiplicativeSmoothedValue sv(1.0f); - sv.Reset(sampleRate, 0.1); // Very short ramp + sv.Reset(sampleRate, 0.1); // Very short ramp sv.SetTargetValue(2.0f); float value = 1.0f; - for (int i = 0; i < 20; ++i) { // More iterations for very short ramp + for (int i = 0; i < 20; ++i) { // More iterations for very short ramp value = sv.GetNextValue(); } // For very short ramps, expect to get reasonably close - EXPECT_TRUE(IsApproximatelyEqual(value, 2.0f, 0.05f)); // 5% tolerance + EXPECT_TRUE(IsApproximatelyEqual(value, 2.0f, 0.05f)); // 5% tolerance } // Test multiple target changes - with realistic tolerances -TEST_F(MultiplicativeSmoothedValueTest, MultipleTargetChanges) { +TEST_F(MultiplicativeSmoothedValueTest, MultipleTargetChanges) +{ MultiplicativeSmoothedValue sv(1.0f); sv.Reset(sampleRate, 50.0); @@ -405,20 +434,21 @@ TEST_F(MultiplicativeSmoothedValueTest, MultipleTargetChanges) { } float valueBeforeChange = sv.GetNextValue(); - sv.SetTargetValue(0.5f); // Going down + sv.SetTargetValue(0.5f); // Going down float valueAfterChange = sv.GetNextValue(); - EXPECT_LT(valueAfterChange, valueBeforeChange); // Should start decreasing + EXPECT_LT(valueAfterChange, valueBeforeChange); // Should start decreasing for (int i = 0; i < 5000; ++i) { sv.GetNextValue(); } float finalValue = sv.GetNextValue(); - EXPECT_TRUE(IsApproximatelyEqual(finalValue, 0.5f, 0.01f)); // 1% tolerance + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 0.5f, 0.01f)); // 1% tolerance } // Test same target value -TEST_F(MultiplicativeSmoothedValueTest, SameTargetValue) { +TEST_F(MultiplicativeSmoothedValueTest, SameTargetValue) +{ MultiplicativeSmoothedValue sv(5.0f); sv.Reset(sampleRate, rampLengthMs); sv.SetTargetValue(5.0f); @@ -428,10 +458,11 @@ TEST_F(MultiplicativeSmoothedValueTest, SameTargetValue) { } // Test decreasing values (important for multiplicative) -TEST_F(MultiplicativeSmoothedValueTest, DecreasingValues) { +TEST_F(MultiplicativeSmoothedValueTest, DecreasingValues) +{ MultiplicativeSmoothedValue sv(8.0f); sv.Reset(sampleRate, rampLengthMs); - sv.SetTargetValue(2.0f); // Decreasing + sv.SetTargetValue(2.0f); // Decreasing float value1 = sv.GetNextValue(); float value2 = sv.GetNextValue(); @@ -442,7 +473,8 @@ TEST_F(MultiplicativeSmoothedValueTest, DecreasingValues) { } // Test large sample rate -TEST_F(MultiplicativeSmoothedValueTest, LargeSampleRate) { +TEST_F(MultiplicativeSmoothedValueTest, LargeSampleRate) +{ MultiplicativeSmoothedValue sv(1.0f); sv.Reset(192000.0, 100.0); sv.SetTargetValue(2.0f); @@ -452,17 +484,18 @@ TEST_F(MultiplicativeSmoothedValueTest, LargeSampleRate) { EXPECT_GT(value1, 1.0f); EXPECT_GT(value2, value1); - EXPECT_LT(value1, 1.01f); // Should be a very small increment + EXPECT_LT(value1, 1.01f); // Should be a very small increment } // Test musical interval - with more realistic expectations -TEST_F(MultiplicativeSmoothedValueTest, MusicalInterval) { - MultiplicativeSmoothedValue sv(440.0f); // A4 - sv.Reset(sampleRate, 120.0); // 120ms for 12 steps - sv.SetTargetValue(880.0f); // A5 +TEST_F(MultiplicativeSmoothedValueTest, MusicalInterval) +{ + MultiplicativeSmoothedValue sv(440.0f); // A4 + sv.Reset(sampleRate, 120.0); // 120ms for 12 steps + sv.SetTargetValue(880.0f); // A5 // Just run for the expected duration plus some buffer - int totalSamples = static_cast((150.0 / 1000.0) * sampleRate); // 150ms buffer + int totalSamples = static_cast((150.0 / 1000.0) * sampleRate); // 150ms buffer for (int i = 0; i < totalSamples; ++i) { sv.GetNextValue(); } @@ -470,5 +503,5 @@ TEST_F(MultiplicativeSmoothedValueTest, MusicalInterval) { float finalValue = sv.GetNextValue(); // Check that we get reasonably close to 880Hz (within 1%) - EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 8.8f)); // ~1% tolerance + EXPECT_TRUE(IsApproximatelyEqual(finalValue, 880.0f, 8.8f)); // ~1% tolerance } From e5aa2701030abf549723fb8869f22d9e44d82307 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Sun, 21 Sep 2025 16:58:17 -0500 Subject: [PATCH 5/7] Fix Makefile --- Makefile | 38 ++++++++++---------------------------- vendor/googletest | 2 +- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index deee4f0..a42d506 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,12 @@ TARGET = libneuron -MODULE_DIR = src +INCLUDE_DIR = include +SRC_DIR = src # Each Module Directory is listed below with it's modules. # Header only modules are listed commented out # below the others. -ABSTRACTIONS_MOD_DIR = abstractions -ABSTRACTIONS_MODULES = \ - -AUDIO_MOD_DIR = audio -AUDIO_MODULES = \ - GENERATOR_MOD_DIR = generators GENERATOR_MODULES = \ oscillator \ @@ -20,26 +15,19 @@ MODULATOR_MOD_DIR = modulators MODULATOR_MODULES = \ adsr \ -PROCESSOR_EFFECTS_MOD_DIR = processors/effects -PROCESSOR_EFFECTS_MODULES = \ +PROCESSOR_MOD_DIR = processors +PROCESSOR_MODULES = \ +filter \ saturator \ wavefolder \ -PROCESSOR_FILTERS_MOD_DIR = processors/filters -PROCESS_FILTERS_MODULES = \ -filter \ - -UTILITY_MOD_DIR = utilities -UTILITY_MODULES = \ - ###################################### # source ###################################### -CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(GENERATOR_MOD_DIR)/$(GENERATOR_MODULES)) -CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(MODULATOR_MOD_DIR)/$(MODULATOR_MODULES)) -CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(PROCESSOR_EFFECTS_MOD_DIR)/$(PROCESSOR_EFFECTS_MODULES)) -CPP_SOURCES += $(addsuffix .cpp, $(MODULE_DIR)/$(PROCESSOR_FILTERS_MOD_DIR)/$(PROCESS_FILTERS_MODULES)) +CPP_SOURCES += $(addsuffix .cpp, $(SRC_DIR)/$(GENERATOR_MOD_DIR)/$(GENERATOR_MODULES)) +CPP_SOURCES += $(addsuffix .cpp, $(SRC_DIR)/$(MODULATOR_MOD_DIR)/$(MODULATOR_MODULES)) +CPP_SOURCES += $(addsuffix .cpp, $(SRC_DIR)/$(PROCESSOR_MOD_DIR)/$(PROCESSOR_MODULES)) ###################################### # building variables @@ -112,14 +100,8 @@ C_DEFS = \ -DSTM32H750xx C_INCLUDES = \ --I$(MODULE_DIR) \ --I$(MODULE_DIR)/$(ABSTRACTIONS_MOD_DIR) \ --I$(MODULE_DIR)/$(AUDIO_MOD_DIR) \ --I$(MODULE_DIR)/$(GENERATOR_MOD_DIR) \ --I$(MODULE_DIR)/$(MODULATOR_MOD_DIR) \ --I$(MODULE_DIR)/$(PROCESSOR_EFFECTS_MOD_DIR) \ --I$(MODULE_DIR)/$(PROCESSOR_FILTERS_MOD_DIR) \ --I$(MODULE_DIR)/$(UTILITY_MOD_DIR) \ +-I$(INCLUDE_DIR) \ +-I$(SRC_DIR) \ # compile gcc flags ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections diff --git a/vendor/googletest b/vendor/googletest index df1544b..35d0c36 160000 --- a/vendor/googletest +++ b/vendor/googletest @@ -1 +1 @@ -Subproject commit df1544bcee0c7ce35cd5ea0b3eb8cc81855a4140 +Subproject commit 35d0c365609296fa4730d62057c487e3cfa030ff From 9b3845db14f2a537f17078b068fd04f6d68ab2b0 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Sun, 21 Sep 2025 17:05:53 -0500 Subject: [PATCH 6/7] Fix tests --- CMakeLists.txt | 22 +++++++++---------- .../{abstractions => core}/parameter_test.cpp | 4 ++-- .../parameter_test_atomic.cpp | 4 ++-- .../{ => dsp}/generators/oscillator_test.cpp | 4 ++-- tests/{ => dsp}/modulators/adsr_test.cpp | 4 ++-- .../processors}/filter_test.cpp | 5 +++-- .../processors}/saturator_test.cpp | 4 ++-- .../processors}/wavefolder_test.cpp | 4 ++-- .../{utilities => utils}/arithmetic_test.cpp | 4 ++-- tests/{utilities => utils}/midi_test.cpp | 4 ++-- .../smoothed_value_test.cpp | 3 ++- tests/{audio => utils}/waveform_test.cpp | 4 ++-- 12 files changed, 34 insertions(+), 32 deletions(-) rename tests/{abstractions => core}/parameter_test.cpp (95%) rename tests/{abstractions => core}/parameter_test_atomic.cpp (97%) rename tests/{ => dsp}/generators/oscillator_test.cpp (98%) rename tests/{ => dsp}/modulators/adsr_test.cpp (98%) rename tests/{processors/filters => dsp/processors}/filter_test.cpp (80%) rename tests/{processors/effects => dsp/processors}/saturator_test.cpp (96%) rename tests/{processors/effects => dsp/processors}/wavefolder_test.cpp (96%) rename tests/{utilities => utils}/arithmetic_test.cpp (99%) rename tests/{utilities => utils}/midi_test.cpp (93%) rename tests/{utilities => utils}/smoothed_value_test.cpp (99%) rename tests/{audio => utils}/waveform_test.cpp (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 813cea0..ea11eeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,18 +41,18 @@ if (NEO_BUILD_TESTS) add_subdirectory(vendor/googletest) if (NEO_PLUGIN_SUPPORT) - add_neuron_test(parameter_atomic tests/abstractions/parameter_test_atomic.cpp) + add_neuron_test(parameter_atomic tests/core/parameter_test_atomic.cpp) else () - add_neuron_test(parameter tests/abstractions/parameter_test.cpp) - add_neuron_test(waveform tests/audio/waveform_test.cpp) - add_neuron_test(oscillator tests/generators/oscillator_test.cpp) - add_neuron_test(adsr tests/modulators/adsr_test.cpp) - add_neuron_test(saturator tests/processors/effects/saturator_test.cpp) - add_neuron_test(wavefolder tests/processors/effects/wavefolder_test.cpp) - add_neuron_test(filter tests/processors/filters/filter_test.cpp) - add_neuron_test(arithmetic tests/utilities/arithmetic_test.cpp) - add_neuron_test(midi tests/utilities/midi_test.cpp) - add_neuron_test(smoothed_value tests/utilities/smoothed_value_test.cpp) + add_neuron_test(parameter tests/core/parameter_test.cpp) + add_neuron_test(waveform tests/utils/waveform_test.cpp) + add_neuron_test(oscillator tests/dsp/generators/oscillator_test.cpp) + add_neuron_test(adsr tests/dsp/modulators/adsr_test.cpp) + add_neuron_test(saturator tests/dsp/processors/saturator_test.cpp) + add_neuron_test(wavefolder tests/dsp/processors/wavefolder_test.cpp) + add_neuron_test(filter tests/dsp/processors/filter_test.cpp) + add_neuron_test(arithmetic tests/utils/arithmetic_test.cpp) + add_neuron_test(midi tests/utils/midi_test.cpp) + add_neuron_test(smoothed_value tests/utils/smoothed_value_test.cpp) endif () enable_testing() diff --git a/tests/abstractions/parameter_test.cpp b/tests/core/parameter_test.cpp similarity index 95% rename from tests/abstractions/parameter_test.cpp rename to tests/core/parameter_test.cpp index 74084ee..834f3c9 100644 --- a/tests/abstractions/parameter_test.cpp +++ b/tests/core/parameter_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/core/parameter.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/abstractions/parameter_test_atomic.cpp b/tests/core/parameter_test_atomic.cpp similarity index 97% rename from tests/abstractions/parameter_test_atomic.cpp rename to tests/core/parameter_test_atomic.cpp index b42bb97..4efe3c6 100644 --- a/tests/abstractions/parameter_test_atomic.cpp +++ b/tests/core/parameter_test_atomic.cpp @@ -1,8 +1,8 @@ +#include "neuron/core/parameter.h" + #include #include -#include "neuron.h" - using namespace neuron; TEST(parameter_suite, attach_source_test) diff --git a/tests/generators/oscillator_test.cpp b/tests/dsp/generators/oscillator_test.cpp similarity index 98% rename from tests/generators/oscillator_test.cpp rename to tests/dsp/generators/oscillator_test.cpp index 18f4762..56abfcc 100644 --- a/tests/generators/oscillator_test.cpp +++ b/tests/dsp/generators/oscillator_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/dsp/generators/oscillator.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/modulators/adsr_test.cpp b/tests/dsp/modulators/adsr_test.cpp similarity index 98% rename from tests/modulators/adsr_test.cpp rename to tests/dsp/modulators/adsr_test.cpp index 9c29c99..89d86b0 100644 --- a/tests/modulators/adsr_test.cpp +++ b/tests/dsp/modulators/adsr_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/dsp/modulators/adsr.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/processors/filters/filter_test.cpp b/tests/dsp/processors/filter_test.cpp similarity index 80% rename from tests/processors/filters/filter_test.cpp rename to tests/dsp/processors/filter_test.cpp index 90289e9..cec58d1 100644 --- a/tests/processors/filters/filter_test.cpp +++ b/tests/dsp/processors/filter_test.cpp @@ -1,6 +1,7 @@ -#include +#include "neuron/dsp/generators/oscillator.h" +#include "neuron/dsp/processors/filter.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/processors/effects/saturator_test.cpp b/tests/dsp/processors/saturator_test.cpp similarity index 96% rename from tests/processors/effects/saturator_test.cpp rename to tests/dsp/processors/saturator_test.cpp index e25e2e1..68315bb 100644 --- a/tests/processors/effects/saturator_test.cpp +++ b/tests/dsp/processors/saturator_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/dsp/processors/saturator.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/processors/effects/wavefolder_test.cpp b/tests/dsp/processors/wavefolder_test.cpp similarity index 96% rename from tests/processors/effects/wavefolder_test.cpp rename to tests/dsp/processors/wavefolder_test.cpp index e0682a7..4497598 100644 --- a/tests/processors/effects/wavefolder_test.cpp +++ b/tests/dsp/processors/wavefolder_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/dsp/processors/wavefolder.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/utilities/arithmetic_test.cpp b/tests/utils/arithmetic_test.cpp similarity index 99% rename from tests/utilities/arithmetic_test.cpp rename to tests/utils/arithmetic_test.cpp index db1157d..0b2f887 100644 --- a/tests/utilities/arithmetic_test.cpp +++ b/tests/utils/arithmetic_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/utils/arithmetic.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/utilities/midi_test.cpp b/tests/utils/midi_test.cpp similarity index 93% rename from tests/utilities/midi_test.cpp rename to tests/utils/midi_test.cpp index 916e92f..dccfeba 100644 --- a/tests/utilities/midi_test.cpp +++ b/tests/utils/midi_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/utils/midi.h" -#include "neuron.h" +#include using namespace neuron; diff --git a/tests/utilities/smoothed_value_test.cpp b/tests/utils/smoothed_value_test.cpp similarity index 99% rename from tests/utilities/smoothed_value_test.cpp rename to tests/utils/smoothed_value_test.cpp index e7bda7a..6f88734 100644 --- a/tests/utilities/smoothed_value_test.cpp +++ b/tests/utils/smoothed_value_test.cpp @@ -1,4 +1,5 @@ -#include "neuron.h" +#include "neuron/utils/smoothed_value.h" + #include #include diff --git a/tests/audio/waveform_test.cpp b/tests/utils/waveform_test.cpp similarity index 97% rename from tests/audio/waveform_test.cpp rename to tests/utils/waveform_test.cpp index 5d66133..9d4548f 100644 --- a/tests/audio/waveform_test.cpp +++ b/tests/utils/waveform_test.cpp @@ -1,6 +1,6 @@ -#include +#include "neuron/utils/waveform.h" -#include "neuron.h" +#include using namespace neuron; From 95b3ed0d60c65d4f5fe50798e23c04dc1e7da413 Mon Sep 17 00:00:00 2001 From: Matthew Maxwell Date: Sun, 21 Sep 2025 17:06:39 -0500 Subject: [PATCH 7/7] Fix Makefile dirs --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a42d506..94630dd 100644 --- a/Makefile +++ b/Makefile @@ -7,15 +7,15 @@ SRC_DIR = src # Header only modules are listed commented out # below the others. -GENERATOR_MOD_DIR = generators +GENERATOR_MOD_DIR = dsp/generators GENERATOR_MODULES = \ oscillator \ -MODULATOR_MOD_DIR = modulators +MODULATOR_MOD_DIR = dsp/modulators MODULATOR_MODULES = \ adsr \ -PROCESSOR_MOD_DIR = processors +PROCESSOR_MOD_DIR = dsp/processors PROCESSOR_MODULES = \ filter \ saturator \