More advanced version

This commit is contained in:
Timothy Scully
2025-10-12 16:41:38 +01:00
parent 01d446af2d
commit 3967560318
11 changed files with 1288 additions and 133 deletions

View File

@@ -12,65 +12,335 @@
//==============================================================================
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
: AudioProcessorEditor (&p), audioProcessor (p), scopeComponent(audioProcessor.getAudioBufferQueue())
: AudioProcessorEditor (&p), audioProcessor (p), mainScopeComponent(audioProcessor.getAudioBufferQueue())
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize(400, 500);
auto& tree = audioProcessor.parameters;
auto area = getLocalBounds();
scopeComponent.setTopLeftPosition(0, 0);
scopeComponent.setSize(400, 200);
//auto area = getLocalBounds();
//mainScopeComponent.setBounds(5, 5, 800, 200);
// scopeComponent.setSize(800, 200);
addAndMakeVisible(scopeComponent);
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);
addAndMakeVisible(waveformSelector);
attackSlider.setRange(0.0, 1.0);
decaySlider.setRange(0.0, 1.0);
sustainSlider.setRange(0.0, 1.0);
releaseSlider.setRange(0.0, 1.0);
}*/
waveformSelector.setTopLeftPosition(15, 225);
int leftPosition = 15;
/*void NeuralSynthAudioProcessorEditor::createDelay(int xCoord, int yCoord) {
int fontSize = 11;
int leftPosition = xCoord;
const int sliderWidth = 60;
for (auto* slider : { &attackSlider, &decaySlider, &sustainSlider, &releaseSlider })
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);
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, sliderWidth + 20, 20);
//slider->setTopLeftPosition(0, 0);
slider->setBounds(leftPosition, yCoord + 150, sliderWidth, sliderWidthWithPadding);
addAndMakeVisible(*slider);
slider->setTopLeftPosition(leftPosition, 250);
leftPosition += (sliderWidth + 40);
leftPosition += sliderWidth;
}
waveformSelector.addItem("Sine", 1);
waveformSelector.addItem("Saw", 2);
waveformSelector.addItem("Square", 3);
waveformSelector.addItem("Triangle", 4);
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);
// Attach to parameter
waveformAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ComboBoxAttachment>(
audioProcessor.parameters, "waveform", waveformSelector);
auto& tree = this->audioProcessor.parameters;
delayDelayAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "delayDelay", reverbRoomSizeSlider);
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);
delayDelaySlider.setRange(0.0, 1.0);
}
*/
NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor()
{
}
/*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)
@@ -83,19 +353,52 @@ void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g)
//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);
//auto row = bounds.removeFromTop(150);
int knobWidth = row.getWidth() / 4;
//int knobWidth = row.getWidth() / 4;
attackSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
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));
releaseSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));*/
//waveformSelector.setBounds(20, 20, 120, 30);
waveformSelector.setBounds(20, 20, 120, 30);
}