mirror of
https://github.com/yokemura/Magical8bitPlug2.git
synced 2025-07-17 11:04:16 -04:00
Added code
This commit is contained in:
163
Source/AdvancedParamsComponent.cpp
Normal file
163
Source/AdvancedParamsComponent.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "AdvancedParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
AdvancedParamsComponent::AdvancedParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
: processor(p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
volumeCompo.reset (new CustomEnvelopeComponent (p, "volume", "Volume", "isVolumeSequenceEnabled_raw"));
|
||||
addAndMakeVisible (volumeCompo.get());
|
||||
volumeCompo->setName ("volume component");
|
||||
|
||||
label5.reset (new Label ("new label",
|
||||
TRANS("Custom Envelopes")));
|
||||
addAndMakeVisible (label5.get());
|
||||
label5->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label5->setJustificationType (Justification::centredLeft);
|
||||
label5->setEditable (false, false, false);
|
||||
label5->setColour (TextEditor::textColourId, Colours::black);
|
||||
label5->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label5->setBounds (0, 4, 150, 24);
|
||||
|
||||
pitchCompo.reset (new CustomEnvelopeComponent (p, "pitch", "Pitch", "isPitchSequenceEnabled_raw"));
|
||||
addAndMakeVisible (pitchCompo.get());
|
||||
pitchCompo->setName ("pitch component");
|
||||
|
||||
dutyCompo.reset (new CustomEnvelopeComponent (p, "duty", "Duty", "isDutySequenceEnabled_raw"));
|
||||
addAndMakeVisible (dutyCompo.get());
|
||||
dutyCompo->setName ("duty component");
|
||||
|
||||
coarseOrFineChoice.reset (new ChoiceComponent (p, "pitchSequenceMode_raw", "Resolution"));
|
||||
addAndMakeVisible (coarseOrFineChoice.get());
|
||||
coarseOrFineChoice->setName ("Coarse or fine");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (700, 216);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
p.settingRefs.volumeSequenceListener = (FrameSequenceChangeListener*)volumeCompo.get();
|
||||
p.settingRefs.pitchSequenceListener = (FrameSequenceChangeListener*)pitchCompo.get();
|
||||
p.settingRefs.dutySequenceListener = (FrameSequenceChangeListener*)dutyCompo.get();
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
AdvancedParamsComponent::~AdvancedParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
volumeCompo = nullptr;
|
||||
label5 = nullptr;
|
||||
pitchCompo = nullptr;
|
||||
dutyCompo = nullptr;
|
||||
coarseOrFineChoice = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AdvancedParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void AdvancedParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
volumeCompo->setBounds (0, 26, getWidth() - 160, 56);
|
||||
pitchCompo->setBounds (0, 82, getWidth() - 204, 56);
|
||||
dutyCompo->setBounds (0, 138, getWidth() - 160, 56);
|
||||
coarseOrFineChoice->setBounds (getWidth() - 4 - 200, 86, 200, 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="AdvancedParamsComponent"
|
||||
componentName="" parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="processor(p)" snapPixels="8" snapActive="1"
|
||||
snapShown="1" overlayOpacity="0.330" fixedSize="1" initialWidth="700"
|
||||
initialHeight="216">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<GENERICCOMPONENT name="volume component" id="829adedfc4b9300f" memberName="volumeCompo"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 160M 56" class="CustomEnvelopeComponent"
|
||||
params="p, "volume", "Volume", "isVolumeSequenceEnabled_raw""/>
|
||||
<LABEL name="new label" id="bae3132bcad681ce" memberName="label5" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 24" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Custom Envelopes" editableSingleClick="0"
|
||||
editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font"
|
||||
fontsize="17.0" kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="pitch component" id="30dd6e142bdc9ed5" memberName="pitchCompo"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 82 204M 56" class="CustomEnvelopeComponent"
|
||||
params="p, "pitch", "Pitch", "isPitchSequenceEnabled_raw""/>
|
||||
<GENERICCOMPONENT name="duty component" id="e5e04cf3ca5aec1" memberName="dutyCompo"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 138 160M 56" class="CustomEnvelopeComponent"
|
||||
params="p, "duty", "Duty", "isDutySequenceEnabled_raw""/>
|
||||
<GENERICCOMPONENT name="Coarse or fine" id="950de1eb69e47c4c" memberName="coarseOrFineChoice"
|
||||
virtualName="" explicitFocusOrder="0" pos="4Rr 86 200 28" class="ChoiceComponent"
|
||||
params="p, "pitchSequenceMode_raw", "Resolution""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
73
Source/AdvancedParamsComponent.h
Normal file
73
Source/AdvancedParamsComponent.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "CustomEnvelopeComponent.h"
|
||||
#include "ChoiceComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class AdvancedParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
AdvancedParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~AdvancedParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
Magical8bitPlug2AudioProcessor& processor;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<CustomEnvelopeComponent> volumeCompo;
|
||||
std::unique_ptr<Label> label5;
|
||||
std::unique_ptr<CustomEnvelopeComponent> pitchCompo;
|
||||
std::unique_ptr<CustomEnvelopeComponent> dutyCompo;
|
||||
std::unique_ptr<ChoiceComponent> coarseOrFineChoice;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AdvancedParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
226
Source/BaseVoice.cpp
Normal file
226
Source/BaseVoice.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BaseVoice.cpp
|
||||
Created: 11 Nov 2019 9:38:44pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "BaseVoice.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Base Voice
|
||||
// (Abstract)
|
||||
//
|
||||
//---------------------------------------------
|
||||
BaseVoice::BaseVoice (SettingRefs* sRefs)
|
||||
{
|
||||
settingRefs = sRefs;
|
||||
}
|
||||
|
||||
bool BaseVoice::canPlaySound (SynthesiserSound* sound)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseVoice::startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int currentPitchBendPosition)
|
||||
{
|
||||
|
||||
noteNumber = midiNoteNumber;
|
||||
|
||||
envelopePhase = kEnvelopePhaseA;
|
||||
currentAngle = 0.0;
|
||||
currentEnvelopeLevel = 0.0;
|
||||
|
||||
ampByVelocityAndGain = * (settingRefs->gain) * velocity; // velocity value range is 0.0f-1.0f
|
||||
|
||||
calculateAngleDelta();
|
||||
|
||||
//
|
||||
// Envelope
|
||||
//
|
||||
double srate = getSampleRate();
|
||||
|
||||
if (* (settingRefs->attack) == 0 ) { attack_slope = 1.0; }
|
||||
else
|
||||
{
|
||||
attack_slope = 1.0 / (* (settingRefs->attack) * srate);
|
||||
}
|
||||
|
||||
if (* (settingRefs->decay) == 0 ) { decay_slope = 1.0; }
|
||||
else
|
||||
{
|
||||
decay_slope = 1.0 / (* (settingRefs->decay) * srate);
|
||||
}
|
||||
|
||||
sustain_level = * (settingRefs->suslevel);
|
||||
|
||||
if (* (settingRefs->release) == 0 ) { release_slope = 1.0; }
|
||||
else
|
||||
{
|
||||
release_slope = 1.0 / (* (settingRefs->release) * srate);
|
||||
}
|
||||
|
||||
//
|
||||
// Control frame
|
||||
//
|
||||
controlFrameTimer = 0;
|
||||
currentVolumeSequenceFrame = 0;
|
||||
|
||||
if (settingRefs->isVolumeSequenceEnabled())
|
||||
{
|
||||
currentEnvelopeLevel = (float) (settingRefs->volumeSequence.valueAt (0)) / 15.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseVoice::stopNote (float, bool allowTailOff)
|
||||
{
|
||||
if (!allowTailOff)
|
||||
{
|
||||
clearCurrentNote();
|
||||
angleDelta = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingRefs->isVolumeSequenceEnabled())
|
||||
{
|
||||
if (settingRefs->volumeSequence.hasRelease)
|
||||
{
|
||||
currentVolumeSequenceFrame = settingRefs->volumeSequence.releaseSequenceStartIndex;
|
||||
currentEnvelopeLevel = (float) (settingRefs->volumeSequence.valueAt (0)) / 15.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
clearCurrentNote();
|
||||
angleDelta = 0.0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
envelopePhase = kEnvelopePhaseR;
|
||||
}
|
||||
|
||||
void BaseVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
|
||||
{
|
||||
if (angleDelta == 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (--numSamples >= 0)
|
||||
{
|
||||
//
|
||||
// Envelope
|
||||
//
|
||||
if (settingRefs->isVolumeSequenceEnabled())
|
||||
{
|
||||
currentEnvelopeLevel = (float) (settingRefs->volumeSequence.valueAt (currentVolumeSequenceFrame)) / 15.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (envelopePhase)
|
||||
{
|
||||
case kEnvelopePhaseA:
|
||||
currentEnvelopeLevel += attack_slope;
|
||||
|
||||
if (currentEnvelopeLevel > 1.0)
|
||||
{
|
||||
currentEnvelopeLevel = 1.0;
|
||||
envelopePhase = kEnvelopePhaseD;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kEnvelopePhaseD:
|
||||
currentEnvelopeLevel -= decay_slope;
|
||||
|
||||
if (currentEnvelopeLevel < sustain_level)
|
||||
{
|
||||
envelopePhase = kEnvelopePhaseS;
|
||||
currentEnvelopeLevel = sustain_level;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kEnvelopePhaseS:
|
||||
currentEnvelopeLevel = sustain_level;
|
||||
break;
|
||||
|
||||
case kEnvelopePhaseR:
|
||||
currentEnvelopeLevel -= release_slope;
|
||||
|
||||
if (currentEnvelopeLevel < 0)
|
||||
{
|
||||
currentEnvelopeLevel = 0;
|
||||
clearCurrentNote();
|
||||
angleDelta = 0.0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Write to buffer
|
||||
//
|
||||
float currentSample = voltageForAngle (currentAngle) * currentEnvelopeLevel * ampByVelocityAndGain;
|
||||
|
||||
for (auto i = outputBuffer.getNumChannels(); --i >= 0;)
|
||||
outputBuffer.addSample (i, startSample, currentSample);
|
||||
|
||||
//
|
||||
// Advance phase
|
||||
//
|
||||
calculateAngleDelta();
|
||||
|
||||
currentAngle += angleDelta;
|
||||
|
||||
while (currentAngle > 2.0 * MathConstants<float>::pi)
|
||||
{
|
||||
currentAngle -= 2.0 * MathConstants<float>::pi;
|
||||
}
|
||||
|
||||
//
|
||||
// Advance control frame
|
||||
//
|
||||
controlFrameTimer += 1.0 / getSampleRate();
|
||||
|
||||
if (controlFrameTimer >= controlFrameLength)
|
||||
{
|
||||
advanceControlFrame();
|
||||
|
||||
while (controlFrameTimer >= controlFrameLength)
|
||||
{
|
||||
controlFrameTimer -= controlFrameLength;
|
||||
}
|
||||
}
|
||||
|
||||
onFrameAdvanced();
|
||||
|
||||
++startSample;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseVoice::calculateAngleDelta()
|
||||
{
|
||||
auto cyclesPerSecond = MidiMessage::getMidiNoteInHertz (noteNumber);
|
||||
auto cyclesPerSample = cyclesPerSecond / getSampleRate();
|
||||
|
||||
angleDelta = cyclesPerSample * 2.0 * MathConstants<double>::pi;
|
||||
}
|
||||
|
||||
void BaseVoice::advanceControlFrame()
|
||||
{
|
||||
currentVolumeSequenceFrame = settingRefs->volumeSequence.nextIndexOf (currentVolumeSequenceFrame);
|
||||
|
||||
if (currentVolumeSequenceFrame == FrameSequence::SHOULD_RETIRE)
|
||||
{
|
||||
currentEnvelopeLevel = 0;
|
||||
clearCurrentNote();
|
||||
angleDelta = 0.0;
|
||||
}
|
||||
}
|
54
Source/BaseVoice.h
Normal file
54
Source/BaseVoice.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BaseVoice.h
|
||||
Created: 11 Nov 2019 9:38:44pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Voices.h"
|
||||
|
||||
struct BaseVoice : public SynthesiserVoice
|
||||
{
|
||||
SettingRefs* settingRefs;
|
||||
|
||||
BaseVoice (SettingRefs* sRefs);
|
||||
|
||||
bool canPlaySound (SynthesiserSound* sound) override;
|
||||
void startNote (int midiNoteNumber, float velocity,
|
||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||
void stopNote (float /*velocity*/, bool allowTailOff) override;
|
||||
void pitchWheelMoved (int) override {}
|
||||
void controllerMoved (int, int) override {}
|
||||
void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override;
|
||||
|
||||
virtual float voltageForAngle (double angle) = 0;
|
||||
virtual void onFrameAdvanced() {};
|
||||
virtual void advanceControlFrame();
|
||||
virtual void calculateAngleDelta();
|
||||
|
||||
protected:
|
||||
// Basic
|
||||
int noteNumber;
|
||||
float ampByVelocityAndGain = 1.0;
|
||||
|
||||
// Oscillator State
|
||||
double currentAngle = 0.0;
|
||||
double angleDelta = 0.0;
|
||||
|
||||
// Envelope
|
||||
double currentEnvelopeLevel = 0.0;
|
||||
EnvelopePhase envelopePhase = kEnvelopePhaseA;
|
||||
double attack_slope = 1.0;
|
||||
double decay_slope = 0.0; // Positive to decrease
|
||||
double sustain_level = 1.0;
|
||||
double release_slope = 1.0; // Positive to decrease
|
||||
|
||||
// For Frame Counting for Customs
|
||||
double controlFrameTimer = 0;
|
||||
const double controlFrameLength = 1.0 / 60.0;
|
||||
int currentVolumeSequenceFrame = 0;
|
||||
};
|
215
Source/BasicParamsComponent.cpp
Normal file
215
Source/BasicParamsComponent.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
#include "PluginEditor.h"
|
||||
//[/Headers]
|
||||
|
||||
#include "BasicParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
BasicParamsComponent::BasicParamsComponent (Magical8bitPlug2AudioProcessor& p, Magical8bitPlug2AudioProcessorEditor& e)
|
||||
: processor(p),editor(e)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
polyLabel.reset (new Label ("label",
|
||||
TRANS("Poly")));
|
||||
addAndMakeVisible (polyLabel.get());
|
||||
polyLabel->setFont (Font (15.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
polyLabel->setJustificationType (Justification::centredLeft);
|
||||
polyLabel->setEditable (false, false, false);
|
||||
polyLabel->setColour (TextEditor::textColourId, Colours::black);
|
||||
polyLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
polyLabel->setBounds (232, 8, 40, 15);
|
||||
|
||||
gainSlider.reset (new SliderComponent (p, "gain", "Gain"));
|
||||
addAndMakeVisible (gainSlider.get());
|
||||
gainSlider->setName ("gain slider");
|
||||
|
||||
gainSlider->setBounds (0, 32, 360, 32);
|
||||
|
||||
oscChoice.reset (new ChoiceComponent (p, "osc", "OSC Type"));
|
||||
addAndMakeVisible (oscChoice.get());
|
||||
oscChoice->setName ("osc selector");
|
||||
|
||||
oscChoice->setBounds (0, 4, 224, 28);
|
||||
|
||||
polyNumberInput.reset (new Slider ("poly number input"));
|
||||
addAndMakeVisible (polyNumberInput.get());
|
||||
polyNumberInput->setRange (0, 32, 1);
|
||||
polyNumberInput->setSliderStyle (Slider::IncDecButtons);
|
||||
polyNumberInput->setTextBoxStyle (Slider::TextBoxLeft, false, 30, 20);
|
||||
polyNumberInput->addListener (this);
|
||||
|
||||
polyNumberInput->setBounds (268, 4, 86, 24);
|
||||
|
||||
advancedSwitch.reset (new CheckBoxComponent (p, "isAdvancedPanelOpen_raw", "Show Advanced Options"));
|
||||
addAndMakeVisible (advancedSwitch.get());
|
||||
advancedSwitch->setName ("advanced option switch");
|
||||
|
||||
colorSchemeChoice.reset (new ChoiceComponent (p, "colorScheme", "Color"));
|
||||
addAndMakeVisible (colorSchemeChoice.get());
|
||||
colorSchemeChoice->setName ("color selector");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (700, 64);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
oscChoice->setListener (this);
|
||||
advancedSwitch->setListener (this);
|
||||
colorSchemeChoice->setListener (this);
|
||||
colorSchemeChoice->setVisible (p.settingRefs.isAdvancedPanelOpen());
|
||||
attc.reset (new SliderAttachment (p.parameters, "maxPoly", *polyNumberInput));
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
BasicParamsComponent::~BasicParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
oscChoice->removeListener();
|
||||
advancedSwitch->removeListener();
|
||||
attc.reset();
|
||||
//[/Destructor_pre]
|
||||
|
||||
polyLabel = nullptr;
|
||||
gainSlider = nullptr;
|
||||
oscChoice = nullptr;
|
||||
polyNumberInput = nullptr;
|
||||
advancedSwitch = nullptr;
|
||||
colorSchemeChoice = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void BasicParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void BasicParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
advancedSwitch->setBounds (getWidth() - 240, 4, 240, 28);
|
||||
colorSchemeChoice->setBounds (getWidth() - 4 - 185, 32, 185, 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void BasicParamsComponent::sliderValueChanged (Slider* sliderThatWasMoved)
|
||||
{
|
||||
//[UsersliderValueChanged_Pre]
|
||||
//[/UsersliderValueChanged_Pre]
|
||||
|
||||
if (sliderThatWasMoved == polyNumberInput.get())
|
||||
{
|
||||
//[UserSliderCode_polyNumberInput] -- add your slider handling code here..
|
||||
processor.setupVoice();
|
||||
//[/UserSliderCode_polyNumberInput]
|
||||
}
|
||||
|
||||
//[UsersliderValueChanged_Post]
|
||||
//[/UsersliderValueChanged_Post]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
void BasicParamsComponent::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
|
||||
{
|
||||
processor.setupVoice();
|
||||
editor.resized();
|
||||
printf ("setup voice!!\n");
|
||||
}
|
||||
|
||||
void BasicParamsComponent::buttonClicked (Button* buttonThatWasClicked)
|
||||
{
|
||||
colorSchemeChoice->setVisible (buttonThatWasClicked->getToggleState());
|
||||
editor.resizeWholePanel();
|
||||
}
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="BasicParamsComponent" componentName=""
|
||||
parentClasses="public Component, public ComboBox::Listener, public Button::Listener"
|
||||
constructorParams="Magical8bitPlug2AudioProcessor& p, Magical8bitPlug2AudioProcessorEditor& e"
|
||||
variableInitialisers="processor(p),editor(e)" snapPixels="8"
|
||||
snapActive="1" snapShown="1" overlayOpacity="0.330" fixedSize="1"
|
||||
initialWidth="700" initialHeight="64">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="a5b2b89e6dca4fe" memberName="polyLabel" virtualName=""
|
||||
explicitFocusOrder="0" pos="232 8 40 15" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Poly" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="15.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="gain slider" id="4bb22b329fed19e9" memberName="gainSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 32 360 32" class="SliderComponent"
|
||||
params="p, "gain", "Gain""/>
|
||||
<GENERICCOMPONENT name="osc selector" id="fa2387d441a3005d" memberName="oscChoice"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 4 224 28" class="ChoiceComponent"
|
||||
params="p, "osc", "OSC Type""/>
|
||||
<SLIDER name="poly number input" id="f767aca03a9fe3ae" memberName="polyNumberInput"
|
||||
virtualName="" explicitFocusOrder="0" pos="268 4 86 24" min="0.0"
|
||||
max="32.0" int="1.0" style="IncDecButtons" textBoxPos="TextBoxLeft"
|
||||
textBoxEditable="1" textBoxWidth="30" textBoxHeight="20" skewFactor="1.0"
|
||||
needsCallback="1"/>
|
||||
<GENERICCOMPONENT name="advanced option switch" id="9d35239102eeb521" memberName="advancedSwitch"
|
||||
virtualName="" explicitFocusOrder="0" pos="0Rr 4 240 28" class="CheckBoxComponent"
|
||||
params="p, "isAdvancedPanelOpen_raw", "Show Advanced Options""/>
|
||||
<GENERICCOMPONENT name="color selector" id="21d73ddc37680dd7" memberName="colorSchemeChoice"
|
||||
virtualName="" explicitFocusOrder="0" pos="4Rr 32 185 28" class="ChoiceComponent"
|
||||
params="p, "colorScheme", "Color""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
86
Source/BasicParamsComponent.h
Normal file
86
Source/BasicParamsComponent.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "PluginProcessor.h"
|
||||
#include "SliderComponent.h"
|
||||
#include "ChoiceComponent.h"
|
||||
#include "CheckBoxComponent.h"
|
||||
class Magical8bitPlug2AudioProcessorEditor;
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class BasicParamsComponent : public Component,
|
||||
public ComboBox::Listener,
|
||||
public Button::Listener,
|
||||
public Slider::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
BasicParamsComponent (Magical8bitPlug2AudioProcessor& p, Magical8bitPlug2AudioProcessorEditor& e);
|
||||
~BasicParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
void comboBoxChanged (ComboBox* comboBoxThatHasChanged) override;
|
||||
void buttonClicked (Button* buttonThatWasClicked) override;
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void sliderValueChanged (Slider* sliderThatWasMoved) override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
Magical8bitPlug2AudioProcessor& processor;
|
||||
Magical8bitPlug2AudioProcessorEditor& editor;
|
||||
|
||||
std::unique_ptr<SliderAttachment> attc;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> polyLabel;
|
||||
std::unique_ptr<SliderComponent> gainSlider;
|
||||
std::unique_ptr<ChoiceComponent> oscChoice;
|
||||
std::unique_ptr<Slider> polyNumberInput;
|
||||
std::unique_ptr<CheckBoxComponent> advancedSwitch;
|
||||
std::unique_ptr<ChoiceComponent> colorSchemeChoice;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
131
Source/BendParamsComponent.cpp
Normal file
131
Source/BendParamsComponent.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "BendParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
BendParamsComponent::BendParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Bend Range")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
sliderCompo.reset (new SliderComponent (p, "bendRange", "Range"));
|
||||
addAndMakeVisible (sliderCompo.get());
|
||||
sliderCompo->setName ("slider");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 58);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
BendParamsComponent::~BendParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
sliderCompo = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void BendParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void BendParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
sliderCompo->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="BendParamsComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="58">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Bend Range" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="slider" id="b01ddc412ec6dc27" memberName="sliderCompo"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
||||
params="p, "bendRange", "Range""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
68
Source/BendParamsComponent.h
Normal file
68
Source/BendParamsComponent.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "SliderComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class BendParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
BendParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~BendParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<SliderComponent> sliderCompo;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BendParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
149
Source/CheckBoxComponent.cpp
Normal file
149
Source/CheckBoxComponent.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
#include "PluginProcessor.h"
|
||||
//[/Headers]
|
||||
|
||||
#include "CheckBoxComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
CheckBoxComponent::CheckBoxComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
toggleButton.reset (new ToggleButton ("toggle button"));
|
||||
addAndMakeVisible (toggleButton.get());
|
||||
toggleButton->setButtonText (TRANS("new toggle button"));
|
||||
toggleButton->addListener (this);
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (360, 28);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
attc.reset (new ButtonAttachment (p.parameters, paramId, *toggleButton));
|
||||
|
||||
toggleButton->setButtonText (name);
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
CheckBoxComponent::~CheckBoxComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
attc.reset();
|
||||
//[/Destructor_pre]
|
||||
|
||||
toggleButton = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void CheckBoxComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void CheckBoxComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
toggleButton->setBounds (32, 0, getWidth() - 40, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void CheckBoxComponent::buttonClicked (Button* buttonThatWasClicked)
|
||||
{
|
||||
//[UserbuttonClicked_Pre]
|
||||
//[/UserbuttonClicked_Pre]
|
||||
|
||||
if (buttonThatWasClicked == toggleButton.get())
|
||||
{
|
||||
//[UserButtonCode_toggleButton] -- add your button handler code here..
|
||||
//[/UserButtonCode_toggleButton]
|
||||
}
|
||||
|
||||
//[UserbuttonClicked_Post]
|
||||
if (buttonThatWasClicked == toggleButton.get() && checkBoxListener != nullptr)
|
||||
{
|
||||
checkBoxListener->buttonClicked (buttonThatWasClicked);
|
||||
}
|
||||
|
||||
//[/UserbuttonClicked_Post]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
void CheckBoxComponent::setListener (Button::Listener* lnr)
|
||||
{
|
||||
checkBoxListener = lnr;
|
||||
}
|
||||
|
||||
void CheckBoxComponent::removeListener()
|
||||
{
|
||||
checkBoxListener = nullptr;
|
||||
}
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="CheckBoxComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p, String paramId, String name"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="360" initialHeight="28">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<TOGGLEBUTTON name="toggle button" id="78b65dc9a6b61921" memberName="toggleButton"
|
||||
virtualName="" explicitFocusOrder="0" pos="32 0 40M 24" buttonText="new toggle button"
|
||||
connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
73
Source/CheckBoxComponent.h
Normal file
73
Source/CheckBoxComponent.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "Defs.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class CheckBoxComponent : public Component,
|
||||
public Button::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
CheckBoxComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name);
|
||||
~CheckBoxComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
void setListener (Button::Listener* lnr);
|
||||
void removeListener();
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void buttonClicked (Button* buttonThatWasClicked) override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
std::unique_ptr<ButtonAttachment> attc;
|
||||
Button::Listener* checkBoxListener = nullptr;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<ToggleButton> toggleButton;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CheckBoxComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
177
Source/ChoiceComponent.cpp
Normal file
177
Source/ChoiceComponent.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "ChoiceComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
ChoiceComponent::ChoiceComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
comboBox.reset (new ComboBox ("combo box"));
|
||||
addAndMakeVisible (comboBox.get());
|
||||
comboBox->setEditableText (false);
|
||||
comboBox->setJustificationType (Justification::centredLeft);
|
||||
comboBox->setTextWhenNothingSelected (String());
|
||||
comboBox->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
|
||||
comboBox->addListener (this);
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Label")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (14.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredRight);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (8, 1, 60, 24);
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (360, 28);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
label->setText (name, dontSendNotification);
|
||||
|
||||
AudioParameterChoice* c = (AudioParameterChoice*)p.parameters.getParameter (paramId);
|
||||
|
||||
for (int i = 0; i < c->choices.size(); i++)
|
||||
{
|
||||
String choice = c->choices[i];
|
||||
comboBox->addItem (choice, i + 1);
|
||||
}
|
||||
|
||||
attc.reset (new ComboBoxAttachment (p.parameters, paramId, *comboBox));
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
ChoiceComponent::~ChoiceComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
attc.reset();
|
||||
//[/Destructor_pre]
|
||||
|
||||
comboBox = nullptr;
|
||||
label = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ChoiceComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void ChoiceComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
comboBox->setBounds (72, 0, getWidth() - 80, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void ChoiceComponent::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
|
||||
{
|
||||
//[UsercomboBoxChanged_Pre]
|
||||
//[/UsercomboBoxChanged_Pre]
|
||||
|
||||
if (comboBoxThatHasChanged == comboBox.get())
|
||||
{
|
||||
//[UserComboBoxCode_comboBox] -- add your combo box handling code here..
|
||||
printf ("value = %d\n", comboBoxThatHasChanged->getSelectedId());
|
||||
//[/UserComboBoxCode_comboBox]
|
||||
}
|
||||
|
||||
//[UsercomboBoxChanged_Post]
|
||||
if (comboBoxThatHasChanged == comboBox.get() && comboBoxListener != nullptr)
|
||||
{
|
||||
comboBoxListener->comboBoxChanged (comboBoxThatHasChanged);
|
||||
}
|
||||
|
||||
//[/UsercomboBoxChanged_Post]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
void ChoiceComponent::setListener (ComboBox::Listener* lnr)
|
||||
{
|
||||
comboBoxListener = lnr;
|
||||
}
|
||||
|
||||
void ChoiceComponent::removeListener()
|
||||
{
|
||||
comboBoxListener = nullptr;
|
||||
}
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="ChoiceComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p, String paramId, String name"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="360" initialHeight="28">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<COMBOBOX name="combo box" id="67bfdf47357e233d" memberName="comboBox"
|
||||
virtualName="" explicitFocusOrder="0" pos="72 0 80M 24" editable="0"
|
||||
layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
|
||||
<LABEL name="label" id="af1fa4a96c3448e5" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="8 1 60 24" edTextCol="ff000000" edBkgCol="0"
|
||||
labelText="Label" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="14.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="34"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
75
Source/ChoiceComponent.h
Normal file
75
Source/ChoiceComponent.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "PluginProcessor.h"
|
||||
#include "Defs.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class ChoiceComponent : public Component,
|
||||
public ComboBox::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
ChoiceComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name);
|
||||
~ChoiceComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
void setListener (ComboBox::Listener* lnr);
|
||||
void removeListener();
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void comboBoxChanged (ComboBox* comboBoxThatHasChanged) override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
std::unique_ptr<ComboBoxAttachment> attc;
|
||||
ComboBox::Listener* comboBoxListener = nullptr;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<ComboBox> comboBox;
|
||||
std::unique_ptr<Label> label;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoiceComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
98
Source/ColorScheme.cpp
Normal file
98
Source/ColorScheme.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ColorScheme.cpp
|
||||
Created: 8 Dec 2019 1:00:26pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "ColorScheme.h"
|
||||
|
||||
ColorScheme::ColorScheme (ColorSchemeType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case kColorSchemeYmck:
|
||||
background = Colour (0xffffffff);
|
||||
textBoxFill = Colour (0xfff4f4ff);
|
||||
boxFill = Colour (0xff00aeff);
|
||||
main = Colour (0xff00aeff);
|
||||
mainThinLine = Colour (0xff0086ff);
|
||||
mainDarkened = Colour (0xff0080bb);
|
||||
accent = Colour (0xffffdd00);
|
||||
reversedForeground = Colour (0xffffffff);
|
||||
genericBorder = Colour (0xff0080bb);
|
||||
warning = Colour (0xffe22be0);
|
||||
break;
|
||||
|
||||
case kColorSchemeYmckDark:
|
||||
background = Colour (0xff000000);
|
||||
textBoxFill = Colour (0xff101010);
|
||||
boxFill = Colour (0xff004070);
|
||||
main = Colour (0xff00aeff);
|
||||
mainThinLine = Colour (0xff40A0ff);
|
||||
mainDarkened = Colour (0xff004070);
|
||||
accent = Colour (0xffffdd00);
|
||||
reversedForeground = Colour (0xffffffff);
|
||||
genericBorder = Colour (0xff0080bb);
|
||||
warning = Colour (0xffe22be0);
|
||||
break;
|
||||
|
||||
case kColorSchemeFamicom:
|
||||
background = Colour (0xfff4f5ec);
|
||||
boxFill = Colour (0xffead780);
|
||||
textBoxFill = Colour (0xfffdfee9);
|
||||
main = Colour (0xffc04136);
|
||||
mainThinLine = Colour (0xff97372b);
|
||||
mainDarkened = Colour (0xffc5b0ae);
|
||||
accent = Colour (0xffeed27d);
|
||||
reversedForeground = Colour (0xff101010);
|
||||
genericBorder = Colour (0xff641c11);
|
||||
warning = Colour (0xff641c11);
|
||||
break;
|
||||
|
||||
case kColorSchemeNes:
|
||||
background = Colour (0xffefefef);
|
||||
boxFill = Colour (0xff69616e);
|
||||
textBoxFill = Colour (0xffd1c8c3);
|
||||
main = Colour (0xff1b1718);
|
||||
mainThinLine = Colour (0xff000000);
|
||||
mainDarkened = Colour (0xffa1988f);
|
||||
accent = Colour (0xffc04136);
|
||||
reversedForeground = Colour (0xffffffff);
|
||||
genericBorder = Colour (0xffa1988f);
|
||||
warning = Colour (0xffc04136);
|
||||
break;
|
||||
|
||||
case kColorSchemeMonotoneLight:
|
||||
background = Colour (0xffffffff);
|
||||
boxFill = Colour (0xffffffff);
|
||||
textBoxFill = Colour (0xfff0f0f0);
|
||||
main = Colour (0xff202020);
|
||||
mainThinLine = Colour (0xff000000);
|
||||
mainDarkened = Colour (0xffc0c0c0);
|
||||
accent = Colour (0xff808080);
|
||||
reversedForeground = Colour (0xff000000);
|
||||
genericBorder = Colour (0xff606060);
|
||||
warning = Colour (0xff000000);
|
||||
break;
|
||||
|
||||
case kColorSchemeMonotoneDark:
|
||||
background = Colour (0xff000000);
|
||||
boxFill = Colour (0xff101010);
|
||||
textBoxFill = Colour (0xff000000);
|
||||
main = Colour (0xffffffff);
|
||||
mainThinLine = Colour (0xffffffff);
|
||||
mainDarkened = Colour (0xff404040);
|
||||
accent = Colour (0xffa0a0a0);
|
||||
reversedForeground = Colour (0xffffffff);
|
||||
genericBorder = Colour (0xffc0c0c0);
|
||||
warning = Colour (0xffffffff);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
38
Source/ColorScheme.h
Normal file
38
Source/ColorScheme.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ColorScheme.h
|
||||
Created: 8 Dec 2019 1:00:26pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
|
||||
enum ColorSchemeType
|
||||
{
|
||||
kColorSchemeYmck = 0,
|
||||
kColorSchemeYmckDark,
|
||||
kColorSchemeFamicom,
|
||||
kColorSchemeNes,
|
||||
kColorSchemeMonotoneLight,
|
||||
kColorSchemeMonotoneDark
|
||||
};
|
||||
|
||||
struct ColorScheme
|
||||
{
|
||||
Colour background;
|
||||
Colour boxFill;
|
||||
Colour textBoxFill;
|
||||
Colour main;
|
||||
Colour mainThinLine;
|
||||
Colour mainDarkened;
|
||||
Colour accent;
|
||||
Colour reversedForeground;
|
||||
Colour genericBorder;
|
||||
Colour warning;
|
||||
|
||||
ColorScheme (ColorSchemeType type);
|
||||
};
|
226
Source/CustomEnvelopeComponent.cpp
Normal file
226
Source/CustomEnvelopeComponent.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
#include "PluginProcessor.h"
|
||||
#include "FrameSequenceParseErrors.h"
|
||||
//[/Headers]
|
||||
|
||||
#include "CustomEnvelopeComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
CustomEnvelopeComponent::CustomEnvelopeComponent (Magical8bitPlug2AudioProcessor& p, String type, String displayName, String flagParameterName)
|
||||
: processor(p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
textEditor.reset (new TextEditor ("text editor"));
|
||||
addAndMakeVisible (textEditor.get());
|
||||
textEditor->setMultiLine (false);
|
||||
textEditor->setReturnKeyStartsNewLine (false);
|
||||
textEditor->setReadOnly (false);
|
||||
textEditor->setScrollbarsShown (false);
|
||||
textEditor->setCaretVisible (true);
|
||||
textEditor->setPopupMenuEnabled (true);
|
||||
textEditor->setText (String());
|
||||
|
||||
toggleButton.reset (new ToggleButton ("toggle button"));
|
||||
addAndMakeVisible (toggleButton.get());
|
||||
toggleButton->setButtonText (TRANS("Enabled"));
|
||||
toggleButton->addListener (this);
|
||||
|
||||
toggleButton->setBounds (8, 4, 104, 24);
|
||||
|
||||
label.reset (new Label ("new label",
|
||||
String()));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (12.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (540, 56);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
paramType = type;
|
||||
attc.reset (new ButtonAttachment (p.parameters, flagParameterName, *toggleButton));
|
||||
|
||||
textEditor->addListener (this);
|
||||
textEditor->setText (p.settingRefs.getSequenceString (type));
|
||||
|
||||
toggleButton->setButtonText (displayName);
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
CustomEnvelopeComponent::~CustomEnvelopeComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
textEditor = nullptr;
|
||||
toggleButton = nullptr;
|
||||
label = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
attc.reset();
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void CustomEnvelopeComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void CustomEnvelopeComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
textEditor->setBounds (112, 4, getWidth() - 124, 24);
|
||||
label->setBounds (112, 28, getWidth() - 124, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void CustomEnvelopeComponent::buttonClicked (Button* buttonThatWasClicked)
|
||||
{
|
||||
//[UserbuttonClicked_Pre]
|
||||
//[/UserbuttonClicked_Pre]
|
||||
|
||||
if (buttonThatWasClicked == toggleButton.get())
|
||||
{
|
||||
//[UserButtonCode_toggleButton] -- add your button handler code here..
|
||||
//[/UserButtonCode_toggleButton]
|
||||
}
|
||||
|
||||
//[UserbuttonClicked_Post]
|
||||
//[/UserbuttonClicked_Post]
|
||||
}
|
||||
|
||||
void CustomEnvelopeComponent::lookAndFeelChanged()
|
||||
{
|
||||
//[UserCode_lookAndFeelChanged] -- Add your code here...
|
||||
ColorScheme cs = ColorScheme (processor.settingRefs.colorSchemeType());
|
||||
|
||||
labelLookAndFeel.setColour (Label::textColourId, cs.warning);
|
||||
label->setLookAndFeel (&labelLookAndFeel);
|
||||
|
||||
textEditor->applyColourToAllText (cs.mainThinLine, true);
|
||||
|
||||
//[/UserCode_lookAndFeelChanged]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
void CustomEnvelopeComponent::textEditorTextChanged (TextEditor& editor)
|
||||
{
|
||||
printf ("*** text changed!\n");
|
||||
String txt = editor.getText();
|
||||
|
||||
ParseError err = kParseErrorNone;
|
||||
processor.settingRefs.setSequenceWithString (paramType, txt, &err);
|
||||
|
||||
if (err == kParseErrorValueOutOfRange)
|
||||
{
|
||||
if (paramType == "volume")
|
||||
{
|
||||
label->setText (getParseErrorString (err, 0, 15), dontSendNotification);
|
||||
}
|
||||
else if (paramType == "pitch")
|
||||
{
|
||||
label->setText (getParseErrorString (err, -64, 63), dontSendNotification);
|
||||
}
|
||||
else if (paramType == "duty")
|
||||
{
|
||||
label->setText (getParseErrorString (err, 0, 2), dontSendNotification);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label->setText (getParseErrorString (err), dontSendNotification);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomEnvelopeComponent::sequenceChanged (String& str)
|
||||
{
|
||||
textEditor->setText (str);
|
||||
}
|
||||
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="CustomEnvelopeComponent"
|
||||
componentName="" parentClasses="public Component, TextEditor::Listener, FrameSequenceChangeListener"
|
||||
constructorParams="Magical8bitPlug2AudioProcessor& p, String type, String displayName, String flagParameterName"
|
||||
variableInitialisers="processor(p)" snapPixels="8" snapActive="1"
|
||||
snapShown="1" overlayOpacity="0.330" fixedSize="1" initialWidth="540"
|
||||
initialHeight="56">
|
||||
<METHODS>
|
||||
<METHOD name="lookAndFeelChanged()"/>
|
||||
</METHODS>
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<TEXTEDITOR name="text editor" id="9e63a9c08f238222" memberName="textEditor"
|
||||
virtualName="" explicitFocusOrder="0" pos="112 4 124M 24" initialText=""
|
||||
multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="0"
|
||||
caret="1" popupmenu="1"/>
|
||||
<TOGGLEBUTTON name="toggle button" id="87baaa12bb810ff" memberName="toggleButton"
|
||||
virtualName="" explicitFocusOrder="0" pos="8 4 104 24" buttonText="Enabled"
|
||||
connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/>
|
||||
<LABEL name="new label" id="ea955df87cc606d6" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="112 28 124M 24" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="12.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
81
Source/CustomEnvelopeComponent.h
Normal file
81
Source/CustomEnvelopeComponent.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "PluginProcessor.h"
|
||||
#include "Defs.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class CustomEnvelopeComponent : public Component,
|
||||
TextEditor::Listener,
|
||||
FrameSequenceChangeListener,
|
||||
public Button::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
CustomEnvelopeComponent (Magical8bitPlug2AudioProcessor& p, String type, String displayName, String flagParameterName);
|
||||
~CustomEnvelopeComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
void textEditorTextChanged (TextEditor& editor) override;
|
||||
void sequenceChanged (String& str) override;
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void buttonClicked (Button* buttonThatWasClicked) override;
|
||||
void lookAndFeelChanged() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
Magical8bitPlug2AudioProcessor& processor;
|
||||
std::unique_ptr<ButtonAttachment> attc;
|
||||
String paramType;
|
||||
LookAndFeel_V4 labelLookAndFeel;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<TextEditor> textEditor;
|
||||
std::unique_ptr<ToggleButton> toggleButton;
|
||||
std::unique_ptr<Label> label;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomEnvelopeComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
15
Source/Defs.h
Normal file
15
Source/Defs.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Defs.h
|
||||
Created: 13 Jul 2019 11:03:52pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef AudioProcessorValueTreeState::SliderAttachment SliderAttachment;
|
||||
typedef AudioProcessorValueTreeState::ButtonAttachment ButtonAttachment;
|
||||
typedef juce::AudioProcessorValueTreeState::ComboBoxAttachment ComboBoxAttachment;
|
196
Source/EnvelopeParamsComponent.cpp
Normal file
196
Source/EnvelopeParamsComponent.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "EnvelopeParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
EnvelopeParamsComponent::EnvelopeParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Envelope")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
attackSlider.reset (new SliderComponent (p, "attack", "Attack"));
|
||||
addAndMakeVisible (attackSlider.get());
|
||||
attackSlider->setName ("attack slider");
|
||||
|
||||
decaySlider.reset (new SliderComponent (p, "decay", "Decay"));
|
||||
addAndMakeVisible (decaySlider.get());
|
||||
decaySlider->setName ("decay slider");
|
||||
|
||||
sustainSlider.reset (new SliderComponent (p, "suslevel", "Sustain"));
|
||||
addAndMakeVisible (sustainSlider.get());
|
||||
sustainSlider->setName ("sustain slider");
|
||||
|
||||
releaseSlider.reset (new SliderComponent (p, "release", "Release"));
|
||||
addAndMakeVisible (releaseSlider.get());
|
||||
releaseSlider->setName ("release slider");
|
||||
|
||||
warningLabel.reset (new Label ("warning label",
|
||||
String()));
|
||||
addAndMakeVisible (warningLabel.get());
|
||||
warningLabel->setFont (Font (15.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
warningLabel->setJustificationType (Justification::centredRight);
|
||||
warningLabel->setEditable (false, false, false);
|
||||
warningLabel->setColour (Label::textColourId, Colour (0xffe22be0));
|
||||
warningLabel->setColour (TextEditor::textColourId, Colours::black);
|
||||
warningLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 142);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
ColorScheme cs = ColorScheme (p.settingRefs.colorSchemeType());
|
||||
warningLabelLookAndFeel.setColour (Label::textColourId, cs.warning);
|
||||
warningLabel->setLookAndFeel (&warningLabelLookAndFeel);
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
EnvelopeParamsComponent::~EnvelopeParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
attackSlider = nullptr;
|
||||
decaySlider = nullptr;
|
||||
sustainSlider = nullptr;
|
||||
releaseSlider = nullptr;
|
||||
warningLabel = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void EnvelopeParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void EnvelopeParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
attackSlider->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
decaySlider->setBounds (0, 54, proportionOfWidth (1.0000f), 28);
|
||||
sustainSlider->setBounds (0, 82, proportionOfWidth (1.0000f), 28);
|
||||
releaseSlider->setBounds (0, 110, proportionOfWidth (1.0000f), 28);
|
||||
warningLabel->setBounds (getWidth() - 8 - 246, 4, 246, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void EnvelopeParamsComponent::enablementChanged()
|
||||
{
|
||||
//[UserCode_enablementChanged] -- Add your code here...
|
||||
if (isEnabled())
|
||||
{
|
||||
warningLabel->setText (TRANS (""), dontSendNotification);
|
||||
}
|
||||
else
|
||||
{
|
||||
warningLabel->setText (TRANS ("Overridden by Custom Envelope"), dontSendNotification);
|
||||
}
|
||||
|
||||
//[/UserCode_enablementChanged]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="EnvelopeParamsComponent"
|
||||
componentName="" parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="142">
|
||||
<METHODS>
|
||||
<METHOD name="enablementChanged()"/>
|
||||
</METHODS>
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Envelope" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="attack slider" id="93ec1e79c45ddad4" memberName="attackSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
||||
params="p, "attack", "Attack""/>
|
||||
<GENERICCOMPONENT name="decay slider" id="1be45518932375fc" memberName="decaySlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 54 100% 28" class="SliderComponent"
|
||||
params="p, "decay", "Decay""/>
|
||||
<GENERICCOMPONENT name="sustain slider" id="5c2169fddb4cc33" memberName="sustainSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 82 100% 28" class="SliderComponent"
|
||||
params="p, "suslevel", "Sustain""/>
|
||||
<GENERICCOMPONENT name="release slider" id="9d35239102eeb521" memberName="releaseSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 110 100% 28" class="SliderComponent"
|
||||
params="p, "release", "Release""/>
|
||||
<LABEL name="warning label" id="624aa3e1415981e3" memberName="warningLabel"
|
||||
virtualName="" explicitFocusOrder="0" pos="8Rr 4 246 24" textCol="ffe22be0"
|
||||
edTextCol="ff000000" edBkgCol="0" labelText="" editableSingleClick="0"
|
||||
editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font"
|
||||
fontsize="15.0" kerning="0.0" bold="0" italic="0" justification="34"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
74
Source/EnvelopeParamsComponent.h
Normal file
74
Source/EnvelopeParamsComponent.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "SliderComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class EnvelopeParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
EnvelopeParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~EnvelopeParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void enablementChanged() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
LookAndFeel_V4 warningLabelLookAndFeel;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<SliderComponent> attackSlider;
|
||||
std::unique_ptr<SliderComponent> decaySlider;
|
||||
std::unique_ptr<SliderComponent> sustainSlider;
|
||||
std::unique_ptr<SliderComponent> releaseSlider;
|
||||
std::unique_ptr<Label> warningLabel;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EnvelopeParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
71
Source/FrameSequence.h
Normal file
71
Source/FrameSequence.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FrameSequence.h
|
||||
Created: 11 Dec 2019 11:37:27am
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
struct FrameSequence
|
||||
{
|
||||
std::vector<int> sequence;
|
||||
bool isLooped = false;
|
||||
bool hasRelease = false;
|
||||
int loopStartIndex = 0;
|
||||
int releaseSequenceStartIndex = 0;
|
||||
static const int SHOULD_RETIRE = 65535;
|
||||
|
||||
int valueAt (int index)
|
||||
{
|
||||
if (index < 0 || index >= sequence.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sequence[index];
|
||||
}
|
||||
|
||||
int nextIndexOf (int current)
|
||||
{
|
||||
if (current < releaseSequenceStartIndex) // Hold
|
||||
{
|
||||
if (current == releaseSequenceStartIndex - 1) // Reached to the end
|
||||
{
|
||||
if (isLooped)
|
||||
{
|
||||
return loopStartIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return current; // Hold the last value
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return current + 1;
|
||||
}
|
||||
|
||||
// No reach here
|
||||
}
|
||||
else // Released
|
||||
{
|
||||
if (current >= sequence.size() - 1) // Reached to the end
|
||||
{
|
||||
return SHOULD_RETIRE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return current + 1;
|
||||
}
|
||||
|
||||
// No reach here
|
||||
}
|
||||
|
||||
// No reach here
|
||||
}
|
||||
};
|
84
Source/FrameSequenceParseErrors.cpp
Normal file
84
Source/FrameSequenceParseErrors.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FrameSequenceParseErrors.cpp
|
||||
Created: 11 Dec 2019 7:16:17pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "FrameSequenceParseErrors.h"
|
||||
|
||||
String getParseErrorString (ParseError err, int minValue, int maxValue)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case kParseErrorDuplicatedReleaseDelimiter:
|
||||
return TRANS ("You cannot use \"|\" more than once");
|
||||
break;
|
||||
|
||||
case kParseErrorDuplicatedOpenBracket:
|
||||
return TRANS ("You cannot use \"[\" more than once");
|
||||
break;
|
||||
|
||||
case kParseErrorDuplicatedCloseBracket:
|
||||
return TRANS ("You cannot use \"]\" more than once");
|
||||
break;
|
||||
|
||||
case kParseErrorRepeatingInReleaseBlock:
|
||||
return TRANS ("You cannot use repeat in release phase");
|
||||
break;
|
||||
|
||||
case kParseErrorUnmatchingOpenBracket:
|
||||
return TRANS ("Unmatching \"[\"");
|
||||
break;
|
||||
|
||||
case kParseErrorUnmatchingCloseBracket:
|
||||
return TRANS ("Unmatching \"]\"");
|
||||
break;
|
||||
|
||||
case kParseErrorUnmatchingBracketNumber:
|
||||
return TRANS ("Number of brackets not matching");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingSlopeValueDelimiter:
|
||||
return TRANS ("\"to\" must be speccified in slope description");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingSlopeLengthDelimiter:
|
||||
return TRANS ("\"in\" must be speccified in slope description");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingSlopeInitialValue:
|
||||
return TRANS ("Missing initial value before \"to\"");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingSlopeFinalValue:
|
||||
return TRANS ("Missing destination value before \"in\"");
|
||||
break;
|
||||
|
||||
case kParseErrorNotANumber:
|
||||
return TRANS ("Number parse failed.");
|
||||
break;
|
||||
|
||||
case kParseErrorValueOutOfRange:
|
||||
return String::formatted (TRANS ("Value should be between %d and %d."), minValue, maxValue);
|
||||
break;
|
||||
|
||||
case kParseErrorFrameLengthTooShort:
|
||||
return TRANS ("Frame count should be more than 2");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingValueForRepeatDelimiter:
|
||||
return TRANS ("Operator x should be followed by a number.");
|
||||
break;
|
||||
|
||||
case kParseErrorMissingFrameCountForRepeatDelimiter:
|
||||
return TRANS ("A number should be specified after operator x.");
|
||||
break;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
37
Source/FrameSequenceParseErrors.h
Normal file
37
Source/FrameSequenceParseErrors.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FrameSequenceParseErrors.h
|
||||
Created: 11 Dec 2019 5:06:52pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
|
||||
enum ParseError
|
||||
{
|
||||
kParseErrorNone = 0,
|
||||
kParseErrorLevelWarning,
|
||||
kParseErrorLevelFatal,
|
||||
kParseErrorDuplicatedReleaseDelimiter,
|
||||
kParseErrorDuplicatedOpenBracket,
|
||||
kParseErrorDuplicatedCloseBracket,
|
||||
kParseErrorRepeatingInReleaseBlock,
|
||||
kParseErrorUnmatchingOpenBracket,
|
||||
kParseErrorUnmatchingCloseBracket,
|
||||
kParseErrorUnmatchingBracketNumber,
|
||||
kParseErrorMissingSlopeValueDelimiter,
|
||||
kParseErrorMissingSlopeLengthDelimiter,
|
||||
kParseErrorMissingSlopeInitialValue,
|
||||
kParseErrorMissingSlopeFinalValue,
|
||||
kParseErrorNotANumber,
|
||||
kParseErrorValueOutOfRange,
|
||||
kParseErrorFrameLengthTooShort,
|
||||
kParseErrorMissingValueForRepeatDelimiter,
|
||||
kParseErrorMissingFrameCountForRepeatDelimiter,
|
||||
};
|
||||
|
||||
String getParseErrorString (ParseError err, int minValue = 0, int maxValue = 0);
|
462
Source/FrameSequenceParser.cpp
Normal file
462
Source/FrameSequenceParser.cpp
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FrameSequenceParser.cpp
|
||||
Created: 11 Dec 2019 8:49:02am
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "FrameSequenceParser.h"
|
||||
|
||||
//
|
||||
// Fileprivate
|
||||
//
|
||||
|
||||
std::vector<int> parseSlope (const String& input,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
ParseError* error)
|
||||
{
|
||||
std::vector<int> retval;
|
||||
|
||||
// find index of "to"
|
||||
int toIndex = input.indexOf ("to");
|
||||
|
||||
if (toIndex < 0)
|
||||
{
|
||||
// Normally this is impossible because it's checking existance of "to" to check if it's a slope
|
||||
*error = kParseErrorMissingSlopeValueDelimiter;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (toIndex < 1)
|
||||
{
|
||||
*error = kParseErrorMissingSlopeInitialValue;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// find index of "in"
|
||||
int inIndex = input.indexOf ("in");
|
||||
|
||||
if (inIndex > input.length() - 3)
|
||||
{
|
||||
*error = kParseErrorMissingSlopeFinalValue;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (inIndex < 0)
|
||||
{
|
||||
*error = kParseErrorMissingSlopeLengthDelimiter;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// get 3 substrings separated by "to" and "in" and put them into `from`, `to`, `cntStr`
|
||||
String fromStr = input.substring (0, toIndex);
|
||||
String toStr = input.substring (toIndex + 2, inIndex);
|
||||
String cntStr = input.substring (inIndex + 2, input.length());
|
||||
|
||||
|
||||
// remove "f" from `cntStr` if exists
|
||||
String cntStr_t = cntStr.replace ("f", "");
|
||||
|
||||
if (!fromStr.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!toStr.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!cntStr_t.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// convert each strings to int
|
||||
double fromValue = fromStr.getDoubleValue();
|
||||
double toValue = toStr.getDoubleValue();
|
||||
double cntValue = cntStr_t.getDoubleValue();
|
||||
|
||||
if (fromValue > (double)maxValue || toValue > (double)maxValue )
|
||||
{
|
||||
*error = kParseErrorValueOutOfRange;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (fromValue < (double)minValue || toValue < (double)minValue )
|
||||
{
|
||||
*error = kParseErrorValueOutOfRange;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (cntValue < 2.0)
|
||||
{
|
||||
*error = kParseErrorFrameLengthTooShort;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// calculate slope as double
|
||||
double slope = (toValue - fromValue) / (cntValue - 1.0);
|
||||
|
||||
for (double i = 0; i < cntValue; i += 1.0)
|
||||
{
|
||||
double value = fromValue + slope * i;
|
||||
int rounded = round (value);
|
||||
retval.push_back (rounded);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<int> parseRepeat (const String& input,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
ParseError* error)
|
||||
{
|
||||
std::vector<int> retval;
|
||||
// find index of "x"
|
||||
int xIndex = input.indexOf ("x");
|
||||
|
||||
if (xIndex < 1)
|
||||
{
|
||||
*error = kParseErrorMissingValueForRepeatDelimiter;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (xIndex > input.length() - 1)
|
||||
{
|
||||
*error = kParseErrorMissingFrameCountForRepeatDelimiter;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// separate into value, count
|
||||
String valueStr = input.substring (0, xIndex);
|
||||
String cntStr = input.substring (xIndex + 1, input.length());
|
||||
// remove "f" from `cntStr` if exists
|
||||
String cntStr_t = cntStr.replace ("f", "");
|
||||
|
||||
if (!valueStr.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!cntStr_t.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int value = valueStr.getIntValue();
|
||||
|
||||
if (value < minValue || value > maxValue)
|
||||
{
|
||||
*error = kParseErrorValueOutOfRange;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int count = cntStr_t.getIntValue();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
retval.push_back (value);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<int> parseSegment (const String& input,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
ParseError* error)
|
||||
{
|
||||
std::vector<int> retval;
|
||||
|
||||
StringArray temp;
|
||||
temp.addTokens (input, ",", "");
|
||||
|
||||
for (String aToken : temp)
|
||||
{
|
||||
std::vector<int> parsed;
|
||||
|
||||
if (aToken.contains ("to"))
|
||||
{
|
||||
// parse as slope
|
||||
parsed = parseSlope (aToken, minValue, maxValue, error);
|
||||
}
|
||||
else if (aToken.contains ("x"))
|
||||
{
|
||||
// parse as repeat-fixed-value
|
||||
parsed = parseRepeat (aToken, minValue, maxValue, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parse as single value
|
||||
if (aToken.length() < 1)
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!aToken.containsOnly ("-0123456789"))
|
||||
{
|
||||
*error = kParseErrorNotANumber;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int value = aToken.getIntValue();
|
||||
|
||||
if (value < minValue || value > maxValue)
|
||||
{
|
||||
*error = kParseErrorValueOutOfRange;
|
||||
return retval;
|
||||
}
|
||||
|
||||
parsed.push_back (value);
|
||||
}
|
||||
|
||||
retval.insert (retval.end(), parsed.begin(), parsed.end());
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
FrameSequence FrameSequenceParser::parse (const String& input,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
ParseError* error)
|
||||
{
|
||||
|
||||
FrameSequence fs;
|
||||
|
||||
//-----------------------------------
|
||||
//
|
||||
// Preprocessing
|
||||
//
|
||||
//-----------------------------------
|
||||
|
||||
// Remove white spaces
|
||||
String trimmed = input.replace (" ", "");
|
||||
|
||||
//
|
||||
// Overall structure
|
||||
//
|
||||
|
||||
int releaseBlockIndex = -1;
|
||||
int repeatStartIndex = -1;
|
||||
int repeatEndIndex = -1;
|
||||
int openBracketCount = 0;
|
||||
int closeBracketCount = 0;
|
||||
|
||||
// loop by character
|
||||
for (int i = 0; i < trimmed.length(); i++)
|
||||
{
|
||||
if (trimmed[i] == '|') // found "|":
|
||||
{
|
||||
if (releaseBlockIndex >= 0)
|
||||
{
|
||||
// if releaseBlockIndex is already determined: Duplication Error
|
||||
*error = kParseErrorDuplicatedReleaseDelimiter;
|
||||
return fs;
|
||||
}
|
||||
|
||||
// if(repeatStartIndex >= 0) {
|
||||
// // if appeard before "[" or "]": Repetition After Release Error
|
||||
// throw new FrameSequenceParseException(TRANS("You cannot repeat in release phase"), true);
|
||||
// }
|
||||
// set releaseBlockIndex
|
||||
releaseBlockIndex = i + 1;
|
||||
|
||||
if (repeatEndIndex < 0)
|
||||
{
|
||||
// if "]" is omitted: Also set repeatEndIndex
|
||||
repeatEndIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (trimmed[i] == '[') /// found "[":
|
||||
{
|
||||
openBracketCount++;
|
||||
|
||||
if (openBracketCount > 1)
|
||||
{
|
||||
// Duplication Error
|
||||
*error = kParseErrorDuplicatedOpenBracket;
|
||||
return fs;
|
||||
}
|
||||
|
||||
if (releaseBlockIndex >= 0)
|
||||
{
|
||||
// if repeat end is already defined: Repetition After Release Error
|
||||
*error = kParseErrorRepeatingInReleaseBlock;
|
||||
return fs;
|
||||
}
|
||||
|
||||
if (repeatEndIndex >= 0)
|
||||
{
|
||||
// if repeat end is already defined: Repetition After Release Error
|
||||
*error = kParseErrorDuplicatedOpenBracket;
|
||||
return fs;
|
||||
}
|
||||
|
||||
// set repeatStartIndex
|
||||
repeatStartIndex = i + 1;
|
||||
}
|
||||
|
||||
if (trimmed[i] == ']') // found "]":
|
||||
{
|
||||
closeBracketCount++;
|
||||
|
||||
if (closeBracketCount > 1)
|
||||
{
|
||||
// Duplication Error
|
||||
*error = kParseErrorDuplicatedCloseBracket;
|
||||
return fs;
|
||||
}
|
||||
|
||||
if (repeatStartIndex < 0)
|
||||
{
|
||||
// if repeatStartIndex hasn't set: Syntax Error
|
||||
*error = kParseErrorUnmatchingCloseBracket;
|
||||
return fs;
|
||||
}
|
||||
|
||||
if (releaseBlockIndex >= 0)
|
||||
{
|
||||
// if repeat end is already defined: Repetition After Release Error
|
||||
*error = kParseErrorRepeatingInReleaseBlock;
|
||||
return fs;
|
||||
}
|
||||
|
||||
repeatEndIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// if (releaseBlockIndex < 0) { // "|" didn't explicitly specified
|
||||
// releaseBlockIndex = trimmed.length();
|
||||
// }
|
||||
|
||||
if (openBracketCount != closeBracketCount)
|
||||
{
|
||||
*error = kParseErrorUnmatchingBracketNumber;
|
||||
return fs;
|
||||
}
|
||||
|
||||
if (releaseBlockIndex - repeatEndIndex > 1)
|
||||
{
|
||||
// throw new FrameSequenceParseException(TRANS("Elements between repeat block and release block will be ignored"), false);
|
||||
// FiXME: non-fatal exceptionをどう扱うか
|
||||
}
|
||||
|
||||
// Just for convenience
|
||||
bool hasRelease = (releaseBlockIndex >= 0);
|
||||
bool shouldRepeat = (repeatStartIndex >= 0);
|
||||
|
||||
//-----------------------------------
|
||||
//
|
||||
// Split segments
|
||||
//
|
||||
//-----------------------------------
|
||||
|
||||
String str_beforeRepeat;
|
||||
String str_insideRepeat;
|
||||
String str_release;
|
||||
|
||||
if (shouldRepeat)
|
||||
{
|
||||
if (hasRelease)
|
||||
{
|
||||
str_beforeRepeat = trimmed.substring (0, repeatStartIndex - 1);
|
||||
}
|
||||
|
||||
str_insideRepeat = trimmed.substring (repeatStartIndex, repeatEndIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasRelease)
|
||||
{
|
||||
str_beforeRepeat = trimmed.substring (0, releaseBlockIndex - 1);
|
||||
str_release = trimmed.substring (releaseBlockIndex, trimmed.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
str_beforeRepeat = trimmed.substring (0, trimmed.length());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "before repeat : " + str_beforeRepeat + "\n";
|
||||
std::cout << "inside repeat : " + str_insideRepeat + "\n";
|
||||
std::cout << "after release : " + str_release + "\n";
|
||||
|
||||
|
||||
//-----------------------------------
|
||||
//
|
||||
// Parse segments
|
||||
//
|
||||
//-----------------------------------
|
||||
|
||||
// Parse main segment to get frameSequence
|
||||
// And set frameSequence value to working variable
|
||||
// FrameSequence *fs = std::make_unique<FrameSequence>();
|
||||
|
||||
std::vector<int> sequence = parseSegment (str_beforeRepeat, minValue, maxValue, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return fs;
|
||||
}
|
||||
|
||||
fs.sequence = sequence;
|
||||
fs.sequence.reserve (1000);
|
||||
fs.releaseSequenceStartIndex = (int)fs.sequence.size();
|
||||
|
||||
if (shouldRepeat) // If repeat segment exists:
|
||||
{
|
||||
// Set repeatStartIndex according to current working frameSequence length
|
||||
fs.isLooped = true;
|
||||
fs.loopStartIndex = (int)fs.sequence.size();
|
||||
|
||||
// Parse repeat segment and to get frameSequence
|
||||
std::vector<int> repeatSeq = parseSegment (str_insideRepeat, minValue, maxValue, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return fs;
|
||||
}
|
||||
|
||||
// Add the result to working frameSequence
|
||||
fs.sequence.insert (fs.sequence.end(), repeatSeq.begin(), repeatSeq.end());
|
||||
|
||||
// Set repeatEndIndex according to current working frameSequence length
|
||||
fs.releaseSequenceStartIndex = (int)fs.sequence.size();
|
||||
}
|
||||
|
||||
if (hasRelease) // If release exists:
|
||||
{
|
||||
// Set releaseStartIndex according to current working frameSequence length
|
||||
fs.releaseSequenceStartIndex = (int)fs.sequence.size();
|
||||
fs.hasRelease = true;
|
||||
|
||||
// Parse release segment to get frameSequence
|
||||
std::vector<int> releaseSeq = parseSegment (str_release, minValue, maxValue, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return fs;
|
||||
}
|
||||
|
||||
// Add the result to working frameSequence
|
||||
fs.sequence.insert (fs.sequence.end(), releaseSeq.begin(), releaseSeq.end());
|
||||
printf ("success");
|
||||
}
|
||||
|
||||
// return the frameSequence
|
||||
return fs;
|
||||
}
|
19
Source/FrameSequenceParser.h
Normal file
19
Source/FrameSequenceParser.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
FrameSequenceParser.h
|
||||
Created: 11 Dec 2019 8:49:02am
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "FrameSequence.h"
|
||||
#include "FrameSequenceParseErrors.h"
|
||||
|
||||
struct FrameSequenceParser
|
||||
{
|
||||
FrameSequence parse (const String& input, int minValue, int maxValue, ParseError* error);
|
||||
};
|
131
Source/NoiseParamsComponent.cpp
Normal file
131
Source/NoiseParamsComponent.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "NoiseParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
NoiseParamsComponent::NoiseParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Noise")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
algorithmSelector.reset (new ChoiceComponent (p, "noiseAlgorithm_raw", "Noise Type"));
|
||||
addAndMakeVisible (algorithmSelector.get());
|
||||
algorithmSelector->setName ("algorithm selector");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 58);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
NoiseParamsComponent::~NoiseParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
algorithmSelector = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void NoiseParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void NoiseParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
algorithmSelector->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="NoiseParamsComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="58">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Noise" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="algorithm selector" id="b01ddc412ec6dc27" memberName="algorithmSelector"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="ChoiceComponent"
|
||||
params="p, "noiseAlgorithm_raw", "Noise Type""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
68
Source/NoiseParamsComponent.h
Normal file
68
Source/NoiseParamsComponent.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "ChoiceComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class NoiseParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
NoiseParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~NoiseParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<ChoiceComponent> algorithmSelector;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NoiseParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
88
Source/NoiseVoice.cpp
Normal file
88
Source/NoiseVoice.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NoiseVoice.cpp
|
||||
Created: 11 Nov 2019 9:37:21pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "NoiseVoice.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Noise Voice
|
||||
//
|
||||
//---------------------------------------------
|
||||
NoiseVoice::NoiseVoice(SettingRefs *sRefs) : TonalVoice(sRefs) {}
|
||||
|
||||
void NoiseVoice::startNote(int midiNoteNumber, float velocity, SynthesiserSound *, int currentPitchBendPosition) {
|
||||
TonalVoice::startNote(midiNoteNumber, velocity, 0, currentPitchBendPosition);
|
||||
switch (settingRefs->noiseAlgorithm()) {
|
||||
case kNoiseInfinite2:
|
||||
cycleLength = MathConstants<float>::pi / 25.0;
|
||||
break;
|
||||
|
||||
case kNoiseLong:
|
||||
case kNoiseShort:
|
||||
cycleLength = MathConstants<float>::pi / 8.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
cycleLength = MathConstants<float>::pi / 8.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float NoiseVoice::voltageForAngle (double angle)
|
||||
{
|
||||
// TODO: StartVoice側でangleDeltaを調整する方が良い
|
||||
// double dividedAngle = fmod(angle, MathConstants<float>::pi / 2.0);
|
||||
bool isNewCycle = angle < previousAngle;
|
||||
bool shouldUpdate = false;
|
||||
|
||||
if (isNewCycle)
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
else if (nextAngle != 0)
|
||||
{
|
||||
if (angle >= nextAngle)
|
||||
{
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldUpdate)
|
||||
{
|
||||
if (settingRefs->noiseAlgorithm() == kNoiseInfinite2)
|
||||
{
|
||||
currentVoltage = float (rand() % 16 - 8) / 16.;
|
||||
}
|
||||
else
|
||||
{
|
||||
int compareBitPos = settingRefs->noiseAlgorithm() == kNoiseLong ? 1 : 6;
|
||||
|
||||
unsigned int bit0 = rgstr & 0b0000001;
|
||||
unsigned int compared = (rgstr & 1 << compareBitPos) >> compareBitPos;
|
||||
unsigned int feedback = bit0 ^ compared;
|
||||
|
||||
rgstr = rgstr >> 1;
|
||||
|
||||
unsigned int mask = ~ (1 << 14);
|
||||
unsigned int writeback = feedback << 14;
|
||||
rgstr = (rgstr & mask) | writeback;
|
||||
|
||||
currentVoltage = (float)bit0 - 0.5;
|
||||
}
|
||||
|
||||
nextAngle = (double) ((int) (angle / cycleLength) + 1) * cycleLength;
|
||||
|
||||
if (nextAngle >= MathConstants<float>::pi * 2) { nextAngle = 0; }
|
||||
}
|
||||
|
||||
previousAngle = angle;
|
||||
|
||||
return currentVoltage;
|
||||
}
|
28
Source/NoiseVoice.h
Normal file
28
Source/NoiseVoice.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
NoiseVoice.h
|
||||
Created: 11 Nov 2019 9:37:21pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "TonalVoice.h"
|
||||
|
||||
struct NoiseVoice : public TonalVoice {
|
||||
|
||||
NoiseVoice(SettingRefs *sRefs);
|
||||
double cycleLength = MathConstants<float>::pi / 8.0;
|
||||
|
||||
// Noise states
|
||||
float currentVoltage = -0.5;
|
||||
double nextAngle = cycleLength;
|
||||
double previousAngle = 0;
|
||||
unsigned int rgstr = 0b111111111111111;
|
||||
|
||||
void startNote (int midiNoteNumber, float velocity,
|
||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||
float voltageForAngle (double angle) override;
|
||||
};
|
291
Source/PluginEditor.cpp
Normal file
291
Source/PluginEditor.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file was auto-generated!
|
||||
|
||||
It contains the basic framework code for a JUCE plugin editor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "PluginProcessor.h"
|
||||
#include "PluginEditor.h"
|
||||
#include "AdvancedParamsComponent.h"
|
||||
#include "PulseParamsComponent.h"
|
||||
#include "BasicParamsComponent.h"
|
||||
#include "EnvelopeParamsComponent.h"
|
||||
#include "NoiseParamsComponent.h"
|
||||
#include "BendParamsComponent.h"
|
||||
#include "SweepParamsComponent.h"
|
||||
#include "VibratoParamsComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
Magical8bitPlug2AudioProcessorEditor::Magical8bitPlug2AudioProcessorEditor (Magical8bitPlug2AudioProcessor& 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.
|
||||
applyLookAndFeel();
|
||||
|
||||
basicCompo.reset (new BasicParamsComponent (p, *this));
|
||||
addAndMakeVisible (basicCompo.get());
|
||||
|
||||
envCompo.reset (new EnvelopeParamsComponent (p));
|
||||
addAndMakeVisible (envCompo.get());
|
||||
|
||||
advCompo.reset (new AdvancedParamsComponent (p));
|
||||
addAndMakeVisible (advCompo.get());
|
||||
|
||||
pulCompo.reset (new PulseParamsComponent (p));
|
||||
addAndMakeVisible (pulCompo.get());
|
||||
|
||||
noiCompo.reset (new NoiseParamsComponent (p));
|
||||
addAndMakeVisible (noiCompo.get());
|
||||
|
||||
bendCompo.reset (new BendParamsComponent (p));
|
||||
addAndMakeVisible (bendCompo.get());
|
||||
|
||||
sweepCompo.reset (new SweepParamsComponent (p));
|
||||
addAndMakeVisible (sweepCompo.get());
|
||||
|
||||
vibCompo.reset (new VibratoParamsComponent (p));
|
||||
addAndMakeVisible (vibCompo.get());
|
||||
|
||||
(p.parameters.getParameter ("isVolumeSequenceEnabled_raw"))->addListener (this);
|
||||
(p.parameters.getParameter ("isDutySequenceEnabled_raw"))->addListener (this);
|
||||
|
||||
|
||||
resizeWholePanel();
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessorEditor::applyLookAndFeel()
|
||||
{
|
||||
ColorScheme cs = ColorScheme (processor.settingRefs.colorSchemeType());
|
||||
|
||||
//
|
||||
// Slider
|
||||
//
|
||||
getLookAndFeel().setColour (Slider::trackColourId, cs.main);
|
||||
getLookAndFeel().setColour (Slider::thumbColourId, cs.accent);
|
||||
getLookAndFeel().setColour (Slider::backgroundColourId, cs.mainDarkened);
|
||||
getLookAndFeel().setColour (Slider::textBoxTextColourId, cs.mainThinLine);
|
||||
getLookAndFeel().setColour (Slider::textBoxBackgroundColourId, cs.textBoxFill);
|
||||
getLookAndFeel().setColour (Slider::textBoxOutlineColourId, cs.genericBorder);
|
||||
|
||||
getLookAndFeel().setColour (TextButton::ColourIds::buttonColourId, cs.boxFill);
|
||||
getLookAndFeel().setColour (TextButton::ColourIds::textColourOffId, cs.reversedForeground);
|
||||
|
||||
//
|
||||
// Label
|
||||
//
|
||||
getLookAndFeel().setColour (Label::textColourId, cs.mainThinLine);
|
||||
|
||||
//
|
||||
// Toggle Button
|
||||
//
|
||||
getLookAndFeel().setColour (ToggleButton::textColourId, cs.mainThinLine);
|
||||
getLookAndFeel().setColour (ToggleButton::tickDisabledColourId, cs.mainThinLine);
|
||||
getLookAndFeel().setColour (ToggleButton::tickColourId, cs.mainThinLine);
|
||||
|
||||
//
|
||||
// Text Editor
|
||||
//
|
||||
getLookAndFeel().setColour (TextEditor::textColourId, cs.mainThinLine);
|
||||
getLookAndFeel().setColour (TextEditor::backgroundColourId, cs.textBoxFill);
|
||||
getLookAndFeel().setColour (TextEditor::outlineColourId, cs.genericBorder);
|
||||
|
||||
//
|
||||
// Combo Box
|
||||
//
|
||||
getLookAndFeel().setColour (ComboBox::backgroundColourId, cs.boxFill);
|
||||
getLookAndFeel().setColour (ComboBox::textColourId, cs.reversedForeground);
|
||||
getLookAndFeel().setColour (ComboBox::arrowColourId, cs.reversedForeground);
|
||||
getLookAndFeel().setColour (ComboBox::buttonColourId, cs.mainThinLine);
|
||||
getLookAndFeel().setColour (ComboBox::outlineColourId, cs.genericBorder);
|
||||
}
|
||||
|
||||
Magical8bitPlug2AudioProcessorEditor::~Magical8bitPlug2AudioProcessorEditor()
|
||||
{
|
||||
(processor.parameters.getParameter ("isVolumeSequenceEnabled_raw"))->removeListener (this);
|
||||
(processor.parameters.getParameter ("isDutySequenceEnabled_raw"))->removeListener (this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct
|
||||
{
|
||||
const int totalWidth = 640;
|
||||
const int topMargin = 10;
|
||||
const int leftMargin = 10;
|
||||
const int bottomMargin = 20;
|
||||
const int halfComponentWidth = 300;
|
||||
const int fullComponentWidth = 620;
|
||||
const int sectionSeparatorHeight = 16;
|
||||
const int verticalSeparatorWidth = 16;
|
||||
const int componentMargin = 2;
|
||||
const int indexHeight = 22;
|
||||
const int genericControlHeight = 28;
|
||||
const int customEnvelopeHeight = 56;
|
||||
|
||||
const int basCompoHeight = componentMargin * 2
|
||||
+ genericControlHeight * 2;
|
||||
const int toneSpecificControlHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ genericControlHeight;
|
||||
const int envCompoHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ genericControlHeight * 4;
|
||||
const int bendCompoHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ genericControlHeight;
|
||||
const int sweepCompoHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ genericControlHeight * 2;
|
||||
const int vibCompoHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ genericControlHeight * 4;
|
||||
const int advCompoHeight = componentMargin * 2
|
||||
+ indexHeight
|
||||
+ customEnvelopeHeight * 3;
|
||||
const int totalHeight (bool isAdvOptOn)
|
||||
{
|
||||
if (isAdvOptOn)
|
||||
{
|
||||
return topMargin
|
||||
+ basCompoHeight
|
||||
+ sectionSeparatorHeight
|
||||
+ toneSpecificControlHeight
|
||||
+ envCompoHeight
|
||||
+ bendCompoHeight
|
||||
+ sectionSeparatorHeight
|
||||
+ advCompoHeight
|
||||
+ bottomMargin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return topMargin
|
||||
+ basCompoHeight
|
||||
+ sectionSeparatorHeight
|
||||
+ toneSpecificControlHeight
|
||||
+ envCompoHeight
|
||||
+ bendCompoHeight
|
||||
+ bottomMargin;
|
||||
}
|
||||
}
|
||||
} sizes;
|
||||
|
||||
void Magical8bitPlug2AudioProcessorEditor::paint (Graphics& g)
|
||||
{
|
||||
// fill the whole window white
|
||||
ColorScheme cs = ColorScheme (processor.settingRefs.colorSchemeType());
|
||||
g.fillAll (cs.background);
|
||||
|
||||
int y = sizes.topMargin
|
||||
+ sizes.basCompoHeight
|
||||
+ sizes.sectionSeparatorHeight / 2;
|
||||
g.setColour (cs.genericBorder);
|
||||
|
||||
Line<float> line (Point<float> (sizes.leftMargin, y),
|
||||
Point<float> (sizes.leftMargin + sizes.fullComponentWidth, y));
|
||||
|
||||
g.drawLine (line, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
void Magical8bitPlug2AudioProcessorEditor::resized()
|
||||
{
|
||||
applyLookAndFeel();
|
||||
|
||||
//
|
||||
// Header
|
||||
//
|
||||
int x = sizes.leftMargin;
|
||||
int y = sizes.topMargin;
|
||||
int w = sizes.halfComponentWidth;
|
||||
basicCompo->setBounds (x, y, sizes.fullComponentWidth, sizes.basCompoHeight);
|
||||
|
||||
//
|
||||
// Main part - Left
|
||||
//
|
||||
y = sizes.topMargin + sizes.basCompoHeight + sizes.sectionSeparatorHeight;
|
||||
|
||||
pulCompo->setBounds (x, y, w, sizes.toneSpecificControlHeight);
|
||||
noiCompo->setBounds (x, y, w, sizes.toneSpecificControlHeight);
|
||||
y += sizes.toneSpecificControlHeight;
|
||||
|
||||
envCompo->setBounds (x, y, w, sizes.envCompoHeight);
|
||||
y += sizes.envCompoHeight;
|
||||
|
||||
bendCompo->setBounds (x, y, w, sizes.bendCompoHeight);
|
||||
y += sizes.bendCompoHeight;
|
||||
|
||||
//
|
||||
// Main part - Right
|
||||
//
|
||||
x = sizes.leftMargin + sizes.halfComponentWidth + sizes.verticalSeparatorWidth;
|
||||
int y2 = sizes.topMargin + sizes.basCompoHeight + sizes.sectionSeparatorHeight;
|
||||
|
||||
sweepCompo->setBounds (x, y2, w, sizes.sweepCompoHeight);
|
||||
y2 += sizes.sweepCompoHeight;
|
||||
|
||||
vibCompo->setBounds (x, y2, w, sizes.vibCompoHeight);
|
||||
y2 += sizes.vibCompoHeight;
|
||||
|
||||
//
|
||||
// Advanced part
|
||||
//
|
||||
x = sizes.leftMargin;
|
||||
int y3 = y > y2 ? y : y2;
|
||||
y3 += sizes.sectionSeparatorHeight;
|
||||
advCompo->setBounds (x, y3, sizes.fullComponentWidth, sizes.advCompoHeight);
|
||||
|
||||
//
|
||||
// Visibility
|
||||
//
|
||||
switch (processor.settingRefs.oscillatorType())
|
||||
{
|
||||
case kVoiceTypePulse:
|
||||
pulCompo->setVisible (true);
|
||||
noiCompo->setVisible (false);
|
||||
break;
|
||||
|
||||
case kVoiceTypeNoise:
|
||||
pulCompo->setVisible (false);
|
||||
noiCompo->setVisible (true);
|
||||
break;
|
||||
|
||||
default:
|
||||
pulCompo->setVisible (false);
|
||||
noiCompo->setVisible (false);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Enable/Disable
|
||||
//
|
||||
envCompo->setEnabled (!processor.settingRefs.isVolumeSequenceEnabled());
|
||||
pulCompo->setEnabled (!processor.settingRefs.isDutySequenceEnabled());
|
||||
|
||||
sendLookAndFeelChange();
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessorEditor::resizeWholePanel()
|
||||
{
|
||||
setSize (sizes.totalWidth, sizes.totalHeight (processor.settingRefs.isAdvancedPanelOpen()));
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessorEditor::parameterValueChanged (int parameterIndex, float newValue)
|
||||
{
|
||||
if (parameterIndex == (processor.parameters.getParameter ("isVolumeSequenceEnabled_raw"))->getParameterIndex())
|
||||
{
|
||||
printf ("Volume sequence enabled flag %f\n", newValue);
|
||||
bool isEnabled = newValue > 0.5;
|
||||
envCompo->setEnabled (!isEnabled);
|
||||
}
|
||||
else if (parameterIndex == (processor.parameters.getParameter ("isDutySequenceEnabled_raw"))->getParameterIndex())
|
||||
{
|
||||
printf ("Duty sequence enabled flag %f\n", newValue);
|
||||
bool isEnabled = newValue > 0.5;
|
||||
pulCompo->setEnabled (!isEnabled);
|
||||
}
|
||||
}
|
||||
|
56
Source/PluginEditor.h
Normal file
56
Source/PluginEditor.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file was auto-generated!
|
||||
|
||||
It contains the basic framework code for a JUCE plugin editor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "PluginProcessor.h"
|
||||
class AdvancedParamsComponent;
|
||||
class PulseParamsComponent;
|
||||
class BasicParamsComponent;
|
||||
class EnvelopeParamsComponent;
|
||||
class NoiseParamsComponent;
|
||||
class BendParamsComponent;
|
||||
class SweepParamsComponent;
|
||||
class VibratoParamsComponent;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class Magical8bitPlug2AudioProcessorEditor : public AudioProcessorEditor
|
||||
, public AudioProcessorParameter::Listener
|
||||
{
|
||||
public:
|
||||
Magical8bitPlug2AudioProcessorEditor (Magical8bitPlug2AudioProcessor&);
|
||||
~Magical8bitPlug2AudioProcessorEditor();
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics&) override;
|
||||
void resized() override;
|
||||
void resizeWholePanel();
|
||||
void applyLookAndFeel();
|
||||
|
||||
void parameterValueChanged (int parameterIndex, float newValue) override;
|
||||
void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) override {};
|
||||
|
||||
private:
|
||||
Magical8bitPlug2AudioProcessor& processor;
|
||||
|
||||
std::unique_ptr<BasicParamsComponent> basicCompo;
|
||||
std::unique_ptr<EnvelopeParamsComponent> envCompo;
|
||||
std::unique_ptr<AdvancedParamsComponent> advCompo;
|
||||
std::unique_ptr<PulseParamsComponent> pulCompo;
|
||||
std::unique_ptr<NoiseParamsComponent> noiCompo;
|
||||
std::unique_ptr<BendParamsComponent> bendCompo;
|
||||
std::unique_ptr<SweepParamsComponent> sweepCompo;
|
||||
std::unique_ptr<VibratoParamsComponent> vibCompo;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Magical8bitPlug2AudioProcessorEditor)
|
||||
};
|
476
Source/PluginProcessor.cpp
Normal file
476
Source/PluginProcessor.cpp
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file was auto-generated!
|
||||
|
||||
It contains the basic framework code for a JUCE plugin processor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "PluginProcessor.h"
|
||||
#include "PluginEditor.h"
|
||||
#include "PulseVoice.h"
|
||||
#include "TriangleVoice.h"
|
||||
#include "NoiseVoice.h"
|
||||
#include "FrameSequenceParseErrors.h"
|
||||
|
||||
//==============================================================================
|
||||
Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
||||
: parameters (
|
||||
*this, nullptr, Identifier ("Params"),
|
||||
{
|
||||
//
|
||||
// Meta
|
||||
//
|
||||
std::make_unique<AudioParameterBool> ("isAdvancedPanelOpen_raw", "Advanced", false),
|
||||
std::make_unique<AudioParameterChoice> ("colorScheme", "Color Scheme", StringArray ({"YMCK", "YMCK Dark", "Japan", "Worldwide", "Monotone", "Mono Dark"}), 0),
|
||||
//
|
||||
// Basic
|
||||
//
|
||||
std::make_unique<AudioParameterChoice> ("osc", "OSC Type", StringArray ({"Pulse/Square", "Triangle", "Noise"}), 0),
|
||||
std::make_unique<AudioParameterFloat> ("gain", "Gain", 0.0f, 1.0f, 0.5f),
|
||||
std::make_unique<AudioParameterFloat> ("maxPoly", "Max Poly", NormalisableRange<float> (1.0f, //min
|
||||
64.0f, //max
|
||||
1.0f, //step
|
||||
1.0f), //skew
|
||||
8),
|
||||
//
|
||||
// ADSR
|
||||
//
|
||||
std::make_unique<AudioParameterFloat> ("attack", //ID
|
||||
"Attack", //name
|
||||
NormalisableRange<float> (0.0f, //min
|
||||
5.0f, //max
|
||||
0.001f, //step
|
||||
0.5f), //skew
|
||||
0.0f), //default
|
||||
std::make_unique<AudioParameterFloat> ("decay", //ID
|
||||
"Decay", //name
|
||||
NormalisableRange<float> (0.0f, //min
|
||||
5.0f, //max
|
||||
0.001f, //step
|
||||
0.5f), //skew
|
||||
0.0f), //default
|
||||
std::make_unique<AudioParameterFloat> ("suslevel", //ID
|
||||
"Sustain", //name
|
||||
0.0f, //min
|
||||
1.0f, //max
|
||||
1.0f),//default
|
||||
std::make_unique<AudioParameterFloat> ("release", //ID
|
||||
"Release", //name
|
||||
NormalisableRange<float> (0.0f, //min
|
||||
5.0f, //max
|
||||
0.001f, //step
|
||||
0.5f), //skew
|
||||
0.0f), //default
|
||||
//
|
||||
// Arpeggio
|
||||
//
|
||||
std::make_unique<AudioParameterBool> ("isArpeggioEnabled_raw", "Enabled", false),
|
||||
std::make_unique<AudioParameterFloat> ("arpeggioTime", "Time", 0.0f, 0.3f, 0.033f),
|
||||
std::make_unique<AudioParameterChoice> ("arpeggioDirection", "Direction", StringArray ({"up", "down"}), 0),
|
||||
//
|
||||
// Bend
|
||||
//
|
||||
std::make_unique<AudioParameterInt> ("bendRange", "Bend Range", 0, 24, 2),
|
||||
//
|
||||
// Vibrato
|
||||
//
|
||||
std::make_unique<AudioParameterFloat> ("vibratoRate", //ID
|
||||
"Rate", //name
|
||||
NormalisableRange<float> (0.01f, //min
|
||||
1.0f, //max
|
||||
0.001f, //step
|
||||
0.5f), //skew
|
||||
0.15f), //default
|
||||
std::make_unique<AudioParameterFloat> ("vibratoDepth", "Depth", 0.0f, 2.0f, 0.0f),
|
||||
std::make_unique<AudioParameterFloat> ("vibratoDelay", "Delay", 0.0f, 1.0f, 0.3f),
|
||||
std::make_unique<AudioParameterBool> ("vibratoIgnoresWheel_raw", "Ignores Wheel", true),
|
||||
//
|
||||
// Sweep
|
||||
//
|
||||
std::make_unique<AudioParameterInt> ("sweepInitialPitch", "Ini.Pitch", -24, 24, 0),
|
||||
std::make_unique<AudioParameterFloat> ("sweepTime", //ID
|
||||
"Time", //name
|
||||
NormalisableRange<float> (0.01f, //min
|
||||
5.0f, //max
|
||||
0.001f, //step
|
||||
0.5f), //skew
|
||||
0.1f), //default
|
||||
//
|
||||
// For Pulse
|
||||
//
|
||||
std::make_unique<AudioParameterChoice> ("duty", "Duty", StringArray ({"12.5%", "25%", "50%"}), 0),
|
||||
//
|
||||
// For Noise
|
||||
//
|
||||
std::make_unique<AudioParameterChoice> ("noiseAlgorithm_raw", "Algorithm", StringArray ({"4bit Pure Random", "1bit Long Cycle", "1bit Short Cycle"}), 0),
|
||||
std::make_unique<AudioParameterBool> ("restrictsToNESFrequency_raw", "Restricts to NES frequency", false),
|
||||
//
|
||||
// Sequence
|
||||
//
|
||||
std::make_unique<AudioParameterBool> ("isVolumeSequenceEnabled_raw", "Enabled", false),
|
||||
std::make_unique<AudioParameterBool> ("isPitchSequenceEnabled_raw", "Enabled", false),
|
||||
std::make_unique<AudioParameterBool> ("isDutySequenceEnabled_raw", "Enabled", false),
|
||||
std::make_unique<AudioParameterChoice> ("pitchSequenceMode_raw", "Mode", StringArray ({"Coarse", "Fine"}), 0)
|
||||
}
|
||||
)
|
||||
, settingRefs (¶meters)
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
, AudioProcessor (BusesProperties()
|
||||
#if ! JucePlugin_IsMidiEffect
|
||||
#if ! JucePlugin_IsSynth
|
||||
.withInput ("Input", AudioChannelSet::stereo(), true)
|
||||
#endif
|
||||
.withOutput ("Output", AudioChannelSet::stereo(), true)
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
{
|
||||
synth.setCurrentPlaybackSampleRate (44100); // Temporary setup, just in case. The actual sample rate is set in prepareToPlay func.
|
||||
|
||||
setupVoice();
|
||||
synth.addSound (new GenericSound());
|
||||
}
|
||||
|
||||
Magical8bitPlug2AudioProcessor::~Magical8bitPlug2AudioProcessor()
|
||||
{
|
||||
}
|
||||
//==============================================================================
|
||||
void Magical8bitPlug2AudioProcessor::setupVoice()
|
||||
{
|
||||
int poly = synth.getNumVoices();
|
||||
|
||||
for (auto i = 0; i < poly; i++)
|
||||
{
|
||||
synth.removeVoice (0);
|
||||
}
|
||||
|
||||
int type = roundToInt (*settingRefs.osc);
|
||||
|
||||
for (auto i = 0; i < (int) (*settingRefs.maxPoly); ++i)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case kVoiceTypePulse:
|
||||
synth.addVoice (new PulseVoice (&settingRefs));
|
||||
break;
|
||||
|
||||
case kVoiceTypeTriangle:
|
||||
synth.addVoice (new TriangleVoice (&settingRefs));
|
||||
break;
|
||||
|
||||
case kVoiceTypeNoise:
|
||||
synth.addVoice (new NoiseVoice (&settingRefs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
const String Magical8bitPlug2AudioProcessor::getName() const
|
||||
{
|
||||
return JucePlugin_Name;
|
||||
}
|
||||
|
||||
bool Magical8bitPlug2AudioProcessor::acceptsMidi() const
|
||||
{
|
||||
#if JucePlugin_WantsMidiInput
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Magical8bitPlug2AudioProcessor::producesMidi() const
|
||||
{
|
||||
#if JucePlugin_ProducesMidiOutput
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Magical8bitPlug2AudioProcessor::isMidiEffect() const
|
||||
{
|
||||
#if JucePlugin_IsMidiEffect
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
double Magical8bitPlug2AudioProcessor::getTailLengthSeconds() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int Magical8bitPlug2AudioProcessor::getNumPrograms()
|
||||
{
|
||||
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
|
||||
// so this should be at least 1, even if you're not really implementing programs.
|
||||
}
|
||||
|
||||
int Magical8bitPlug2AudioProcessor::getCurrentProgram()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessor::setCurrentProgram (int index)
|
||||
{
|
||||
}
|
||||
|
||||
const String Magical8bitPlug2AudioProcessor::getProgramName (int index)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessor::changeProgramName (int index, const String& newName)
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Magical8bitPlug2AudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
|
||||
{
|
||||
// Use this method as the place to do any pre-playback
|
||||
// initialisation that you need..
|
||||
synth.setCurrentPlaybackSampleRate (sampleRate);
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessor::releaseResources()
|
||||
{
|
||||
// When playback stops, you can use this as an opportunity to free up any
|
||||
// spare memory, etc.
|
||||
}
|
||||
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
bool Magical8bitPlug2AudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
|
||||
{
|
||||
#if JucePlugin_IsMidiEffect
|
||||
ignoreUnused (layouts);
|
||||
return true;
|
||||
#else
|
||||
|
||||
// This is the place where you check if the layout is supported.
|
||||
// In this template code we only support mono or stereo.
|
||||
if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
|
||||
&& layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
|
||||
return false;
|
||||
|
||||
// This checks if the input layout matches the output layout
|
||||
#if ! JucePlugin_IsSynth
|
||||
|
||||
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Magical8bitPlug2AudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
|
||||
{
|
||||
|
||||
synth.renderNextBlock (buffer, midiMessages, 0, buffer.getNumSamples()); // [5]
|
||||
|
||||
/*
|
||||
buffer.clear();
|
||||
MidiBuffer processedMidi;
|
||||
int time;
|
||||
MidiMessage m;
|
||||
for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
|
||||
{
|
||||
if (m.isNoteOn())
|
||||
{
|
||||
uint8 newVel = (uint8)noteOnVel;
|
||||
m = MidiMessage::noteOn(m.getChannel(), m.getNoteNumber(), newVel);
|
||||
}
|
||||
else if (m.isNoteOff())
|
||||
{
|
||||
}
|
||||
else if (m.isAftertouch())
|
||||
{
|
||||
}
|
||||
else if (m.isPitchWheel())
|
||||
{
|
||||
}
|
||||
processedMidi.addEvent (m, time);
|
||||
}
|
||||
midiMessages.swapWith (processedMidi);
|
||||
|
||||
|
||||
ScopedNoDenormals noDenormals;
|
||||
auto totalNumInputChannels = getTotalNumInputChannels();
|
||||
auto totalNumOutputChannels = getTotalNumOutputChannels();
|
||||
|
||||
// In case we have more outputs than inputs, this code clears any output
|
||||
// channels that didn't contain input data, (because these aren't
|
||||
// guaranteed to be empty - they may contain garbage).
|
||||
// This is here to avoid people getting screaming feedback
|
||||
// when they first compile a plugin, but obviously you don't need to keep
|
||||
// this code if your algorithm always overwrites all the output channels.
|
||||
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
|
||||
buffer.clear (i, 0, buffer.getNumSamples());
|
||||
|
||||
// This is the place where you'd normally do the guts of your plugin's
|
||||
// audio processing...
|
||||
// Make sure to reset the state if your inner loop is processing
|
||||
// the samples and the outer loop is handling the channels.
|
||||
// Alternatively, you can process the samples with the channels
|
||||
// interleaved by keeping the same state.
|
||||
for (int channel = 0; channel < totalNumInputChannels; ++channel)
|
||||
{
|
||||
auto* channelData = buffer.getWritePointer (channel);
|
||||
|
||||
// ..do something to the data...
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Magical8bitPlug2AudioProcessor::hasEditor() const
|
||||
{
|
||||
return true; // (change this to false if you choose to not supply an editor)
|
||||
}
|
||||
|
||||
AudioProcessorEditor* Magical8bitPlug2AudioProcessor::createEditor()
|
||||
{
|
||||
return new Magical8bitPlug2AudioProcessorEditor (*this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Magical8bitPlug2AudioProcessor::getStateInformation (MemoryBlock& destData)
|
||||
{
|
||||
auto state = parameters.copyState();
|
||||
|
||||
XmlElement* rootElement = new XmlElement ("root");
|
||||
|
||||
std::unique_ptr<XmlElement> stateElement = std::unique_ptr<XmlElement> (state.createXml());
|
||||
rootElement->addChildElement (stateElement.get());
|
||||
stateElement.release(); // give up the ownership already because xml object will delete it
|
||||
|
||||
XmlElement* volEnvElement = new XmlElement ("volumeEnv");
|
||||
XmlElement* pitEnvElement = new XmlElement ("pitchEnv");
|
||||
XmlElement* dutEnvElement = new XmlElement ("dutyEnv");
|
||||
volEnvElement->addTextElement (settingRefs.volumeSequenceString);
|
||||
pitEnvElement->addTextElement (settingRefs.pitchSequenceString);
|
||||
dutEnvElement->addTextElement (settingRefs.dutySequenceString);
|
||||
rootElement->addChildElement (volEnvElement);
|
||||
rootElement->addChildElement (pitEnvElement);
|
||||
rootElement->addChildElement (dutEnvElement);
|
||||
|
||||
std::unique_ptr<XmlElement> xml (rootElement);
|
||||
|
||||
copyXmlToBinary (*xml, destData);
|
||||
}
|
||||
|
||||
void Magical8bitPlug2AudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
||||
{
|
||||
std::unique_ptr<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
|
||||
|
||||
if (xmlState.get() != nullptr)
|
||||
{
|
||||
if (xmlState->hasTagName ("root"))
|
||||
{
|
||||
// ValueTree
|
||||
XmlElement* valueTreeXml = xmlState->getChildByName (parameters.state.getType());
|
||||
|
||||
if (valueTreeXml != nullptr)
|
||||
{
|
||||
parameters.replaceState (ValueTree::fromXml (*valueTreeXml));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Saved plugin parameters are incompatible");
|
||||
}
|
||||
|
||||
// Custom Env
|
||||
XmlElement* volumeEnvXml = xmlState->getChildByName ("volumeEnv");
|
||||
XmlElement* pitchEnvXml = xmlState->getChildByName ("pitchEnv");
|
||||
XmlElement* dutyEnvXml = xmlState->getChildByName ("dutyEnv");
|
||||
|
||||
if (volumeEnvXml != nullptr)
|
||||
{
|
||||
XmlElement* volElem = volumeEnvXml->getFirstChildElement();
|
||||
|
||||
if (volElem != nullptr && volElem->isTextElement())
|
||||
{
|
||||
String volStr = volElem->getText();
|
||||
|
||||
ParseError err = kParseErrorNone;
|
||||
settingRefs.setSequenceWithString ("volume", volStr, &err);
|
||||
|
||||
if (settingRefs.volumeSequenceListener != nullptr)
|
||||
{
|
||||
settingRefs.volumeSequenceListener->sequenceChanged (volStr);
|
||||
}
|
||||
|
||||
Logger::writeToLog ("volume seq = " + volStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::writeToLog ("volumeEnv entry found, but seems not like a text element.");
|
||||
}
|
||||
}
|
||||
|
||||
if (pitchEnvXml != nullptr)
|
||||
{
|
||||
XmlElement* pitElem = pitchEnvXml->getFirstChildElement();
|
||||
|
||||
if (pitElem != nullptr && pitElem->isTextElement())
|
||||
{
|
||||
String pitStr = pitElem->getText();
|
||||
ParseError err = kParseErrorNone;
|
||||
settingRefs.setSequenceWithString ("pitch", pitStr, &err);
|
||||
|
||||
if (settingRefs.pitchSequenceListener != nullptr)
|
||||
{
|
||||
settingRefs.pitchSequenceListener->sequenceChanged (pitStr);
|
||||
}
|
||||
|
||||
Logger::writeToLog ("pitch seq = " + pitStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::writeToLog ("pitchEnv entry found, but seems not like a text element.");
|
||||
}
|
||||
}
|
||||
|
||||
if (dutyEnvXml != nullptr)
|
||||
{
|
||||
XmlElement* dutElem = dutyEnvXml->getFirstChildElement();
|
||||
|
||||
if (dutElem != nullptr && dutElem->isTextElement())
|
||||
{
|
||||
String dutStr = dutElem->getText();
|
||||
ParseError err = kParseErrorNone;
|
||||
settingRefs.setSequenceWithString ("duty", dutStr, &err);
|
||||
|
||||
if (settingRefs.dutySequenceListener != nullptr)
|
||||
{
|
||||
settingRefs.dutySequenceListener->sequenceChanged (dutStr);
|
||||
}
|
||||
|
||||
Logger::writeToLog ("duty seq = " + dutStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::writeToLog ("dutyEnv entry found, but seems not like a text element.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupVoice();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// This creates new instances of the plugin..
|
||||
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
||||
{
|
||||
return new Magical8bitPlug2AudioProcessor();
|
||||
}
|
83
Source/PluginProcessor.h
Normal file
83
Source/PluginProcessor.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file was auto-generated!
|
||||
|
||||
It contains the basic framework code for a JUCE plugin processor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "Settings.h"
|
||||
#include "Voices.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct GenericSound : public SynthesiserSound
|
||||
{
|
||||
GenericSound() {}
|
||||
|
||||
bool appliesToNote (int) override { return true; }
|
||||
bool appliesToChannel (int) override { return true; }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class Magical8bitPlug2AudioProcessor : public AudioProcessor
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
Magical8bitPlug2AudioProcessor();
|
||||
~Magical8bitPlug2AudioProcessor();
|
||||
|
||||
//==============================================================================
|
||||
float noteOnVel;
|
||||
|
||||
void prepareToPlay (double sampleRate, int samplesPerBlock) override;
|
||||
void releaseResources() override;
|
||||
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
|
||||
#endif
|
||||
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override;
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorEditor* createEditor() override;
|
||||
bool hasEditor() const override;
|
||||
|
||||
//==============================================================================
|
||||
const String getName() const override;
|
||||
|
||||
bool acceptsMidi() const override;
|
||||
bool producesMidi() const override;
|
||||
bool isMidiEffect() const override;
|
||||
double getTailLengthSeconds() const override;
|
||||
|
||||
//==============================================================================
|
||||
int getNumPrograms() override;
|
||||
int getCurrentProgram() override;
|
||||
void setCurrentProgram (int index) override;
|
||||
const String getProgramName (int index) override;
|
||||
void changeProgramName (int index, const String& newName) override;
|
||||
|
||||
//==============================================================================
|
||||
void getStateInformation (MemoryBlock& destData) override;
|
||||
void setStateInformation (const void* data, int sizeInBytes) override;
|
||||
|
||||
//==============================================================================
|
||||
void setupVoice();
|
||||
|
||||
AudioProcessorValueTreeState parameters;
|
||||
SettingRefs settingRefs;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Synthesiser synth;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Magical8bitPlug2AudioProcessor)
|
||||
};
|
168
Source/PulseParamsComponent.cpp
Normal file
168
Source/PulseParamsComponent.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "PulseParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
PulseParamsComponent::PulseParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Pulse")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
dutySelector.reset (new ChoiceComponent (p, "duty", "Duty"));
|
||||
addAndMakeVisible (dutySelector.get());
|
||||
dutySelector->setName ("duty selector");
|
||||
|
||||
warningLabel.reset (new Label ("warning label",
|
||||
String()));
|
||||
addAndMakeVisible (warningLabel.get());
|
||||
warningLabel->setFont (Font (15.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
warningLabel->setJustificationType (Justification::centredRight);
|
||||
warningLabel->setEditable (false, false, false);
|
||||
warningLabel->setColour (TextEditor::textColourId, Colours::black);
|
||||
warningLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 58);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
ColorScheme cs = ColorScheme (p.settingRefs.colorSchemeType());
|
||||
warningLabelLookAndFeel.setColour (Label::textColourId, cs.warning);
|
||||
warningLabel->setLookAndFeel (&warningLabelLookAndFeel);
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
PulseParamsComponent::~PulseParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
dutySelector = nullptr;
|
||||
warningLabel = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PulseParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void PulseParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
dutySelector->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
warningLabel->setBounds (getWidth() - 8 - 246, 4, 246, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void PulseParamsComponent::enablementChanged()
|
||||
{
|
||||
//[UserCode_enablementChanged] -- Add your code here...
|
||||
if (isEnabled())
|
||||
{
|
||||
warningLabel->setText (TRANS (""), dontSendNotification);
|
||||
}
|
||||
else
|
||||
{
|
||||
warningLabel->setText (TRANS ("Overridden by Duty Envelope"), dontSendNotification);
|
||||
}
|
||||
|
||||
//[/UserCode_enablementChanged]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="PulseParamsComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="58">
|
||||
<METHODS>
|
||||
<METHOD name="enablementChanged()"/>
|
||||
</METHODS>
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Pulse" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="duty selector" id="b01ddc412ec6dc27" memberName="dutySelector"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="ChoiceComponent"
|
||||
params="p, "duty", "Duty""/>
|
||||
<LABEL name="warning label" id="624aa3e1415981e3" memberName="warningLabel"
|
||||
virtualName="" explicitFocusOrder="0" pos="8Rr 4 246 24" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="15.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="34"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
71
Source/PulseParamsComponent.h
Normal file
71
Source/PulseParamsComponent.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "ChoiceComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class PulseParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PulseParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~PulseParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
void enablementChanged() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
LookAndFeel_V4 warningLabelLookAndFeel;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<ChoiceComponent> dutySelector;
|
||||
std::unique_ptr<Label> warningLabel;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PulseParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
62
Source/PulseVoice.cpp
Normal file
62
Source/PulseVoice.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PulseVoice.cpp
|
||||
Created: 11 Nov 2019 9:36:51pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "PulseVoice.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Pulse Voice
|
||||
//
|
||||
//---------------------------------------------
|
||||
PulseVoice::PulseVoice (SettingRefs* sRefs) : TonalVoice (sRefs) {}
|
||||
|
||||
void PulseVoice::startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int currentPitchBendPosition)
|
||||
{
|
||||
TonalVoice::startNote (midiNoteNumber, velocity, 0, currentPitchBendPosition);
|
||||
|
||||
currentDutySequenceFrame = 0;
|
||||
currentDuty = (PulseDuty) ((int) (*settingRefs->duty));
|
||||
}
|
||||
|
||||
float PulseVoice::voltageForAngle (double angle)
|
||||
{
|
||||
float rate = 1.0;
|
||||
|
||||
switch (currentDuty)
|
||||
{
|
||||
case kPulseDuty125:
|
||||
rate = 0.25;
|
||||
break;
|
||||
|
||||
case kPulseDuty250:
|
||||
rate = 0.50;
|
||||
break;
|
||||
|
||||
case kPulseDuty500:
|
||||
rate = 1.00;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return angle < rate * MathConstants<float>::pi ? -1.0 : 1.0;
|
||||
}
|
||||
|
||||
void PulseVoice::advanceControlFrame()
|
||||
{
|
||||
TonalVoice::advanceControlFrame();
|
||||
|
||||
if (settingRefs->isDutySequenceEnabled())
|
||||
{
|
||||
currentDutySequenceFrame = settingRefs->dutySequence.nextIndexOf (currentDutySequenceFrame);
|
||||
currentDuty = (PulseDuty)settingRefs->dutySequence.valueAt (currentDutySequenceFrame);
|
||||
}
|
||||
}
|
28
Source/PulseVoice.h
Normal file
28
Source/PulseVoice.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
PulseVoice.h
|
||||
Created: 11 Nov 2019 9:36:51pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "TonalVoice.h"
|
||||
|
||||
struct PulseVoice : public TonalVoice
|
||||
{
|
||||
|
||||
PulseVoice (SettingRefs* sRefs);
|
||||
|
||||
PulseDuty currentDuty = kPulseDuty500; // May be changed by Duty Sequence
|
||||
|
||||
// Custom Duty Sequence states
|
||||
int currentDutySequenceFrame = 0;
|
||||
|
||||
void startNote (int midiNoteNumber, float velocity,
|
||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||
float voltageForAngle (double angle) override;
|
||||
void advanceControlFrame() override;
|
||||
};
|
79
Source/Settings.cpp
Normal file
79
Source/Settings.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Settings.cpp
|
||||
Created: 23 May 2019 11:54:44am
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "Settings.h"
|
||||
#include "FrameSequenceParser.h"
|
||||
|
||||
bool SettingRefs::setSequenceWithString (const String& type, const String& input, ParseError* error)
|
||||
{
|
||||
FrameSequenceParser parser;
|
||||
|
||||
if (type == "volume")
|
||||
{
|
||||
FrameSequence res = parser.parse (input, 0, 15, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
volumeSequence = res;
|
||||
volumeSequenceString = input;
|
||||
return true;
|
||||
}
|
||||
else if (type == "pitch")
|
||||
{
|
||||
FrameSequence res = parser.parse (input, -64, 63, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pitchSequence = res;
|
||||
pitchSequenceString = input;
|
||||
return true;
|
||||
}
|
||||
else if (type == "duty")
|
||||
{
|
||||
FrameSequence res = parser.parse (input, 0, 2, error);
|
||||
|
||||
if (*error > kParseErrorLevelFatal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dutySequence = res;
|
||||
dutySequenceString = input;
|
||||
return true;
|
||||
}
|
||||
|
||||
printf ("*** parameter type invalid!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
String& SettingRefs::getSequenceString (const String& type)
|
||||
{
|
||||
if (type == "volume")
|
||||
{
|
||||
return volumeSequenceString;
|
||||
}
|
||||
else if (type == "pitch")
|
||||
{
|
||||
return pitchSequenceString;
|
||||
}
|
||||
else if (type == "duty")
|
||||
{
|
||||
return dutySequenceString;
|
||||
}
|
||||
|
||||
printf ("*** parameter type invalid!\n");
|
||||
return volumeSequenceString;
|
||||
}
|
199
Source/Settings.h
Normal file
199
Source/Settings.h
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Settings.h
|
||||
Created: 23 May 2019 11:54:44am
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "ColorScheme.h"
|
||||
#include "FrameSequence.h"
|
||||
#include "FrameSequenceParseErrors.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Plugin Global
|
||||
//
|
||||
//---------------------------------------------
|
||||
enum VoiceType
|
||||
{
|
||||
kVoiceTypePulse = 0,
|
||||
kVoiceTypeTriangle,
|
||||
kVoiceTypeNoise
|
||||
};
|
||||
|
||||
struct PluginSettings
|
||||
{
|
||||
VoiceType type = kVoiceTypePulse;
|
||||
int maxPoly = 1;
|
||||
double gain = 1.0;
|
||||
double arpeggioTime = 0;
|
||||
double bendRange = 2;
|
||||
};
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Tone Specific
|
||||
//
|
||||
//---------------------------------------------
|
||||
enum PulseDuty
|
||||
{
|
||||
kPulseDuty125 = 0,
|
||||
kPulseDuty250,
|
||||
kPulseDuty500,
|
||||
};
|
||||
|
||||
enum NoiseAlgorithm
|
||||
{
|
||||
kNoiseInfinite2 = 0,
|
||||
kNoiseLong,
|
||||
kNoiseShort,
|
||||
};
|
||||
|
||||
enum PitchSequenceMode
|
||||
{
|
||||
kPitchSequenceModeCoarse = 0,
|
||||
kPitchSequenceModeFine
|
||||
};
|
||||
|
||||
class FrameSequenceChangeListener
|
||||
{
|
||||
public:
|
||||
FrameSequenceChangeListener() {}
|
||||
virtual ~FrameSequenceChangeListener() {};
|
||||
virtual void sequenceChanged (String& str) {};
|
||||
};
|
||||
|
||||
|
||||
struct FrameSequenceParseException
|
||||
{
|
||||
String message;
|
||||
bool isFatal;
|
||||
|
||||
FrameSequenceParseException (String mes, bool fatalFlag)
|
||||
{
|
||||
message = mes;
|
||||
isFatal = fatalFlag;
|
||||
}
|
||||
};
|
||||
|
||||
struct SettingRefs
|
||||
{
|
||||
// Meta
|
||||
float* isAdvancedPanelOpen_raw = nullptr;
|
||||
float* colorScheme = nullptr;
|
||||
// Basic
|
||||
float* osc = nullptr;
|
||||
float* gain = nullptr;
|
||||
float* maxPoly = nullptr;
|
||||
// ADSR
|
||||
float* attack = nullptr;
|
||||
float* decay = nullptr;
|
||||
float* suslevel = nullptr;
|
||||
float* release = nullptr;
|
||||
// Arpeggio
|
||||
float* isArpeggioEnabled_raw = nullptr;
|
||||
float* arpeggioTime = nullptr;
|
||||
float* arpeggioDirection = nullptr;
|
||||
// Bend
|
||||
float* bendRange = nullptr;
|
||||
// Vibrato
|
||||
float* vibratoRate = nullptr;
|
||||
float* vibratoDepth = nullptr;
|
||||
float* vibratoDelay = nullptr;
|
||||
float* vibratoIgnoresWheel_raw = nullptr;
|
||||
// Sweep
|
||||
float* sweepInitialPitch = nullptr;
|
||||
float* sweepTime = nullptr;
|
||||
// For Pulse
|
||||
float* duty = nullptr;
|
||||
// For Noise
|
||||
float* noiseAlgorithm_raw = nullptr;
|
||||
float* restrictsToNESFrequency_raw = nullptr;
|
||||
// Sequence
|
||||
float* isVolumeSequenceEnabled_raw = nullptr;
|
||||
float* isPitchSequenceEnabled_raw = nullptr;
|
||||
float* isDutySequenceEnabled_raw = nullptr;
|
||||
float* pitchSequenceMode_raw = nullptr;
|
||||
|
||||
FrameSequence volumeSequence;
|
||||
FrameSequence pitchSequence;
|
||||
FrameSequence dutySequence;
|
||||
String volumeSequenceString = "";
|
||||
String pitchSequenceString = "";
|
||||
String dutySequenceString = "";
|
||||
|
||||
bool setSequenceWithString (const String& type, const String& input, ParseError* error);
|
||||
String& getSequenceString (const String& type);
|
||||
|
||||
FrameSequence parseSequenceString (const String& input);
|
||||
FrameSequenceChangeListener* volumeSequenceListener = nullptr;
|
||||
FrameSequenceChangeListener* pitchSequenceListener = nullptr;
|
||||
FrameSequenceChangeListener* dutySequenceListener = nullptr;
|
||||
|
||||
//
|
||||
// accessors
|
||||
//
|
||||
int oscillatorType() { return (int) (*osc); }
|
||||
bool isAdvancedPanelOpen() { return *isAdvancedPanelOpen_raw > 0.5; }
|
||||
ColorSchemeType colorSchemeType() { return (ColorSchemeType) ((int) (*colorScheme)); }
|
||||
|
||||
bool isArpeggioEnabled() { return *isArpeggioEnabled_raw > 0.5; }
|
||||
NoiseAlgorithm noiseAlgorithm() { return (NoiseAlgorithm) ((int) (*noiseAlgorithm_raw)); }
|
||||
|
||||
bool vibratoIgnoresWheel() { return *vibratoIgnoresWheel_raw > 0.5; }
|
||||
|
||||
bool isVolumeSequenceEnabled() { return *isVolumeSequenceEnabled_raw > 0.5; }
|
||||
bool isPitchSequenceEnabled() { return *isPitchSequenceEnabled_raw > 0.5; }
|
||||
bool isDutySequenceEnabled() { return *isDutySequenceEnabled_raw > 0.5; }
|
||||
PitchSequenceMode pitchSequenceMode() { return (PitchSequenceMode) ((int) (*pitchSequenceMode_raw)); }
|
||||
|
||||
|
||||
//
|
||||
// constructor
|
||||
//
|
||||
SettingRefs (AudioProcessorValueTreeState* parameters)
|
||||
{
|
||||
// Meta
|
||||
isAdvancedPanelOpen_raw = parameters->getRawParameterValue ("isAdvancedPanelOpen_raw");
|
||||
colorScheme = parameters->getRawParameterValue ("colorScheme");
|
||||
// Basic
|
||||
osc = parameters->getRawParameterValue ("osc");
|
||||
gain = parameters->getRawParameterValue ("gain");
|
||||
maxPoly = parameters->getRawParameterValue ("maxPoly");
|
||||
// ADSR
|
||||
attack = parameters->getRawParameterValue ("attack");
|
||||
decay = parameters->getRawParameterValue ("decay");
|
||||
suslevel = parameters->getRawParameterValue ("suslevel");
|
||||
release = parameters->getRawParameterValue ("release");
|
||||
// Arpeggio
|
||||
isArpeggioEnabled_raw = parameters->getRawParameterValue ("isArpeggioEnabled_raw");
|
||||
arpeggioTime = parameters->getRawParameterValue ("arpeggioTime");
|
||||
arpeggioDirection = parameters->getRawParameterValue ("arpeggioDirection");
|
||||
// Bend
|
||||
bendRange = parameters->getRawParameterValue ("bendRange");
|
||||
// Vibrato
|
||||
vibratoRate = parameters->getRawParameterValue ("vibratoRate");
|
||||
vibratoDepth = parameters->getRawParameterValue ("vibratoDepth");
|
||||
vibratoDelay = parameters->getRawParameterValue ("vibratoDelay");
|
||||
vibratoIgnoresWheel_raw = parameters->getRawParameterValue ("vibratoIgnoresWheel_raw");
|
||||
// Sweep
|
||||
sweepInitialPitch = parameters->getRawParameterValue ("sweepInitialPitch");
|
||||
sweepTime = parameters->getRawParameterValue ("sweepTime");
|
||||
// For Pulse
|
||||
duty = parameters->getRawParameterValue ("duty");
|
||||
// For Noise
|
||||
noiseAlgorithm_raw = parameters->getRawParameterValue ("noiseAlgorithm_raw");
|
||||
restrictsToNESFrequency_raw = parameters->getRawParameterValue ("restrictsToNESFrequency_raw");
|
||||
// Sequence
|
||||
isVolumeSequenceEnabled_raw = parameters->getRawParameterValue ("isVolumeSequenceEnabled_raw");
|
||||
isPitchSequenceEnabled_raw = parameters->getRawParameterValue ("isPitchSequenceEnabled_raw");
|
||||
isDutySequenceEnabled_raw = parameters->getRawParameterValue ("isDutySequenceEnabled_raw");
|
||||
pitchSequenceMode_raw = parameters->getRawParameterValue ("pitchSequenceMode_raw");
|
||||
|
||||
}
|
||||
};
|
139
Source/SliderComponent.cpp
Normal file
139
Source/SliderComponent.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "SliderComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
SliderComponent::SliderComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Label")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (14.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredRight);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (8, 1, 60, 24);
|
||||
|
||||
slider.reset (new Slider ("slider"));
|
||||
addAndMakeVisible (slider.get());
|
||||
slider->setRange (0, 10, 0.01);
|
||||
slider->setSliderStyle (Slider::LinearHorizontal);
|
||||
slider->setTextBoxStyle (Slider::TextBoxRight, false, 50, 20);
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (360, 28);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
label->setText (name, dontSendNotification);
|
||||
|
||||
attc.reset (new SliderAttachment (p.parameters, paramId, *slider));
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
SliderComponent::~SliderComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
attc.reset();
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
slider = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SliderComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void SliderComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
slider->setBounds (72, 1, getWidth() - 80, 24);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="SliderComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p, String paramId, String name"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="360" initialHeight="28">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="af1fa4a96c3448e5" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="8 1 60 24" edTextCol="ff000000" edBkgCol="0"
|
||||
labelText="Label" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="14.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="34"/>
|
||||
<SLIDER name="slider" id="2d6901c46e73c1e" memberName="slider" virtualName=""
|
||||
explicitFocusOrder="0" pos="72 1 80M 24" min="0.0" max="10.0"
|
||||
int="0.01" style="LinearHorizontal" textBoxPos="TextBoxRight"
|
||||
textBoxEditable="1" textBoxWidth="50" textBoxHeight="20" skewFactor="1.0"
|
||||
needsCallback="0"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
70
Source/SliderComponent.h
Normal file
70
Source/SliderComponent.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "PluginProcessor.h"
|
||||
#include "Defs.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class SliderComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
SliderComponent (Magical8bitPlug2AudioProcessor& p, String paramId, String name);
|
||||
~SliderComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
std::unique_ptr<SliderAttachment> attc;
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<Slider> slider;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
140
Source/SweepParamsComponent.cpp
Normal file
140
Source/SweepParamsComponent.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "SweepParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
SweepParamsComponent::SweepParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Auto Bend")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
iniPitchSlider.reset (new SliderComponent (p, "sweepInitialPitch", "Ini.Pitch"));
|
||||
addAndMakeVisible (iniPitchSlider.get());
|
||||
iniPitchSlider->setName ("inital pitch slider");
|
||||
|
||||
timeSlider.reset (new SliderComponent (p, "sweepTime", "Time"));
|
||||
addAndMakeVisible (timeSlider.get());
|
||||
timeSlider->setName ("time slider");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 86);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
SweepParamsComponent::~SweepParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
iniPitchSlider = nullptr;
|
||||
timeSlider = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SweepParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void SweepParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
iniPitchSlider->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
timeSlider->setBounds (0, 54, proportionOfWidth (1.0000f), 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="SweepParamsComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="86">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Auto Bend" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="inital pitch slider" id="93ec1e79c45ddad4" memberName="iniPitchSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
||||
params="p, "sweepInitialPitch", "Ini.Pitch""/>
|
||||
<GENERICCOMPONENT name="time slider" id="1be45518932375fc" memberName="timeSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 54 100% 28" class="SliderComponent"
|
||||
params="p, "sweepTime", "Time""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
69
Source/SweepParamsComponent.h
Normal file
69
Source/SweepParamsComponent.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "SliderComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class SweepParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
SweepParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~SweepParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<SliderComponent> iniPitchSlider;
|
||||
std::unique_ptr<SliderComponent> timeSlider;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SweepParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
136
Source/TonalVoice.cpp
Normal file
136
Source/TonalVoice.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
TonalVoice.cpp
|
||||
Created: 11 Nov 2019 9:36:34pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "TonalVoice.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Tonal Voice
|
||||
// The base for pulse/triangle (Abstract)
|
||||
//
|
||||
//---------------------------------------------
|
||||
TonalVoice::TonalVoice (SettingRefs* sRefs) : BaseVoice (sRefs) {}
|
||||
|
||||
void TonalVoice::startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int currentPitchBendPosition)
|
||||
{
|
||||
BaseVoice::startNote (midiNoteNumber, velocity, 0, currentPitchBendPosition);
|
||||
|
||||
currentBendAmount = 0;
|
||||
currentPitchSequenceFrame = 0;
|
||||
vibratoCount = 0;
|
||||
|
||||
float iniPitch = * (settingRefs->sweepInitialPitch);
|
||||
float time = * (settingRefs->sweepTime);
|
||||
currentAutoBendAmount = iniPitch;
|
||||
autoBendDelta = -1.0 * iniPitch / (time * getSampleRate());
|
||||
}
|
||||
|
||||
void TonalVoice::advanceControlFrame()
|
||||
{
|
||||
BaseVoice::advanceControlFrame();
|
||||
|
||||
currentPitchSequenceFrame = settingRefs->pitchSequence.nextIndexOf (currentPitchSequenceFrame);
|
||||
}
|
||||
|
||||
void TonalVoice::calculateAngleDelta()
|
||||
{
|
||||
|
||||
int noteNumberMod = 0;
|
||||
double finePitchInSeq = 0;
|
||||
|
||||
if (settingRefs->isPitchSequenceEnabled())
|
||||
{
|
||||
switch (settingRefs->pitchSequenceMode())
|
||||
{
|
||||
case kPitchSequenceModeFine:
|
||||
finePitchInSeq = (double)settingRefs->pitchSequence.valueAt (currentPitchSequenceFrame) / 8.0;
|
||||
break;
|
||||
|
||||
case kPitchSequenceModeCoarse:
|
||||
noteNumberMod = settingRefs->pitchSequence.valueAt (currentPitchSequenceFrame);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double byWheel = settingRefs->vibratoIgnoresWheel() ? 1.0 : currentModWheelValue;
|
||||
double vibratoAmount = * (settingRefs->vibratoDepth) * sin (getVibratoPhase()) * byWheel;
|
||||
double noteNoInDouble = noteNumber
|
||||
+ noteNumberMod
|
||||
+ currentBendAmount
|
||||
+ currentAutoBendAmount
|
||||
+ vibratoAmount
|
||||
+ finePitchInSeq;
|
||||
|
||||
auto cyclesPerSecond = noteNoToHeltzDouble (noteNoInDouble);
|
||||
auto cyclesPerSample = cyclesPerSecond / getSampleRate();
|
||||
|
||||
angleDelta = cyclesPerSample * 2.0 * MathConstants<double>::pi;
|
||||
}
|
||||
|
||||
void TonalVoice::pitchWheelMoved (int amount)
|
||||
{
|
||||
currentBendAmount = * (settingRefs->bendRange) * ((double) (amount - 8192)) / 8192.0;
|
||||
}
|
||||
|
||||
void TonalVoice::controllerMoved (int type, int amount)
|
||||
{
|
||||
if (type == 1) // Modulation
|
||||
{
|
||||
currentModWheelValue = (double)amount / 127.0;
|
||||
}
|
||||
}
|
||||
|
||||
double TonalVoice::noteNoToHeltzDouble (double noteNoInDouble, const double frequencyOfA)
|
||||
{
|
||||
return frequencyOfA * std::pow (2.0, (noteNoInDouble - 69) / 12.0);
|
||||
}
|
||||
|
||||
|
||||
double TonalVoice::getVibratoPhase()
|
||||
{
|
||||
double sec = (double)vibratoCount / getSampleRate();
|
||||
|
||||
float delay = * (settingRefs->vibratoDelay);
|
||||
float rate = * (settingRefs->vibratoRate);
|
||||
|
||||
if ( sec < delay ) { return 0.0; }
|
||||
|
||||
double phase = fmodf (( sec - delay ), rate) / rate * MathConstants<double>::twoPi;
|
||||
return phase;
|
||||
}
|
||||
|
||||
void TonalVoice::onFrameAdvanced()
|
||||
{
|
||||
vibratoCount++;
|
||||
|
||||
currentAutoBendAmount = currentAutoBendAmount + autoBendDelta;
|
||||
|
||||
if (autoBendDelta > 0)
|
||||
{
|
||||
// positive slope
|
||||
if (currentAutoBendAmount > 0)
|
||||
{
|
||||
currentAutoBendAmount = 0;
|
||||
autoBendDelta = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// negative slope
|
||||
if (currentAutoBendAmount < 0)
|
||||
{
|
||||
currentAutoBendAmount = 0;
|
||||
autoBendDelta = 0;
|
||||
}
|
||||
}
|
||||
};
|
49
Source/TonalVoice.h
Normal file
49
Source/TonalVoice.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
TonalVoice.h
|
||||
Created: 11 Nov 2019 9:36:34pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "BaseVoice.h"
|
||||
|
||||
struct TonalVoice : public BaseVoice // The base for Pulse and Triangle
|
||||
{
|
||||
|
||||
TonalVoice (SettingRefs* sRefs);
|
||||
float voltageForAngle (double angle) override = 0;
|
||||
|
||||
// Vibrato
|
||||
double vibratoPhase = 0;
|
||||
double vibratoPhaseDelta = 0;
|
||||
|
||||
// BendState
|
||||
double currentBendAmount = 0;
|
||||
|
||||
// Auto Bend
|
||||
double currentAutoBendAmount = 0;
|
||||
double autoBendDelta = 0;
|
||||
|
||||
// Vibrato
|
||||
int vibratoCount;
|
||||
double currentModWheelValue;
|
||||
double getVibratoPhase();
|
||||
|
||||
// Custom Pitch/Note states
|
||||
int currentPitchSequenceFrame = 0;
|
||||
|
||||
void startNote (int midiNoteNumber, float velocity,
|
||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||
void advanceControlFrame() override;
|
||||
void calculateAngleDelta() override;
|
||||
void pitchWheelMoved (int) override;
|
||||
void controllerMoved (int, int) override;
|
||||
|
||||
double noteNoToHeltzDouble (double noteNoInDouble, const double frequencyOfA = 440);
|
||||
|
||||
void onFrameAdvanced() override;
|
||||
};
|
34
Source/TriangleVoice.cpp
Normal file
34
Source/TriangleVoice.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
TriangleVoice.cpp
|
||||
Created: 11 Nov 2019 9:37:04pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "TriangleVoice.h"
|
||||
|
||||
//---------------------------------------------
|
||||
//
|
||||
// Triangle Voice
|
||||
//
|
||||
//---------------------------------------------
|
||||
TriangleVoice::TriangleVoice (SettingRefs* sRefs) : TonalVoice (sRefs) {}
|
||||
|
||||
float TriangleVoice::voltageForAngle (double angle)
|
||||
{
|
||||
int sequence[32] = { 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
8, 7, 6, 5, 4, 3, 2, 1,
|
||||
0, -1, -2, -3, -4, -5, -6, -7,
|
||||
-7, -6, -5, -4, -3, -2, -1, 0
|
||||
};
|
||||
|
||||
double twopi = MathConstants<float>::pi * 2.0;
|
||||
int step = (int) (32 * angle / twopi);
|
||||
|
||||
int level = sequence[step];
|
||||
float output = ((float)level - 0.5f) / 7.5f;
|
||||
return output;
|
||||
}
|
18
Source/TriangleVoice.h
Normal file
18
Source/TriangleVoice.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
TriangleVoice.h
|
||||
Created: 11 Nov 2019 9:37:04pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "TonalVoice.h"
|
||||
|
||||
struct TriangleVoice : public TonalVoice
|
||||
{
|
||||
TriangleVoice (SettingRefs* sRefs);
|
||||
float voltageForAngle (double angle) override;
|
||||
};
|
158
Source/VibratoParamsComponent.cpp
Normal file
158
Source/VibratoParamsComponent.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//[Headers] You can add your own extra header files here...
|
||||
//[/Headers]
|
||||
|
||||
#include "VibratoParamsComponent.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
VibratoParamsComponent::VibratoParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
label.reset (new Label ("label",
|
||||
TRANS("Vibrato")));
|
||||
addAndMakeVisible (label.get());
|
||||
label->setFont (Font (17.00f, Font::plain).withTypefaceStyle ("Regular"));
|
||||
label->setJustificationType (Justification::centredLeft);
|
||||
label->setEditable (false, false, false);
|
||||
label->setColour (TextEditor::textColourId, Colours::black);
|
||||
label->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
|
||||
|
||||
label->setBounds (0, 4, 150, 22);
|
||||
|
||||
ratioSlider.reset (new SliderComponent (p, "vibratoRate", "Rate"));
|
||||
addAndMakeVisible (ratioSlider.get());
|
||||
ratioSlider->setName ("ratio slider");
|
||||
|
||||
depthSlider.reset (new SliderComponent (p, "vibratoDepth", "Depth"));
|
||||
addAndMakeVisible (depthSlider.get());
|
||||
depthSlider->setName ("depth slider");
|
||||
|
||||
delaySlider.reset (new SliderComponent (p, "vibratoDelay", "Delay"));
|
||||
addAndMakeVisible (delaySlider.get());
|
||||
delaySlider->setName ("delay slider");
|
||||
|
||||
ignoreWheelSwitch.reset (new CheckBoxComponent (p, "vibratoIgnoresWheel_raw", "Ignores Wheel"));
|
||||
addAndMakeVisible (ignoreWheelSwitch.get());
|
||||
ignoreWheelSwitch->setName ("ignore wheel switch");
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (340, 142);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
VibratoParamsComponent::~VibratoParamsComponent()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
label = nullptr;
|
||||
ratioSlider = nullptr;
|
||||
depthSlider = nullptr;
|
||||
delaySlider = nullptr;
|
||||
ignoreWheelSwitch = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void VibratoParamsComponent::paint (Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void VibratoParamsComponent::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
ratioSlider->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||
depthSlider->setBounds (0, 54, proportionOfWidth (1.0000f), 28);
|
||||
delaySlider->setBounds (0, 82, proportionOfWidth (1.0000f), 28);
|
||||
ignoreWheelSwitch->setBounds (0, 110, proportionOfWidth (1.0000f), 28);
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
//[/MiscUserCode]
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if 0
|
||||
/* -- Projucer information section --
|
||||
|
||||
This is where the Projucer stores the metadata that describe this GUI layout, so
|
||||
make changes in here at your peril!
|
||||
|
||||
BEGIN_JUCER_METADATA
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="VibratoParamsComponent" componentName=""
|
||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="142">
|
||||
<BACKGROUND backgroundColour="ffffff"/>
|
||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||
edBkgCol="0" labelText="Vibrato" editableSingleClick="0" editableDoubleClick="0"
|
||||
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||
<GENERICCOMPONENT name="ratio slider" id="93ec1e79c45ddad4" memberName="ratioSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
||||
params="p, "vibratoRate", "Rate""/>
|
||||
<GENERICCOMPONENT name="depth slider" id="1be45518932375fc" memberName="depthSlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 54 100% 28" class="SliderComponent"
|
||||
params="p, "vibratoDepth", "Depth""/>
|
||||
<GENERICCOMPONENT name="delay slider" id="5c2169fddb4cc33" memberName="delaySlider"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 82 100% 28" class="SliderComponent"
|
||||
params="p, "vibratoDelay", "Delay""/>
|
||||
<GENERICCOMPONENT name="ignore wheel switch" id="9d35239102eeb521" memberName="ignoreWheelSwitch"
|
||||
virtualName="" explicitFocusOrder="0" pos="0 110 100% 28" class="CheckBoxComponent"
|
||||
params="p, "vibratoIgnoresWheel_raw", "Ignores Wheel""/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
72
Source/VibratoParamsComponent.h
Normal file
72
Source/VibratoParamsComponent.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This is an automatically generated GUI class created by the Projucer!
|
||||
|
||||
Be careful when adding custom code to these files, as only the code within
|
||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
|
||||
and re-saved.
|
||||
|
||||
Created with Projucer version: 5.4.5
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The Projucer is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "SliderComponent.h"
|
||||
#include "CheckBoxComponent.h"
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class VibratoParamsComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
VibratoParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||
~VibratoParamsComponent();
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<Label> label;
|
||||
std::unique_ptr<SliderComponent> ratioSlider;
|
||||
std::unique_ptr<SliderComponent> depthSlider;
|
||||
std::unique_ptr<SliderComponent> delaySlider;
|
||||
std::unique_ptr<CheckBoxComponent> ignoreWheelSwitch;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VibratoParamsComponent)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
11
Source/Voices.cpp
Normal file
11
Source/Voices.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Voices.cpp
|
||||
Created: 22 May 2019 7:05:29pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "Voices.h"
|
21
Source/Voices.h
Normal file
21
Source/Voices.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
Voices.h
|
||||
Created: 22 May 2019 7:05:29pm
|
||||
Author: 除村 武志
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "Settings.h"
|
||||
|
||||
enum EnvelopePhase
|
||||
{
|
||||
kEnvelopePhaseA,
|
||||
kEnvelopePhaseD,
|
||||
kEnvelopePhaseS,
|
||||
kEnvelopePhaseR
|
||||
};
|
Reference in New Issue
Block a user