Upload files to "Source"
This commit is contained in:
@@ -1,404 +1,170 @@
|
|||||||
/*
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
This file contains the basic framework code for a JUCE plugin editor.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "PluginProcessor.h"
|
#include "PluginProcessor.h"
|
||||||
#include "PluginEditor.h"
|
#include "PluginEditor.h"
|
||||||
#include "ScopeComponent.h"
|
#include "ScopeComponent.h"
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
|
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
|
||||||
: AudioProcessorEditor (&p), audioProcessor (p), mainScopeComponent(audioProcessor.getAudioBufferQueue())
|
: AudioProcessorEditor (&p),
|
||||||
|
audioProcessor (p),
|
||||||
|
mainScopeComponent(audioProcessor.getAudioBufferQueue())
|
||||||
{
|
{
|
||||||
auto& tree = audioProcessor.parameters;
|
auto& tree = audioProcessor.parameters;
|
||||||
|
|
||||||
//auto area = getLocalBounds();
|
|
||||||
//mainScopeComponent.setBounds(5, 5, 800, 200);
|
|
||||||
// scopeComponent.setSize(800, 200);
|
|
||||||
|
|
||||||
addAndMakeVisible(mainScopeComponent);
|
addAndMakeVisible(mainScopeComponent);
|
||||||
|
|
||||||
waveformSelector.setModel(&waveformContents);
|
waveformSelector.setModel(&waveformContents);
|
||||||
|
waveformContents.onSelect = [this](int row)
|
||||||
|
{
|
||||||
|
// write to the parameter so voices update safely
|
||||||
|
audioProcessor.parameters.getParameterAsValue("waveform") = (float)juce::jlimit(0, 3, row);
|
||||||
|
};
|
||||||
addAndMakeVisible(waveformSelector);
|
addAndMakeVisible(waveformSelector);
|
||||||
|
|
||||||
|
// --- Panels ---
|
||||||
chorusComponent.emplace(tree, "chorus");
|
adsrComponent.emplace(tree, "adsr", "Amp Env");
|
||||||
|
|
||||||
chorusComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue());
|
|
||||||
addAndMakeVisible(*chorusComponent);
|
|
||||||
|
|
||||||
delayComponent.emplace(tree, "delay");
|
|
||||||
delayComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue());
|
|
||||||
addAndMakeVisible(*delayComponent);
|
|
||||||
|
|
||||||
reverbComponent.emplace(tree, "reverb");
|
|
||||||
|
|
||||||
reverbComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue());
|
|
||||||
addAndMakeVisible(*reverbComponent);
|
|
||||||
|
|
||||||
|
|
||||||
adsrComponent.emplace(tree, "adsr");
|
|
||||||
|
|
||||||
adsrComponent->enableGraphScope([this](float x) {
|
adsrComponent->enableGraphScope([this](float x) {
|
||||||
auto& tree = this->audioProcessor.parameters;
|
auto& tree = this->audioProcessor.parameters;
|
||||||
|
|
||||||
float attackValue = tree.getParameter("adsr_attack")->getValue();
|
float A = tree.getParameter("adsr_attack")->getValue();
|
||||||
float decayValue = tree.getParameter("adsr_decay")->getValue();
|
float D = tree.getParameter("adsr_decay")->getValue();
|
||||||
float sustainValue = tree.getParameter("adsr_sustain")->getValue();
|
float S = tree.getParameter("adsr_sustain")->getValue();
|
||||||
float releaseValue = tree.getParameter("adsr_release")->getValue();
|
float R = tree.getParameter("adsr_release")->getValue();
|
||||||
|
|
||||||
float sustainLength = 1.0f;
|
const float sustainLen = 1.0f;
|
||||||
float totalTime = attackValue + decayValue + sustainLength + releaseValue;
|
const float total = A + D + sustainLen + R;
|
||||||
|
A /= total; D /= total; R /= total;
|
||||||
attackValue /= totalTime;
|
|
||||||
decayValue /= totalTime;
|
|
||||||
sustainLength /= totalTime;
|
|
||||||
releaseValue /= totalTime;
|
|
||||||
|
|
||||||
float m, c;
|
|
||||||
if (x < attackValue)
|
|
||||||
{
|
|
||||||
m = (1.0f / attackValue);
|
|
||||||
c = 0;
|
|
||||||
}
|
|
||||||
else if (x < (attackValue + decayValue)) {
|
|
||||||
m = (sustainValue - 1.0f) / decayValue;
|
|
||||||
c = 1.0f - m * attackValue;
|
|
||||||
}
|
|
||||||
else if (x < (attackValue + decayValue + sustainLength)) {
|
|
||||||
m = 0.0f;
|
|
||||||
c = sustainValue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m = (sustainValue / -releaseValue);
|
|
||||||
c = -m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
float m = 0.0f, c = 0.0f;
|
||||||
|
if (x < A) { m = 1.0f / A; c = 0.0f; }
|
||||||
|
else if (x < A + D) { m = (S - 1.0f) / D; c = 1.0f - m * A; }
|
||||||
|
else if (x < A + D + (sustainLen / total)) { m = 0.0f; c = S; }
|
||||||
|
else { m = (S / -R); c = -m; }
|
||||||
return m * x + c;
|
return m * x + c;
|
||||||
});
|
});
|
||||||
addAndMakeVisible(*adsrComponent);
|
addAndMakeVisible(*adsrComponent);
|
||||||
|
|
||||||
//createADSR(5, 250);
|
chorusComponent.emplace(tree, "chorus", "Chorus");
|
||||||
//createEQ();
|
chorusComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue());
|
||||||
|
addAndMakeVisible(*chorusComponent);
|
||||||
|
|
||||||
addAndMakeVisible(masterLevelSlider);
|
delayComponent.emplace(tree, "delay", "Delay");
|
||||||
|
delayComponent->enableSampleScope(audioProcessor.getDelayAudioBufferQueue());
|
||||||
|
addAndMakeVisible(*delayComponent);
|
||||||
|
|
||||||
eqComponent.emplace(tree);
|
reverbComponent.emplace(tree, "reverb", "Reverb");
|
||||||
|
reverbComponent->enableSampleScope(audioProcessor.getReverbAudioBufferQueue());
|
||||||
|
addAndMakeVisible(*reverbComponent);
|
||||||
|
|
||||||
|
eqComponent.emplace(tree, "EQ");
|
||||||
addAndMakeVisible(*eqComponent);
|
addAndMakeVisible(*eqComponent);
|
||||||
|
|
||||||
// Attach to parameter
|
flangerComponent.emplace(tree, "flanger", "Flanger");
|
||||||
//waveformAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ComboBoxAttachment>(
|
|
||||||
// audioProcessor.parameters, "waveform", waveformSelector);
|
|
||||||
|
|
||||||
//attachments.push_back(std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
|
||||||
// tree, sliderDetail.name, *sliders.back()));
|
|
||||||
|
|
||||||
gainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
|
||||||
audioProcessor.parameters, "master", masterLevelSlider.slider
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
flangerComponent.emplace(tree, "flanger");
|
|
||||||
flangerComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue());
|
flangerComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue());
|
||||||
addAndMakeVisible(*flangerComponent);
|
addAndMakeVisible(*flangerComponent);
|
||||||
|
|
||||||
distortionComponent.emplace(tree, "distortion");
|
distortionComponent.emplace(tree, "distortion", "Distortion");
|
||||||
distortionComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue());
|
distortionComponent->enableSampleScope(audioProcessor.getDistortionAudioBufferQueue());
|
||||||
addAndMakeVisible(*distortionComponent);
|
addAndMakeVisible(*distortionComponent);
|
||||||
|
|
||||||
filterComponent.emplace(tree, "filter");
|
filterComponent.emplace(tree, "filter", "Filter");
|
||||||
filterComponent->enableSampleScope(audioProcessor.getFilterAudioBufferQueue());
|
filterComponent->enableSampleScope(audioProcessor.getFilterAudioBufferQueue());
|
||||||
addAndMakeVisible(*filterComponent);
|
addAndMakeVisible(*filterComponent);
|
||||||
|
|
||||||
//addAndMakeVisible(midiKeyboardComponent);
|
filterEnvComponent.emplace(tree, "fenv", "Filter Env");
|
||||||
|
filterEnvComponent->enableGraphScope([this](float x) {
|
||||||
|
|
||||||
//scopeComponent.setSize(area.getWidth(), area.getHeight());
|
|
||||||
|
|
||||||
//midiKeyboardComponent.setMidiChannel(2);
|
|
||||||
//midiKeyboardState.addListener(&audioProcessor.getMidiMessageCollector());
|
|
||||||
|
|
||||||
//midiKeyboardComponent.setBounds(area.removeFromTop(80).reduced(8));
|
|
||||||
//midiKeyboardComponent.setTopLeftPosition(8, 420);
|
|
||||||
|
|
||||||
// Make sure that before the constructor has finished, you've set the
|
|
||||||
// editor's size to whatever you need it to be.
|
|
||||||
setSize(1400, 700);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*void NeuralSynthAudioProcessorEditor::updateEQFromSliders()
|
|
||||||
{
|
|
||||||
using Coefficients = juce::dsp::IIR::Coefficients<float>;
|
|
||||||
|
|
||||||
auto& low = audioProcessor.getProcess.get<0>();
|
|
||||||
auto& mid = audioProcessor.eqChain.get<1>();
|
|
||||||
auto& high = audioProcessor.eqChain.get<2>();
|
|
||||||
|
|
||||||
low.coefficients = Coefficients::makeLowShelf(audioProcessor.sampleRate, 100.0f, 0.707f,
|
|
||||||
juce::Decibels::decibelsToGain(lowGainSlider.getValue()));
|
|
||||||
mid.coefficients = Coefficients::makePeakFilter(audioProcessor.sampleRate, 1000.0f, 0.707f,
|
|
||||||
juce::Decibels::decibelsToGain(midGainSlider.getValue()));
|
|
||||||
high.coefficients = Coefficients::makeHighShelf(audioProcessor.sampleRate, 8000.0f, 0.707f,
|
|
||||||
juce::Decibels::decibelsToGain(highGainSlider.getValue()));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/*void NeuralSynthAudioProcessorEditor::createADSR(int xCoord, int yCoord) {
|
|
||||||
adsrGraph.setFunction([this](float x) {
|
|
||||||
auto& tree = this->audioProcessor.parameters;
|
auto& tree = this->audioProcessor.parameters;
|
||||||
|
|
||||||
float attackValue = tree.getParameter("attack")->getValue();
|
float A = tree.getParameter("fenv_attack")->getValue();
|
||||||
float decayValue = tree.getParameter("decay")->getValue();
|
float D = tree.getParameter("fenv_decay")->getValue();
|
||||||
float sustainValue = tree.getParameter("sustain")->getValue();
|
float S = tree.getParameter("fenv_sustain")->getValue();
|
||||||
float releaseValue = tree.getParameter("release")->getValue();
|
float R = tree.getParameter("fenv_release")->getValue();
|
||||||
|
|
||||||
float sustainLength = 1.0f;
|
const float sustainLen = 1.0f;
|
||||||
float totalTime = attackValue + decayValue + sustainLength + releaseValue;
|
const float total = A + D + sustainLen + R;
|
||||||
|
A /= total; D /= total; R /= total;
|
||||||
attackValue /= totalTime;
|
|
||||||
decayValue /= totalTime;
|
|
||||||
sustainLength /= totalTime;
|
|
||||||
releaseValue /= totalTime;
|
|
||||||
|
|
||||||
float m, c;
|
|
||||||
if (x < attackValue)
|
|
||||||
{
|
|
||||||
m = (1.0f / attackValue);
|
|
||||||
c = 0;
|
|
||||||
} else if (x < (attackValue + decayValue)) {
|
|
||||||
m = (sustainValue - 1.0f) / decayValue;
|
|
||||||
c = 1.0f - m * attackValue;
|
|
||||||
} else if (x < (attackValue + decayValue + sustainLength)) {
|
|
||||||
m = 0.0f;
|
|
||||||
c = sustainValue;
|
|
||||||
} else {
|
|
||||||
m = (sustainValue / -releaseValue);
|
|
||||||
c = -m;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
float m = 0.0f, c = 0.0f;
|
||||||
|
if (x < A) { m = 1.0f / A; c = 0.0f; }
|
||||||
|
else if (x < A + D) { m = (S - 1.0f) / D; c = 1.0f - m * A; }
|
||||||
|
else if (x < A + D + (sustainLen / total)) { m = 0.0f; c = S; }
|
||||||
|
else { m = (S / -R); c = -m; }
|
||||||
return m * x + c;
|
return m * x + c;
|
||||||
});
|
});
|
||||||
|
addAndMakeVisible(*filterEnvComponent);
|
||||||
|
|
||||||
|
// Master fader + label
|
||||||
int fontSize = 11;
|
addAndMakeVisible(masterLevelSlider);
|
||||||
int leftPosition = xCoord;
|
masterLevelLabel.setText("Master", juce::dontSendNotification);
|
||||||
const int sliderWidth = 60;
|
|
||||||
const int sliderWidthWithPadding = sliderWidth + 20;
|
|
||||||
|
|
||||||
adsrGraph.setBounds(xCoord, yCoord, 240, 150);
|
|
||||||
|
|
||||||
addAndMakeVisible(adsrGraph);
|
|
||||||
|
|
||||||
|
|
||||||
for (auto* slider : { &attackSlider, &decaySlider, &sustainSlider, &releaseSlider })
|
|
||||||
{
|
{
|
||||||
slider->setSliderStyle(juce::Slider::Rotary);
|
juce::Font f; f.setHeight(12.0f); f.setBold(true);
|
||||||
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, sliderWidth + 20, 20);
|
masterLevelLabel.setFont(f);
|
||||||
//slider->setTopLeftPosition(0, 0);
|
|
||||||
slider->setBounds(leftPosition, yCoord + 150, sliderWidth, sliderWidthWithPadding);
|
|
||||||
addAndMakeVisible(*slider);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
}
|
||||||
|
masterLevelLabel.setJustificationType(juce::Justification::centred);
|
||||||
|
addAndMakeVisible(masterLevelLabel);
|
||||||
|
|
||||||
leftPosition = xCoord + 3; // (sliderWidth / 2);
|
// Blank placeholder
|
||||||
for (auto* label : { &attackLabel, &decayLabel, &sustainLabel, &releaseLabel })
|
addAndMakeVisible(blankPanel);
|
||||||
{
|
|
||||||
label->setFont(juce::Font((float)fontSize, juce::Font::bold));
|
|
||||||
//label->setTopLeftPosition(leftPosition, 300);
|
|
||||||
label->setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
|
||||||
label->setJustificationType(juce::Justification::centred);
|
|
||||||
label->setBounds(leftPosition, yCoord + 240, 50, 20);
|
|
||||||
//label->setText("");
|
|
||||||
addAndMakeVisible(*label);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
attackLabel.setText("Attack", juce::dontSendNotification); decayLabel.setText("Decay", juce::dontSendNotification);
|
// Attach master parameter
|
||||||
sustainLabel.setText("Sustain", juce::dontSendNotification); releaseLabel.setText("Release", juce::dontSendNotification);
|
gainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
||||||
|
audioProcessor.parameters, "master", masterLevelSlider.slider);
|
||||||
|
|
||||||
auto& tree = this->audioProcessor.parameters;
|
setSize(1400, 720);
|
||||||
|
|
||||||
attackAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "attack", attackSlider);
|
|
||||||
decayAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "decay", decaySlider);
|
|
||||||
sustainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "sustain", sustainSlider);
|
|
||||||
releaseAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "release", releaseSlider);
|
|
||||||
|
|
||||||
attackSlider.setRange(0.0, 1.0);
|
|
||||||
decaySlider.setRange(0.0, 1.0);
|
|
||||||
sustainSlider.setRange(0.0, 1.0);
|
|
||||||
releaseSlider.setRange(0.0, 1.0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*void NeuralSynthAudioProcessorEditor::createDelay(int xCoord, int yCoord) {
|
|
||||||
int fontSize = 11;
|
|
||||||
int leftPosition = xCoord;
|
|
||||||
const int sliderWidth = 60;
|
|
||||||
const int sliderWidthWithPadding = sliderWidth + 20;
|
|
||||||
|
|
||||||
delayScopeComponent.setBounds(xCoord, yCoord, 300, 150);
|
|
||||||
|
|
||||||
addAndMakeVisible(delayScopeComponent);
|
|
||||||
|
|
||||||
|
|
||||||
for (auto* slider : { &delayDelaySlider })
|
|
||||||
{
|
|
||||||
slider->setSliderStyle(juce::Slider::Rotary);
|
|
||||||
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, sliderWidth + 20, 20);
|
|
||||||
//slider->setTopLeftPosition(0, 0);
|
|
||||||
slider->setBounds(leftPosition, yCoord + 150, sliderWidth, sliderWidthWithPadding);
|
|
||||||
addAndMakeVisible(*slider);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
leftPosition = xCoord + 3; // (sliderWidth / 2);
|
|
||||||
for (auto* label : { &delayDelayLabel })
|
|
||||||
{
|
|
||||||
label->setFont(juce::Font((float)fontSize, juce::Font::bold));
|
|
||||||
//label->setTopLeftPosition(leftPosition, 300);
|
|
||||||
label->setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
|
||||||
label->setJustificationType(juce::Justification::centred);
|
|
||||||
label->setBounds(leftPosition, yCoord + 240, 50, 20);
|
|
||||||
//label->setText("");
|
|
||||||
addAndMakeVisible(*label);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
delayDelayLabel.setText("Delay", juce::dontSendNotification);
|
|
||||||
|
|
||||||
auto& tree = this->audioProcessor.parameters;
|
|
||||||
delayDelayAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "delayDelay", reverbRoomSizeSlider);
|
|
||||||
|
|
||||||
delayDelaySlider.setRange(0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*void NeuralSynthAudioProcessorEditor::createReverb(int xCoord, int yCoord) {
|
//==============================================================================
|
||||||
|
NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor() = default;
|
||||||
int fontSize = 11;
|
|
||||||
int leftPosition = xCoord;
|
|
||||||
const int sliderWidth = 60;
|
|
||||||
const int sliderWidthWithPadding = sliderWidth + 20;
|
|
||||||
|
|
||||||
reverbScopeComponent.setBounds(xCoord, yCoord, 360, 150);
|
|
||||||
|
|
||||||
addAndMakeVisible(reverbScopeComponent);
|
|
||||||
|
|
||||||
|
|
||||||
for (auto* slider : { &reverbRoomSizeSlider, &reverbDampingSlider, &reverbWetLevelSlider, &reverbDryLevelSlider, &reverbWidthSlider, &reverbFreezeModeSlider })
|
|
||||||
{
|
|
||||||
slider->setSliderStyle(juce::Slider::Rotary);
|
|
||||||
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, sliderWidth + 20, 20);
|
|
||||||
//slider->setTopLeftPosition(0, 0);
|
|
||||||
slider->setBounds(leftPosition, yCoord + 150, sliderWidth, sliderWidthWithPadding);
|
|
||||||
addAndMakeVisible(*slider);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
leftPosition = xCoord + 3; // (sliderWidth / 2);
|
|
||||||
for (auto* label : { &reverbRoomSizeLabel, &reverbDampingLabel, &reverbWetLevelLabel, &reverbDryLevelLabel, &reverbWidthLabel, &reverbFreezeModeLabel })
|
|
||||||
{
|
|
||||||
label->setFont(juce::Font((float)fontSize, juce::Font::bold));
|
|
||||||
//label->setTopLeftPosition(leftPosition, 300);
|
|
||||||
label->setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
|
||||||
label->setJustificationType(juce::Justification::centred);
|
|
||||||
label->setBounds(leftPosition, yCoord + 240, 50, 20);
|
|
||||||
//label->setText("");
|
|
||||||
addAndMakeVisible(*label);
|
|
||||||
leftPosition += sliderWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
reverbRoomSizeLabel.setText("Room Size", juce::dontSendNotification); reverbDampingLabel.setText("Damping", juce::dontSendNotification);
|
|
||||||
reverbWetLevelLabel.setText("Wet Level", juce::dontSendNotification); reverbDryLevelLabel.setText("Dry Level", juce::dontSendNotification);
|
|
||||||
reverbWidthLabel.setText("Width", juce::dontSendNotification); reverbFreezeModeLabel.setText("Freeze Mode", juce::dontSendNotification);
|
|
||||||
|
|
||||||
auto& tree = this->audioProcessor.parameters;
|
|
||||||
|
|
||||||
reverbRoomSizeAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbRoomSize", reverbRoomSizeSlider);
|
|
||||||
reverbDampingAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbDamping", reverbDampingSlider);
|
|
||||||
reverbWetLevelAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbWetLevel", reverbWetLevelSlider);
|
|
||||||
reverbDryLevelAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbDryLevel", reverbDryLevelSlider);
|
|
||||||
reverbWidthAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbWidth", reverbWidthSlider);
|
|
||||||
reverbFreezeModeAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "reverbFreezeMode", reverbFreezeModeSlider);
|
|
||||||
|
|
||||||
|
|
||||||
reverbRoomSizeSlider.setRange(0.0, 1.0);
|
|
||||||
reverbDampingSlider.setRange(0.0, 1.0);
|
|
||||||
reverbWetLevelSlider.setRange(0.0, 1.0);
|
|
||||||
reverbDryLevelSlider.setRange(0.0, 1.0);
|
|
||||||
reverbWidthSlider.setRange(0.0, 1.0);
|
|
||||||
reverbFreezeModeSlider.setRange(0.0, 1.0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g)
|
void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g)
|
||||||
{
|
{
|
||||||
// (Our component is opaque, so we must completely fill the background with a solid colour)
|
g.fillAll(getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
|
||||||
g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
|
|
||||||
|
|
||||||
//g.setColour (juce::Colours::white);
|
|
||||||
//g.setFont (juce::FontOptions (15.0f));
|
|
||||||
//g.drawFittedText ("Hello World!", getLocalBounds(), juce::Justification::centred, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void NeuralSynthAudioProcessorEditor::resized()
|
void NeuralSynthAudioProcessorEditor::resized()
|
||||||
{
|
{
|
||||||
// This is generally where you'll want to lay out the positions of any
|
auto bounds = getLocalBounds().reduced(16);
|
||||||
// subcomponents in your editor..
|
|
||||||
auto bounds = getLocalBounds().reduced(20);
|
|
||||||
//auto row = bounds.removeFromTop(150);
|
|
||||||
|
|
||||||
//int knobWidth = row.getWidth() / 4;
|
|
||||||
|
|
||||||
juce::Grid grid;
|
juce::Grid grid;
|
||||||
grid.templateRows = { juce::Grid::TrackInfo(juce::Grid::Fr(20)),
|
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(40)),
|
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(40)) };
|
|
||||||
|
|
||||||
|
grid.templateRows = {
|
||||||
|
juce::Grid::TrackInfo(juce::Grid::Fr(20)), // scope row
|
||||||
|
juce::Grid::TrackInfo(juce::Grid::Fr(40)), // row 1
|
||||||
|
juce::Grid::TrackInfo(juce::Grid::Fr(40)) // row 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// 6 columns: 5 content + 1 sidebar (waveform+master)
|
||||||
grid.templateColumns = {
|
grid.templateColumns = {
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(8))
|
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||||
|
juce::Grid::TrackInfo(juce::Grid::Fr(10))
|
||||||
};
|
};
|
||||||
|
|
||||||
grid.items = {
|
// Row 0
|
||||||
juce::GridItem(mainScopeComponent).withArea({}, juce::GridItem::Span(4)),
|
grid.items.add(juce::GridItem(mainScopeComponent)
|
||||||
juce::GridItem(waveformSelector),
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(5)));
|
||||||
juce::GridItem(*adsrComponent),
|
grid.items.add(juce::GridItem(waveformSelector)
|
||||||
juce::GridItem(*chorusComponent),
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(1)));
|
||||||
juce::GridItem(*delayComponent),
|
|
||||||
juce::GridItem(*reverbComponent),
|
|
||||||
juce::GridItem(masterLevelSlider).withArea(juce::GridItem::Span(2), {}),
|
|
||||||
juce::GridItem(*eqComponent),
|
|
||||||
juce::GridItem(*flangerComponent),
|
|
||||||
juce::GridItem(*distortionComponent),
|
|
||||||
juce::GridItem(*filterComponent),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Row 1
|
||||||
|
grid.items.add(juce::GridItem(*adsrComponent));
|
||||||
|
grid.items.add(juce::GridItem(*chorusComponent));
|
||||||
|
grid.items.add(juce::GridItem(*delayComponent));
|
||||||
|
grid.items.add(juce::GridItem(*reverbComponent));
|
||||||
|
grid.items.add(juce::GridItem(*eqComponent));
|
||||||
|
grid.items.add(juce::GridItem(masterLevelLabel));
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
grid.items.add(juce::GridItem(*flangerComponent));
|
||||||
|
grid.items.add(juce::GridItem(*distortionComponent));
|
||||||
|
grid.items.add(juce::GridItem(*filterComponent));
|
||||||
|
grid.items.add(juce::GridItem(*filterEnvComponent));
|
||||||
|
grid.items.add(juce::GridItem(blankPanel));
|
||||||
|
grid.items.add(juce::GridItem(masterLevelSlider));
|
||||||
|
|
||||||
grid.performLayout(bounds);
|
grid.performLayout(bounds);
|
||||||
|
|
||||||
/*attackSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
|
|
||||||
decaySlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
|
|
||||||
sustainSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
|
|
||||||
releaseSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));*/
|
|
||||||
|
|
||||||
//waveformSelector.setBounds(20, 20, 120, 30);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,3 @@
|
|||||||
/*
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
This file contains the basic framework code for a JUCE plugin editor.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
@@ -13,12 +5,18 @@
|
|||||||
#include "GraphComponent.h"
|
#include "GraphComponent.h"
|
||||||
#include "ScopeComponent.h"
|
#include "ScopeComponent.h"
|
||||||
|
|
||||||
|
//============================== ScopeSliderComponent ==========================
|
||||||
|
// A generic panel: optional scope/graph + rotary sliders + labels.
|
||||||
|
// Adds a per-panel "On" toggle (bound to "<group>_on").
|
||||||
class ScopeSliderComponent : public juce::Component {
|
class ScopeSliderComponent : public juce::Component {
|
||||||
static const int fontSize = 11;
|
static const int fontSize = 11;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopeSliderComponent(juce::AudioProcessorValueTreeState& tree, const std::string paramGroup) {
|
ScopeSliderComponent(juce::AudioProcessorValueTreeState& tree,
|
||||||
|
const std::string paramGroup,
|
||||||
|
const juce::String& titleText = {})
|
||||||
|
: paramGroupId(paramGroup), treeRef(tree)
|
||||||
|
{
|
||||||
const auto& sliderDetails = PARAM_SETTINGS.at(paramGroup);
|
const auto& sliderDetails = PARAM_SETTINGS.at(paramGroup);
|
||||||
|
|
||||||
for (const auto& [name, sliderDetail] : sliderDetails) {
|
for (const auto& [name, sliderDetail] : sliderDetails) {
|
||||||
@@ -27,7 +25,7 @@ public:
|
|||||||
attachments.push_back(std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
attachments.push_back(std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
||||||
tree, paramGroup + "_" + name, *sliders.back()));
|
tree, paramGroup + "_" + name, *sliders.back()));
|
||||||
|
|
||||||
labels.back()->setText(sliderDetail.label, juce::NotificationType::dontSendNotification);
|
labels.back()->setText(sliderDetail.label, juce::dontSendNotification);
|
||||||
sliders.back()->setRange(sliderDetail.min, sliderDetail.max);
|
sliders.back()->setRange(sliderDetail.min, sliderDetail.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,19 +38,35 @@ public:
|
|||||||
|
|
||||||
for (auto& label : labels)
|
for (auto& label : labels)
|
||||||
{
|
{
|
||||||
label->setFont(juce::Font((float)fontSize, juce::Font::bold));
|
juce::Font f; f.setHeight((float)fontSize); f.setBold(true);
|
||||||
|
label->setFont(f);
|
||||||
label->setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
label->setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
||||||
label->setJustificationType(juce::Justification::centred);
|
label->setJustificationType(juce::Justification::centred);
|
||||||
//label->setBoundsToFit()
|
|
||||||
addAndMakeVisible(*label);
|
addAndMakeVisible(*label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (titleText.isNotEmpty())
|
||||||
|
{
|
||||||
|
titleLabel.setText(titleText, juce::dontSendNotification);
|
||||||
|
juce::Font tf; tf.setHeight(12.0f); tf.setBold(true);
|
||||||
|
titleLabel.setFont(tf);
|
||||||
|
titleLabel.setJustificationType(juce::Justification::centredLeft);
|
||||||
|
titleLabel.setColour(juce::Label::textColourId, juce::Colours::white);
|
||||||
|
addAndMakeVisible(titleLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bypass toggle (per panel), id "<group>_on"
|
||||||
|
bypassButton.setButtonText("On");
|
||||||
|
bypassButton.setClickingTogglesState(true);
|
||||||
|
addAndMakeVisible(bypassButton);
|
||||||
|
bypassAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(
|
||||||
|
treeRef, paramGroupId + "_on", bypassButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableSampleScope(AudioBufferQueue<float>& audioBufferQueue) {
|
void enableSampleScope(AudioBufferQueue<float>& audioBufferQueue) {
|
||||||
scope.emplace(audioBufferQueue);
|
scope.emplace(audioBufferQueue);
|
||||||
useGraphScope = false;
|
useGraphScope = false;
|
||||||
addAndMakeVisible(*scope);
|
addAndMakeVisible(*scope);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableGraphScope(const std::function<float(float)>& func) {
|
void enableGraphScope(const std::function<float(float)>& func) {
|
||||||
@@ -65,109 +79,157 @@ public:
|
|||||||
private:
|
private:
|
||||||
void paint(juce::Graphics& g) override
|
void paint(juce::Graphics& g) override
|
||||||
{
|
{
|
||||||
//juce::Random rng;
|
|
||||||
//g.fillAll(juce::Colour::fromFloatRGBA(rng.nextFloat(), rng.nextFloat(), rng.nextFloat(), 1.0f));
|
|
||||||
|
|
||||||
g.fillAll(juce::Colours::darkgrey);
|
g.fillAll(juce::Colours::darkgrey);
|
||||||
|
|
||||||
g.setColour(juce::Colours::white);
|
g.setColour(juce::Colours::white);
|
||||||
g.drawRect(getLocalBounds());
|
g.drawRect(getLocalBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void resized() override {
|
void resized() override
|
||||||
|
{
|
||||||
|
// --- Top bar (manual) ----------------------------------------------
|
||||||
|
auto area = getLocalBounds().reduced(10);
|
||||||
|
auto top = area.removeFromTop(22);
|
||||||
|
auto btnW = 46;
|
||||||
|
bypassButton.setBounds(top.removeFromRight(btnW).reduced(2, 1));
|
||||||
|
titleLabel.setBounds(top);
|
||||||
|
|
||||||
|
// --- Rest (grid) ----------------------------------------------------
|
||||||
juce::Grid grid;
|
juce::Grid grid;
|
||||||
grid.templateRows = { juce::Grid::TrackInfo(juce::Grid::Fr(50)),
|
grid.templateRows = {
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(30)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(55)), // scope/graph
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(10)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(30)), // sliders
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(10))
|
juce::Grid::TrackInfo(juce::Grid::Fr(15)) // labels
|
||||||
};
|
};
|
||||||
|
|
||||||
grid.templateColumns.resize(sliders.size());
|
const int n = (int)sliders.size();
|
||||||
for (int i = 0; i < sliders.size(); i++) {
|
grid.templateColumns.resize(n);
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
grid.templateColumns.getReference(i) = juce::Grid::TrackInfo(juce::Grid::Fr(1));
|
grid.templateColumns.getReference(i) = juce::Grid::TrackInfo(juce::Grid::Fr(1));
|
||||||
|
|
||||||
|
grid.items.clear();
|
||||||
|
|
||||||
|
// Row 1: scope/graph – only add if constructed
|
||||||
|
if (useGraphScope)
|
||||||
|
{
|
||||||
|
if (graphScope)
|
||||||
|
grid.items.add(juce::GridItem(*graphScope)
|
||||||
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(n)));
|
||||||
|
else
|
||||||
|
grid.items.add(juce::GridItem()
|
||||||
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(n)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (scope)
|
||||||
|
grid.items.add(juce::GridItem(*scope)
|
||||||
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(n)));
|
||||||
|
else
|
||||||
|
grid.items.add(juce::GridItem()
|
||||||
|
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(n)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<juce::GridItem> scopeGridItem;
|
// Row 2: sliders
|
||||||
scopeGridItem.emplace(useGraphScope ? juce::GridItem(*graphScope).withArea({}, juce::GridItem::Span(sliders.size()))
|
for (int i = 0; i < n; ++i)
|
||||||
: juce::GridItem(*scope).withArea({}, juce::GridItem::Span(sliders.size())));
|
grid.items.add(juce::GridItem(*sliders[(size_t)i]));
|
||||||
|
|
||||||
grid.items.resize(1 + 2 * sliders.size());
|
// Row 3: labels
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
grid.items.add(juce::GridItem(*labels[(size_t)i]));
|
||||||
|
|
||||||
grid.items.getReference(0) = *scopeGridItem;
|
grid.performLayout(area);
|
||||||
|
|
||||||
for (int i = 0; i < sliders.size(); i++) {
|
|
||||||
grid.items.getReference(i + 1) = juce::GridItem(*sliders[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < sliders.size(); i++) {
|
|
||||||
grid.items.getReference(i + sliders.size() + 1) = juce::GridItem(*labels[i]);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto bounds = getLocalBounds().reduced(10);
|
|
||||||
grid.performLayout(bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useGraphScope{ false };
|
bool useGraphScope{ false };
|
||||||
std::optional<ScopeComponent<float> > scope;
|
std::optional<ScopeComponent<float>> scope;
|
||||||
std::optional<GraphComponent<float> > graphScope;
|
std::optional<GraphComponent<float>> graphScope;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<juce::Slider> > sliders;
|
std::vector<std::unique_ptr<juce::Slider>> sliders;
|
||||||
std::vector<std::unique_ptr<juce::Label> > labels;
|
std::vector<std::unique_ptr<juce::Label>> labels;
|
||||||
std::vector<std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> > attachments;
|
std::vector<std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment>> attachments;
|
||||||
|
|
||||||
|
juce::ToggleButton bypassButton;
|
||||||
|
std::unique_ptr<juce::AudioProcessorValueTreeState::ButtonAttachment> bypassAttachment;
|
||||||
|
|
||||||
|
juce::Label titleLabel;
|
||||||
|
|
||||||
|
std::string paramGroupId;
|
||||||
|
juce::AudioProcessorValueTreeState& treeRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================== EqualizerComponent ============================
|
||||||
|
// Adds an On/Off toggle bound to "eq_on".
|
||||||
class EqualizerComponent : public juce::Component {
|
class EqualizerComponent : public juce::Component {
|
||||||
static const int fontSize = 11;
|
static const int fontSize = 11;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EqualizerComponent(juce::AudioProcessorValueTreeState& tree) {
|
explicit EqualizerComponent(juce::AudioProcessorValueTreeState& tree,
|
||||||
|
const juce::String& titleText = {})
|
||||||
|
{
|
||||||
setupSlider(lowGainSlider);
|
setupSlider(lowGainSlider);
|
||||||
setupSlider(midGainSlider);
|
setupSlider(midGainSlider);
|
||||||
setupSlider(highGainSlider);
|
setupSlider(highGainSlider);
|
||||||
|
|
||||||
setupLabel(lowGainLabel, "L");
|
setupLabel(lowGainLabel, "L");
|
||||||
setupLabel(midGainLabel, "M");
|
setupLabel(midGainLabel, "M");
|
||||||
setupLabel(highGainLabel, "H");
|
setupLabel(highGainLabel, "H");
|
||||||
|
|
||||||
lowGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "lowEQ", lowGainSlider);
|
if (titleText.isNotEmpty())
|
||||||
midGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "midEQ", midGainSlider);
|
{
|
||||||
|
titleLabel.setText(titleText, juce::dontSendNotification);
|
||||||
|
juce::Font tf; tf.setHeight(13.0f); tf.setBold(true);
|
||||||
|
titleLabel.setFont(tf);
|
||||||
|
titleLabel.setJustificationType(juce::Justification::centredLeft);
|
||||||
|
titleLabel.setColour(juce::Label::textColourId, juce::Colours::white);
|
||||||
|
addAndMakeVisible(titleLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
lowGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "lowEQ", lowGainSlider);
|
||||||
|
midGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "midEQ", midGainSlider);
|
||||||
highGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "highEQ", highGainSlider);
|
highGainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "highEQ", highGainSlider);
|
||||||
}
|
|
||||||
|
|
||||||
void setupSlider(juce::Slider& slider) {
|
// EQ bypass toggle
|
||||||
slider.setRange(-24.0f, 24.0f, 0.1f);
|
bypassButton.setButtonText("On");
|
||||||
|
bypassButton.setClickingTogglesState(true);
|
||||||
slider.setSliderStyle(juce::Slider::LinearBarVertical);
|
addAndMakeVisible(bypassButton);
|
||||||
slider.setTextBoxStyle(juce::Slider::TextBoxBelow, false, 50, 20);
|
bypassAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(tree, "eq_on", bypassButton);
|
||||||
|
|
||||||
addAndMakeVisible(slider);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupLabel(juce::Label &lbl, juce::String txt) {
|
|
||||||
lbl.setFont(juce::Font((float)fontSize, juce::Font::bold));
|
|
||||||
lbl.setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
|
||||||
lbl.setJustificationType(juce::Justification::centred);
|
|
||||||
lbl.setText(txt, juce::NotificationType::dontSendNotification);
|
|
||||||
|
|
||||||
addAndMakeVisible(lbl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paint(juce::Graphics& g) override
|
void setupSlider(juce::Slider& slider) {
|
||||||
{
|
slider.setRange(-24.0f, 24.0f, 0.1f);
|
||||||
|
slider.setSliderStyle(juce::Slider::LinearBarVertical);
|
||||||
|
slider.setTextBoxStyle(juce::Slider::TextBoxBelow, false, 50, 20);
|
||||||
|
addAndMakeVisible(slider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupLabel(juce::Label& lbl, juce::String txt) {
|
||||||
|
juce::Font f; f.setHeight((float)fontSize); f.setBold(true);
|
||||||
|
lbl.setFont(f);
|
||||||
|
lbl.setColour(juce::Label::textColourId, juce::Colours::lightgreen);
|
||||||
|
lbl.setJustificationType(juce::Justification::centred);
|
||||||
|
lbl.setText(txt, juce::dontSendNotification);
|
||||||
|
addAndMakeVisible(lbl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void paint(juce::Graphics& g) override {
|
||||||
g.fillAll(juce::Colours::darkgrey);
|
g.fillAll(juce::Colours::darkgrey);
|
||||||
g.setColour(juce::Colours::white);
|
g.setColour(juce::Colours::white);
|
||||||
g.drawRect(getLocalBounds());
|
g.drawRect(getLocalBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
void resized() override {
|
void resized() override {
|
||||||
|
auto area = getLocalBounds().reduced(10);
|
||||||
|
auto top = area.removeFromTop(22);
|
||||||
|
auto btnW = 46;
|
||||||
|
bypassButton.setBounds(top.removeFromRight(btnW).reduced(2, 1));
|
||||||
|
titleLabel.setBounds(top);
|
||||||
|
|
||||||
juce::Grid grid;
|
juce::Grid grid;
|
||||||
grid.templateRows = {
|
grid.templateRows = {
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(1))
|
juce::Grid::TrackInfo(juce::Grid::Fr(1))
|
||||||
};
|
};
|
||||||
|
|
||||||
grid.templateColumns = {
|
grid.templateColumns = {
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
||||||
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
juce::Grid::TrackInfo(juce::Grid::Fr(1)),
|
||||||
@@ -175,194 +237,105 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
grid.items = {
|
grid.items = {
|
||||||
lowGainSlider, midGainSlider, highGainSlider,
|
lowGainSlider, midGainSlider, highGainSlider,
|
||||||
lowGainLabel, midGainLabel, highGainLabel
|
lowGainLabel, midGainLabel, highGainLabel
|
||||||
};
|
};
|
||||||
|
|
||||||
auto bounds = getLocalBounds().reduced(10);
|
grid.performLayout(area);
|
||||||
grid.performLayout(bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::Slider lowGainSlider, midGainSlider, highGainSlider;
|
juce::Slider lowGainSlider, midGainSlider, highGainSlider;
|
||||||
juce::Label lowGainLabel, midGainLabel, highGainLabel;
|
juce::Label lowGainLabel, midGainLabel, highGainLabel;
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> lowGainAttachment, midGainAttachment, highGainAttachment;
|
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> lowGainAttachment, midGainAttachment, highGainAttachment;
|
||||||
|
|
||||||
|
juce::ToggleButton bypassButton;
|
||||||
|
std::unique_ptr<juce::AudioProcessorValueTreeState::ButtonAttachment> bypassAttachment;
|
||||||
|
|
||||||
|
juce::Label titleLabel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================== Waveform List Model ===========================
|
||||||
struct WaveformSelectorContents final : public juce::ListBoxModel
|
struct WaveformSelectorContents final : public juce::ListBoxModel
|
||||||
{
|
{
|
||||||
// The following methods implement the necessary virtual functions from ListBoxModel,
|
int getNumRows() override { return 4; }
|
||||||
// telling the listbox how many rows there are, painting them, etc.
|
|
||||||
int getNumRows() override
|
|
||||||
{
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
void paintListBoxItem(int rowNumber, juce::Graphics& g,
|
void paintListBoxItem(int rowNumber, juce::Graphics& g,
|
||||||
int width, int height, bool rowIsSelected) override
|
int width, int height, bool rowIsSelected) override
|
||||||
{
|
{
|
||||||
if (rowIsSelected)
|
if (rowIsSelected) g.fillAll(juce::Colours::lightblue);
|
||||||
g.fillAll(juce::Colours::lightblue);
|
g.setColour(juce::LookAndFeel::getDefaultLookAndFeel()
|
||||||
|
.findColour(juce::Label::textColourId));
|
||||||
|
|
||||||
g.setColour(juce::LookAndFeel::getDefaultLookAndFeel().findColour(juce::Label::textColourId));
|
juce::Font f; f.setHeight((float)height * 0.7f);
|
||||||
g.setFont((float)height * 0.7f);
|
g.setFont(f);
|
||||||
|
g.drawText(waves[(size_t)rowNumber], 5, 0, width, height,
|
||||||
g.drawText(waves[rowNumber], 5, 0, width, height, juce::Justification::centredLeft, true);
|
juce::Justification::centredLeft, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<juce::String> waves = { "Sine", "Saw", "Square", "Triangle" };
|
void selectedRowsChanged (int lastRowSelected) override
|
||||||
|
{
|
||||||
|
if (onSelect) onSelect(lastRowSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<void (int)> onSelect;
|
||||||
|
|
||||||
|
std::vector<juce::String> waves { "Sine", "Saw", "Square", "Triangle" };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================== MasterVolumeComponent =========================
|
||||||
class MasterVolumeComponent : public juce::Component
|
class MasterVolumeComponent : public juce::Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MasterVolumeComponent()
|
MasterVolumeComponent()
|
||||||
{
|
{
|
||||||
slider.setSliderStyle(juce::Slider::LinearBarVertical);
|
slider.setSliderStyle(juce::Slider::LinearBarVertical);
|
||||||
slider.setTextBoxStyle(juce::Slider::NoTextBox, false, 20, 20); // Optional
|
slider.setTextBoxStyle(juce::Slider::NoTextBox, false, 20, 20);
|
||||||
addAndMakeVisible(slider);
|
addAndMakeVisible(slider);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resized() override
|
void resized() override
|
||||||
{
|
{
|
||||||
auto padded = getLocalBounds().reduced(30); // Adjust padding here
|
slider.setBounds(getLocalBounds().reduced(30));
|
||||||
slider.setBounds(padded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::Slider slider;
|
juce::Slider slider;
|
||||||
};
|
};
|
||||||
|
|
||||||
//==============================================================================
|
//============================== Editor =======================================
|
||||||
/**
|
|
||||||
*/
|
|
||||||
class NeuralSynthAudioProcessorEditor : public juce::AudioProcessorEditor
|
class NeuralSynthAudioProcessorEditor : public juce::AudioProcessorEditor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor&);
|
NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor&);
|
||||||
~NeuralSynthAudioProcessorEditor() override;
|
~NeuralSynthAudioProcessorEditor() override;
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void paint (juce::Graphics&) override;
|
void paint (juce::Graphics&) override;
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This reference is provided as a quick way for your editor to
|
|
||||||
// access the processor object that created it.
|
|
||||||
NeuralSynthAudioProcessor& audioProcessor;
|
NeuralSynthAudioProcessor& audioProcessor;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessorEditor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessorEditor)
|
||||||
|
|
||||||
juce::ListBox waveformSelector;
|
juce::ListBox waveformSelector;
|
||||||
WaveformSelectorContents waveformContents;
|
WaveformSelectorContents waveformContents;
|
||||||
|
|
||||||
//std::unique_ptr<juce::AudioProcessorValueTreeState::ListBoxAttachment> waveformAttachment;
|
std::optional<ScopeSliderComponent> adsrComponent; // Amp Env
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// ADSR
|
|
||||||
|
|
||||||
/*void createADSR(int xCoord, int yCoord);
|
|
||||||
juce::Slider attackSlider, decaySlider, sustainSlider, releaseSlider;
|
|
||||||
juce::Label attackLabel, decayLabel, sustainLabel, releaseLabel;
|
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> attackAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> decayAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> sustainAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> releaseAttachment;*/
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
std::optional<ScopeSliderComponent> adsrComponent;
|
|
||||||
std::optional<ScopeSliderComponent> chorusComponent;
|
std::optional<ScopeSliderComponent> chorusComponent;
|
||||||
std::optional<ScopeSliderComponent> delayComponent;
|
std::optional<ScopeSliderComponent> delayComponent;
|
||||||
std::optional<ScopeSliderComponent> reverbComponent;
|
std::optional<ScopeSliderComponent> reverbComponent;
|
||||||
|
|
||||||
|
|
||||||
std::optional<ScopeSliderComponent> flangerComponent;
|
std::optional<ScopeSliderComponent> flangerComponent;
|
||||||
std::optional<ScopeSliderComponent> distortionComponent;
|
std::optional<ScopeSliderComponent> distortionComponent;
|
||||||
std::optional<ScopeSliderComponent> filterComponent;
|
std::optional<ScopeSliderComponent> filterComponent;
|
||||||
|
std::optional<ScopeSliderComponent> filterEnvComponent; // Filter Env panel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*//==============================================================================
|
|
||||||
// Chorus
|
|
||||||
|
|
||||||
void createChorus(int xCoord, int yCoord);
|
|
||||||
juce::Slider chorusRateSlider, chorusDepthSlider, chorusCentreSlider, chorusFeedbackSlider, chorusMixSlider;
|
|
||||||
juce::Label chorusRateLabel, chorusDepthLabel, chorusCentreLabel, chorusFeedbackLabel, chorusMixLabel;
|
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> chorusRateAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> chorusDepthAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> chorusCentreAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> chorusFeedbackAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> chorusMixAttachment;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// Delay
|
|
||||||
|
|
||||||
void createDelay(int xCoord, int yCoord);
|
|
||||||
juce::Slider delayDelaySlider;
|
|
||||||
juce::Label delayDelayLabel;
|
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> delayDelayAttachment;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// Reverb
|
|
||||||
|
|
||||||
void createReverb(int xCoord, int yCoord);
|
|
||||||
juce::Slider reverbRoomSizeSlider, reverbDampingSlider, reverbWetLevelSlider, reverbDryLevelSlider, reverbWidthSlider,
|
|
||||||
reverbFreezeModeSlider;
|
|
||||||
juce::Label reverbRoomSizeLabel, reverbDampingLabel, reverbWetLevelLabel, reverbDryLevelLabel, reverbWidthLabel,
|
|
||||||
reverbFreezeModeLabel;
|
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbRoomSizeAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbDampingAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbWetLevelAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbDryLevelAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbWidthAttachment;
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> reverbFreezeModeAttachment;*/
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// Master
|
|
||||||
|
|
||||||
MasterVolumeComponent masterLevelSlider;
|
MasterVolumeComponent masterLevelSlider;
|
||||||
juce::Label masterLevelLabel;
|
juce::Label masterLevelLabel;
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// EQ
|
|
||||||
|
|
||||||
//void updateEQFromSliders();
|
|
||||||
std::optional<EqualizerComponent> eqComponent;
|
std::optional<EqualizerComponent> eqComponent;
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// Master
|
|
||||||
|
|
||||||
juce::Slider gainSlider;
|
|
||||||
juce::Label gainLabel;
|
|
||||||
|
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> gainAttachment;
|
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> gainAttachment;
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
//juce::MidiKeyboardState midiKeyboardState;
|
|
||||||
//juce::MidiKeyboardComponent midiKeyboardComponent{ midiKeyboardState, juce::MidiKeyboardComponent::horizontalKeyboard };
|
|
||||||
ScopeComponent<float> mainScopeComponent;
|
ScopeComponent<float> mainScopeComponent;
|
||||||
/*ScopeComponent<float> chorusScopeComponent;
|
|
||||||
ScopeComponent<float> delayScopeComponent;
|
|
||||||
ScopeComponent<float> reverbScopeComponent;
|
|
||||||
|
|
||||||
GraphComponent<float> adsrGraph;*/
|
|
||||||
|
|
||||||
|
juce::Component blankPanel;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user