diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..480f52b 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,7 @@
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 113d361..6160d8a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,6 +66,8 @@ else()
endif()
+
+
target_sources(kAmp
PRIVATE
${SOURCES})
@@ -111,6 +113,7 @@ target_link_libraries(kAmp
juce::juce_audio_basics
juce::juce_audio_utils
juce::juce_gui_extra
+ juce::juce_dsp
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
diff --git a/include/DistortionEffect.h b/include/DistortionEffect.h
index 26d28fe..2d47b54 100644
--- a/include/DistortionEffect.h
+++ b/include/DistortionEffect.h
@@ -33,7 +33,7 @@ class DistortionEffect : public AbstractEffect {
*/
void setRange(float rangeValue);
- static float DistortionEffect::clipWithCurrentRange(float x);
+ static float clipWithCurrentRange(float x);
diff --git a/include/EqualizerEffect.h b/include/EqualizerEffect.h
new file mode 100644
index 0000000..37334aa
--- /dev/null
+++ b/include/EqualizerEffect.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+#include "AbstractEffect.h"
+#include
+
+
+class EqualizerEffect : public AbstractEffect {
+public:
+ EqualizerEffect();
+ ~EqualizerEffect() override = default;
+
+ void apply(const AudioSourceChannelInfo &bufferToFill) override;
+ void setGain(int bandIndex, float gain);
+ float getGain(int bandIndex) const;
+ bool operator==(const AbstractEffect* effect) override;
+
+ [[nodiscard]] String getEffectType() const override { return "EqualizerEffect"; }
+
+ [[nodiscard]] var toJSON() const override;
+ void fromJSON(const var &json) override;
+
+private:
+ static constexpr int numBands = 10;
+ float bandGains[numBands]; // Gain en dB pour chaque bande
+ std::vector> filters;
+
+ void updateFilters();
+};
diff --git a/include/EqualizerEffectComponent.h b/include/EqualizerEffectComponent.h
new file mode 100644
index 0000000..32ecbe1
--- /dev/null
+++ b/include/EqualizerEffectComponent.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include
+#include "BasePedalComponent.h"
+#include "EqualizerEffect.h"
+
+class EqualizerEffectComponent : public BasePedalComponent {
+public:
+ explicit EqualizerEffectComponent(AbstractEffect* effect);
+ ~EqualizerEffectComponent() override = default;
+
+private:
+ EqualizerEffect* eqEffect;
+ Slider sliders[10];
+ Label labels[10];
+
+ Grid grid;
+
+ void sliderValueChanged(Slider* slider);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EqualizerEffectComponent)
+};
diff --git a/src/EffectComponentFactory.cpp b/src/EffectComponentFactory.cpp
index 2dec27e..ffaf897 100644
--- a/src/EffectComponentFactory.cpp
+++ b/src/EffectComponentFactory.cpp
@@ -3,6 +3,8 @@
#include "DistortionEffect.h"
#include "DistortionEffectComponent.h"
#include "EffectComponentFactory.h"
+#include "EqualizerEffect.h"
+#include "EqualizerEffectComponent.h"
#include "NoiseGateEffect.h"
#include "NoiseGateEffectComponent.h"
@@ -13,6 +15,10 @@ EffectComponent* EffectComponentFactory::CreateEffectComponent(AbstractEffect* e
if (dynamic_cast(effect) != nullptr) {
return new DistortionEffectComponent(effect);
}
+ if (dynamic_cast(effect) != nullptr)
+ {
+ return new EqualizerEffectComponent(effect);
+ }
if (dynamic_cast(effect) != nullptr) {
return new NoiseGateEffectComponent(effect);
}
diff --git a/src/Pedalboard.cpp b/src/Pedalboard.cpp
index cebec8d..22203d9 100644
--- a/src/Pedalboard.cpp
+++ b/src/Pedalboard.cpp
@@ -1,11 +1,13 @@
#include "DelayEffect.h"
#include "DistortionEffect.h"
#include "Pedalboard.h"
+#include "EqualizerEffect.h"
#include "NoiseGateEffect.h"
Pedalboard::Pedalboard() {
this->append(new DelayEffect());
this->append(new DistortionEffect());
+ this->append(new EqualizerEffect());
this->append(new NoiseGateEffect());
}
diff --git a/src/components/DelayEffectComponent.cpp b/src/components/DelayEffectComponent.cpp
index 9090256..a38ade3 100644
--- a/src/components/DelayEffectComponent.cpp
+++ b/src/components/DelayEffectComponent.cpp
@@ -53,9 +53,8 @@ DelayEffectComponent::DelayEffectComponent(AbstractEffect* effect) : BasePedalCo
addAndMakeVisible(delaySlider);
addAndMakeVisible(delayLabel);
- setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
-
this->initializePedal();
+ setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
diff --git a/src/components/DistortionEffectComponent.cpp b/src/components/DistortionEffectComponent.cpp
index 3519cfe..0154fb3 100644
--- a/src/components/DistortionEffectComponent.cpp
+++ b/src/components/DistortionEffectComponent.cpp
@@ -40,9 +40,8 @@ DistortionEffectComponent::DistortionEffectComponent(AbstractEffect* effect)
addAndMakeVisible(rangeSlider);
addAndMakeVisible(rangeLabel);
-
- setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
this->initializePedal();
+ setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
}
}
diff --git a/src/components/EqualizerEffectComponent.cpp b/src/components/EqualizerEffectComponent.cpp
new file mode 100644
index 0000000..ab116e2
--- /dev/null
+++ b/src/components/EqualizerEffectComponent.cpp
@@ -0,0 +1,72 @@
+#include "EqualizerEffectComponent.h"
+#include
+
+#include "EqualizerEffectComponent.h"
+
+
+EqualizerEffectComponent::EqualizerEffectComponent(AbstractEffect* effect)
+ : BasePedalComponent(effect), eqEffect(dynamic_cast(effect)) {
+
+ jassert(eqEffect != nullptr);
+
+ primaryColor = juce::Colours::orange;
+
+ const char* freqLabels[10] = { "31Hz", "62Hz", "125Hz", "250Hz", "500Hz", "1k", "2k", "4k", "8k", "16k" };
+
+ using Track = juce::Grid::TrackInfo;
+ using Fr = juce::Grid::Fr;
+
+ // 2 lignes : sliders + labels
+ grid.templateRows = { Track(Fr(1)), Track(Fr(3)) };
+ grid.templateColumns = { Track(Fr(1)), Track(Fr(1)), Track(Fr(1)), Track(Fr(1)), Track(Fr(1)),
+ Track(Fr(1)), Track(Fr(1)), Track(Fr(1)), Track(Fr(1)), Track(Fr(1)) };
+
+ for (int i = 0; i < 10; ++i) {
+ sliders[i].setSliderStyle(juce::Slider::LinearVertical);
+ sliders[i].setTextBoxStyle(juce::Slider::TextBoxBelow, false, 50, 20);
+ sliders[i].setRange(-24.0, 24.0, 0.1);
+ sliders[i].setValue(0.0);
+ sliders[i].setColour(juce::Slider::textBoxOutlineColourId, juce::Colours::transparentWhite);
+ sliders[i].onValueChange = [this, i]
+ {
+ if (static_cast(sliders[i].getValue())) {
+ eqEffect->setGain(i, static_cast(sliders[i].getValue()));
+ }
+ };
+ sliders[i].setTitle(freqLabels[i]);
+ sliders[i].setBounds(i * (getWidth() / 10), 0, getWidth() / 10, (getHeight() / 5) * 4);
+
+ labels[i].setText(freqLabels[i], juce::dontSendNotification);
+ labels[i].setJustificationType(juce::Justification::centred);
+ labels[i].attachToComponent(&sliders[i], false);
+ labels[i].setBounds(i * (getWidth() / 10), 0, getWidth() / 10, getHeight() / 5);
+
+ addAndMakeVisible(sliders[i]);
+ addAndMakeVisible(labels[i]);
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ grid.items.add(GridItem(labels[i]));
+ }
+ for (int i = 0; i < 10; ++i)
+ {
+ grid.items.add(juce::GridItem(sliders[i]));
+ }
+
+ settingsLayout = new PedalSettingsLayoutComponent(&grid);
+
+ this->initializePedal();
+ setSize(400, 300);
+}
+
+
+
+void EqualizerEffectComponent::sliderValueChanged(juce::Slider* slider) {
+ for (int i = 0; i < 10; ++i) {
+ if (slider == &sliders[i]) {
+ eqEffect->setGain(i, slider->getValue());
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/NoiseGateEffectComponent.cpp b/src/components/NoiseGateEffectComponent.cpp
index 3c748d1..0389c56 100644
--- a/src/components/NoiseGateEffectComponent.cpp
+++ b/src/components/NoiseGateEffectComponent.cpp
@@ -75,9 +75,8 @@ NoiseGateEffectComponent::NoiseGateEffectComponent(AbstractEffect* effect): Base
addAndMakeVisible(releaseSlider);
addAndMakeVisible(releaseLabel);
- setSize(300, 300);
-
this->initializePedal();
+ setSize(300, 300);
}
}
diff --git a/src/effects/DelayEffect.cpp b/src/effects/DelayEffect.cpp
index dbf68a2..fd19713 100644
--- a/src/effects/DelayEffect.cpp
+++ b/src/effects/DelayEffect.cpp
@@ -9,15 +9,9 @@ DelayEffect::DelayEffect() {
DelayEffect::~DelayEffect() = default;
void DelayEffect::apply(const AudioSourceChannelInfo &bufferToFill) {
- if (delay > 0 && rate > 0)
- {
- auto* leftBuffer = bufferToFill.buffer->getWritePointer(0);
- auto* rightBuffer = bufferToFill.buffer->getNumChannels() > 1
- ? bufferToFill.buffer->getWritePointer(1)
- : nullptr;
- const auto numSamples = bufferToFill.numSamples;
-
- // TODO : Remove constants and check if they can be recovered with JUCE.
+ if (delay > 0 && rate > 0) {
+ const int numChannels = bufferToFill.buffer->getNumChannels();
+ const int numSamples = bufferToFill.numSamples;
constexpr auto sampleRate = 44100.0;
const auto delaySamples = static_cast(delay * sampleRate / 1000.0f);
@@ -26,19 +20,16 @@ void DelayEffect::apply(const AudioSourceChannelInfo &bufferToFill) {
writePosition = 0;
}
+
for (int i = 0; i < numSamples; ++i) {
auto delayedSample = circularBuffer[writePosition];
-
- auto inputSampleLeft = leftBuffer[i];
- leftBuffer[i] = inputSampleLeft + delayedSample * (rate / 100.0f);
-
- if (rightBuffer) {
- auto inputSampleRight = rightBuffer[i];
- rightBuffer[i] = inputSampleRight + delayedSample * (rate / 100.0f);
+ for (int channel = 0; channel < numChannels; ++channel)
+ {
+ auto* channelBuffer = bufferToFill.buffer->getWritePointer(channel);
+ auto inputSample = channelBuffer[i];
+ channelBuffer[i] = inputSample + delayedSample * (rate / 100.0f);
+ circularBuffer[writePosition] = inputSample;
}
-
- circularBuffer[writePosition] = inputSampleLeft;
-
writePosition = (writePosition + 1) % delaySamples;
}
}
diff --git a/src/effects/DistortionEffect.cpp b/src/effects/DistortionEffect.cpp
index c1c9ce0..14e7b50 100644
--- a/src/effects/DistortionEffect.cpp
+++ b/src/effects/DistortionEffect.cpp
@@ -75,6 +75,7 @@ void DistortionEffect::apply(const juce::AudioSourceChannelInfo& bufferToFill)
(size_t) bufferToFill.startSample);
auto subBlock = block.getSubBlock(0, (size_t) bufferToFill.numSamples);
juce::dsp::ProcessContextReplacing context(subBlock);
+ subBlock.multiplyBy(1.0f / std::max(1.0f - currentRange, 0.01f)); // Normalisation du volume
process(context);
}
diff --git a/src/effects/EqualizerEffect.cpp b/src/effects/EqualizerEffect.cpp
new file mode 100644
index 0000000..db7d960
--- /dev/null
+++ b/src/effects/EqualizerEffect.cpp
@@ -0,0 +1,78 @@
+#include "EqualizerEffect.h"
+#include
+
+EqualizerEffect::EqualizerEffect() {
+ effectName = "Equalizer";
+ filters.resize(numBands);
+ for (int i = 0; i < numBands; ++i) bandGains[i] = 0.0f;
+ updateFilters();
+}
+
+void EqualizerEffect::apply(const juce::AudioSourceChannelInfo &bufferToFill) {
+ auto* buffer = bufferToFill.buffer;
+ const int numChannels = buffer->getNumChannels();
+ const int numSamples = bufferToFill.numSamples;
+
+ juce::dsp::AudioBlock block(*buffer);
+
+ for (int channel = 0; channel < numChannels; ++channel) {
+ auto channelBlock = block.getSingleChannelBlock((size_t)channel);
+ juce::dsp::ProcessContextReplacing context(channelBlock);
+
+ for (int i = 0; i < numBands; ++i) {
+ filters[i].process(context);
+ }
+ }
+}
+
+void EqualizerEffect::setGain(int bandIndex, float gain) {
+ if (bandIndex >= 0 && bandIndex < numBands) {
+ bandGains[bandIndex] = gain;
+ updateFilters();
+ }
+}
+
+float EqualizerEffect::getGain(int bandIndex) const {
+ return (bandIndex >= 0 && bandIndex < numBands) ? bandGains[bandIndex] : 0.0f;
+}
+
+void EqualizerEffect::updateFilters() {
+ // Fréquences fixes typiques d'un égaliseur 10 bandes
+ const float freqs[10] = {31, 62, 125, 250, 500, 1000, 2000, 4000, 8000, 16000};
+ constexpr float sampleRate = 44100.0f;
+
+ for (int i = 0; i < numBands; ++i) {
+ filters[i].reset();
+ auto coeffs = juce::dsp::IIR::Coefficients::makePeakFilter(
+ sampleRate, freqs[i], 1.0f, juce::Decibels::decibelsToGain(bandGains[i])
+ );
+ filters[i].coefficients = coeffs;
+ }
+}
+
+bool EqualizerEffect::operator==(const AbstractEffect* effect) {
+ return this == effect;
+}
+
+juce::var EqualizerEffect::toJSON() const {
+ auto obj = AbstractEffect::toJSON();
+ if (auto *dynamicObj = obj.getDynamicObject()) {
+ juce::Array gains;
+ for (float g : bandGains) gains.add(g);
+ dynamicObj->setProperty("bandGains", gains);
+ }
+ return obj;
+}
+
+void EqualizerEffect::fromJSON(const juce::var &json) {
+ AbstractEffect::fromJSON(json);
+ if (const auto* obj = json.getDynamicObject()) {
+ const auto& gains = obj->getProperty("bandGains");
+ if (auto* arr = gains.getArray()) {
+ for (int i = 0; i < juce::jmin((int)arr->size(), numBands); ++i) {
+ bandGains[i] = static_cast((*arr)[i]);
+ }
+ updateFilters();
+ }
+ }
+}
diff --git a/src/utils/ResourceManager.cpp b/src/utils/ResourceManager.cpp
index 42cc164..e6ef989 100644
--- a/src/utils/ResourceManager.cpp
+++ b/src/utils/ResourceManager.cpp
@@ -1,23 +1,23 @@
#include "ResourceManager.h"
-ResourceManager::ResourceManager() {}
-ResourceManager::~ResourceManager() {}
+ResourceManager::ResourceManager() = default;
+ResourceManager::~ResourceManager() = default;
-juce::Image ResourceManager::loadImage(const juce::String& relativePath)
+Image ResourceManager::loadImage(const String& relativePath)
{
- juce::File imageFile;
+ File imageFile;
#if JUCE_MAC
- imageFile = juce::File::getSpecialLocation(juce::File::currentApplicationFile)
- .getParentDirectory()
- .getParentDirectory()
- .getParentDirectory()
- .getChildFile(relativePath);
+ imageFile = File::getSpecialLocation(File::currentApplicationFile)
+ .getParentDirectory()
+ .getParentDirectory()
+ .getParentDirectory()
+ .getChildFile(relativePath);
#else
imageFile = juce::File::getCurrentWorkingDirectory().getChildFile(relativePath);
#endif
- juce::Image image = juce::ImageFileFormat::loadFrom(imageFile);
+ Image image = ImageFileFormat::loadFrom(imageFile);
if (image.isNull())
{