Skip to content

Commit

Permalink
Merge pull request #8 from midilab/feature/mods
Browse files Browse the repository at this point in the history
Feature/mods + AU fix
  • Loading branch information
midilab committed Jan 21, 2024
2 parents e0594fa + 561c070 commit 2080bb6
Show file tree
Hide file tree
Showing 20 changed files with 4,803 additions and 5,765 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# build artifacts
build*/
Build*/
Builds*/
lib*/
bin/
*_Packaged
*.exe
*.dmg
vstsdk2.4/
src/JuceLibraryCode/JuceHeader.h
src/JuceLibraryCode/ReadMe.txt

# ide settings
.vscode/
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)

project(JC303 VERSION 0.0.1)
project(JC303 VERSION 0.10.1)


### Dependency versions ###
Expand Down Expand Up @@ -99,7 +99,7 @@ juce_add_plugin("${PROJECT_NAME}"
# Filter, Generator, Mastering, Modulation, Mono, Network, NoOfflineProcess,
# OnlyOfflineProcess, OnlyRT, Pitch Shift, Restoration, Reverb, Sampler, Spatial,
# Stereo, Surround, Synth, Tools, Up-Downmix
AU_MAIN_TYPE "kAudioUnitType_Generator kAudioUnitType_MusicDevice" # Should be one or more, separated by spaces, of the following:
AU_MAIN_TYPE "kAudioUnitType_MusicDevice" # Should be one or more, separated by spaces, of the following:
# kAudioUnitType_Effect, kAudioUnitType_FormatConverter, kAudioUnitType_Generator,
# kAudioUnitType_MIDIProcessor, kAudioUnitType_Mixer, kAudioUnitType_MusicDevice,
# kAudioUnitType_MusicEffect, kAudioUnitType_OfflineEffect, kAudioUnitType_Output,
Expand Down
Binary file modified img/jc303.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ target_sources("${PROJECT_NAME}"
dsp/rosic_RealFunctions.cpp
dsp/rosic_TeeBeeFilter.cpp

ui/BinaryData.cpp
JuceLibraryCode/BinaryData.cpp

Gui.cpp
JC303.cpp)
Expand Down
273 changes: 173 additions & 100 deletions src/Gui.cpp
Original file line number Diff line number Diff line change
@@ -1,101 +1,174 @@
#include "Gui.h"

//==============================================================================
JC303Editor::JC303Editor (JC303& p, juce::AudioProcessorValueTreeState& vts)
: AudioProcessorEditor (&p), processorRef (p), valueTreeState (vts)
{
// Create and configure rotary sliders for each parameter
addAndMakeVisible(waveformSlider = createSlider());
addAndMakeVisible(tuningSlider = createSlider());
addAndMakeVisible(cutoffFreqSlider = createSlider());
addAndMakeVisible(resonanceSlider = createSlider());
addAndMakeVisible(envelopModSlider = createSlider());
addAndMakeVisible(decaySlider = createSlider());
addAndMakeVisible(accentSlider = createSlider());
addAndMakeVisible(volumeSlider = createSlider());
addAndMakeVisible(slideTimeSlider = createSlider());

// attch controls to processor parameters tree
waveformAttachment.reset (new SliderAttachment (valueTreeState, "waveform", *waveformSlider));
tuningAttachment.reset (new SliderAttachment (valueTreeState, "tuning", *tuningSlider));
cutoffFreqAttachment.reset (new SliderAttachment (valueTreeState, "cutoff", *cutoffFreqSlider));
resonanceAttachment.reset (new SliderAttachment (valueTreeState, "resonance", *resonanceSlider));
envelopModAttachment.reset (new SliderAttachment (valueTreeState, "envmod", *envelopModSlider));
decayAttachment.reset (new SliderAttachment (valueTreeState, "decay", *decaySlider));
accentAttachment.reset (new SliderAttachment (valueTreeState, "accent", *accentSlider));
volumeAttachment.reset (new SliderAttachment (valueTreeState, "volume", *volumeSlider));
slideTimeAttachment.reset(new SliderAttachment(valueTreeState, "slideTime", *slideTimeSlider));

setControlsLayout();

// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize (745, 288);
}

JC303Editor::~JC303Editor()
{
}

//==============================================================================
void JC303Editor::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 (15.0f);

// main gui is a simple background with labels
juce::Image background = ImageCache::getFromMemory (BinaryData::jc303gui_png, BinaryData::jc303gui_pngSize);
g.drawImageAt (background, 0, 0);
}

