MonoStep: monophonic 2-oscillator step-sequencer synth

This commit is contained in:
armin 2026-08-05 19:55:57 +02:00
commit e52e5cb161
14 changed files with 2674 additions and 0 deletions

190
Source/PluginEditor.h Normal file
View file

@ -0,0 +1,190 @@
#pragma once
#include <JuceHeader.h>
#include "ui/SequencerMatrix.h"
class MonoStepAudioProcessor;
class EditorLookAndFeel final : public juce::LookAndFeel_V4
{
public:
EditorLookAndFeel();
void drawRotarySlider (juce::Graphics&, int x, int y, int w, int h,
float sliderPos, float rotaryStartAngle, float rotaryEndAngle,
juce::Slider&) override;
void drawToggleButton (juce::Graphics&, juce::ToggleButton&,
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override;
void drawButtonBackground (juce::Graphics&, juce::Button&,
const juce::Colour& backgroundColour, bool shouldDrawButtonAsHighlighted,
bool shouldDrawButtonAsDown) override;
void drawButtonText (juce::Graphics&, juce::TextButton&,
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override;
};
class Knob final : public juce::Component
{
public:
explicit Knob (const juce::String& title);
juce::Slider& getSlider() { return slider; }
void attach (juce::AudioProcessorValueTreeState& apvts, const juce::String& paramId)
{
attachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment> (apvts, paramId, slider);
}
void setFormat (std::function<juce::String (float)> formatFn)
{
format = std::move (formatFn);
updateValueLabel();
}
void setOnValueChanged (std::function<void (float)> valueChangedFn)
{
customOnValueChange = std::move (valueChangedFn);
}
void resized() override;
private:
void updateValueLabel();
juce::Slider slider;
juce::Label titleLabel;
juce::Label valueLabel;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> attachment;
std::function<juce::String (float)> format;
std::function<void (float)> customOnValueChange;
};
class ChoiceBar final : public juce::Component,
public juce::AudioProcessorValueTreeState::Listener
{
public:
ChoiceBar (juce::AudioProcessorValueTreeState& apvts,
const juce::String& paramId,
const juce::StringArray& choices);
ChoiceBar (const juce::StringArray& choices,
std::function<void (int)> onSelected);
~ChoiceBar() override;
void parameterChanged (const juce::String&, float) override;
void setManualHandler (std::function<void (int)> handler) { manualHandler = std::move (handler); }
void resized() override;
private:
void refreshFromParam();
void setIndex (int index);
juce::AudioProcessorValueTreeState* apvts = nullptr;
juce::String paramId;
std::function<void (int)> manualHandler;
juce::OwnedArray<juce::TextButton> buttons;
};
class StepPanel final : public juce::Component
{
public:
explicit StepPanel (MonoStepAudioProcessor& processor);
void setSelectedStep (int stepIdx);
void refresh();
std::function<void (int)> onStepSelected;
void resized() override;
private:
void clearPattern();
MonoStepAudioProcessor& processor;
int selectedStep = 0;
bool updating = false;
juce::Label titleLabel;
juce::Label noteLabel;
juce::Label gateLabel;
Knob fineKnob;
juce::TextButton prevButton;
juce::TextButton nextButton;
juce::Label hintLabel;
juce::TextButton clearButton;
};
class MonoStepAudioProcessorEditor final : public juce::AudioProcessorEditor,
public juce::Timer
{
public:
explicit MonoStepAudioProcessorEditor (MonoStepAudioProcessor& processor);
~MonoStepAudioProcessorEditor() override;
void paint (juce::Graphics&) override;
void resized() override;
void timerCallback() override;
private:
void paintContent (juce::Graphics&);
class ContentComponent final : public juce::Component
{
public:
explicit ContentComponent (MonoStepAudioProcessorEditor& owner) : ownerRef (owner) {}
void paint (juce::Graphics& g) override { ownerRef.paintContent (g); }
private:
MonoStepAudioProcessorEditor& ownerRef;
};
MonoStepAudioProcessor& processorRef;
ContentComponent content;
static constexpr int baseWidth = 1060;
static constexpr int baseHeight = 640;
float zoomFactor = 1.0f;
void setZoomFactor (float newZoom);
std::unique_ptr<EditorLookAndFeel> lnf;
std::vector<std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment>> attachments;
Knob lengthKnob;
Knob swingKnob;
Knob rootKnob;
Knob gateKnob;
Knob masterKnob;
Knob detuneKnob;
Knob mixKnob;
Knob cutoffKnob;
Knob resKnob;
Knob glideKnob;
Knob attackKnob;
Knob decayKnob;
Knob sustainKnob;
Knob releaseKnob;
ChoiceBar rateBar;
ChoiceBar octaveBar;
ChoiceBar zoomBar;
ChoiceBar wave1Bar;
ChoiceBar wave2Bar;
SequencerMatrix matrix;
StepPanel stepPanel;
int lastPlayStep = -1;
void refreshEditor();
};