Initial release — InstaGrain granular synthesizer v1.0
8-voice polyphonic granular synth (VST3/AU/LV2) with: - 128 grain pool per voice, Hann windowing, linear interpolation - Root note selector, sample rate correction, sustain pedal (CC64) - Scatter controls, direction modes (Fwd/Rev/PingPong), freeze - ADSR envelope, global filter (LP/HP/BP), reverb - Waveform display with grain visualization - Drag & drop sample loading, full state save/restore - CI/CD for Windows/macOS/Linux Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
93
Source/EffectsPanel.cpp
Normal file
93
Source/EffectsPanel.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "EffectsPanel.h"
|
||||
|
||||
EffectsPanel::EffectsPanel()
|
||||
{
|
||||
titleLabel.setText ("FILTER / REVERB", juce::dontSendNotification);
|
||||
titleLabel.setJustificationType (juce::Justification::centredLeft);
|
||||
titleLabel.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textPrimary);
|
||||
addAndMakeVisible (titleLabel);
|
||||
|
||||
filterTypeBox.addItem ("LP", 1);
|
||||
filterTypeBox.addItem ("HP", 2);
|
||||
filterTypeBox.addItem ("BP", 3);
|
||||
filterTypeBox.setSelectedId (1);
|
||||
addAndMakeVisible (filterTypeBox);
|
||||
|
||||
filterLabel.setText ("Type", juce::dontSendNotification);
|
||||
filterLabel.setJustificationType (juce::Justification::centred);
|
||||
filterLabel.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textSecondary);
|
||||
addAndMakeVisible (filterLabel);
|
||||
|
||||
auto setupKnob = [this] (juce::Slider& knob, juce::Label& label, const juce::String& name,
|
||||
double min, double max, double def, const juce::String& type,
|
||||
const juce::String& suffix = "")
|
||||
{
|
||||
knob.setSliderStyle (juce::Slider::RotaryHorizontalVerticalDrag);
|
||||
knob.setTextBoxStyle (juce::Slider::TextBoxBelow, false, 55, 14);
|
||||
knob.setRange (min, max);
|
||||
knob.setValue (def);
|
||||
knob.setTextValueSuffix (suffix);
|
||||
knob.getProperties().set (InstaGrainLookAndFeel::knobTypeProperty, type);
|
||||
addAndMakeVisible (knob);
|
||||
|
||||
label.setText (name, juce::dontSendNotification);
|
||||
label.setJustificationType (juce::Justification::centred);
|
||||
label.setColour (juce::Label::textColourId, InstaGrainLookAndFeel::textSecondary);
|
||||
addAndMakeVisible (label);
|
||||
};
|
||||
|
||||
setupKnob (cutoffKnob, cutoffLabel, "Cutoff", 20.0, 20000.0, 20000.0, "orange", " Hz");
|
||||
cutoffKnob.setSkewFactorFromMidPoint (1000.0);
|
||||
|
||||
setupKnob (resoKnob, resoLabel, "Reso", 0.1, 10.0, 0.707, "dark");
|
||||
resoKnob.setSkewFactorFromMidPoint (1.5);
|
||||
|
||||
setupKnob (reverbSizeKnob, revSizeLabel, "Rev Size", 0.0, 1.0, 0.0, "dark");
|
||||
setupKnob (reverbDecayKnob, revDecayLabel, "Rev Decay", 0.0, 1.0, 0.0, "dark");
|
||||
}
|
||||
|
||||
void EffectsPanel::resized()
|
||||
{
|
||||
auto bounds = getLocalBounds().reduced (4);
|
||||
titleLabel.setBounds (bounds.removeFromTop (20));
|
||||
|
||||
int colW = bounds.getWidth() / 5;
|
||||
|
||||
// Filter type combo
|
||||
auto typeCol = bounds.removeFromLeft (colW);
|
||||
filterLabel.setBounds (typeCol.removeFromTop (14));
|
||||
filterTypeBox.setBounds (typeCol.reduced (4, 2).removeFromTop (24));
|
||||
|
||||
// Cutoff
|
||||
auto cutCol = bounds.removeFromLeft (colW);
|
||||
auto cutKnobArea = cutCol.withTrimmedBottom (16);
|
||||
cutoffKnob.setBounds (cutKnobArea.reduced (2));
|
||||
cutoffLabel.setBounds (cutCol.getX(), cutKnobArea.getBottom() - 2, cutCol.getWidth(), 16);
|
||||
|
||||
// Reso
|
||||
auto resCol = bounds.removeFromLeft (colW);
|
||||
auto resKnobArea = resCol.withTrimmedBottom (16);
|
||||
resoKnob.setBounds (resKnobArea.reduced (2));
|
||||
resoLabel.setBounds (resCol.getX(), resKnobArea.getBottom() - 2, resCol.getWidth(), 16);
|
||||
|
||||
// Reverb Size
|
||||
auto rsCol = bounds.removeFromLeft (colW);
|
||||
auto rsKnobArea = rsCol.withTrimmedBottom (16);
|
||||
reverbSizeKnob.setBounds (rsKnobArea.reduced (2));
|
||||
revSizeLabel.setBounds (rsCol.getX(), rsKnobArea.getBottom() - 2, rsCol.getWidth(), 16);
|
||||
|
||||
// Reverb Decay
|
||||
auto rdCol = bounds;
|
||||
auto rdKnobArea = rdCol.withTrimmedBottom (16);
|
||||
reverbDecayKnob.setBounds (rdKnobArea.reduced (2));
|
||||
revDecayLabel.setBounds (rdCol.getX(), rdKnobArea.getBottom() - 2, rdCol.getWidth(), 16);
|
||||
}
|
||||
|
||||
void EffectsPanel::paint (juce::Graphics& g)
|
||||
{
|
||||
auto bounds = getLocalBounds().toFloat();
|
||||
g.setColour (InstaGrainLookAndFeel::bgMedium.withAlpha (0.5f));
|
||||
g.fillRoundedRectangle (bounds, 4.0f);
|
||||
g.setColour (InstaGrainLookAndFeel::bgLight.withAlpha (0.3f));
|
||||
g.drawRoundedRectangle (bounds, 4.0f, 1.0f);
|
||||
}
|
||||
Reference in New Issue
Block a user