commit bc77bbeceba5d0b0a5c77836f08c183ef72abeb2 parent 1c2257207192b20183a302e97d56ccc54be03428 Author: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com> Date: Thu, 21 Feb 2019 01:13:32 -0800 Add parameters for biasing, loss effects, and tape type Diffstat:
19 files changed, 491 insertions(+), 138 deletions(-)
diff --git a/Plugin/CHOWTapeModel.jucer b/Plugin/CHOWTapeModel.jucer @@ -4,7 +4,19 @@ pluginFormats="buildAU,buildStandalone,buildVST,buildVST3"> <MAINGROUP id="oKBSK1" name="CHOWTapeModel"> <GROUP id="{7659EE80-6477-48A0-C7B6-CD8900735F10}" name="Source"> + <GROUP id="{6EA40328-703D-5E93-4DC1-47040482016F}" name="GUI Components"> + <FILE id="C8pGDO" name="BiasControls.cpp" compile="1" resource="0" + file="Source/GUI Components/BiasControls.cpp"/> + <FILE id="PORdVN" name="BiasControls.h" compile="0" resource="0" file="Source/GUI Components/BiasControls.h"/> + <FILE id="jubA6Z" name="LossControls.cpp" compile="1" resource="0" + file="Source/GUI Components/LossControls.cpp"/> + <FILE id="KrcGEd" name="LossControls.h" compile="0" resource="0" file="Source/GUI Components/LossControls.h"/> + <FILE id="S8Xybc" name="MainControls.cpp" compile="1" resource="0" + file="Source/GUI Components/MainControls.cpp"/> + <FILE id="zXwghi" name="MainControls.h" compile="0" resource="0" file="Source/GUI Components/MainControls.h"/> + </GROUP> <GROUP id="{7867F016-80C7-7749-B604-ED042C040FC7}" name="GUI Extras"> + <FILE id="xd7cQs" name="ChowSlider.h" compile="0" resource="0" file="Source/GUI Extras/ChowSlider.h"/> <FILE id="mQFlPP" name="MyLNF.h" compile="0" resource="0" file="Source/GUI Extras/MyLNF.h"/> </GROUP> <GROUP id="{D2422983-A0E9-6A14-2092-2381CB1F3E7F}" name="Processors"> diff --git a/Plugin/Source/GUI Components/BiasControls.cpp b/Plugin/Source/GUI Components/BiasControls.cpp @@ -0,0 +1,51 @@ +#include "BiasControls.h" +#include "../PluginEditor.h" + +BiasControls::BiasControls (ChowtapeModelAudioProcessor& proc) : + processor (proc) +{ + ChowtapeModelAudioProcessorEditor::createSlider (biasFreqSlide, processor.biasFreq, myLNF, this, String ("kHz"), 1.0f); + biasFreqSlide.setSkewFactorFromMidPoint (55.0); + + ChowtapeModelAudioProcessorEditor::createSlider (biasGainSlide, processor.biasGain, myLNF, this, String ("dB")); + biasGainSlide.setSkewFactorFromMidPoint (14.0); + + ChowtapeModelAudioProcessorEditor::createLabel (biasFreqLabel, processor.biasFreq, this); + ChowtapeModelAudioProcessorEditor::createLabel (biasGainLabel, processor.biasGain, this); +} + +void BiasControls::paint (Graphics& g) +{ + g.setColour (Colours::antiquewhite); + g.setFont (Font ((float) nameHeight).boldened()); + + g.drawFittedText ("Biasing Parameters:", Rectangle<int> (xOffset, yOffset, width, labelHeight), + Justification::centredLeft, 1); +} + +void BiasControls::resized() +{ + biasFreqLabel.setBounds (0, 2 * yOffset + labelY, sliderWidth, labelHeight); + biasFreqSlide.setBounds (0, 2 * yOffset + sliderY, sliderWidth, sliderWidth); + + biasGainLabel.setBounds (biasFreqSlide.getRight(), 2 * yOffset + labelY, sliderWidth, labelHeight); + biasGainSlide.setBounds (biasFreqSlide.getRight(), 2 * yOffset + sliderY, sliderWidth, sliderWidth); +} + +void BiasControls::sliderValueChanged (Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + *param = (float) slider->getValue(); +} + +void BiasControls::sliderDragStarted(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->beginChangeGesture(); +} + +void BiasControls::sliderDragEnded(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->endChangeGesture(); +} diff --git a/Plugin/Source/GUI Components/BiasControls.h b/Plugin/Source/GUI Components/BiasControls.h @@ -0,0 +1,35 @@ +#ifndef BIASCONTROLS_H_INCLUDED +#define BIASCONTROLS_H_INCLUDED + +#include "../PluginProcessor.h" +#include "../GUI Extras/ChowSlider.h" +#include "../GUI Extras/MyLNF.h" + +class BiasControls : public Component, + public Slider::Listener +{ +public: + BiasControls (ChowtapeModelAudioProcessor& proc); + + void paint (Graphics&) override; + void resized() override; + +private: + void sliderValueChanged (Slider* slider) override; + void sliderDragStarted (Slider* slider) override; + void sliderDragEnded (Slider* slider) override; + + MyLNF myLNF; + + ChowtapeModelAudioProcessor& processor; + + ChowSlider biasFreqSlide; + ChowSlider biasGainSlide; + + Label biasFreqLabel; + Label biasGainLabel; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BiasControls) +}; + +#endif //BIASCONTROLS_H_INCLUDED diff --git a/Plugin/Source/GUI Components/LossControls.cpp b/Plugin/Source/GUI Components/LossControls.cpp @@ -0,0 +1,53 @@ +#include "LossControls.h" +#include "../PluginEditor.h" + +LossControls::LossControls (ChowtapeModelAudioProcessor& proc) : + processor (proc) +{ + ChowtapeModelAudioProcessorEditor::createSlider (spacingSlider, processor.tapeSpacing, myLNF, this, String ("um")); + ChowtapeModelAudioProcessorEditor::createSlider (thicknessSlider, processor.tapeThickness, myLNF, this, String ("um")); + ChowtapeModelAudioProcessorEditor::createSlider (gapSlider, processor.gapWidth, myLNF, this, String ("um")); + + ChowtapeModelAudioProcessorEditor::createLabel (spacingLabel, processor.tapeSpacing, this); + ChowtapeModelAudioProcessorEditor::createLabel (thicknessLabel, processor.tapeThickness, this); + ChowtapeModelAudioProcessorEditor::createLabel (gapLabel, processor.gapWidth, this); +} + +void LossControls::paint (Graphics& g) +{ + g.setColour (Colours::antiquewhite); + g.setFont (Font ((float) nameHeight).boldened()); + + g.drawFittedText ("Loss Parameters:", Rectangle<int> (xOffset, yOffset, width, labelHeight), + Justification::centredLeft, 1); +} + +void LossControls::resized() +{ + spacingLabel.setBounds (0, 2 * yOffset + labelY, sliderWidth, labelHeight); + spacingSlider.setBounds (0, 2 * yOffset + sliderY, sliderWidth, sliderWidth); + + thicknessLabel.setBounds (spacingSlider.getRight(), 2 * yOffset + labelY, sliderWidth, labelHeight); + thicknessSlider.setBounds (spacingSlider.getRight(), 2 * yOffset + sliderY, sliderWidth, sliderWidth); + + gapLabel.setBounds (thicknessSlider.getRight(), 2 * yOffset + labelY, sliderWidth, labelHeight); + gapSlider.setBounds (thicknessSlider.getRight(), 2 * yOffset + sliderY, sliderWidth, sliderWidth); +} + +void LossControls::sliderValueChanged (Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + *param = (float) slider->getValue(); +} + +void LossControls::sliderDragStarted(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->beginChangeGesture(); +} + +void LossControls::sliderDragEnded(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->endChangeGesture(); +} diff --git a/Plugin/Source/GUI Components/LossControls.h b/Plugin/Source/GUI Components/LossControls.h @@ -0,0 +1,37 @@ +#ifndef LOSSCONTROLS_H_INCLUDED +#define LOSSCONTROLS_H_INCLUDED + +#include "../PluginProcessor.h" +#include "../GUI Extras/ChowSlider.h" +#include "../GUI Extras/MyLNF.h" + +class LossControls : public Component, + public Slider::Listener +{ +public: + LossControls (ChowtapeModelAudioProcessor& proc); + + void paint (Graphics&) override; + void resized() override; + +private: + void sliderValueChanged (Slider* slider) override; + void sliderDragStarted (Slider* slider) override; + void sliderDragEnded (Slider* slider) override; + + MyLNF myLNF; + + ChowtapeModelAudioProcessor& processor; + + ChowSlider spacingSlider; + ChowSlider thicknessSlider; + ChowSlider gapSlider; + + Label spacingLabel; + Label thicknessLabel; + Label gapLabel; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LossControls) +}; + +#endif LOSSCONTROLS_H_INCLUDED diff --git a/Plugin/Source/GUI Components/MainControls.cpp b/Plugin/Source/GUI Components/MainControls.cpp @@ -0,0 +1,62 @@ +#include "MainControls.h" +#include "../PluginEditor.h" + +MainControls::MainControls (ChowtapeModelAudioProcessor& proc) : + processor (proc) +{ + ChowtapeModelAudioProcessorEditor::createSlider (gainInKnob, processor.inGain, myLNF, this, String ("dB")); + ChowtapeModelAudioProcessorEditor::createSlider (gainOutKnob, processor.outGain, myLNF, this, String ("dB")); + ChowtapeModelAudioProcessorEditor::createComboBox (oversampling, processor.overSampling, this); + ChowtapeModelAudioProcessorEditor::createComboBox (tapeSpeed, processor.tapeSpeed, this); + ChowtapeModelAudioProcessorEditor::createComboBox (tapeType, processor.tapeType, this); + + ChowtapeModelAudioProcessorEditor::createLabel (inGainLabel, processor.inGain, this); + ChowtapeModelAudioProcessorEditor::createLabel (outGainLabel, processor.outGain, this); + ChowtapeModelAudioProcessorEditor::createLabel (oversampleLabel, processor.overSampling, this); + ChowtapeModelAudioProcessorEditor::createLabel (speedLabel, processor.tapeSpeed, this); + ChowtapeModelAudioProcessorEditor::createLabel (typeLabel, processor.tapeType, this); +} + +void MainControls::paint (Graphics&) {} + +void MainControls::resized() +{ + inGainLabel.setBounds (0, labelY, sliderWidth, labelHeight); + gainInKnob.setBounds (0, sliderY, sliderWidth, sliderWidth); + + oversampleLabel.setBounds (gainInKnob.getRight() - 7 * xOffset, 2 * labelY + yOffset, tapeWidth, labelHeight); + oversampling.setBounds (gainInKnob.getRight(), oversampleLabel.getBottom(), overWidth, boxHeight); + + speedLabel.setBounds (oversampling.getRight(), 2 * labelY + yOffset, tapeWidth, labelHeight); + tapeSpeed.setBounds (oversampling.getRight() + 2 * xOffset, speedLabel.getBottom(), tapeWidth, boxHeight); + + typeLabel.setBounds (gainInKnob.getRight(), oversampling.getBottom() + yOffset, typeWidth, labelHeight); + tapeType.setBounds (gainInKnob.getRight(), typeLabel.getBottom(), typeWidth, boxHeight); + + outGainLabel.setBounds (tapeSpeed.getRight(), labelY, sliderWidth, labelHeight); + gainOutKnob.setBounds (tapeSpeed.getRight(), sliderY, sliderWidth, sliderWidth); +} + +void MainControls::sliderValueChanged (Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + *param = (float) slider->getValue(); +} + +void MainControls::sliderDragStarted(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->beginChangeGesture(); +} + +void MainControls::sliderDragEnded(Slider* slider) +{ + if (AudioParameterFloat* param = ChowtapeModelAudioProcessorEditor::getParamForSlider (slider, processor)) + param->endChangeGesture(); +} + +void MainControls::comboBoxChanged (ComboBox* box) +{ + if (AudioParameterChoice* param = ChowtapeModelAudioProcessorEditor::getParamForBox (box, processor)) + *param = box->getSelectedItemIndex(); +} diff --git a/Plugin/Source/GUI Components/MainControls.h b/Plugin/Source/GUI Components/MainControls.h @@ -0,0 +1,44 @@ +#ifndef MAINCONTROLS_H_INCLUDED +#define MAINCONTROLS_H_INCLUDED + +#include "../PluginProcessor.h" +#include "../GUI Extras/ChowSlider.h" +#include "../GUI Extras/MyLNF.h" + +class MainControls : public Component, + public Slider::Listener, + public ComboBox::Listener +{ +public: + MainControls (ChowtapeModelAudioProcessor& proc); + + void paint (Graphics&) override; + void resized() override; + +private: + void comboBoxChanged (ComboBox* box) override; + void sliderValueChanged (Slider* slider) override; + void sliderDragStarted (Slider* slider) override; + void sliderDragEnded (Slider* slider) override; + + MyLNF myLNF; + + ChowtapeModelAudioProcessor& processor; + + ChowSlider gainInKnob; + ChowSlider gainOutKnob; + + ComboBox oversampling; + ComboBox tapeSpeed; + ComboBox tapeType; + + Label inGainLabel; + Label outGainLabel; + Label oversampleLabel; + Label speedLabel; + Label typeLabel; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainControls) +}; + +#endif //MAINCONTROLS_H_INCLUDED diff --git a/Plugin/Source/GUI Extras/ChowSlider.h b/Plugin/Source/GUI Extras/ChowSlider.h @@ -0,0 +1,24 @@ +#ifndef CHOWSLIDER_H_INCLUDED +#define CHOWSLIDER_H_INCLUDED + +#include "JuceHeader.h" + +class ChowSlider : public Slider +{ +public: + ChowSlider() {} + + void setDefaultValue (const float value) { defaultValue = value; } + + void mouseDoubleClick (const MouseEvent&) override + { + setValue (defaultValue); + } + +private: + float defaultValue = 0.0f; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChowSlider) +}; + +#endif CHOWSLIDER_H_INCLUDED diff --git a/Plugin/Source/GUI Extras/MyLNF.h b/Plugin/Source/GUI Extras/MyLNF.h @@ -9,6 +9,10 @@ public: MyLNF() { setColour (ComboBox::outlineColourId, Colours::darkorange); + + setColour (PopupMenu::backgroundColourId, Colours::black); + setColour (PopupMenu::textColourId, Colours::antiquewhite); + setColour (PopupMenu::highlightedBackgroundColourId, Colours::darkgrey); } Font getTextButtonFont (TextButton& button, int buttonHeight) override diff --git a/Plugin/Source/PluginEditor.cpp b/Plugin/Source/PluginEditor.cpp @@ -1,59 +1,34 @@ #include "PluginProcessor.h" #include "PluginEditor.h" -enum -{ - width = 375, - height = 150, - - nameHeight = 20, - - xOffset = 2, - yOffset = 5, - - labelY = 15, - labelHeight = 20, - - sliderWidth = 110, - sliderY = 25, - - overWidth = 65, - tapeWidth = 90, - boxHeight = 25, - boxY = 75, -}; - //============================================================================== ChowtapeModelAudioProcessorEditor::ChowtapeModelAudioProcessorEditor (ChowtapeModelAudioProcessor& p) : AudioProcessorEditor (&p), processor (p) { - // Make sure that before the constructor has finished, you've set the - // editor's size to whatever you need it to be. - setSize (width, height); + mainControls.reset (new MainControls (processor)); + addAndMakeVisible (mainControls.get()); - createSlider (gainInKnob, processor.inGain, String ("dB")); - createSlider (gainOutKnob, processor.outGain, String ("dB")); + biasControls.reset (new BiasControls (processor)); + addAndMakeVisible (biasControls.get()); - createComboBox (oversampling, processor.overSampling); - createComboBox (tapeSpeed, processor.tapeSpeed); + lossControls.reset (new LossControls (processor)); + addAndMakeVisible (lossControls.get()); - createLabel (inGainLabel, processor.inGain); - createLabel (outGainLabel, processor.outGain); - createLabel (oversampleLabel, processor.overSampling); - createLabel (speedLabel, processor.tapeSpeed); + setSize (width, height); } ChowtapeModelAudioProcessorEditor::~ChowtapeModelAudioProcessorEditor() { } -void ChowtapeModelAudioProcessorEditor::createSlider (ChowSlider& slide, AudioParameterFloat* param, String suffix, float step){ +void ChowtapeModelAudioProcessorEditor::createSlider (ChowSlider& slide, AudioParameterFloat* param, LookAndFeel& lnf, + Component* comp, String suffix, float step){ slide.setName(param->name); slide.setRange(param->range.start, param->range.end, step); slide.setDefaultValue (param->convertFrom0to1 (dynamic_cast<AudioProcessorParameterWithID*> (param)->getDefaultValue())); slide.setValue(*param); - slide.setLookAndFeel (&myLNF); + slide.setLookAndFeel (&lnf); slide.setSliderStyle(Slider::RotaryHorizontalVerticalDrag); slide.setColour(Slider::rotarySliderFillColourId, Colours::black); slide.setColour(Slider::rotarySliderOutlineColourId, Colours::darkred); @@ -65,11 +40,11 @@ void ChowtapeModelAudioProcessorEditor::createSlider (ChowSlider& slide, AudioPa if (suffix.isNotEmpty()) slide.setTextValueSuffix (" " + suffix); - slide.addListener(this); - addAndMakeVisible (slide); + slide.addListener (dynamic_cast<Slider::Listener*> (comp)); + comp->addAndMakeVisible (slide); } -void ChowtapeModelAudioProcessorEditor::createComboBox (ComboBox& box, AudioParameterChoice* choice) +void ChowtapeModelAudioProcessorEditor::createComboBox (ComboBox& box, AudioParameterChoice* choice, Component* comp) { box.setName (choice->name); box.addItemList (choice->getAllValueStrings(), 1); @@ -79,21 +54,19 @@ void ChowtapeModelAudioProcessorEditor::createComboBox (ComboBox& box, AudioPara box.setColour (ComboBox::outlineColourId, Colours::saddlebrown); box.setColour (ComboBox::textColourId, Colours::antiquewhite); box.setColour (ComboBox::arrowColourId, Colours::antiquewhite); - getLookAndFeel().setColour (PopupMenu::backgroundColourId, Colours::black); - getLookAndFeel().setColour (PopupMenu::textColourId, Colours::antiquewhite); - getLookAndFeel().setColour (PopupMenu::highlightedBackgroundColourId, Colours::darkgrey); - box.addListener (this); - addAndMakeVisible (box); + box.addListener (dynamic_cast<ComboBox::Listener*> (comp)); + comp->addAndMakeVisible (box); } -void ChowtapeModelAudioProcessorEditor::createLabel (Label& label, AudioProcessorParameterWithID* param) +void ChowtapeModelAudioProcessorEditor::createLabel (Label& label, AudioProcessorParameterWithID* param, Component* comp) { label.setText (param->name, dontSendNotification); label.setJustificationType (Justification::centred); label.setColour (Label::textColourId, Colours::antiquewhite); label.setFont (17.0f); - addAndMakeVisible (label); + + comp->addAndMakeVisible (label); } //============================================================================== @@ -104,63 +77,46 @@ void ChowtapeModelAudioProcessorEditor::paint (Graphics& g) g.setColour (Colours::antiquewhite); g.setFont (Font ((float) nameHeight).boldened()); g.drawFittedText ("CHOW Tape Model", getLocalBounds().removeFromTop (nameHeight), Justification::centred, 1); + + g.drawHorizontalLine (sectionHeight, 0, width); + g.drawHorizontalLine (2 * sectionHeight, 0, width); } void ChowtapeModelAudioProcessorEditor::resized() { - inGainLabel.setBounds (0, labelY, sliderWidth, labelHeight); - gainInKnob.setBounds (0, sliderY, sliderWidth, sliderWidth); - - oversampleLabel.setBounds (gainInKnob.getRight() - 7 * xOffset, 3 * labelY + yOffset, tapeWidth, labelHeight); - oversampling.setBounds (gainInKnob.getRight(), boxY, overWidth, boxHeight); - - speedLabel.setBounds (oversampling.getRight(), 3 * labelY + yOffset, tapeWidth, labelHeight); - tapeSpeed.setBounds (oversampling.getRight() + 2 * xOffset, boxY, tapeWidth, boxHeight); - - outGainLabel.setBounds (tapeSpeed.getRight(), labelY, sliderWidth, labelHeight); - gainOutKnob.setBounds (tapeSpeed.getRight(), sliderY, sliderWidth, sliderWidth); + mainControls->setBounds (0, 0, width, sectionHeight); + biasControls->setBounds (0, sectionHeight, width, sectionHeight); + lossControls->setBounds (0, 2 * sectionHeight, width, sectionHeight); } -AudioParameterFloat* ChowtapeModelAudioProcessorEditor::getParamForSlider (Slider* slider) +AudioParameterFloat* ChowtapeModelAudioProcessorEditor::getParamForSlider (Slider* slider, ChowtapeModelAudioProcessor& proc) { - if (processor.inGain->name == slider->getName()) - return processor.inGain; - else if (processor.outGain->name == slider->getName()) - return processor.outGain; + if (proc.inGain->name == slider->getName()) + return proc.inGain; + else if (proc.outGain->name == slider->getName()) + return proc.outGain; + else if (proc.biasFreq->name == slider->getName()) + return proc.biasFreq; + else if (proc.biasGain->name == slider->getName()) + return proc.biasGain; + else if (proc.tapeSpacing->name == slider->getName()) + return proc.tapeSpacing; + else if (proc.tapeThickness->name == slider->getName()) + return proc.tapeThickness; + else if (proc.gapWidth->name == slider->getName()) + return proc.gapWidth; else return nullptr; } -AudioParameterChoice* ChowtapeModelAudioProcessorEditor::getParamForBox (ComboBox* box) +AudioParameterChoice* ChowtapeModelAudioProcessorEditor::getParamForBox (ComboBox* box, ChowtapeModelAudioProcessor& proc) { - if (processor.overSampling->name == box->getName()) - return processor.overSampling; - else if (processor.tapeSpeed->name == box->getName()) - return processor.tapeSpeed; + if (proc.overSampling->name == box->getName()) + return proc.overSampling; + else if (proc.tapeSpeed->name == box->getName()) + return proc.tapeSpeed; + else if (proc.tapeType->name == box->getName()) + return proc.tapeType; else return nullptr; } - -void ChowtapeModelAudioProcessorEditor::comboBoxChanged (ComboBox* box) -{ - if (AudioParameterChoice* param = getParamForBox (box)) - *param = box->getSelectedItemIndex(); -} - -void ChowtapeModelAudioProcessorEditor::sliderValueChanged (Slider* slider) -{ - if (AudioParameterFloat* param = getParamForSlider (slider)) - *param = (float) slider->getValue(); -} - -void ChowtapeModelAudioProcessorEditor::sliderDragStarted(Slider* slider) -{ - if (AudioParameterFloat* param = getParamForSlider (slider)) - param->beginChangeGesture(); -} - -void ChowtapeModelAudioProcessorEditor::sliderDragEnded(Slider* slider) -{ - if (AudioParameterFloat* param = getParamForSlider (slider)) - param->endChangeGesture(); -} diff --git a/Plugin/Source/PluginEditor.h b/Plugin/Source/PluginEditor.h @@ -1,30 +1,37 @@ #pragma once -#include "../JuceLibraryCode/JuceHeader.h" #include "PluginProcessor.h" #include "GUI Extras/MyLNF.h" +#include "GUI Extras/ChowSlider.h" +#include "GUI Components/BiasControls.h" +#include "GUI Components/MainControls.h" +#include "GUI Components/LossControls.h" -class ChowSlider : public Slider +enum { -public: - ChowSlider() {} + width = 375, + sectionHeight = 150, + height = 3 * sectionHeight, + + nameHeight = 20, - void setDefaultValue (const float value) { defaultValue = value; } + xOffset = 2, + yOffset = 5, - void mouseDoubleClick (const MouseEvent&) override - { - setValue (defaultValue); - } + labelY = 15, + labelHeight = 20, -private: - float defaultValue = 0.0f; + sliderWidth = 110, + sliderY = 25, - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChowSlider) + overWidth = 65, + tapeWidth = 90, + typeWidth = 150, + speedWidth = 150, + boxHeight = 25, }; -class ChowtapeModelAudioProcessorEditor : public AudioProcessorEditor, - public Slider::Listener, - public ComboBox::Listener +class ChowtapeModelAudioProcessorEditor : public AudioProcessorEditor { public: ChowtapeModelAudioProcessorEditor (ChowtapeModelAudioProcessor&); @@ -34,33 +41,22 @@ public: void paint (Graphics&) override; void resized() override; -private: - AudioParameterFloat* getParamForSlider (Slider* slider); - void sliderValueChanged (Slider* slider) override; - void sliderDragStarted (Slider* slider) override; - void sliderDragEnded (Slider* slider) override; + static void createSlider (ChowSlider& slide, AudioParameterFloat* param, LookAndFeel& lnf, + Component* comp, String suffix = String(), float step = 0.1f); + static void createComboBox (ComboBox& box, AudioParameterChoice* choice, Component* comp); + static void createLabel (Label& label, AudioProcessorParameterWithID* param, Component* comp); - AudioParameterChoice* getParamForBox (ComboBox* box); - void comboBoxChanged (ComboBox* box) override; + static AudioParameterFloat* getParamForSlider (Slider* slider, ChowtapeModelAudioProcessor& proc); + static AudioParameterChoice* getParamForBox (ComboBox* box, ChowtapeModelAudioProcessor& proc); +private: MyLNF myLNF; ChowtapeModelAudioProcessor& processor; - ChowSlider gainInKnob; - ChowSlider gainOutKnob; - - ComboBox oversampling; - ComboBox tapeSpeed; - - Label inGainLabel; - Label outGainLabel; - Label oversampleLabel; - Label speedLabel; - - void createSlider (ChowSlider& slide, AudioParameterFloat* param, String suffix = String(), float step = 0.1f); - void createComboBox (ComboBox& box, AudioParameterChoice* choice); - void createLabel (Label& label, AudioProcessorParameterWithID* param); + std::unique_ptr<MainControls> mainControls; + std::unique_ptr<BiasControls> biasControls; + std::unique_ptr<LossControls> lossControls; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChowtapeModelAudioProcessorEditor) }; diff --git a/Plugin/Source/PluginProcessor.cpp b/Plugin/Source/PluginProcessor.cpp @@ -14,6 +14,7 @@ ChowtapeModelAudioProcessor::ChowtapeModelAudioProcessor() ) #endif { + //Main Controls addParameter (inGain = new AudioParameterFloat (String ("inGain"), String ("Input Gain"), -30.0f, 30.0f, 0.0f)); inGain->addListener (this); @@ -28,8 +29,30 @@ ChowtapeModelAudioProcessor::ChowtapeModelAudioProcessor() StringArray ({ "3.75 ips", "7.5 ips", "15 ips" }), 1)); tapeSpeed->addListener (this); + addParameter (tapeType = new AudioParameterChoice (String ("tapeType"), String ("Tape Type"), + StringArray ({ "Iron Oxide", "Chromium Oxide" }), 0)); + tapeType->addListener(this); + + //Bias Controls + addParameter (biasFreq = new AudioParameterFloat (String ("biasFreq"), String ("Bias Frequency"), 30.0f, 80.0f, 55.0)); + biasFreq->addListener (this); + + addParameter (biasGain = new AudioParameterFloat (String ("biasGain"), String ("Bias Gain"), 0.0f, 20.0f, 14.0f)); + biasGain->addListener (this); + + //Loss Controls + addParameter (tapeSpacing = new AudioParameterFloat (String ("tapeSpacing"), String ("Spacing"), 0.0f, 50.0f, 0.001f)); + tapeSpacing->addListener (this); + + addParameter (tapeThickness = new AudioParameterFloat (String ("tapeThickness"), String ("Thickness"), 0.0f, 50.0f, 10.0f)); + tapeThickness->addListener (this); + + addParameter (gapWidth = new AudioParameterFloat (String ("gapWidth"), String ("Gap Width"), 2.5f, 12.0f, 3.0f)); + gapWidth->addListener (this); + lossEffects.setSpeed (*tapeSpeed); hysteresis.setOverSamplingFactor (*overSampling); + hysteresis.setBiasFreq (*biasFreq); } ChowtapeModelAudioProcessor::~ChowtapeModelAudioProcessor() @@ -46,6 +69,18 @@ void ChowtapeModelAudioProcessor::parameterValueChanged (int paramIndex, float n hysteresis.setOverSamplingFactor (*overSampling); else if (paramIndex == tapeSpeed->getParameterIndex()) lossEffects.setSpeed (*tapeSpeed); + else if (paramIndex == tapeType->getParameterIndex()) + return; //@TODO + else if (paramIndex == biasFreq->getParameterIndex()) + hysteresis.setBiasFreq (biasFreq->convertFrom0to1 (newValue)); + else if (paramIndex == biasGain->getParameterIndex()) + hysteresis.setBiasGain (biasGain->convertFrom0to1 (newValue)); + else if (paramIndex == tapeSpacing->getParameterIndex()) + lossEffects.setSpacing (tapeSpacing->convertFrom0to1 (newValue)); + else if (paramIndex == tapeThickness->getParameterIndex()) + lossEffects.setThickness (tapeThickness->convertFrom0to1 (newValue)); + else if (paramIndex == gapWidth->getParameterIndex()) + lossEffects.setGap (gapWidth->convertFrom0to1 (newValue)); } //============================================================================== diff --git a/Plugin/Source/PluginProcessor.h b/Plugin/Source/PluginProcessor.h @@ -53,6 +53,14 @@ public: AudioParameterFloat* outGain; AudioParameterChoice* overSampling; AudioParameterChoice* tapeSpeed; + AudioParameterChoice* tapeType; + + AudioParameterFloat* biasFreq; + AudioParameterFloat* biasGain; + + AudioParameterFloat* tapeSpacing; + AudioParameterFloat* tapeThickness; + AudioParameterFloat* gapWidth; void parameterValueChanged (int paramIndex, float newValue) override; void parameterGestureChanged (int /*paramIndex*/, bool /*gestureIsStarting*/) override {} diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp b/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp @@ -2,7 +2,6 @@ namespace { - constexpr float fBias = 55000.0f; constexpr float biasFilterFreq = 24000.0f; } @@ -42,17 +41,17 @@ void HysteresisProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& float* ptrArray[] = { osBlock.getChannelPointer(0), osBlock.getChannelPointer(1) }; AudioBuffer<float> osBuffer (ptrArray, 2, static_cast<int> (osBlock.getNumSamples())); - const auto sineTerm = MathConstants<float>::twoPi * fBias / (float) (getSampleRate() * overSamplingFactor); + const auto sineTerm = MathConstants<float>::twoPi * biasFreq / (float) (getSampleRate() * overSamplingFactor); for (int channel = 0; channel < osBuffer.getNumChannels(); ++channel) { auto* x = osBuffer.getWritePointer (channel); for (int samp = 0; samp < osBuffer.getNumSamples(); samp++) { - x[samp] = 27.f * hProcs[channel].process ((float) 1e4 * (x[samp] + 5.0f * sinf (sineTerm * (float) n[channel]))); + x[samp] = hProcs[channel].process ((float) 1e5 * (x[samp]));// + biasGain * sinf (sineTerm * (float) n[channel]))); n[channel]++; - if ((float) (getSampleRate() * overSamplingFactor * n[channel]) >= 1.0f / fBias) + if ((float) (n[channel] / (getSampleRate() * overSamplingFactor)) >= 1.0f / biasFreq) n[channel] = 0; } } @@ -63,7 +62,7 @@ void HysteresisProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& void HysteresisProcessor::setOverSamplingFactor (String osFactor) { - return; + osFactor = "4x"; //@TODO: figure out how to change oversampling factor without breaking everything int factor = overSamplingFactor; @@ -88,3 +87,13 @@ void HysteresisProcessor::setOverSamplingFactor (String osFactor) overSample->reset(); overSample->initProcessing (getBlockSize()); } + +void HysteresisProcessor::setBiasFreq (float newFreqKHz) +{ + biasFreq = newFreqKHz * 100.0f; +} + +void HysteresisProcessor::setBiasGain (float newGainDB) +{ + biasGain = Decibels::decibelsToGain (newGainDB); +} diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.h b/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.h @@ -17,6 +17,8 @@ public: double getTailLengthSeconds() const override { return overSample->getLatencyInSamples() * getSampleRate(); } void setOverSamplingFactor (String osFactor); + void setBiasFreq (float newFreqKHz); + void setBiasGain (float newGainDB); private: HysteresisProcessing hProcs[2]; @@ -24,6 +26,9 @@ private: BiasFilter biasFilter; int overSamplingFactor = 8; + + float biasFreq = 0.0f; + float biasGain = 5.0f; int n[2] = { 0, 0 }; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HysteresisProcessor) diff --git a/Plugin/Source/Processors/Loss Effects/LossEffects.cpp b/Plugin/Source/Processors/Loss Effects/LossEffects.cpp @@ -3,7 +3,7 @@ LossEffects::LossEffects() {} -void LossEffects::init (float sampleRate, float speed) +void LossEffects::init (float sampleRate, float speed, float spacing, float thickness, float gap) { const auto numBins = sampleRate / (float) order; const auto binWidth = sampleRate / numBins; diff --git a/Plugin/Source/Processors/Loss Effects/LossEffects.h b/Plugin/Source/Processors/Loss Effects/LossEffects.h @@ -5,9 +5,6 @@ namespace { - constexpr float spacing = (float) 1e-9; - constexpr float gap = (float) 2e-6; - constexpr float thickness = (float) 10e-6; constexpr float inchesToMeters = 0.0254f; enum @@ -21,7 +18,7 @@ class LossEffects public: LossEffects(); - void init (float sampleRate, float speed); + void init (float sampleRate, float speed, float spacing, float thickness, float gap); float process (float in); private: diff --git a/Plugin/Source/Processors/Loss Effects/LossEffectsFilter.cpp b/Plugin/Source/Processors/Loss Effects/LossEffectsFilter.cpp @@ -4,8 +4,8 @@ void LossEffectsFilter::prepareToPlay (double sampleRate, int samplesPerBlock) { setRateAndBufferSizeDetails (sampleRate, samplesPerBlock); - lossProcessors[0].init ((float) sampleRate, speed); - lossProcessors[1].init ((float) sampleRate, speed); + lossProcessors[0].init ((float) sampleRate, speed, spacing, thickness, gap); + lossProcessors[1].init ((float) sampleRate, speed, spacing, thickness, gap); } void LossEffectsFilter::releaseResources() @@ -35,3 +35,21 @@ void LossEffectsFilter::setSpeed (String newSpeed) prepareToPlay (getSampleRate(), getBlockSize()); } + +void LossEffectsFilter::setSpacing (float newSpacingMicrons) +{ + spacing = newSpacingMicrons * (float) 1e-6; + prepareToPlay (getSampleRate(), getBlockSize()); +} + +void LossEffectsFilter::setThickness (float newThicknessMicrons) +{ + thickness = newThicknessMicrons * (float) 1e-6; + prepareToPlay (getSampleRate(), getBlockSize()); +} + +void LossEffectsFilter::setGap (float newGapMicrons) +{ + gap = newGapMicrons * (float) 1e-6; + prepareToPlay (getSampleRate(), getBlockSize()); +} diff --git a/Plugin/Source/Processors/Loss Effects/LossEffectsFilter.h b/Plugin/Source/Processors/Loss Effects/LossEffectsFilter.h @@ -14,10 +14,17 @@ public: void processBlock (AudioBuffer<float>& buffer, MidiBuffer& /*midiBuffer*/) override; void setSpeed (String newSpeed); + void setSpacing (float newSpacingMicrons); + void setThickness (float newThicknessMicrons); + void setGap (float newGapMicrons); private: LossEffects lossProcessors[2]; + float speed = 15.0f; + float spacing = (float) 1e-9; + float gap = (float) 3e-6; + float thickness = (float) 10e-6; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LossEffectsFilter) };