Skip to content

Commit 08eb10b

Browse files
committed
Chorus plugin implemented and tweaks to flanger param ranges
1 parent 8d78795 commit 08eb10b

File tree

9 files changed

+57
-34
lines changed

9 files changed

+57
-34
lines changed

plugins/Chorus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ add_plugin(Chorus
1717
RESOURCES
1818
logos/Jonssonic_logo.png
1919
knobs/JonssonicRotarySlider.png
20+
knobs/JonssonicRotarySlider_Chorus.png
2021
)

plugins/Chorus/Params.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,21 @@
1111
struct ChorusParams {
1212

1313
// Parameter IDs as enum
14-
enum class ID { Mix, Enable, Mode };
14+
enum class ID { Feedback, Rate, Depth, Delay, Spread, Mix };
1515

1616
// Create parameter definitions
1717
inline jnsc::juce_interface::ParameterSet<ID> createParams() {
1818
using namespace jnsc::juce_interface;
1919

2020
ParameterSet<ID> params;
2121
// clang-format off
22-
// Float parameter ↓ id ↓ name ↓ min ↓ max ↓ def ↓ unit ↓ skew
23-
params.add(FloatParam<ID>{ID::Mix, "Mix", 0.0f, 100.0f, 50.0f, "%", 1.0f});
24-
25-
// Bool parameter ↓ id ↓ name ↓ def ↓ true label ↓ false label
26-
params.add(BoolParam<ID>{ID::Enable, "Enable", false, "On", "Off"});
27-
28-
// Choice parameter ↓ id ↓ name ↓ choices ↓ def idx
29-
params.add(ChoiceParam<ID>{ID::Mode, "Mode", {"Mode1", "Mode2", "Mode3"}, 0});
22+
// Float parameter ↓ id ↓ name ↓ min ↓ max ↓ def ↓ unit ↓ skew
23+
params.add(FloatParam<ID>{ID::Rate, "Rate", 0.1f, 5.0f, 1.0f, "Hz", 1.0f});
24+
params.add(FloatParam<ID>{ID::Depth, "Depth", 0.0f, 100.0f, 50.0f, "%", 1.0f});
25+
params.add(FloatParam<ID>{ID::Spread, "Spread", 0.0f, 100.0f, 0.0f, "%", 1.0f});
26+
params.add(FloatParam<ID>{ID::Delay, "Delay", 10.0f, 30.0f, 20.0f, "ms", 1.0f});
27+
params.add(FloatParam<ID>{ID::Feedback, "Feedback", 0.0f, 100.0f, 0.0f, "%", 1.0f});
28+
params.add(FloatParam<ID>{ID::Mix, "Mix", 0.0f, 100.0f, 50.0f, "%", 1.0f});
3029
// clang-format on
3130
return params;
3231
}

plugins/Chorus/PluginEditor.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ ChorusAudioProcessorEditor::ChorusAudioProcessorEditor(ChorusAudioProcessor& p)
66
jnsc::juce_interface::ControlPanelConfig c;
77
c.columns = 3; // Number of columns in the control panel
88
c.showValueBoxes = true; // Show value boxes for sliders
9-
c.controlHeight = 80; // Height of each control in pixels
10-
c.labelHeight = 20; // Height of labels in pixels
11-
c.spacing = 10; // Spacing between controls in pixels
129
c.title = "JONSSONIC"; // Plugin title
13-
c.subtitle = "CHORUS"; // Plugin subtitle
14-
// Optionally set other config fields here
10+
c.subtitle = "CHORUS"; // Plugin subtitle
11+
c.backgroundColor = juce::Colour(0xff3C8CC8).brighter(0.1f);
12+
// Optionally set other config fields here
1513
return c;
1614
}()),
1715
controlPanel(audioProcessor.getAPVTS(), controlPanelConfig) {
18-
customLookAndFeel = std::make_unique<TemplateLookAndFeel>(&controlPanelConfig);
16+
customLookAndFeel = std::make_unique<ChorusLookAndFeel>(&controlPanelConfig);
1917
setLookAndFeel(customLookAndFeel.get());
2018
addAndMakeVisible(controlPanel); // Add and make the control panel visible in the editor
2119
setSize(400, 350); // Set the size of the editor window in pixels
@@ -29,14 +27,14 @@ ChorusAudioProcessorEditor::~ChorusAudioProcessorEditor() {
2927
//==============================================================================
3028
void ChorusAudioProcessorEditor::paint(juce::Graphics& g) {
3129

32-
if (auto* laf = dynamic_cast<TemplateLookAndFeel*>(&getLookAndFeel()))
30+
if (auto* laf = dynamic_cast<ChorusLookAndFeel*>(&getLookAndFeel()))
3331
laf->drawCachedMainBackground(g);
3432
else
3533
g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));
3634
}
3735

