/* ============================================================================== 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( // audioProcessor.parameters, "waveform", waveformSelector); //attachments.push_back(std::make_unique( // tree, sliderDetail.name, *sliders.back())); gainAttachment = std::make_unique( 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; 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(tree, "attack", attackSlider); decayAttachment = std::make_unique(tree, "decay", decaySlider); sustainAttachment = std::make_unique(tree, "sustain", sustainSlider); releaseAttachment = std::make_unique(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(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(tree, "reverbRoomSize", reverbRoomSizeSlider); reverbDampingAttachment = std::make_unique(tree, "reverbDamping", reverbDampingSlider); reverbWetLevelAttachment = std::make_unique(tree, "reverbWetLevel", reverbWetLevelSlider); reverbDryLevelAttachment = std::make_unique(tree, "reverbDryLevel", reverbDryLevelSlider); reverbWidthAttachment = std::make_unique(tree, "reverbWidth", reverbWidthSlider); reverbFreezeModeAttachment = std::make_unique(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); }