void JC303Editor::resized()
{
setControlsLayout();
}

juce::Slider* JC303Editor::createSlider()
{
auto* slider = new juce::Slider();
slider->setSliderStyle(juce::Slider::RotaryHorizontalVerticalDrag);
slider->setLookAndFeel(&lookAndFeel);
slider->setTextBoxStyle(juce::Slider::TextEntryBoxPosition::NoTextBox, true, 0, 0);
//slider->setRange(parameter->range.start, parameter->range.end);
//slider->setValue(*parameter);
//slider->addListener(this);
return slider;
}

void JC303Editor::setControlsLayout()
{
// Set the bounds and other properties for each slider
// Adjust the parameters accordingly to fit your needs
const int sliderWidth = 120;
const int sliderHeight = 120;

// knob positioning location
// first row
pair<int, int> waveFormLocation = {9, 20};
pair<int, int> volumeLocation = {130, 20};
// second row
pair<int, int> tuningLocation = {9, 160};
pair<int, int> cutoffFreqLocation = {130, 160};
pair<int, int> resonanceLocation = {252, 160};
pair<int, int> envelopeLocation = {374, 160};
pair<int, int> decayLocation = {496, 160};
pair<int, int> accentLocation = {618, 160};
// small knobs
pair<int, int> slideTimeLocation = {692, 25};

waveformSlider->setBounds(waveFormLocation.first, waveFormLocation.second, sliderWidth, sliderHeight);
volumeSlider->setBounds(volumeLocation.first, volumeLocation.second, sliderWidth, sliderHeight);
tuningSlider->setBounds(tuningLocation.first, tuningLocation.second, sliderWidth, sliderHeight);
cutoffFreqSlider->setBounds(cutoffFreqLocation.first, cutoffFreqLocation.second, sliderWidth, sliderHeight);
resonanceSlider->setBounds(resonanceLocation.first, resonanceLocation.second, sliderWidth, sliderHeight);
envelopModSlider->setBounds(envelopeLocation.first, envelopeLocation.second, sliderWidth, sliderHeight);
decaySlider->setBounds(decayLocation.first, decayLocation.second, sliderWidth, sliderHeight);
accentSlider->setBounds(accentLocation.first, accentLocation.second, sliderWidth, sliderHeight);
slideTimeSlider->setBounds(slideTimeLocation.first, slideTimeLocation.second, sliderWidth / 4, sliderHeight / 4);
#include "Gui.h"

//==============================================================================
JC303Editor::JC303Editor (JC303& p, juce::AudioProcessorValueTreeState& vts)
: AudioProcessorEditor (&p), processorRef (p), valueTreeState (vts)
{
// Create and configure rotary sliders for each parameter
addAndMakeVisible(waveformSlider = create303Knob());
addAndMakeVisible(tuningSlider = create303Knob());
addAndMakeVisible(cutoffFreqSlider = create303Knob());
addAndMakeVisible(resonanceSlider = create303Knob());
addAndMakeVisible(envelopModSlider = create303Knob());
addAndMakeVisible(decaySlider = create303Knob());
addAndMakeVisible(accentSlider = create303Knob());
addAndMakeVisible(volumeSlider = create303Knob());
// MODs
// row 1
addAndMakeVisible(sqrDriverSlider = createModKnob("sqr. driver"));
addAndMakeVisible(ampReleaseSlider = createModKnob("amp. release"));
addAndMakeVisible(ampSustainSlider = createModKnob("amp. sus."));
addAndMakeVisible(slideTimeSlider = createModKnob("slide time"));
// row 2
addAndMakeVisible(feedbackFilterSlider = createModKnob("hpf feedbck"));
addAndMakeVisible(softAttackSlider = createModKnob("soft attack"));
addAndMakeVisible(normalDecaySlider = createModKnob("norm. decay"));
addAndMakeVisible(accentDecaySlider = createModKnob("acc. decay"));
// on/off mod switch
addAndMakeVisible(switchModButton = createSwitch("mod on"));

// attch controls to processor parameters tree
waveformAttachment.reset (new SliderAttachment (valueTreeState, "waveform", *waveformSlider));
tuningAttachment.reset (new SliderAttachment (valueTreeState, "tuning", *tuningSlider));
cutoffFreqAttachment.reset (new SliderAttachment (valueTreeState, "cutoff", *cutoffFreqSlider));
resonanceAttachment.reset (new SliderAttachment (valueTreeState, "resonance", *resonanceSlider));
envelopModAttachment.reset (new SliderAttachment (valueTreeState, "envmod", *envelopModSlider));
decayAttachment.reset (new SliderAttachment (valueTreeState, "decay", *decaySlider));
accentAttachment.reset (new SliderAttachment (valueTreeState, "accent", *accentSlider));
volumeAttachment.reset (new SliderAttachment (valueTreeState, "volume", *volumeSlider));
// MODs
switchModButtonAttachment.reset(new ButtonAttachment(valueTreeState, "switchModState", *switchModButton));
sqrDriverAttachment.reset(new SliderAttachment(valueTreeState, "sqrDriver", *sqrDriverSlider));
ampReleaseAttachment.reset(new SliderAttachment(valueTreeState, "ampSustain", *ampSustainSlider));
ampSustainAttachment.reset(new SliderAttachment(valueTreeState, "ampRelease", *ampReleaseSlider));
slideTimeAttachment.reset(new SliderAttachment(valueTreeState, "slideTime", *slideTimeSlider));
feedbackFilterAttachment.reset(new SliderAttachment(valueTreeState, "feedbackFilter", *feedbackFilterSlider));
softAttackAttachment.reset(new SliderAttachment(valueTreeState, "softAttack", *softAttackSlider));
normalDecayAttachment.reset(new SliderAttachment(valueTreeState, "normalDecay", *normalDecaySlider));
accentDecayAttachment.reset(new SliderAttachment(valueTreeState, "accentDecay", *accentDecaySlider));

setControlsLayout();

// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize (745, 288);
}

JC303Editor::~JC303Editor()
{
}

//==============================================================================
void JC303Editor::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 (15.0f);

// main gui is a simple background with labels
juce::Image background = ImageCache::getFromMemory (BinaryData::jc303gui_png, BinaryData::jc303gui_pngSize);
g.drawImageAt (background, 0, 0);
}