3836
void ChorusAudioProcessorEditor::resized() {
3937
controlPanel.setBounds(getLocalBounds()); // Make the control panel fill the entire editor area
40-
if (auto* laf = dynamic_cast<TemplateLookAndFeel*>(&getLookAndFeel()))
38+
if (auto* laf = dynamic_cast<ChorusLookAndFeel*>(&getLookAndFeel()))
4139
laf->generateMainBackground(getWidth(), getHeight());
4240
}

plugins/Chorus/PluginEditor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ChorusAudioProcessorEditor : public juce::AudioProcessorEditor {
2424
// Automatic control panel for parameters
2525
jnsc::juce_interface::ControlPanel controlPanel;
2626

27-
std::unique_ptr<TemplateLookAndFeel> customLookAndFeel;
27+
std::unique_ptr<ChorusLookAndFeel> customLookAndFeel;
2828

2929
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ChorusAudioProcessorEditor)
3030
};

plugins/Chorus/PluginLookAndFeel.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
* @note Currently, it overrides the knob strip image with a plugin-specific one if available.
1111
*/
1212

13-
class TemplateLookAndFeel : public jnsc::juce_interface::CustomLookAndFeel {
13+
class ChorusLookAndFeel : public jnsc::juce_interface::CustomLookAndFeel {
1414
public:
15-
TemplateLookAndFeel(const jnsc::juce_interface::ControlPanelConfig* config) : CustomLookAndFeel(config) {
15+
ChorusLookAndFeel(const jnsc::juce_interface::ControlPanelConfig* config) : CustomLookAndFeel(config) {
1616
// Override the knob strip with the plugin-specific one from the bundle's Resources folder at runtime
17-
juce::File knobFile = jnsc::juce_interface::getResourceFile("knobs/JonssonicRotarySlider_Template.png");
17+
juce::File knobFile = jnsc::juce_interface::getResourceFile("knobs/JonssonicRotarySlider_Chorus.png");
1818
if (knobFile.existsAsFile()) {
1919
setKnobStrip(juce::ImageFileFormat::loadFrom(knobFile));
2020
}

plugins/Chorus/PluginProcessor.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "PluginProcessor.h"
22
#include "PluginEditor.h"
3+
#include <JuceHeader.h>
34
#include <iostream>
45
#include <jonssonic/utils/buffer_utils.h>
56

@@ -20,19 +21,36 @@ ChorusAudioProcessor::ChorusAudioProcessor() : parameterManager(ChorusParams().c
2021
// Register callbacks for parameter changes
2122
using ID = ChorusParams::ID;
2223

23-
parameterManager.on(ID::Mix, [this](float value, bool skipSmoothing) {
24-
DBG("[DEBUG] Mix changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
25-
// Call your DSP mix setter here
26-
dryWetMixer.setMix(value * 0.01f); // We are converting from [0,100] to [0,1]
24+
parameterManager.on(ID::Rate, [this](float value, bool skipSmoothing) {
25+
DBG("[DEBUG] Rate changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
26+
chorus.setRate(value, skipSmoothing);
27+
});
28+
29+
parameterManager.on(ID::Depth, [this](float value, bool skipSmoothing) {
30+
DBG("[DEBUG] Depth changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
31+
chorus.setDepth(value * 0.01f, skipSmoothing); // We are converting from [0,100] to [0,1]
32+
});
33+
34+
parameterManager.on(ID::Spread, [this](float value, bool skipSmoothing) {
35+
DBG("[DEBUG] Spread changed: " + juce::String(value) +
36+
", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
37+
chorus.setSpread(value * 0.01f, skipSmoothing); // We are converting from [0,100] to [0,1]
2738
});
28-
parameterManager.on(ID::Enable, [this](bool value, bool skipSmoothing) {
29-
DBG("[DEBUG] Enable changed: " + juce::String(value ? "true" : "false") +
39+
40+
parameterManager.on(ID::Delay, [this](float value, bool skipSmoothing) {
41+
DBG("[DEBUG] Delay changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
42+
chorus.setDelayMs(value, skipSmoothing);
43+
});
44+
45+
parameterManager.on(ID::Feedback, [this](float value, bool skipSmoothing) {
46+
DBG("[DEBUG] Feedback changed: " + juce::String(value) +
3047
", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
31-
// Call your DSP enable setter here
48+
chorus.setFeedback(value * 0.01f, skipSmoothing); // We are converting from [0,100] to [0,1]
3249
});
33-
parameterManager.on(ID::Mode, [this](int value, bool skipSmoothing) {
34-
DBG("[DEBUG] Mode changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
35-
// Call your DSP mode setter here
50+
51+
parameterManager.on(ID::Mix, [this](float value, bool skipSmoothing) {
52+
DBG("[DEBUG] Mix changed: " + juce::String(value) + ", skipSmoothing: " + (skipSmoothing ? "true" : "false"));
53+
dryWetMixer.setMix(value * 0.01f); // We are converting from [0,100] to [0,1]
3654
});
3755
}
3856

@@ -43,6 +61,7 @@ void ChorusAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
4361
// Prepare all DSP objects and buffers here
4462
dryWetMixer.prepare(numChannels, static_cast<float>(sampleRate));
4563
fxBuffer.resize(numChannels, static_cast<size_t>(samplesPerBlock));
64+
chorus.prepare(numChannels, static_cast<float>(sampleRate));
4665

4766
// Initialize DSP with parameter defaults (defined in Params.h) (skip smoothing for instant setup)
4867
parameterManager.syncAll(true);
@@ -52,6 +71,7 @@ void ChorusAudioProcessor::releaseResources() {
5271
// Release DSP resources here
5372
dryWetMixer.reset();
5473
fxBuffer.resize(0, 0);
74+
chorus.reset();
5575
}
5676

5777
void ChorusAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages) {
@@ -78,7 +98,10 @@ void ChorusAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::
7898
numOutputChannels,
7999
numSamples);
80100

81-
// DSP processing here (this template includes only a dry/wet mixer as an example)
101+
// Process the chorus effect
102+
chorus.processBlock(fxBuffer.readPtrs(), fxBuffer.writePtrs(), static_cast<size_t>(numSamples));
103+
104+
// Dry/wet processing
82105
dryWetMixer.processBlock(buffer.getArrayOfReadPointers(), // dry buffer
83106
fxBuffer.readPtrs(), // wet buffer
84107
buffer.getArrayOfWritePointers(), // final output

plugins/Chorus/PluginProcessor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <MinimalJuceHeader.h>
55
#include <jonssonic/core/common/audio_buffer.h>
66
#include <jonssonic/core/mixing/dry_wet_mixer.h>
7+
#include <jonssonic/effects/chorus.h>
78
#include <parameters/ParameterManager.h>
89

910
class ChorusAudioProcessor : public juce::AudioProcessor {
@@ -40,6 +41,7 @@ class ChorusAudioProcessor : public juce::AudioProcessor {
4041
// DSP objects and buffers
4142
jnsc::AudioBuffer<float> fxBuffer; // Buffer for effect processing
4243
jnsc::DryWetMixer<float> dryWetMixer; // Dry/wet mixer
44+
jnsc::effects::Chorus<float> chorus; // Chorus effect processor
4345

4446
// Parameter manager
4547
jnsc::juce_interface::ParameterManager<ChorusParams::ID> parameterManager;

plugins/Flanger/Params.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ struct FlangerParams {
1919
ParameterSet<ID> params;
2020
// ↓ id ↓ name ↓ min ↓ max ↓ def ↓ unit ↓ skew
2121
// clang-format off
22-
params.add(FloatParam<ID>{ID::Rate, "Rate", 0.05f, 2.0f, 0.3f, "Hz", 0.3f});
22+
params.add(FloatParam<ID>{ID::Rate, "Rate", 0.01f, 10.0f, 0.5f, "Hz", 0.3f});
2323
params.add(FloatParam<ID>{ID::Depth, "Depth", 0.0f, 100.0f, 50.0f, "%", 1.0f});
2424
params.add(FloatParam<ID>{ID::Spread, "Spread", 0.0f, 100.0f, 0.0f, "%", 1.0f});
25-
params.add(FloatParam<ID>{ID::Delay, "Delay", 0.2f, 4.0f, 2.0f, "ms", 1.0f});
25+
params.add(FloatParam<ID>{ID::Delay, "Delay", 1.0f, 5.0f, 2.0f, "ms", 1.0f});
2626
params.add(FloatParam<ID>{ID::Feedback, "Feedback", -100.0f, 100.0f, 25.0f, "%", 1.0f});
2727
params.add(FloatParam<ID>{ID::Mix, "Mix", 0.0f, 100.0f, 100.0f, "%", 1.0f});
2828
// clang-format on
1.44 MB
Loading

0 commit comments

Comments
 (0)