mirror of
https://github.com/yokemura/Magical8bitPlug2.git
synced 2025-05-24 23:00:21 -04:00
Custom Waveform
This commit is contained in:
parent
47cefdd0e8
commit
915f9eb5bf
@ -33,6 +33,10 @@
|
|||||||
file="Source/SliderComponent.cpp"/>
|
file="Source/SliderComponent.cpp"/>
|
||||||
<FILE id="qIuf9N" name="SliderComponent.h" compile="0" resource="0"
|
<FILE id="qIuf9N" name="SliderComponent.h" compile="0" resource="0"
|
||||||
file="Source/SliderComponent.h"/>
|
file="Source/SliderComponent.h"/>
|
||||||
|
<FILE id="uajfNh" name="SliderVerticalComponent.cpp" compile="1" resource="0"
|
||||||
|
file="Source/SliderVerticalComponent.cpp"/>
|
||||||
|
<FILE id="p2nPNB" name="SliderVerticalComponent.h" compile="0" resource="0"
|
||||||
|
file="Source/SliderVerticalComponent.h"/>
|
||||||
</GROUP>
|
</GROUP>
|
||||||
<FILE id="SFqkUr" name="AdvancedParamsComponent.cpp" compile="1" resource="0"
|
<FILE id="SFqkUr" name="AdvancedParamsComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/AdvancedParamsComponent.cpp"/>
|
file="Source/AdvancedParamsComponent.cpp"/>
|
||||||
@ -68,6 +72,13 @@
|
|||||||
file="Source/VibratoParamsComponent.h"/>
|
file="Source/VibratoParamsComponent.h"/>
|
||||||
</GROUP>
|
</GROUP>
|
||||||
<GROUP id="{630C27C7-03AA-CFC6-2FC4-4CE2DBE3640A}" name="Source">
|
<GROUP id="{630C27C7-03AA-CFC6-2FC4-4CE2DBE3640A}" name="Source">
|
||||||
|
<FILE id="WS1wsR" name="WaveformParamsComponent.cpp" compile="1" resource="0"
|
||||||
|
file="Source/WaveformParamsComponent.cpp"/>
|
||||||
|
<FILE id="miNL07" name="WaveformParamsComponent.h" compile="0" resource="0"
|
||||||
|
file="Source/WaveformParamsComponent.h"/>
|
||||||
|
<FILE id="vVn1lo" name="WaveformVoice.cpp" compile="1" resource="0"
|
||||||
|
file="Source/WaveformVoice.cpp"/>
|
||||||
|
<FILE id="iZpU3j" name="WaveformVoice.h" compile="0" resource="0" file="Source/WaveformVoice.h"/>
|
||||||
<FILE id="H2Vgbj" name="FrameSequenceParseErrors.cpp" compile="1" resource="0"
|
<FILE id="H2Vgbj" name="FrameSequenceParseErrors.cpp" compile="1" resource="0"
|
||||||
file="Source/FrameSequenceParseErrors.cpp"/>
|
file="Source/FrameSequenceParseErrors.cpp"/>
|
||||||
<FILE id="Gwt2vB" name="FrameSequenceParseErrors.h" compile="0" resource="0"
|
<FILE id="Gwt2vB" name="FrameSequenceParseErrors.h" compile="0" resource="0"
|
||||||
|
@ -154,6 +154,7 @@ void BasicParamsComponent::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
|
|||||||
{
|
{
|
||||||
processor.setupVoice();
|
processor.setupVoice();
|
||||||
editor.resized();
|
editor.resized();
|
||||||
|
editor.resizeWholePanel();
|
||||||
printf ("setup voice!!\n");
|
printf ("setup voice!!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
NoiseVoice::NoiseVoice(SettingRefs *sRefs) : TonalVoice(sRefs) {}
|
NoiseVoice::NoiseVoice(SettingRefs *sRefs) : TonalVoice(sRefs) {}
|
||||||
|
|
||||||
void NoiseVoice::startNote(int midiNoteNumber, float velocity, SynthesiserSound *, int currentPitchBendPosition) {
|
void NoiseVoice::startNote(int midiNoteNumber, float velocity, SynthesiserSound *, int currentPitchBendPosition) {
|
||||||
TonalVoice::startNote(midiNoteNumber, velocity, 0, currentPitchBendPosition);
|
//TonalVoice::startNote(midiNoteNumber, velocity, 0, currentPitchBendPosition);
|
||||||
|
int midiNote = midiNoteNumber;
|
||||||
|
int midiNoteRange[16] = { 5, 17, 29, 34, 41, 46, 53, 57, 61, 65, 70, 77, 89, 101, 113, 125 };
|
||||||
switch (settingRefs->noiseAlgorithm()) {
|
switch (settingRefs->noiseAlgorithm()) {
|
||||||
case kNoiseInfinite2:
|
case kNoiseInfinite2:
|
||||||
cycleLength = MathConstants<float>::pi / 25.0;
|
cycleLength = MathConstants<float>::pi / 25.0;
|
||||||
@ -29,10 +31,19 @@ void NoiseVoice::startNote(int midiNoteNumber, float velocity, SynthesiserSound
|
|||||||
cycleLength = MathConstants<float>::pi / 8.0;
|
cycleLength = MathConstants<float>::pi / 8.0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kNoiseLongNes:
|
||||||
|
case kNoiseShortNes:
|
||||||
|
cycleLength = MathConstants<float>::pi / 20.175;
|
||||||
|
//rgstr = 0x8000;
|
||||||
|
//rgstr = rand();
|
||||||
|
midiNote = midiNoteRange[(midiNote + 8) % 16];
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cycleLength = MathConstants<float>::pi / 8.0;
|
cycleLength = MathConstants<float>::pi / 8.0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
TonalVoice::startNote(midiNote, velocity, 0, currentPitchBendPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
float NoiseVoice::voltageForAngle (double angle)
|
float NoiseVoice::voltageForAngle (double angle)
|
||||||
@ -58,9 +69,10 @@ float NoiseVoice::voltageForAngle (double angle)
|
|||||||
{
|
{
|
||||||
if (settingRefs->noiseAlgorithm() == kNoiseInfinite2)
|
if (settingRefs->noiseAlgorithm() == kNoiseInfinite2)
|
||||||
{
|
{
|
||||||
currentVoltage = float (rand() % 16 - 8) / 16.;
|
currentVoltage = float (rand() % 16 - 8) / 16.0;
|
||||||
|
//currentVoltage = float(rand() % 16 - 7.5) / 15.0;
|
||||||
}
|
}
|
||||||
else
|
else if (settingRefs->noiseAlgorithm() == kNoiseLong || settingRefs->noiseAlgorithm() == kNoiseShort)
|
||||||
{
|
{
|
||||||
int compareBitPos = settingRefs->noiseAlgorithm() == kNoiseLong ? 1 : 6;
|
int compareBitPos = settingRefs->noiseAlgorithm() == kNoiseLong ? 1 : 6;
|
||||||
|
|
||||||
@ -76,6 +88,14 @@ float NoiseVoice::voltageForAngle (double angle)
|
|||||||
|
|
||||||
currentVoltage = (float)bit0 - 0.5;
|
currentVoltage = (float)bit0 - 0.5;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int shortFreq = settingRefs->noiseAlgorithm() == kNoiseLongNes ? 1 : 6;
|
||||||
|
|
||||||
|
rgstr >>= 1;
|
||||||
|
rgstr |= ((rgstr ^ (rgstr >> shortFreq)) & 1) << 15;
|
||||||
|
currentVoltage = (float)(rgstr & 1) - 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
nextAngle = (double) ((int) (angle / cycleLength) + 1) * cycleLength;
|
nextAngle = (double) ((int) (angle / cycleLength) + 1) * cycleLength;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "BendParamsComponent.h"
|
#include "BendParamsComponent.h"
|
||||||
#include "SweepParamsComponent.h"
|
#include "SweepParamsComponent.h"
|
||||||
#include "VibratoParamsComponent.h"
|
#include "VibratoParamsComponent.h"
|
||||||
|
#include "WaveformParamsComponent.h"
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
Magical8bitPlug2AudioProcessorEditor::Magical8bitPlug2AudioProcessorEditor (Magical8bitPlug2AudioProcessor& p)
|
Magical8bitPlug2AudioProcessorEditor::Magical8bitPlug2AudioProcessorEditor (Magical8bitPlug2AudioProcessor& p)
|
||||||
@ -51,6 +52,10 @@ Magical8bitPlug2AudioProcessorEditor::Magical8bitPlug2AudioProcessorEditor (Magi
|
|||||||
vibCompo.reset (new VibratoParamsComponent (p));
|
vibCompo.reset (new VibratoParamsComponent (p));
|
||||||
addAndMakeVisible (vibCompo.get());
|
addAndMakeVisible (vibCompo.get());
|
||||||
|
|
||||||
|
// waveform
|
||||||
|
waveformCompo.reset (new WaveformParamsComponent (p));
|
||||||
|
addAndMakeVisible (waveformCompo.get());
|
||||||
|
|
||||||
(p.parameters.getParameter ("isVolumeSequenceEnabled_raw"))->addListener (this);
|
(p.parameters.getParameter ("isVolumeSequenceEnabled_raw"))->addListener (this);
|
||||||
(p.parameters.getParameter ("isDutySequenceEnabled_raw"))->addListener (this);
|
(p.parameters.getParameter ("isDutySequenceEnabled_raw"))->addListener (this);
|
||||||
|
|
||||||
@ -141,7 +146,7 @@ struct
|
|||||||
+ genericControlHeight;
|
+ genericControlHeight;
|
||||||
const int sweepCompoHeight = componentMargin * 2
|
const int sweepCompoHeight = componentMargin * 2
|
||||||
+ indexHeight
|
+ indexHeight
|
||||||
+ genericControlHeight * 2;
|
+ genericControlHeight * 3;
|
||||||
const int vibCompoHeight = componentMargin * 2
|
const int vibCompoHeight = componentMargin * 2
|
||||||
+ indexHeight
|
+ indexHeight
|
||||||
+ genericControlHeight * 4;
|
+ genericControlHeight * 4;
|
||||||
@ -240,6 +245,11 @@ void Magical8bitPlug2AudioProcessorEditor::resized()
|
|||||||
y3 += sizes.sectionSeparatorHeight;
|
y3 += sizes.sectionSeparatorHeight;
|
||||||
advCompo->setBounds (x, y3, sizes.fullComponentWidth, sizes.advCompoHeight);
|
advCompo->setBounds (x, y3, sizes.fullComponentWidth, sizes.advCompoHeight);
|
||||||
|
|
||||||
|
// Waveform
|
||||||
|
int wrX = sizes.leftMargin + sizes.totalWidth;
|
||||||
|
int wrY = sizes.topMargin;
|
||||||
|
waveformCompo->setBounds(wrX, wrY, waveformCompo->getWidth(), waveformCompo->getHeight());
|
||||||
|
|
||||||
//
|
//
|
||||||
// Visibility
|
// Visibility
|
||||||
//
|
//
|
||||||
@ -272,7 +282,12 @@ void Magical8bitPlug2AudioProcessorEditor::resized()
|
|||||||
|
|
||||||
void Magical8bitPlug2AudioProcessorEditor::resizeWholePanel()
|
void Magical8bitPlug2AudioProcessorEditor::resizeWholePanel()
|
||||||
{
|
{
|
||||||
setSize (sizes.totalWidth, sizes.totalHeight (processor.settingRefs.isAdvancedPanelOpen()));
|
int totalWidth = sizes.totalWidth;
|
||||||
|
if (processor.settingRefs.oscillatorType() == kVoiceTypeWaveform)
|
||||||
|
{
|
||||||
|
totalWidth += sizes.leftMargin * 2 + waveformCompo->getWidth();
|
||||||
|
}
|
||||||
|
setSize (totalWidth, sizes.totalHeight (processor.settingRefs.isAdvancedPanelOpen()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Magical8bitPlug2AudioProcessorEditor::parameterValueChanged (int parameterIndex, float newValue)
|
void Magical8bitPlug2AudioProcessorEditor::parameterValueChanged (int parameterIndex, float newValue)
|
||||||
@ -291,3 +306,13 @@ void Magical8bitPlug2AudioProcessorEditor::parameterValueChanged (int parameterI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waveform
|
||||||
|
//void Magical8bitPlug2AudioProcessorEditor::waveformInit()
|
||||||
|
//{
|
||||||
|
// waveformCompo->sliderInit();
|
||||||
|
//}
|
||||||
|
|
||||||
|
void Magical8bitPlug2AudioProcessorEditor::waveformUpdate()
|
||||||
|
{
|
||||||
|
waveformCompo->sliderRepaint();
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ class NoiseParamsComponent;
|
|||||||
class BendParamsComponent;
|
class BendParamsComponent;
|
||||||
class SweepParamsComponent;
|
class SweepParamsComponent;
|
||||||
class VibratoParamsComponent;
|
class VibratoParamsComponent;
|
||||||
|
class WaveformParamsComponent;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
@ -40,6 +41,10 @@ public:
|
|||||||
void parameterValueChanged (int parameterIndex, float newValue) override;
|
void parameterValueChanged (int parameterIndex, float newValue) override;
|
||||||
void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) override {};
|
void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) override {};
|
||||||
|
|
||||||
|
// waveform
|
||||||
|
//void waveformInit();
|
||||||
|
void waveformUpdate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Magical8bitPlug2AudioProcessor& processor;
|
Magical8bitPlug2AudioProcessor& processor;
|
||||||
|
|
||||||
@ -51,6 +56,7 @@ private:
|
|||||||
std::unique_ptr<BendParamsComponent> bendCompo;
|
std::unique_ptr<BendParamsComponent> bendCompo;
|
||||||
std::unique_ptr<SweepParamsComponent> sweepCompo;
|
std::unique_ptr<SweepParamsComponent> sweepCompo;
|
||||||
std::unique_ptr<VibratoParamsComponent> vibCompo;
|
std::unique_ptr<VibratoParamsComponent> vibCompo;
|
||||||
|
std::unique_ptr<WaveformParamsComponent> waveformCompo;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Magical8bitPlug2AudioProcessorEditor)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Magical8bitPlug2AudioProcessorEditor)
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "PulseVoice.h"
|
#include "PulseVoice.h"
|
||||||
#include "TriangleVoice.h"
|
#include "TriangleVoice.h"
|
||||||
#include "NoiseVoice.h"
|
#include "NoiseVoice.h"
|
||||||
|
#include "WaveformVoice.h"
|
||||||
#include "FrameSequenceParseErrors.h"
|
#include "FrameSequenceParseErrors.h"
|
||||||
#include "EnvelopeParserTest.h"
|
#include "EnvelopeParserTest.h"
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
|||||||
//
|
//
|
||||||
// Basic
|
// Basic
|
||||||
//
|
//
|
||||||
std::make_unique<AudioParameterChoice> ("osc", "OSC Type", StringArray ({"Pulse/Square", "Triangle", "Noise"}), 0),
|
std::make_unique<AudioParameterChoice> ("osc", "OSC Type", StringArray ({"Pulse/Square", "Triangle", "Noise", "Waveform"}), 0),
|
||||||
std::make_unique<AudioParameterFloat> ("gain", "Gain", 0.0f, 1.0f, 0.5f),
|
std::make_unique<AudioParameterFloat> ("gain", "Gain", 0.0f, 1.0f, 0.5f),
|
||||||
std::make_unique<AudioParameterFloat> ("maxPoly", "Max Poly", NormalisableRange<float> (1.0f, //min
|
std::make_unique<AudioParameterFloat> ("maxPoly", "Max Poly", NormalisableRange<float> (1.0f, //min
|
||||||
64.0f, //max
|
64.0f, //max
|
||||||
@ -92,6 +93,7 @@ Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
|||||||
// Sweep
|
// Sweep
|
||||||
//
|
//
|
||||||
std::make_unique<AudioParameterInt> ("sweepInitialPitch", "Ini.Pitch", -24, 24, 0),
|
std::make_unique<AudioParameterInt> ("sweepInitialPitch", "Ini.Pitch", -24, 24, 0),
|
||||||
|
std::make_unique<AudioParameterInt> ("sweepEndPitch", "End.Pitch", -24, 24, 0),
|
||||||
std::make_unique<AudioParameterFloat> ("sweepTime", //ID
|
std::make_unique<AudioParameterFloat> ("sweepTime", //ID
|
||||||
"Time", //name
|
"Time", //name
|
||||||
NormalisableRange<float> (0.01f, //min
|
NormalisableRange<float> (0.01f, //min
|
||||||
@ -106,7 +108,7 @@ Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
|||||||
//
|
//
|
||||||
// For Noise
|
// For Noise
|
||||||
//
|
//
|
||||||
std::make_unique<AudioParameterChoice> ("noiseAlgorithm_raw", "Algorithm", StringArray ({"4bit Pure Random", "1bit Long Cycle", "1bit Short Cycle"}), 0),
|
std::make_unique<AudioParameterChoice> ("noiseAlgorithm_raw", "Algorithm", StringArray ({"4bit Pure Random", "1bit Long Cycle", "1bit Short Cycle", "Nes Long Cycle", "Nes Short Cycle"}), 0),
|
||||||
std::make_unique<AudioParameterBool> ("restrictsToNESFrequency_raw", "Restricts to NES frequency", false),
|
std::make_unique<AudioParameterBool> ("restrictsToNESFrequency_raw", "Restricts to NES frequency", false),
|
||||||
//
|
//
|
||||||
// Sequence
|
// Sequence
|
||||||
@ -114,8 +116,77 @@ Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
|||||||
std::make_unique<AudioParameterBool> ("isVolumeSequenceEnabled_raw", "Enabled", false),
|
std::make_unique<AudioParameterBool> ("isVolumeSequenceEnabled_raw", "Enabled", false),
|
||||||
std::make_unique<AudioParameterBool> ("isPitchSequenceEnabled_raw", "Enabled", false),
|
std::make_unique<AudioParameterBool> ("isPitchSequenceEnabled_raw", "Enabled", false),
|
||||||
std::make_unique<AudioParameterBool> ("isDutySequenceEnabled_raw", "Enabled", false),
|
std::make_unique<AudioParameterBool> ("isDutySequenceEnabled_raw", "Enabled", false),
|
||||||
std::make_unique<AudioParameterChoice> ("pitchSequenceMode_raw", "Mode", StringArray ({"Coarse", "Fine"}), 0)
|
std::make_unique<AudioParameterChoice> ("pitchSequenceMode_raw", "Mode", StringArray ({"Coarse", "Fine8", "Fine16"}), 0),
|
||||||
}
|
// waveform
|
||||||
|
std::make_unique<AudioParameterChoice>("waveformX", "X", StringArray({ "16", "32", "64" }), 2),
|
||||||
|
std::make_unique<AudioParameterChoice>("waveformY", "Y", StringArray({ "16", "32", "64" }), 2),
|
||||||
|
std::make_unique<AudioParameterChoice>("waveformTemplate", "Template", StringArray({ "Custom", "Sine", "Triangle", "Sawtooth", "Square 6.25%", "Square 18.75%", "Square 31.25%", "Square 37.5%", "Square 43.75%" }), 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave0", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave1", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave2", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave3", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave4", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave5", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave6", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave7", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave8", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave9", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave10", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave11", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave12", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave13", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave14", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave15", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave16", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave17", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave18", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave19", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave20", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave21", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave22", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave23", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave24", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave25", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave26", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave27", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave28", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave29", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave30", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave31", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave32", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave33", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave34", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave35", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave36", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave37", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave38", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave39", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave40", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave41", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave42", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave43", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave44", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave45", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave46", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave47", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave48", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave49", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave50", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave51", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave52", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave53", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave54", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave55", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave56", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave57", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave58", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave59", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave60", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave61", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave62", "wave", 0, 63, 0),
|
||||||
|
std::make_unique<AudioParameterFloat>("waveformWave63", "wave", 0, 63, 0)
|
||||||
|
|
||||||
|
}
|
||||||
)
|
)
|
||||||
, settingRefs (¶meters)
|
, settingRefs (¶meters)
|
||||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||||
@ -129,6 +200,16 @@ Magical8bitPlug2AudioProcessor::Magical8bitPlug2AudioProcessor()
|
|||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
// waveform
|
||||||
|
//parameters.createAndAddParameter(std::make_unique<AudioParameterChoice>("waveformX", "X", StringArray({ "16", "32", "64" }), 2));
|
||||||
|
//parameters.createAndAddParameter(std::make_unique<AudioParameterChoice>("waveformY", "Y", StringArray({ "16", "32", "64" }), 2));
|
||||||
|
//parameters.createAndAddParameter(std::make_unique<AudioParameterChoice>("waveformTemplate", "Template", StringArray({ "Custom", "Sine", "Triangle", "Sawtooth", "Square 6.25%", "Square 18.75%", "Square 31.25%", "Square 37.5%", "Square 43.75%" }), 0));
|
||||||
|
//for (int i = 0; i < 64; i++)
|
||||||
|
//{
|
||||||
|
// parameters.createAndAddParameter(std::make_unique<AudioParameterInt>("waveformWave" + String(i), "wave" + String(i), 0, 63, 0));
|
||||||
|
//}
|
||||||
|
//settingRefs.setWaveform(¶meters);
|
||||||
|
|
||||||
synth.setCurrentPlaybackSampleRate (44100); // Temporary setup, just in case. The actual sample rate is set in prepareToPlay func.
|
synth.setCurrentPlaybackSampleRate (44100); // Temporary setup, just in case. The actual sample rate is set in prepareToPlay func.
|
||||||
|
|
||||||
setupVoice();
|
setupVoice();
|
||||||
@ -171,6 +252,10 @@ void Magical8bitPlug2AudioProcessor::setupVoice()
|
|||||||
case kVoiceTypeNoise:
|
case kVoiceTypeNoise:
|
||||||
synth.addVoice (new NoiseVoice (&settingRefs));
|
synth.addVoice (new NoiseVoice (&settingRefs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kVoiceTypeWaveform:
|
||||||
|
synth.addVoice(new WaveformVoice(&settingRefs));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,8 +460,13 @@ void Magical8bitPlug2AudioProcessor::getStateInformation (MemoryBlock& destData)
|
|||||||
copyXmlToBinary (*xml, destData);
|
copyXmlToBinary (*xml, destData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Magical8bitPlug2AudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
void Magical8bitPlug2AudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
||||||
{
|
{
|
||||||
|
//if (Magical8bitPlug2AudioProcessorEditor* activeEditor = (Magical8bitPlug2AudioProcessorEditor*)getActiveEditor())
|
||||||
|
//{
|
||||||
|
// activeEditor->waveformInit();
|
||||||
|
//}
|
||||||
|
|
||||||
std::unique_ptr<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
|
std::unique_ptr<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
|
||||||
|
|
||||||
if (xmlState.get() != nullptr)
|
if (xmlState.get() != nullptr)
|
||||||
@ -473,6 +563,13 @@ void Magical8bitPlug2AudioProcessor::setStateInformation (const void* data, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupVoice();
|
setupVoice();
|
||||||
|
|
||||||
|
if (Magical8bitPlug2AudioProcessorEditor* activeEditor = (Magical8bitPlug2AudioProcessorEditor*)getActiveEditor())
|
||||||
|
{
|
||||||
|
activeEditor->resized();
|
||||||
|
activeEditor->resizeWholePanel();
|
||||||
|
activeEditor->waveformUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -56,7 +56,37 @@ void PulseVoice::advanceControlFrame()
|
|||||||
|
|
||||||
if (settingRefs->isDutySequenceEnabled())
|
if (settingRefs->isDutySequenceEnabled())
|
||||||
{
|
{
|
||||||
currentDutySequenceFrame = settingRefs->dutySequence.nextIndexOf (currentDutySequenceFrame);
|
//currentDutySequenceFrame = settingRefs->dutySequence.nextIndexOf(currentDutySequenceFrame);
|
||||||
currentDuty = (PulseDuty)settingRefs->dutySequence.valueAt (currentDutySequenceFrame);
|
//currentDuty = (PulseDuty)settingRefs->dutySequence.valueAt(currentDutySequenceFrame);
|
||||||
|
|
||||||
|
int currentDutySequenceFrameTmp = settingRefs->dutySequence.nextIndexOf(currentDutySequenceFrame);
|
||||||
|
if (currentDutySequenceFrameTmp != FrameSequence::SHOULD_RETIRE)
|
||||||
|
{
|
||||||
|
currentDutySequenceFrame = currentDutySequenceFrameTmp;
|
||||||
|
currentDuty = (PulseDuty)settingRefs->dutySequence.valueAt(currentDutySequenceFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PulseVoice::stopNote(float velocity, bool allowTailOff)
|
||||||
|
{
|
||||||
|
TonalVoice::stopNote(velocity, allowTailOff);
|
||||||
|
|
||||||
|
if (!allowTailOff)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingRefs->isDutySequenceEnabled())
|
||||||
|
{
|
||||||
|
if (settingRefs->dutySequence.hasRelease)
|
||||||
|
{
|
||||||
|
if (settingRefs->dutySequence.isInRelease(currentDutySequenceFrame)) {
|
||||||
|
// Already in release(Custom Env.)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentDutySequenceFrame = settingRefs->dutySequence.releaseSequenceStartIndex;
|
||||||
|
currentDuty = (PulseDuty)settingRefs->dutySequence.valueAt(currentDutySequenceFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,5 @@ struct PulseVoice : public TonalVoice
|
|||||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||||
float voltageForAngle (double angle) override;
|
float voltageForAngle (double angle) override;
|
||||||
void advanceControlFrame() override;
|
void advanceControlFrame() override;
|
||||||
|
void stopNote(float velocity, bool allowTailOff) override;
|
||||||
};
|
};
|
||||||
|
@ -77,3 +77,29 @@ String& SettingRefs::getSequenceString (const String& type)
|
|||||||
printf ("*** parameter type invalid!\n");
|
printf ("*** parameter type invalid!\n");
|
||||||
return volumeSequenceString;
|
return volumeSequenceString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void SettingRefs::setWaveform(AudioProcessorValueTreeState* parameters)
|
||||||
|
//{
|
||||||
|
// // waveform
|
||||||
|
// for (int i = 0; i < 64; i++)
|
||||||
|
// {
|
||||||
|
// waveformWave[i] = (float*)parameters->getRawParameterValue("waveformWave" + String(i));
|
||||||
|
// }
|
||||||
|
// waveformX = (float*)parameters->getRawParameterValue("waveformX");
|
||||||
|
// waveformY = (float*)parameters->getRawParameterValue("waveformY");
|
||||||
|
// waveformTemplate = (float*)parameters->getRawParameterValue("waveformTemplate");
|
||||||
|
//}
|
||||||
|
|
||||||
|
int SettingRefs::getWaveformX()
|
||||||
|
{
|
||||||
|
int range[3] = {16, 32, 64};
|
||||||
|
|
||||||
|
return range[(int)(*waveformX)];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SettingRefs::getWaveformY()
|
||||||
|
{
|
||||||
|
int range[3] = { 16, 32, 64 };
|
||||||
|
|
||||||
|
return range[(int)(*waveformY)] - 1;
|
||||||
|
}
|
||||||
|
@ -23,7 +23,8 @@ enum VoiceType
|
|||||||
{
|
{
|
||||||
kVoiceTypePulse = 0,
|
kVoiceTypePulse = 0,
|
||||||
kVoiceTypeTriangle,
|
kVoiceTypeTriangle,
|
||||||
kVoiceTypeNoise
|
kVoiceTypeNoise,
|
||||||
|
kVoiceTypeWaveform
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PluginSettings
|
struct PluginSettings
|
||||||
@ -52,12 +53,15 @@ enum NoiseAlgorithm
|
|||||||
kNoiseInfinite2 = 0,
|
kNoiseInfinite2 = 0,
|
||||||
kNoiseLong,
|
kNoiseLong,
|
||||||
kNoiseShort,
|
kNoiseShort,
|
||||||
|
kNoiseLongNes,
|
||||||
|
kNoiseShortNes,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PitchSequenceMode
|
enum PitchSequenceMode
|
||||||
{
|
{
|
||||||
kPitchSequenceModeCoarse = 0,
|
kPitchSequenceModeCoarse = 0,
|
||||||
kPitchSequenceModeFine
|
kPitchSequenceModeFine,
|
||||||
|
kPitchSequenceModeFine16
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameSequenceChangeListener
|
class FrameSequenceChangeListener
|
||||||
@ -108,6 +112,7 @@ struct SettingRefs
|
|||||||
float* vibratoIgnoresWheel_raw = nullptr;
|
float* vibratoIgnoresWheel_raw = nullptr;
|
||||||
// Sweep
|
// Sweep
|
||||||
float* sweepInitialPitch = nullptr;
|
float* sweepInitialPitch = nullptr;
|
||||||
|
float* sweepEndPitch = nullptr;
|
||||||
float* sweepTime = nullptr;
|
float* sweepTime = nullptr;
|
||||||
// For Pulse
|
// For Pulse
|
||||||
float* duty = nullptr;
|
float* duty = nullptr;
|
||||||
@ -123,9 +128,9 @@ struct SettingRefs
|
|||||||
FrameSequence volumeSequence;
|
FrameSequence volumeSequence;
|
||||||
FrameSequence pitchSequence;
|
FrameSequence pitchSequence;
|
||||||
FrameSequence dutySequence;
|
FrameSequence dutySequence;
|
||||||
String volumeSequenceString = "";
|
String volumeSequenceString; //= "15 x 5, 15 to 0 in 15 [5, 4, 3] | 2, 1, 0";
|
||||||
String pitchSequenceString = "";
|
String pitchSequenceString; //= "15 x 5, 15 to 0 in 15 [5, 4, 3] | 2, 1, 0";
|
||||||
String dutySequenceString = "";
|
String dutySequenceString; //= "2 x 5, 2 to 0 in 15 [2, 1, 0] | 2, 1, 0";
|
||||||
|
|
||||||
bool setSequenceWithString (const String& type, const String& input, ParseError* error);
|
bool setSequenceWithString (const String& type, const String& input, ParseError* error);
|
||||||
String& getSequenceString (const String& type);
|
String& getSequenceString (const String& type);
|
||||||
@ -152,6 +157,14 @@ struct SettingRefs
|
|||||||
bool isDutySequenceEnabled() { return *isDutySequenceEnabled_raw > 0.5; }
|
bool isDutySequenceEnabled() { return *isDutySequenceEnabled_raw > 0.5; }
|
||||||
PitchSequenceMode pitchSequenceMode() { return (PitchSequenceMode) ((int) (*pitchSequenceMode_raw)); }
|
PitchSequenceMode pitchSequenceMode() { return (PitchSequenceMode) ((int) (*pitchSequenceMode_raw)); }
|
||||||
|
|
||||||
|
// waveform
|
||||||
|
//void setWaveform(AudioProcessorValueTreeState* parameters);
|
||||||
|
int getWaveformX();
|
||||||
|
int getWaveformY();
|
||||||
|
float* waveformWave[64];
|
||||||
|
float* waveformX = nullptr;
|
||||||
|
float* waveformY = nullptr;
|
||||||
|
float* waveformTemplate = nullptr;
|
||||||
|
|
||||||
//
|
//
|
||||||
// constructor
|
// constructor
|
||||||
@ -183,6 +196,7 @@ struct SettingRefs
|
|||||||
vibratoIgnoresWheel_raw = (float*) parameters->getRawParameterValue ("vibratoIgnoresWheel_raw");
|
vibratoIgnoresWheel_raw = (float*) parameters->getRawParameterValue ("vibratoIgnoresWheel_raw");
|
||||||
// Sweep
|
// Sweep
|
||||||
sweepInitialPitch = (float*) parameters->getRawParameterValue ("sweepInitialPitch");
|
sweepInitialPitch = (float*) parameters->getRawParameterValue ("sweepInitialPitch");
|
||||||
|
sweepEndPitch = (float*)parameters->getRawParameterValue("sweepEndPitch");
|
||||||
sweepTime = (float*) parameters->getRawParameterValue ("sweepTime");
|
sweepTime = (float*) parameters->getRawParameterValue ("sweepTime");
|
||||||
// For Pulse
|
// For Pulse
|
||||||
duty = (float*) parameters->getRawParameterValue ("duty");
|
duty = (float*) parameters->getRawParameterValue ("duty");
|
||||||
@ -194,6 +208,13 @@ struct SettingRefs
|
|||||||
isPitchSequenceEnabled_raw = (float*) parameters->getRawParameterValue ("isPitchSequenceEnabled_raw");
|
isPitchSequenceEnabled_raw = (float*) parameters->getRawParameterValue ("isPitchSequenceEnabled_raw");
|
||||||
isDutySequenceEnabled_raw = (float*) parameters->getRawParameterValue ("isDutySequenceEnabled_raw");
|
isDutySequenceEnabled_raw = (float*) parameters->getRawParameterValue ("isDutySequenceEnabled_raw");
|
||||||
pitchSequenceMode_raw = (float*) parameters->getRawParameterValue ("pitchSequenceMode_raw");
|
pitchSequenceMode_raw = (float*) parameters->getRawParameterValue ("pitchSequenceMode_raw");
|
||||||
|
// waveform
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
waveformWave[i] = (float*)parameters->getRawParameterValue("waveformWave" + String(i));
|
||||||
|
}
|
||||||
|
waveformX = (float*)parameters->getRawParameterValue("waveformX");
|
||||||
|
waveformY = (float*)parameters->getRawParameterValue("waveformY");
|
||||||
|
waveformTemplate = (float*)parameters->getRawParameterValue("waveformTemplate");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
172
Source/SliderVerticalComponent.cpp
Normal file
172
Source/SliderVerticalComponent.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
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: 6.0.8
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The Projucer is part of the JUCE library.
|
||||||
|
Copyright (c) 2020 - Raw Material Software Limited.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
//[Headers] You can add your own extra header files here...
|
||||||
|
//[/Headers]
|
||||||
|
|
||||||
|
#include "SliderVerticalComponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||||
|
//[/MiscUserDefs]
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
SliderVerticalComponent::SliderVerticalComponent (Magical8bitPlug2AudioProcessor& p, String paramId)
|
||||||
|
: processor(p)
|
||||||
|
{
|
||||||
|
//[Constructor_pre] You can add your own custom stuff here..
|
||||||
|
setInterceptsMouseClicks(true, false);
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
verticalSliders[i].reset(new juce::Slider("vertical slider"));
|
||||||
|
addAndMakeVisible(verticalSliders[i].get());
|
||||||
|
verticalSliders[i]->setRange(0, 63, 0);
|
||||||
|
verticalSliders[i]->setSliderStyle(juce::Slider::LinearBarVertical);
|
||||||
|
verticalSliders[i]->setTextBoxStyle(juce::Slider::NoTextBox, true, 30, 20);
|
||||||
|
verticalSliders[i]->setBounds(0 + i * 8, 0, 9, 250);
|
||||||
|
verticalSliders[i]->setInterceptsMouseClicks(false, false);
|
||||||
|
attc[i].reset(new SliderAttachment(p.parameters, paramId + String(i), *verticalSliders[i]));
|
||||||
|
}
|
||||||
|
//[/Constructor_pre]
|
||||||
|
|
||||||
|
|
||||||
|
//[UserPreSize]
|
||||||
|
//[/UserPreSize]
|
||||||
|
|
||||||
|
setSize (513, 250);
|
||||||
|
|
||||||
|
|
||||||
|
//[Constructor] You can add your own custom stuff here..
|
||||||
|
baseMaxValue = 63;
|
||||||
|
//[/Constructor]
|
||||||
|
}
|
||||||
|
|
||||||
|
SliderVerticalComponent::~SliderVerticalComponent()
|
||||||
|
{
|
||||||
|
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
attc[i].reset();
|
||||||
|
verticalSliders[i] = nullptr;
|
||||||
|
}
|
||||||
|
//[/Destructor_pre]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[Destructor]. You can add your own custom destruction code here..
|
||||||
|
//[/Destructor]
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void SliderVerticalComponent::paint (juce::Graphics& g)
|
||||||
|
{
|
||||||
|
//[UserPrePaint] Add your own custom painting code here..
|
||||||
|
//[/UserPrePaint]
|
||||||
|
|
||||||
|
//[UserPaint] Add your own custom painting code here..
|
||||||
|
//[/UserPaint]
|
||||||
|
}
|
||||||
|
|
||||||
|
void SliderVerticalComponent::resized()
|
||||||
|
{
|
||||||
|
//[UserPreResize] Add your own custom resize code here..
|
||||||
|
//[/UserPreResize]
|
||||||
|
|
||||||
|
//[UserResized] Add your own custom resize handling here..
|
||||||
|
//[/UserResized]
|
||||||
|
}
|
||||||
|
|
||||||
|
void SliderVerticalComponent::mouseDown (const juce::MouseEvent& e)
|
||||||
|
{
|
||||||
|
//[UserCode_mouseDown] -- Add your code here...
|
||||||
|
mouseDrag(e);
|
||||||
|
//[/UserCode_mouseDown]
|
||||||
|
}
|
||||||
|
|
||||||
|
void SliderVerticalComponent::mouseDrag (const juce::MouseEvent& e)
|
||||||
|
{
|
||||||
|
//[UserCode_mouseDrag] -- Add your code here...
|
||||||
|
int rate = (baseMaxValue + 1) / (maxValue + 1);
|
||||||
|
int sliderIndex = jlimit(0, numWidth - 1, (int)floor(e.position.x / (getWidth() / ((double)numWidth))));
|
||||||
|
waveValue = jlimit(0, baseMaxValue, (int)(baseMaxValue * ((double)getHeight() - (double)e.position.y) / ((double)getHeight()) + 0.5));
|
||||||
|
waveValue = (int)(waveValue / rate);
|
||||||
|
verticalSliders[sliderIndex]->setValue(((double)waveValue / maxValue * baseMaxValue));
|
||||||
|
getParentComponent()->mouseDrag(e.getEventRelativeTo(getParentComponent()));
|
||||||
|
//[/UserCode_mouseDrag]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||||
|
void SliderVerticalComponent::setForm(int numWidth, int maxValue, int width, int height)
|
||||||
|
{
|
||||||
|
this->numWidth = jlimit(0, 64, numWidth);
|
||||||
|
this->maxValue = maxValue;
|
||||||
|
|
||||||
|
int sliderWidth = width / this->numWidth;
|
||||||
|
|
||||||
|
setSize(sliderWidth * this->numWidth + 1, height);
|
||||||
|
|
||||||
|
int rate = (baseMaxValue + 1) / (maxValue + 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
verticalSliders[i]->setBounds(0 + i * sliderWidth, 0, sliderWidth + 1, height);
|
||||||
|
int value = verticalSliders[i]->getValue();
|
||||||
|
verticalSliders[i]->setValue(((double)(value / rate) / maxValue * baseMaxValue));
|
||||||
|
verticalSliders[i]->repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SliderVerticalComponent::setValue(int index, int value)
|
||||||
|
{
|
||||||
|
verticalSliders[index]->setValue(((double)value / maxValue * baseMaxValue));
|
||||||
|
}
|
||||||
|
//[/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="SliderVerticalComponent"
|
||||||
|
componentName="" parentClasses="public juce::Component" constructorParams="Magical8bitPlug2AudioProcessor& p, String paramId"
|
||||||
|
variableInitialisers="processor(p)" snapPixels="8" snapActive="1"
|
||||||
|
snapShown="1" overlayOpacity="0.330" fixedSize="1" initialWidth="513"
|
||||||
|
initialHeight="250">
|
||||||
|
<METHODS>
|
||||||
|
<METHOD name="mouseDrag (const juce::MouseEvent& e)"/>
|
||||||
|
<METHOD name="mouseDown (const juce::MouseEvent& e)"/>
|
||||||
|
</METHODS>
|
||||||
|
<BACKGROUND backgroundColour="ffffff"/>
|
||||||
|
</JUCER_COMPONENT>
|
||||||
|
|
||||||
|
END_JUCER_METADATA
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//[EndFile] You can add extra defines here...
|
||||||
|
//[/EndFile]
|
||||||
|
|
78
Source/SliderVerticalComponent.h
Normal file
78
Source/SliderVerticalComponent.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
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: 6.0.8
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The Projucer is part of the JUCE library.
|
||||||
|
Copyright (c) 2020 - Raw Material Software Limited.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//[Headers] -- You can add your own extra header files here --
|
||||||
|
#include <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 SliderVerticalComponent : public juce::Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
SliderVerticalComponent (Magical8bitPlug2AudioProcessor& p, String paramId);
|
||||||
|
~SliderVerticalComponent() override;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//[UserMethods] -- You can add your own custom methods in this section.
|
||||||
|
void setForm(int numWidth, int maxValue, int width, int height);
|
||||||
|
void setValue(int index, int value);
|
||||||
|
int waveValue = -1;
|
||||||
|
//[/UserMethods]
|
||||||
|
|
||||||
|
void paint (juce::Graphics& g) override;
|
||||||
|
void resized() override;
|
||||||
|
void mouseDown (const juce::MouseEvent& e) override;
|
||||||
|
void mouseDrag (const juce::MouseEvent& e) override;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//[UserVariables] -- You can add your own custom variables in this section.
|
||||||
|
std::unique_ptr<juce::Slider> verticalSliders[64];
|
||||||
|
int numWidth;
|
||||||
|
int maxValue;
|
||||||
|
int baseMaxValue;
|
||||||
|
Magical8bitPlug2AudioProcessor& processor;
|
||||||
|
std::unique_ptr<SliderAttachment> attc[64];
|
||||||
|
//[/UserVariables]
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderVerticalComponent)
|
||||||
|
};
|
||||||
|
|
||||||
|
//[EndFile] You can add extra defines here...
|
||||||
|
//[/EndFile]
|
||||||
|
|
@ -51,11 +51,15 @@ SweepParamsComponent::SweepParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
|||||||
addAndMakeVisible (timeSlider.get());
|
addAndMakeVisible (timeSlider.get());
|
||||||
timeSlider->setName ("time slider");
|
timeSlider->setName ("time slider");
|
||||||
|
|
||||||
|
endPitchSlider.reset (new SliderComponent (p, "sweepEndPitch", "End.Pitch"));
|
||||||
|
addAndMakeVisible (endPitchSlider.get());
|
||||||
|
endPitchSlider->setName ("end pitch slider");
|
||||||
|
|
||||||
|
|
||||||
//[UserPreSize]
|
//[UserPreSize]
|
||||||
//[/UserPreSize]
|
//[/UserPreSize]
|
||||||
|
|
||||||
setSize (340, 86);
|
setSize (340, 114);
|
||||||
|
|
||||||
|
|
||||||
//[Constructor] You can add your own custom stuff here..
|
//[Constructor] You can add your own custom stuff here..
|
||||||
@ -70,6 +74,7 @@ SweepParamsComponent::~SweepParamsComponent()
|
|||||||
label = nullptr;
|
label = nullptr;
|
||||||
iniPitchSlider = nullptr;
|
iniPitchSlider = nullptr;
|
||||||
timeSlider = nullptr;
|
timeSlider = nullptr;
|
||||||
|
endPitchSlider = nullptr;
|
||||||
|
|
||||||
|
|
||||||
//[Destructor]. You can add your own custom destruction code here..
|
//[Destructor]. You can add your own custom destruction code here..
|
||||||
@ -92,7 +97,8 @@ void SweepParamsComponent::resized()
|
|||||||
//[/UserPreResize]
|
//[/UserPreResize]
|
||||||
|
|
||||||
iniPitchSlider->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
iniPitchSlider->setBounds (0, 26, proportionOfWidth (1.0000f), 28);
|
||||||
timeSlider->setBounds (0, 54, proportionOfWidth (1.0000f), 28);
|
timeSlider->setBounds (0, 82, proportionOfWidth (1.0000f), 28);
|
||||||
|
endPitchSlider->setBounds (0, 54, proportionOfWidth (1.0000f), 28);
|
||||||
//[UserResized] Add your own custom resize handling here..
|
//[UserResized] Add your own custom resize handling here..
|
||||||
//[/UserResized]
|
//[/UserResized]
|
||||||
}
|
}
|
||||||
@ -115,7 +121,7 @@ BEGIN_JUCER_METADATA
|
|||||||
<JUCER_COMPONENT documentType="Component" className="SweepParamsComponent" componentName=""
|
<JUCER_COMPONENT documentType="Component" className="SweepParamsComponent" componentName=""
|
||||||
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||||
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
|
||||||
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="86">
|
overlayOpacity="0.330" fixedSize="1" initialWidth="340" initialHeight="114">
|
||||||
<BACKGROUND backgroundColour="ffffff"/>
|
<BACKGROUND backgroundColour="ffffff"/>
|
||||||
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||||
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||||
@ -126,8 +132,11 @@ BEGIN_JUCER_METADATA
|
|||||||
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
virtualName="" explicitFocusOrder="0" pos="0 26 100% 28" class="SliderComponent"
|
||||||
params="p, "sweepInitialPitch", "Ini.Pitch""/>
|
params="p, "sweepInitialPitch", "Ini.Pitch""/>
|
||||||
<GENERICCOMPONENT name="time slider" id="1be45518932375fc" memberName="timeSlider"
|
<GENERICCOMPONENT name="time slider" id="1be45518932375fc" memberName="timeSlider"
|
||||||
virtualName="" explicitFocusOrder="0" pos="0 54 100% 28" class="SliderComponent"
|
virtualName="" explicitFocusOrder="0" pos="0 82 100% 28" class="SliderComponent"
|
||||||
params="p, "sweepTime", "Time""/>
|
params="p, "sweepTime", "Time""/>
|
||||||
|
<GENERICCOMPONENT name="end pitch slider" id="25cde38cec6274db" memberName="endPitchSlider"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="0 54 100% 28" class="SliderComponent"
|
||||||
|
params="p, "sweepEndPitch", "End.Pitch""/>
|
||||||
</JUCER_COMPONENT>
|
</JUCER_COMPONENT>
|
||||||
|
|
||||||
END_JUCER_METADATA
|
END_JUCER_METADATA
|
||||||
|
@ -58,6 +58,7 @@ private:
|
|||||||
std::unique_ptr<juce::Label> label;
|
std::unique_ptr<juce::Label> label;
|
||||||
std::unique_ptr<SliderComponent> iniPitchSlider;
|
std::unique_ptr<SliderComponent> iniPitchSlider;
|
||||||
std::unique_ptr<SliderComponent> timeSlider;
|
std::unique_ptr<SliderComponent> timeSlider;
|
||||||
|
std::unique_ptr<SliderComponent> endPitchSlider;
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -27,16 +27,28 @@ void TonalVoice::startNote (int midiNoteNumber, float velocity, SynthesiserSound
|
|||||||
vibratoCount = 0;
|
vibratoCount = 0;
|
||||||
|
|
||||||
float iniPitch = * (settingRefs->sweepInitialPitch);
|
float iniPitch = * (settingRefs->sweepInitialPitch);
|
||||||
|
float endPitch = *(settingRefs->sweepEndPitch);
|
||||||
float time = * (settingRefs->sweepTime);
|
float time = * (settingRefs->sweepTime);
|
||||||
currentAutoBendAmount = iniPitch;
|
currentAutoBendAmount = iniPitch;
|
||||||
autoBendDelta = -1.0 * iniPitch / (time * getSampleRate());
|
autoBendDelta = -1.0 * (iniPitch - endPitch) / (time * getSampleRate());
|
||||||
|
|
||||||
|
//if (*(settingRefs->osc) == kVoiceTypeTriangle)
|
||||||
|
//{
|
||||||
|
// nesPitchCorrection = -12;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonalVoice::advanceControlFrame()
|
void TonalVoice::advanceControlFrame()
|
||||||
{
|
{
|
||||||
BaseVoice::advanceControlFrame();
|
BaseVoice::advanceControlFrame();
|
||||||
|
|
||||||
currentPitchSequenceFrame = settingRefs->pitchSequence.nextIndexOf (currentPitchSequenceFrame);
|
//currentPitchSequenceFrame = settingRefs->pitchSequence.nextIndexOf(currentPitchSequenceFrame);
|
||||||
|
|
||||||
|
int currentPitchSequenceFrameTmp = settingRefs->pitchSequence.nextIndexOf(currentPitchSequenceFrame);
|
||||||
|
if (currentPitchSequenceFrameTmp != FrameSequence::SHOULD_RETIRE)
|
||||||
|
{
|
||||||
|
currentPitchSequenceFrame = currentPitchSequenceFrameTmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonalVoice::calculateAngleDelta()
|
void TonalVoice::calculateAngleDelta()
|
||||||
@ -49,6 +61,10 @@ void TonalVoice::calculateAngleDelta()
|
|||||||
{
|
{
|
||||||
switch (settingRefs->pitchSequenceMode())
|
switch (settingRefs->pitchSequenceMode())
|
||||||
{
|
{
|
||||||
|
case kPitchSequenceModeFine16:
|
||||||
|
finePitchInSeq = (double)settingRefs->pitchSequence.valueAt (currentPitchSequenceFrame) / 16.0;
|
||||||
|
break;
|
||||||
|
|
||||||
case kPitchSequenceModeFine:
|
case kPitchSequenceModeFine:
|
||||||
finePitchInSeq = (double)settingRefs->pitchSequence.valueAt (currentPitchSequenceFrame) / 8.0;
|
finePitchInSeq = (double)settingRefs->pitchSequence.valueAt (currentPitchSequenceFrame) / 8.0;
|
||||||
break;
|
break;
|
||||||
@ -69,7 +85,8 @@ void TonalVoice::calculateAngleDelta()
|
|||||||
+ currentBendAmount
|
+ currentBendAmount
|
||||||
+ currentAutoBendAmount
|
+ currentAutoBendAmount
|
||||||
+ vibratoAmount
|
+ vibratoAmount
|
||||||
+ finePitchInSeq;
|
+ finePitchInSeq
|
||||||
|
+ nesPitchCorrection;
|
||||||
|
|
||||||
auto cyclesPerSecond = noteNoToHeltzDouble (noteNoInDouble);
|
auto cyclesPerSecond = noteNoToHeltzDouble (noteNoInDouble);
|
||||||
auto cyclesPerSample = cyclesPerSecond / getSampleRate();
|
auto cyclesPerSample = cyclesPerSecond / getSampleRate();
|
||||||
@ -118,19 +135,41 @@ void TonalVoice::onFrameAdvanced()
|
|||||||
if (autoBendDelta > 0)
|
if (autoBendDelta > 0)
|
||||||
{
|
{
|
||||||
// positive slope
|
// positive slope
|
||||||
if (currentAutoBendAmount > 0)
|
if (currentAutoBendAmount > *(settingRefs->sweepEndPitch))
|
||||||
{
|
{
|
||||||
currentAutoBendAmount = 0;
|
currentAutoBendAmount = *(settingRefs->sweepEndPitch);
|
||||||
autoBendDelta = 0;
|
autoBendDelta = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// negative slope
|
// negative slope
|
||||||
if (currentAutoBendAmount < 0)
|
if (currentAutoBendAmount < *(settingRefs->sweepEndPitch))
|
||||||
{
|
{
|
||||||
currentAutoBendAmount = 0;
|
currentAutoBendAmount = *(settingRefs->sweepEndPitch);
|
||||||
autoBendDelta = 0;
|
autoBendDelta = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void TonalVoice::stopNote(float velocity, bool allowTailOff)
|
||||||
|
{
|
||||||
|
BaseVoice::stopNote(velocity, allowTailOff);
|
||||||
|
|
||||||
|
if (!allowTailOff)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingRefs->isPitchSequenceEnabled())
|
||||||
|
{
|
||||||
|
if (settingRefs->pitchSequence.hasRelease)
|
||||||
|
{
|
||||||
|
if (settingRefs->pitchSequence.isInRelease(currentPitchSequenceFrame)) {
|
||||||
|
// Already in release(Custom Env.)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentPitchSequenceFrame = settingRefs->pitchSequence.releaseSequenceStartIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -36,6 +36,8 @@ struct TonalVoice : public BaseVoice // The base for Pulse and Triangle
|
|||||||
// Custom Pitch/Note states
|
// Custom Pitch/Note states
|
||||||
int currentPitchSequenceFrame = 0;
|
int currentPitchSequenceFrame = 0;
|
||||||
|
|
||||||
|
double nesPitchCorrection = 0;
|
||||||
|
|
||||||
void startNote (int midiNoteNumber, float velocity,
|
void startNote (int midiNoteNumber, float velocity,
|
||||||
SynthesiserSound*, int currentPitchWheelPosition) override;
|
SynthesiserSound*, int currentPitchWheelPosition) override;
|
||||||
void advanceControlFrame() override;
|
void advanceControlFrame() override;
|
||||||
@ -46,4 +48,5 @@ struct TonalVoice : public BaseVoice // The base for Pulse and Triangle
|
|||||||
double noteNoToHeltzDouble (double noteNoInDouble, const double frequencyOfA = 440);
|
double noteNoToHeltzDouble (double noteNoInDouble, const double frequencyOfA = 440);
|
||||||
|
|
||||||
void onFrameAdvanced() override;
|
void onFrameAdvanced() override;
|
||||||
|
void stopNote(float velocity, bool allowTailOff) override;
|
||||||
};
|
};
|
||||||
|
374
Source/WaveformParamsComponent.cpp
Normal file
374
Source/WaveformParamsComponent.cpp
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
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: 6.0.8
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The Projucer is part of the JUCE library.
|
||||||
|
Copyright (c) 2020 - Raw Material Software Limited.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
//[Headers] You can add your own extra header files here...
|
||||||
|
//[/Headers]
|
||||||
|
|
||||||
|
#include "WaveformParamsComponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||||
|
//[/MiscUserDefs]
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
WaveformParamsComponent::WaveformParamsComponent (Magical8bitPlug2AudioProcessor& p)
|
||||||
|
: processor(p)
|
||||||
|
{
|
||||||
|
//[Constructor_pre] You can add your own custom stuff here..
|
||||||
|
//[/Constructor_pre]
|
||||||
|
|
||||||
|
sliderVerticalComponent.reset (new SliderVerticalComponent (p, "waveformWave"));
|
||||||
|
addAndMakeVisible (sliderVerticalComponent.get());
|
||||||
|
sliderVerticalComponent->setName ("slider vertical component");
|
||||||
|
|
||||||
|
sliderVerticalComponent->setBounds (10, 34, 513, 250);
|
||||||
|
|
||||||
|
label.reset (new juce::Label ("label",
|
||||||
|
TRANS("Waveform")));
|
||||||
|
addAndMakeVisible (label.get());
|
||||||
|
label->setFont (juce::Font (17.00f, juce::Font::plain).withTypefaceStyle ("Regular"));
|
||||||
|
label->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
label->setEditable (false, false, false);
|
||||||
|
label->setColour (juce::TextEditor::textColourId, juce::Colours::black);
|
||||||
|
label->setColour (juce::TextEditor::backgroundColourId, juce::Colour (0x00000000));
|
||||||
|
|
||||||
|
label->setBounds (0, 4, 150, 22);
|
||||||
|
|
||||||
|
waveformWaveText.reset (new juce::TextEditor ("waveform wave text"));
|
||||||
|
addAndMakeVisible (waveformWaveText.get());
|
||||||
|
waveformWaveText->setMultiLine (false);
|
||||||
|
waveformWaveText->setReturnKeyStartsNewLine (false);
|
||||||
|
waveformWaveText->setReadOnly (true);
|
||||||
|
waveformWaveText->setScrollbarsShown (false);
|
||||||
|
waveformWaveText->setCaretVisible (false);
|
||||||
|
waveformWaveText->setPopupMenuEnabled (false);
|
||||||
|
waveformWaveText->setText (juce::String());
|
||||||
|
|
||||||
|
waveformWaveText->setBounds (472, 8, 50, 20);
|
||||||
|
|
||||||
|
waveformComboX.reset (new juce::ComboBox ("waveform combo x"));
|
||||||
|
addAndMakeVisible (waveformComboX.get());
|
||||||
|
waveformComboX->setEditableText (false);
|
||||||
|
waveformComboX->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformComboX->setTextWhenNothingSelected (juce::String());
|
||||||
|
waveformComboX->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
|
||||||
|
waveformComboX->addListener (this);
|
||||||
|
|
||||||
|
waveformComboX->setBounds (40, 296, 80, 24);
|
||||||
|
|
||||||
|
waveformXLabel.reset (new juce::Label ("waveform x label",
|
||||||
|
TRANS("X")));
|
||||||
|
addAndMakeVisible (waveformXLabel.get());
|
||||||
|
waveformXLabel->setFont (juce::Font (15.00f, juce::Font::plain).withTypefaceStyle ("Regular"));
|
||||||
|
waveformXLabel->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformXLabel->setEditable (false, false, false);
|
||||||
|
waveformXLabel->setColour (juce::TextEditor::textColourId, juce::Colours::black);
|
||||||
|
waveformXLabel->setColour (juce::TextEditor::backgroundColourId, juce::Colour (0x00000000));
|
||||||
|
|
||||||
|
waveformXLabel->setBounds (16, 296, 24, 24);
|
||||||
|
|
||||||
|
waveformYLabel.reset (new juce::Label ("waveform y label",
|
||||||
|
TRANS("Y")));
|
||||||
|
addAndMakeVisible (waveformYLabel.get());
|
||||||
|
waveformYLabel->setFont (juce::Font (15.00f, juce::Font::plain).withTypefaceStyle ("Regular"));
|
||||||
|
waveformYLabel->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformYLabel->setEditable (false, false, false);
|
||||||
|
waveformYLabel->setColour (juce::TextEditor::textColourId, juce::Colours::black);
|
||||||
|
waveformYLabel->setColour (juce::TextEditor::backgroundColourId, juce::Colour (0x00000000));
|
||||||
|
|
||||||
|
waveformYLabel->setBounds (136, 296, 24, 24);
|
||||||
|
|
||||||
|
waveformComboY.reset (new juce::ComboBox ("waveform combo y"));
|
||||||
|
addAndMakeVisible (waveformComboY.get());
|
||||||
|
waveformComboY->setEditableText (false);
|
||||||
|
waveformComboY->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformComboY->setTextWhenNothingSelected (juce::String());
|
||||||
|
waveformComboY->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
|
||||||
|
waveformComboY->addListener (this);
|
||||||
|
|
||||||
|
waveformComboY->setBounds (160, 296, 80, 24);
|
||||||
|
|
||||||
|
waveformTemplateLabel.reset (new juce::Label ("waveform template label",
|
||||||
|
TRANS("Template")));
|
||||||
|
addAndMakeVisible (waveformTemplateLabel.get());
|
||||||
|
waveformTemplateLabel->setFont (juce::Font (15.00f, juce::Font::plain).withTypefaceStyle ("Regular"));
|
||||||
|
waveformTemplateLabel->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformTemplateLabel->setEditable (false, false, false);
|
||||||
|
waveformTemplateLabel->setColour (juce::TextEditor::textColourId, juce::Colours::black);
|
||||||
|
waveformTemplateLabel->setColour (juce::TextEditor::backgroundColourId, juce::Colour (0x00000000));
|
||||||
|
|
||||||
|
waveformTemplateLabel->setBounds (280, 296, 72, 24);
|
||||||
|
|
||||||
|
waveformComboTemplate.reset (new juce::ComboBox ("waveform combo template"));
|
||||||
|
addAndMakeVisible (waveformComboTemplate.get());
|
||||||
|
waveformComboTemplate->setEditableText (false);
|
||||||
|
waveformComboTemplate->setJustificationType (juce::Justification::centredLeft);
|
||||||
|
waveformComboTemplate->setTextWhenNothingSelected (juce::String());
|
||||||
|
waveformComboTemplate->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
|
||||||
|
waveformComboTemplate->addListener (this);
|
||||||
|
|
||||||
|
waveformComboTemplate->setBounds (352, 296, 168, 24);
|
||||||
|
|
||||||
|
|
||||||
|
//[UserPreSize]
|
||||||
|
//[/UserPreSize]
|
||||||
|
|
||||||
|
setSize (536, 340);
|
||||||
|
|
||||||
|
|
||||||
|
//[Constructor] You can add your own custom stuff here..
|
||||||
|
AudioParameterChoice* cX = (AudioParameterChoice*)p.parameters.getParameter("waveformX");
|
||||||
|
for (int i = 0; i < cX->choices.size(); i++)
|
||||||
|
{
|
||||||
|
String choice = cX->choices[i];
|
||||||
|
waveformComboX->addItem(choice, i + 1);
|
||||||
|
}
|
||||||
|
waveformComboX->setSelectedItemIndex(cX->getIndex());
|
||||||
|
attcX.reset(new ComboBoxAttachment(p.parameters, "waveformX", *waveformComboX));
|
||||||
|
|
||||||
|
AudioParameterChoice* cY = (AudioParameterChoice*)p.parameters.getParameter("waveformY");
|
||||||
|
for (int i = 0; i < cY->choices.size(); i++)
|
||||||
|
{
|
||||||
|
String choice = cY->choices[i];
|
||||||
|
waveformComboY->addItem(choice, i + 1);
|
||||||
|
}
|
||||||
|
waveformComboY->setSelectedItemIndex(cY->getIndex());
|
||||||
|
attcY.reset(new ComboBoxAttachment(p.parameters, "waveformY", *waveformComboY));
|
||||||
|
|
||||||
|
AudioParameterChoice* cTemplate = (AudioParameterChoice*)p.parameters.getParameter("waveformTemplate");
|
||||||
|
for (int i = 0; i < cTemplate->choices.size(); i++)
|
||||||
|
{
|
||||||
|
String choice = cTemplate->choices[i];
|
||||||
|
waveformComboTemplate->addItem(choice, i + 1);
|
||||||
|
}
|
||||||
|
waveformComboTemplate->setSelectedItemIndex(cTemplate->getIndex());
|
||||||
|
attcTemplate.reset(new ComboBoxAttachment(p.parameters, "waveformTemplate", *waveformComboTemplate));
|
||||||
|
|
||||||
|
int fontHeight = waveformWaveText->getFont().getHeight();
|
||||||
|
int topIndent = (waveformWaveText->getHeight() - fontHeight) / 2;
|
||||||
|
int fontWidth = fontHeight;
|
||||||
|
int leftIndent = (waveformWaveText->getWidth() - fontWidth) / 2;
|
||||||
|
waveformWaveText->setBorder(BorderSize<int>(0, 0, 0, 0));
|
||||||
|
waveformWaveText->setIndents(leftIndent, topIndent);
|
||||||
|
//[/Constructor]
|
||||||
|
}
|
||||||
|
|
||||||
|
WaveformParamsComponent::~WaveformParamsComponent()
|
||||||
|
{
|
||||||
|
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||||
|
attcX.reset();
|
||||||
|
attcY.reset();
|
||||||
|
attcTemplate.reset();
|
||||||
|
//[/Destructor_pre]
|
||||||
|
|
||||||
|
sliderVerticalComponent = nullptr;
|
||||||
|
label = nullptr;
|
||||||
|
waveformWaveText = nullptr;
|
||||||
|
waveformComboX = nullptr;
|
||||||
|
waveformXLabel = nullptr;
|
||||||
|
waveformYLabel = nullptr;
|
||||||
|
waveformComboY = nullptr;
|
||||||
|
waveformTemplateLabel = nullptr;
|
||||||
|
waveformComboTemplate = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
//[Destructor]. You can add your own custom destruction code here..
|
||||||
|
//[/Destructor]
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WaveformParamsComponent::paint (juce::Graphics& g)
|
||||||
|
{
|
||||||
|
//[UserPrePaint] Add your own custom painting code here..
|
||||||
|
//[/UserPrePaint]
|
||||||
|
|
||||||
|
//[UserPaint] Add your own custom painting code here..
|
||||||
|
//[/UserPaint]
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveformParamsComponent::resized()
|
||||||
|
{
|
||||||
|
//[UserPreResize] Add your own custom resize code here..
|
||||||
|
//[/UserPreResize]
|
||||||
|
|
||||||
|
//[UserResized] Add your own custom resize handling here..
|
||||||
|
//[/UserResized]
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveformParamsComponent::comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged)
|
||||||
|
{
|
||||||
|
//[UsercomboBoxChanged_Pre]
|
||||||
|
//[/UsercomboBoxChanged_Pre]
|
||||||
|
|
||||||
|
if (comboBoxThatHasChanged == waveformComboX.get())
|
||||||
|
{
|
||||||
|
//[UserComboBoxCode_waveformComboX] -- add your combo box handling code here..
|
||||||
|
sliderVerticalComponent->setForm(processor.settingRefs.getWaveformX(), processor.settingRefs.getWaveformY(), 513, 250);
|
||||||
|
//[/UserComboBoxCode_waveformComboX]
|
||||||
|
}
|
||||||
|
else if (comboBoxThatHasChanged == waveformComboY.get())
|
||||||
|
{
|
||||||
|
//[UserComboBoxCode_waveformComboY] -- add your combo box handling code here..
|
||||||
|
sliderVerticalComponent->setForm(processor.settingRefs.getWaveformX(), processor.settingRefs.getWaveformY(), 513, 250);
|
||||||
|
//[/UserComboBoxCode_waveformComboY]
|
||||||
|
}
|
||||||
|
else if (comboBoxThatHasChanged == waveformComboTemplate.get())
|
||||||
|
{
|
||||||
|
//[UserComboBoxCode_waveformComboTemplate] -- add your combo box handling code here..
|
||||||
|
//0:"Custom", 1:"Sine", 2:"Triangle", 3:"Sawtooth", 4:"Square 6.25%", 5:"Square 18.75%", 6:"Square 31.25%", 7:"Square 37.5%", 8:"Square 43.75%"
|
||||||
|
int x = processor.settingRefs.getWaveformX();
|
||||||
|
int y = processor.settingRefs.getWaveformY();
|
||||||
|
if (waveformComboTemplate->getSelectedItemIndex() == 1)
|
||||||
|
{
|
||||||
|
double twopi = MathConstants<float>::pi * 2.0;
|
||||||
|
for (int i = 0; i < x; i++)
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setValue(i, (int)((std::sin(twopi * i / x) + 1.0) * y / 2.0 + 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (waveformComboTemplate->getSelectedItemIndex() == 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (x / 2); i++)
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setValue(i, (int)(i * (double)y / (x / 2 - 1) + 0.5));
|
||||||
|
sliderVerticalComponent->setValue(i + (x / 2), (int)(y - i * (double)y / (x / 2 - 1) + 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (waveformComboTemplate->getSelectedItemIndex() == 3)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < x; i++)
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setValue(i, (int)(i * (double)y / (x - 1) + 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (waveformComboTemplate->getSelectedItemIndex() >= 4 && waveformComboTemplate->getSelectedItemIndex() <= 8)
|
||||||
|
{
|
||||||
|
double duty[5] = { 0.0625, 0.1875, 0.3125, 0.375, 0.4375 };
|
||||||
|
for (int i = 0; i < (int)(x * duty[waveformComboTemplate->getSelectedItemIndex() - 4]); i++)
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setValue(i, 0);
|
||||||
|
}
|
||||||
|
for (int i = (int)(x * duty[waveformComboTemplate->getSelectedItemIndex() - 4]); i < x; i++)
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setValue(i, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waveformComboTemplate->setSelectedItemIndex(0);
|
||||||
|
//[/UserComboBoxCode_waveformComboTemplate]
|
||||||
|
}
|
||||||
|
|
||||||
|
//[UsercomboBoxChanged_Post]
|
||||||
|
//[/UsercomboBoxChanged_Post]
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveformParamsComponent::mouseDrag (const juce::MouseEvent& e)
|
||||||
|
{
|
||||||
|
//[UserCode_mouseDrag] -- Add your code here...
|
||||||
|
int waveValue = sliderVerticalComponent->waveValue;
|
||||||
|
if (waveValue >= 0)
|
||||||
|
{
|
||||||
|
waveformWaveText->setText(String(waveValue));
|
||||||
|
}
|
||||||
|
//[/UserCode_mouseDrag]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||||
|
void WaveformParamsComponent::sliderRepaint()
|
||||||
|
{
|
||||||
|
sliderVerticalComponent->setForm(processor.settingRefs.getWaveformX(), processor.settingRefs.getWaveformY(), 513, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
//void WaveformParamsComponent::sliderInit()
|
||||||
|
//{
|
||||||
|
// for (int i = 0; i < 64; i++)
|
||||||
|
// {
|
||||||
|
// //sliderVerticalComponent->verticalSliders[i]->setValue(0);
|
||||||
|
// sliderVerticalComponent->verticalSliders[i]->setRange(0, 63, 1);
|
||||||
|
// //sliderVerticalComponent->verticalSliders[i]->repaint();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//[/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="WaveformParamsComponent"
|
||||||
|
componentName="" parentClasses="public Component" constructorParams="Magical8bitPlug2AudioProcessor& p"
|
||||||
|
variableInitialisers="processor(p)" snapPixels="8" snapActive="1"
|
||||||
|
snapShown="1" overlayOpacity="0.330" fixedSize="1" initialWidth="536"
|
||||||
|
initialHeight="340">
|
||||||
|
<METHODS>
|
||||||
|
<METHOD name="mouseDrag (const juce::MouseEvent& e)"/>
|
||||||
|
</METHODS>
|
||||||
|
<BACKGROUND backgroundColour="ffffff"/>
|
||||||
|
<GENERICCOMPONENT name="slider vertical component" id="d3c5ea1dec0891ea" memberName="sliderVerticalComponent"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="10 34 513 250" class="SliderVerticalComponent"
|
||||||
|
params="p, "waveformWave""/>
|
||||||
|
<LABEL name="label" id="bae3132bcad681ce" memberName="label" virtualName=""
|
||||||
|
explicitFocusOrder="0" pos="0 4 150 22" edTextCol="ff000000"
|
||||||
|
edBkgCol="0" labelText="Waveform" editableSingleClick="0" editableDoubleClick="0"
|
||||||
|
focusDiscardsChanges="0" fontname="Default font" fontsize="17.0"
|
||||||
|
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||||
|
<TEXTEDITOR name="waveform wave text" id="a0d4c4fff23ba9a7" memberName="waveformWaveText"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="472 8 50 20" initialText=""
|
||||||
|
multiline="0" retKeyStartsLine="0" readonly="1" scrollbars="0"
|
||||||
|
caret="0" popupmenu="0"/>
|
||||||
|
<COMBOBOX name="waveform combo x" id="47a8fb84e28a923b" memberName="waveformComboX"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="40 296 80 24" editable="0"
|
||||||
|
layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
|
||||||
|
<LABEL name="waveform x label" id="80e4ef8bbf096c16" memberName="waveformXLabel"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="16 296 24 24" edTextCol="ff000000"
|
||||||
|
edBkgCol="0" labelText="X" editableSingleClick="0" editableDoubleClick="0"
|
||||||
|
focusDiscardsChanges="0" fontname="Default font" fontsize="15.0"
|
||||||
|
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||||
|
<LABEL name="waveform y label" id="9d743f56f93330a9" memberName="waveformYLabel"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="136 296 24 24" edTextCol="ff000000"
|
||||||
|
edBkgCol="0" labelText="Y" editableSingleClick="0" editableDoubleClick="0"
|
||||||
|
focusDiscardsChanges="0" fontname="Default font" fontsize="15.0"
|
||||||
|
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||||
|
<COMBOBOX name="waveform combo y" id="519e5c60d0487582" memberName="waveformComboY"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="160 296 80 24" editable="0"
|
||||||
|
layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
|
||||||
|
<LABEL name="waveform template label" id="c0bf04a500a0f7b" memberName="waveformTemplateLabel"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="280 296 72 24" edTextCol="ff000000"
|
||||||
|
edBkgCol="0" labelText="Template" editableSingleClick="0" editableDoubleClick="0"
|
||||||
|
focusDiscardsChanges="0" fontname="Default font" fontsize="15.0"
|
||||||
|
kerning="0.0" bold="0" italic="0" justification="33"/>
|
||||||
|
<COMBOBOX name="waveform combo template" id="a71bba02a0c84649" memberName="waveformComboTemplate"
|
||||||
|
virtualName="" explicitFocusOrder="0" pos="352 296 168 24" editable="0"
|
||||||
|
layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
|
||||||
|
</JUCER_COMPONENT>
|
||||||
|
|
||||||
|
END_JUCER_METADATA
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//[EndFile] You can add extra defines here...
|
||||||
|
//[/EndFile]
|
||||||
|
|
84
Source/WaveformParamsComponent.h
Normal file
84
Source/WaveformParamsComponent.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
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: 6.0.8
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The Projucer is part of the JUCE library.
|
||||||
|
Copyright (c) 2020 - Raw Material Software Limited.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//[Headers] -- You can add your own extra header files here --
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "SliderVerticalComponent.h"
|
||||||
|
//[/Headers]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
//[Comments]
|
||||||
|
An auto-generated component, created by the Projucer.
|
||||||
|
|
||||||
|
Describe your class and how it works here!
|
||||||
|
//[/Comments]
|
||||||
|
*/
|
||||||
|
class WaveformParamsComponent : public Component,
|
||||||
|
public juce::ComboBox::Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
WaveformParamsComponent (Magical8bitPlug2AudioProcessor& p);
|
||||||
|
~WaveformParamsComponent() override;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//[UserMethods] -- You can add your own custom methods in this section.
|
||||||
|
void sliderRepaint();
|
||||||
|
//void sliderInit();
|
||||||
|
//[/UserMethods]
|
||||||
|
|
||||||
|
void paint (juce::Graphics& g) override;
|
||||||
|
void resized() override;
|
||||||
|
void comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged) override;
|
||||||
|
void mouseDrag (const juce::MouseEvent& e) override;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//[UserVariables] -- You can add your own custom variables in this section.
|
||||||
|
Magical8bitPlug2AudioProcessor& processor;
|
||||||
|
std::unique_ptr<ComboBoxAttachment> attcX;
|
||||||
|
std::unique_ptr<ComboBoxAttachment> attcY;
|
||||||
|
std::unique_ptr<ComboBoxAttachment> attcTemplate;
|
||||||
|
//[/UserVariables]
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
std::unique_ptr<SliderVerticalComponent> sliderVerticalComponent;
|
||||||
|
std::unique_ptr<juce::Label> label;
|
||||||
|
std::unique_ptr<juce::TextEditor> waveformWaveText;
|
||||||
|
std::unique_ptr<juce::ComboBox> waveformComboX;
|
||||||
|
std::unique_ptr<juce::Label> waveformXLabel;
|
||||||
|
std::unique_ptr<juce::Label> waveformYLabel;
|
||||||
|
std::unique_ptr<juce::ComboBox> waveformComboY;
|
||||||
|
std::unique_ptr<juce::Label> waveformTemplateLabel;
|
||||||
|
std::unique_ptr<juce::ComboBox> waveformComboTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WaveformParamsComponent)
|
||||||
|
};
|
||||||
|
|
||||||
|
//[EndFile] You can add extra defines here...
|
||||||
|
//[/EndFile]
|
||||||
|
|
39
Source/WaveformVoice.cpp
Normal file
39
Source/WaveformVoice.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
WaveformVoice.cpp
|
||||||
|
Created: 7 Jul 2021 5:57:30am
|
||||||
|
Author: SHACHO
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WaveformVoice.h"
|
||||||
|
|
||||||
|
//---------------------------------------------
|
||||||
|
//
|
||||||
|
// Waveform Voice
|
||||||
|
//
|
||||||
|
//---------------------------------------------
|
||||||
|
WaveformVoice::WaveformVoice(SettingRefs* sRefs) : TonalVoice(sRefs) {}
|
||||||
|
|
||||||
|
float WaveformVoice::voltageForAngle(double angle)
|
||||||
|
{
|
||||||
|
int x = settingRefs->getWaveformX();
|
||||||
|
int y = 63; // settingRefs->getWaveformY();
|
||||||
|
|
||||||
|
float sequence[64];
|
||||||
|
|
||||||
|
for (int i = 0; i < x; i++)
|
||||||
|
{
|
||||||
|
sequence[i] = *(settingRefs->waveformWave[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
double twopi = MathConstants<float>::pi * 2.0;
|
||||||
|
int step = (int)(x * angle / twopi);
|
||||||
|
|
||||||
|
float level = sequence[step];
|
||||||
|
float output = (float)level / (y / 2.0f) - 1.0f;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
18
Source/WaveformVoice.h
Normal file
18
Source/WaveformVoice.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
WaveformVoice.h
|
||||||
|
Created: 7 Jul 2021 5:57:30am
|
||||||
|
Author: SHACHO
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "TonalVoice.h"
|
||||||
|
|
||||||
|
struct WaveformVoice : public TonalVoice
|
||||||
|
{
|
||||||
|
WaveformVoice(SettingRefs* sRefs);
|
||||||
|
float voltageForAngle(double angle) override;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user