Skip to content

Commit

Permalink
Add reverb effect (#12)
Browse files Browse the repository at this point in the history
* Added Reverb effect first implementation

* Added unit test for Reverb effect

* removed test gain setting
  • Loading branch information
ilcardella authored Mar 5, 2022
1 parent 025080a commit 82230c3
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for MCP3002 ADC
- Support for 2x6bit PWM output signal
- I2C SSD1306 Display
- Notification LED
- Distortion effect
- Echo effect
- Delay effect
- Reverb effect
19 changes: 19 additions & 0 deletions extern/guitar_fx_lib/include/guitar_fx_lib/fx/delay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,32 @@ class Delay : public Effect
{
public:
Delay() = default;

Delay(const uint32_t &initial_depth) : depth(initial_depth)
{
}

~Delay() = default;

std::string get_name() override
{
return "Delay";
}

bool set_depth(const float &value)
{
if (value >= DELAY_MAX or value < DELAY_MIN)
{
return false;
}

depth = value;
// TODO: confirm if it's necessary to reset the buffer
// buffer.fill(0.0f);
// counter = 0;
return true;
}

protected:
void on_gain_update(const float &new_gain) override
{
Expand Down
55 changes: 55 additions & 0 deletions extern/guitar_fx_lib/include/guitar_fx_lib/fx/reverb.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#include <guitar_fx_lib/fx/delay.hpp>
#include <guitar_fx_lib/interfaces/effect.hpp>

class Reverb : public Effect
{
public:
Reverb() : delay1(3000), delay2(2000), delay3(1000)
{
}

~Reverb() = default;

std::string get_name() override
{
return "Reverb";
}

protected:
void on_gain_update(const float &new_gain) override
{
// TODO change the depth of each delay
// delay1.set_depth(something)
// delay2.set_depth(something else)
// delay3.set_depth(another value again)
}

bool apply_fx(const float &input, float &output) override
{
// The effect simulates 3+ different delays at different depths

float output1, output2, output3;

// Remove the input portion from each delay processed signal so that the
// input can be added only once
delay1.process(input, output1);
output1 -= input;
delay2.process(input, output2);
output2 -= input;
delay3.process(input, output3);
output3 -= input;

output = (input + output1 + output2 + output3) / DECAY;

return true;
}

private:
static constexpr uint32_t DECAY = 4;

Delay delay1;
Delay delay2;
Delay delay3;
};
6 changes: 5 additions & 1 deletion extern/guitar_fx_lib/include/guitar_fx_lib/fx_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
#include <guitar_fx_lib/fx/delay.hpp>
#include <guitar_fx_lib/fx/distortion.hpp>
#include <guitar_fx_lib/fx/echo.hpp>
#include <guitar_fx_lib/fx/reverb.hpp>
#include <guitar_fx_lib/interfaces/effect.hpp>

enum class Effects
{
CLEAN,
DISTORTION,
ECHO,
DELAY
DELAY,
REVERB
};

class FxFactory
Expand All @@ -38,6 +40,8 @@ class FxFactory
case Effects::DELAY:
return std::make_unique<Delay>();
break;
case Effects::REVERB:
return std::make_unique<Reverb>();

default:
return nullptr;
Expand Down
3 changes: 2 additions & 1 deletion extern/guitar_fx_lib/include/guitar_fx_lib/fx_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class FxManager
FxManager(const uint32_t &min, const uint32_t &max)
: signal_min(min), signal_max(max), signal_middle((max - min) / 2), factory()
{
effects = {Effects::DISTORTION, Effects::ECHO, Effects::DELAY};
effects = {Effects::CLEAN, Effects::DISTORTION, Effects::ECHO, Effects::DELAY,
Effects::REVERB};
effects_it = effects.begin();
active_fx = factory.make(*effects_it);
}
Expand Down
1 change: 1 addition & 0 deletions extern/guitar_fx_lib/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ custom_add_gtest("test_effect_clean")
custom_add_gtest("test_effect_distortion")
custom_add_gtest("test_effect_echo")
custom_add_gtest("test_effect_delay")
custom_add_gtest("test_effect_reverb")

add_custom_target(run_tests COMMAND ctest ARGS --output-on-failure --verbose)
61 changes: 61 additions & 0 deletions extern/guitar_fx_lib/tests/test_effect_reverb.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <gtest/gtest.h>

#include <guitar_fx_lib/fx/reverb.hpp>

class TestEffectReverb : public ::testing::Test
{
};

TEST_F(TestEffectReverb, testEffectInit)
{
ASSERT_NO_THROW(Reverb());

Reverb rev;
ASSERT_EQ(rev.get_name(), "Reverb");
}

TEST_F(TestEffectReverb, testSetGain)
{
Reverb rev;

ASSERT_TRUE(rev.set_gain(0.0f));
ASSERT_TRUE(rev.set_gain(0.12f));
ASSERT_TRUE(rev.set_gain(0.7f));
ASSERT_TRUE(rev.set_gain(1.0f));

ASSERT_FALSE(rev.set_gain(-1.0f));
ASSERT_FALSE(rev.set_gain(-0.1f));
ASSERT_FALSE(rev.set_gain(1.1f));
ASSERT_FALSE(rev.set_gain(100.1f));
}

TEST_F(TestEffectReverb, testProcessValidSignal)
{
float output = 0.0f;

Reverb rev;
rev.set_gain(0.5f);

for (float input = -1.0f; input <= 1.0f; input += 0.1f)
{
ASSERT_TRUE(rev.process(input, output)) << "Failed with input " << input;
ASSERT_GE(output, -1.0f);
ASSERT_LE(output, 1.0f);
}
}

TEST_F(TestEffectReverb, testProcessInvalidSignal)
{
float output = 0;

Reverb rev;

for (float input = -100.0f; input <= 100.0f; input += 0.1f)
{
if (input < -1.0f or input > 1.0f)
{
ASSERT_FALSE(rev.process(input, output));
ASSERT_EQ(0, output);
}
}
}
2 changes: 1 addition & 1 deletion extern/guitar_fx_lib/tests/test_fx_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class TestFxManager : public ::testing::Test
protected:
void SetUp()
{
names = {"Distortion", "Echo", "Delay"};
names = {"Clean", "Distortion", "Echo", "Delay", "Reverb"};
}

std::vector<std::string> names;
Expand Down

0 comments on commit 82230c3

Please sign in to comment.