void JC303Editor::resized()
{
setControlsLayout();
}

juce::Slider* JC303Editor::create303Knob()
{
auto* slider = new juce::Slider();
slider->setSliderStyle(juce::Slider::RotaryHorizontalVerticalDrag);
slider->setLookAndFeel(&knobLookAndFeel);
slider->setTextBoxStyle(juce::Slider::TextEntryBoxPosition::NoTextBox, true, 0, 0);
return slider;
}

juce::Slider* JC303Editor::createModKnob(const juce::String& label)
{
auto* slider = new juce::Slider();
slider->setSliderStyle(juce::Slider::RotaryHorizontalVerticalDrag);
slider->setLookAndFeel(&modKnobLookAndFeel);
slider->setTextBoxStyle(juce::Slider::TextEntryBoxPosition::NoTextBox, true, 0, 0);

// Create a label for the text
auto* labelComponent = new AttachedLabel();
labelComponent->setText(label, juce::dontSendNotification);
labelComponent->setJustificationType(juce::Justification::centredTop);
labelComponent->setColour(juce::Label::textColourId, juce::Colours::black);
labelComponent->attachToComponent(slider, true);

return slider;
}

SwitchButton* JC303Editor::createSwitch(const juce::String& label)
{
//auto* button = new juce::ImageButton();
//button->setLookAndFeel(&buttonLookAndFeel);
auto* button = new SwitchButton(label);
button->setClickingTogglesState(false);

// Create a label for the text
auto* labelComponent = new AttachedLabel();
labelComponent->setText(label, juce::dontSendNotification);
labelComponent->setJustificationType(juce::Justification::centredTop);
labelComponent->setColour(juce::Label::textColourId, juce::Colours::black);
labelComponent->attachToComponent(button, true);

return button;
}

