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 "PluginEditor.h"
|
||||
#include "ScopeComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
|
||||
: AudioProcessorEditor (&p), audioProcessor (p), mainScopeComponent(audioProcessor.getAudioBufferQueue())
|
||||
{
|
||||
auto& tree = audioProcessor.parameters;
|
||||
|
||||
//auto area = getLocalBounds();
|
||||
//mainScopeComponent.setBounds(5, 5, 800, 200);
|
||||
// scopeComponent.setSize(800, 200);
|
||||
|
||||
addAndMakeVisible(mainScopeComponent);
|
||||
|
||||
waveformSelector.setModel(&waveformContents);
|
||||
|
||||
addAndMakeVisible(waveformSelector);
|
||||
|
||||
|
||||
chorusComponent.emplace(tree, "chorus");
|
||||
|
||||
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) {
|
||||
auto& tree = this->audioProcessor.parameters;
|
||||
|
||||
float attackValue = tree.getParameter("adsr_attack")->getValue();
|
||||
float decayValue = tree.getParameter("adsr_decay")->getValue();
|
||||
float sustainValue = tree.getParameter("adsr_sustain")->getValue();
|
||||
float releaseValue = tree.getParameter("adsr_release")->getValue();
|
||||
|
||||
float sustainLength = 1.0f;
|
||||
float totalTime = attackValue + decayValue + sustainLength + releaseValue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return m * x + c;
|
||||
});
|
||||
addAndMakeVisible(*adsrComponent);
|
||||
|
||||
//createADSR(5, 250);
|
||||
//createEQ();
|
||||
|
||||
addAndMakeVisible(masterLevelSlider);
|
||||
|
||||
eqComponent.emplace(tree);
|
||||
addAndMakeVisible(*eqComponent);
|
||||
|
||||
// Attach to parameter
|
||||
//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());
|
||||
addAndMakeVisible(*flangerComponent);
|
||||
|
||||
distortionComponent.emplace(tree, "distortion");
|
||||
distortionComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue());
|
||||
addAndMakeVisible(*distortionComponent);
|
||||
|
||||
filterComponent.emplace(tree, "filter");
|
||||
filterComponent->enableSampleScope(audioProcessor.getFilterAudioBufferQueue());
|
||||
addAndMakeVisible(*filterComponent);
|
||||
|
||||
//addAndMakeVisible(midiKeyboardComponent);
|
||||
|
||||
|
||||
//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;
|
||||
|
||||
float attackValue = tree.getParameter("attack")->getValue();
|
||||
float decayValue = tree.getParameter("decay")->getValue();
|
||||
float sustainValue = tree.getParameter("sustain")->getValue();
|
||||
float releaseValue = tree.getParameter("release")->getValue();
|
||||
|
||||
float sustainLength = 1.0f;
|
||||
float totalTime = attackValue + decayValue + sustainLength + releaseValue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return m * x + c;
|
||||
});
|
||||
|
||||
|
||||
int fontSize = 11;
|
||||
int leftPosition = xCoord;
|
||||
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);
|
||||
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 : { &attackLabel, &decayLabel, &sustainLabel, &releaseLabel })
|
||||
{
|
||||
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);
|
||||
sustainLabel.setText("Sustain", juce::dontSendNotification); releaseLabel.setText("Release", juce::dontSendNotification);
|
||||
|
||||
auto& tree = this->audioProcessor.parameters;
|
||||
|
||||
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) {
|
||||
|
||||
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)
|
||||
{
|
||||
// (Our component is opaque, so we must completely fill the background with a solid colour)
|
||||
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()
|
||||
{
|
||||
// This is generally where you'll want to lay out the positions of any
|
||||
// subcomponents in your editor..
|
||||
auto bounds = getLocalBounds().reduced(20);
|
||||
//auto row = bounds.removeFromTop(150);
|
||||
|
||||
//int knobWidth = row.getWidth() / 4;
|
||||
|
||||
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.templateColumns = {
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(22)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(8))
|
||||
};
|
||||
|
||||
grid.items = {
|
||||
juce::GridItem(mainScopeComponent).withArea({}, juce::GridItem::Span(4)),
|
||||
juce::GridItem(waveformSelector),
|
||||
juce::GridItem(*adsrComponent),
|
||||
juce::GridItem(*chorusComponent),
|
||||
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),
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
#include "PluginProcessor.h"
|
||||
#include "PluginEditor.h"
|
||||
#include "ScopeComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
|
||||
: AudioProcessorEditor (&p),
|
||||
audioProcessor (p),
|
||||
mainScopeComponent(audioProcessor.getAudioBufferQueue())
|
||||
{
|
||||
auto& tree = audioProcessor.parameters;
|
||||
|
||||
addAndMakeVisible(mainScopeComponent);
|
||||
|
||||
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);
|
||||
|
||||
// --- Panels ---
|
||||
adsrComponent.emplace(tree, "adsr", "Amp Env");
|
||||
adsrComponent->enableGraphScope([this](float x) {
|
||||
auto& tree = this->audioProcessor.parameters;
|
||||
|
||||
float A = tree.getParameter("adsr_attack")->getValue();
|
||||
float D = tree.getParameter("adsr_decay")->getValue();
|
||||
float S = tree.getParameter("adsr_sustain")->getValue();
|
||||
float R = tree.getParameter("adsr_release")->getValue();
|
||||
|
||||
const float sustainLen = 1.0f;
|
||||
const float total = A + D + sustainLen + R;
|
||||
A /= total; D /= total; R /= total;
|
||||
|
||||
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;
|
||||
});
|
||||
addAndMakeVisible(*adsrComponent);
|
||||
|
||||
chorusComponent.emplace(tree, "chorus", "Chorus");
|
||||
chorusComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue());
|
||||
addAndMakeVisible(*chorusComponent);
|
||||
|
||||
delayComponent.emplace(tree, "delay", "Delay");
|
||||
delayComponent->enableSampleScope(audioProcessor.getDelayAudioBufferQueue());
|
||||
addAndMakeVisible(*delayComponent);
|
||||
|
||||
reverbComponent.emplace(tree, "reverb", "Reverb");
|
||||
reverbComponent->enableSampleScope(audioProcessor.getReverbAudioBufferQueue());
|
||||
addAndMakeVisible(*reverbComponent);
|
||||
|
||||
eqComponent.emplace(tree, "EQ");
|
||||
addAndMakeVisible(*eqComponent);
|
||||
|
||||
flangerComponent.emplace(tree, "flanger", "Flanger");
|
||||
flangerComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue());
|
||||
addAndMakeVisible(*flangerComponent);
|
||||
|
||||
distortionComponent.emplace(tree, "distortion", "Distortion");
|
||||
distortionComponent->enableSampleScope(audioProcessor.getDistortionAudioBufferQueue());
|
||||
addAndMakeVisible(*distortionComponent);
|
||||
|
||||
filterComponent.emplace(tree, "filter", "Filter");
|
||||
filterComponent->enableSampleScope(audioProcessor.getFilterAudioBufferQueue());
|
||||
addAndMakeVisible(*filterComponent);
|
||||
|
||||
filterEnvComponent.emplace(tree, "fenv", "Filter Env");
|
||||
filterEnvComponent->enableGraphScope([this](float x) {
|
||||
auto& tree = this->audioProcessor.parameters;
|
||||
|
||||
float A = tree.getParameter("fenv_attack")->getValue();
|
||||
float D = tree.getParameter("fenv_decay")->getValue();
|
||||
float S = tree.getParameter("fenv_sustain")->getValue();
|
||||
float R = tree.getParameter("fenv_release")->getValue();
|
||||
|
||||
const float sustainLen = 1.0f;
|
||||
const float total = A + D + sustainLen + R;
|
||||
A /= total; D /= total; R /= total;
|
||||
|
||||
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;
|
||||
});
|
||||
addAndMakeVisible(*filterEnvComponent);
|
||||
|
||||
// Master fader + label
|
||||
addAndMakeVisible(masterLevelSlider);
|
||||
masterLevelLabel.setText("Master", juce::dontSendNotification);
|
||||
{
|
||||
juce::Font f; f.setHeight(12.0f); f.setBold(true);
|
||||
masterLevelLabel.setFont(f);
|
||||
}
|
||||
masterLevelLabel.setJustificationType(juce::Justification::centred);
|
||||
addAndMakeVisible(masterLevelLabel);
|
||||
|
||||
// Blank placeholder
|
||||
addAndMakeVisible(blankPanel);
|
||||
|
||||
// Attach master parameter
|
||||
gainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(
|
||||
audioProcessor.parameters, "master", masterLevelSlider.slider);
|
||||
|
||||
setSize(1400, 720);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor() = default;
|
||||
|
||||
//==============================================================================
|
||||
void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g)
|
||||
{
|
||||
g.fillAll(getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void NeuralSynthAudioProcessorEditor::resized()
|
||||
{
|
||||
auto bounds = getLocalBounds().reduced(16);
|
||||
|
||||
juce::Grid grid;
|
||||
|
||||
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 = {
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(18)),
|
||||
juce::Grid::TrackInfo(juce::Grid::Fr(10))
|
||||
};
|
||||
|
||||
// Row 0
|
||||
grid.items.add(juce::GridItem(mainScopeComponent)
|
||||
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(5)));
|
||||
grid.items.add(juce::GridItem(waveformSelector)
|
||||
.withArea(juce::GridItem::Span(1), juce::GridItem::Span(1)));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user