void JC303Editor::setControlsLayout()
{
// Set the bounds and other properties for each slider
// Adjust the parameters accordingly to fit your needs
const int sliderWidth = 120;
const int sliderHeight = 120;

// knob positioning location
// first row
pair<int, int> waveFormLocation = {9, 20};
pair<int, int> volumeLocation = {130, 20};
// second row
pair<int, int> tuningLocation = {9, 160};
pair<int, int> cutoffFreqLocation = {130, 160};
pair<int, int> resonanceLocation = {252, 160};
pair<int, int> envelopeLocation = {374, 160};
pair<int, int> decayLocation = {496, 160};
pair<int, int> accentLocation = {618, 160};
// MOD Switch
pair<int, int> switchLocation = {412, 21};
// MODs knobs
// first row
pair<int, int> sqrDriverLocation = {482, 15};
pair<int, int> ampReleaseLocation = {552, 15};
pair<int, int> ampSustainLocation = {622, 15};
pair<int, int> slideTimeLocation = {692, 15};
// second row
pair<int, int> feedbackFilterLocation = {482, 53};
pair<int, int> softAttackLocation = {552, 53};
pair<int, int> normalAttackLocation = {622, 53};
pair<int, int> accentDecayLocation = {692, 53};

waveformSlider->setBounds(waveFormLocation.first, waveFormLocation.second, sliderWidth, sliderHeight);
volumeSlider->setBounds(volumeLocation.first, volumeLocation.second, sliderWidth, sliderHeight);
tuningSlider->setBounds(tuningLocation.first, tuningLocation.second, sliderWidth, sliderHeight);
cutoffFreqSlider->setBounds(cutoffFreqLocation.first, cutoffFreqLocation.second, sliderWidth, sliderHeight);
resonanceSlider->setBounds(resonanceLocation.first, resonanceLocation.second, sliderWidth, sliderHeight);
envelopModSlider->setBounds(envelopeLocation.first, envelopeLocation.second, sliderWidth, sliderHeight);
decaySlider->setBounds(decayLocation.first, decayLocation.second, sliderWidth, sliderHeight);
accentSlider->setBounds(accentLocation.first, accentLocation.second, sliderWidth, sliderHeight);
// MODs
sqrDriverSlider->setBounds(sqrDriverLocation.first, sqrDriverLocation.second, sliderWidth / 4, sliderHeight / 4);
ampReleaseSlider->setBounds(ampReleaseLocation.first, ampReleaseLocation.second, sliderWidth / 4, sliderHeight / 4);
ampSustainSlider->setBounds(ampSustainLocation.first, ampSustainLocation.second, sliderWidth / 4, sliderHeight / 4);
slideTimeSlider->setBounds(slideTimeLocation.first, slideTimeLocation.second, sliderWidth / 4, sliderHeight / 4);
feedbackFilterSlider->setBounds(feedbackFilterLocation.first, feedbackFilterLocation.second, sliderWidth / 4, sliderHeight / 4);
softAttackSlider->setBounds(softAttackLocation.first, softAttackLocation.second, sliderWidth / 4, sliderHeight / 4);
normalDecaySlider->setBounds(normalAttackLocation.first, normalAttackLocation.second, sliderWidth / 4, sliderHeight / 4);
accentDecaySlider->setBounds(accentDecayLocation.first, accentDecayLocation.second, sliderWidth / 4, sliderHeight / 4);

switchModButton->setBounds(switchLocation.first, switchLocation.second, sliderWidth / 2, sliderHeight / 2);
}
Loading

0 comments on commit 2080bb6

Please sign in to comment.