Skip to content

Commit

Permalink
MSeg improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
FigBug committed Feb 4, 2024
1 parent b04decf commit b4c2f1f
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 48 deletions.
1 change: 1 addition & 0 deletions modules/gin_dsp/dsp/gin_lfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class LFO
float newCurPhase = std::fmod (phase + parameters.phase, maxPhase);
if (newCurPhase < 0)
newCurPhase += maxPhase;
curPhase = newCurPhase;

updateCurrentValue();
}
Expand Down
56 changes: 32 additions & 24 deletions modules/gin_dsp/dsp/gin_mseg.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,20 @@ class MSEG
juce::Array<Point> points;
int numPoints = 0;
int maxPoints = 50;
int startIndex = 0;
int endIndex = 2;

void toValueTree (juce::ValueTree v)
{
v.removeAllChildren (nullptr);
v.setProperty ("startIndex", startIndex, nullptr);
v.setProperty ("endIndex", endIndex, nullptr);

for (auto i = 0; i < numPoints; i++)
{
juce::ValueTree c (juce::Identifier ("PT"));

c.setProperty ("t", points[i].time, nullptr);
c.setProperty ("t", points[i].time, nullptr);
c.setProperty ("v", points[i].value, nullptr);
c.setProperty ("c", points[i].curve, nullptr);

Expand All @@ -59,7 +63,10 @@ class MSEG
return;
}

numPoints = v.getNumChildren();
numPoints = v.getNumChildren();
startIndex = v.getProperty ("startIndex");
endIndex = v.getProperty ("endIndex");


int i = 0;
for (auto c : v)
Expand All @@ -68,6 +75,7 @@ class MSEG
p.time = c.getProperty ("t");
p.value = c.getProperty ("v");
p.curve = c.getProperty ("c");

i++;
}
}
Expand All @@ -77,7 +85,10 @@ class MSEG
points.set (0, { 0.0f, 0.0f, 5.5f });
points.set (1, { 0.5f, 1.0f, 5.5f });
points.set (2, { 1.0f, 0.0f, 5.5f });
numPoints = 3;

numPoints = 3;
startIndex = 0;
endIndex = 2;
}
};

Expand All @@ -103,7 +114,6 @@ class MSEG
{
output = 0.0f;
phase = 0.0f;
curPhase = 0.0f;
curFade = 1.0f;
fadeDelta = 0.0f;
delaySteps = 0;
Expand All @@ -123,15 +133,10 @@ class MSEG
else
curFade = 0.0f;

curPhase = 0.0f;
phase = phase_ < 0.0f ? 0.0f : phase_;
phase = phase_ < 0.0f ? parameters.phase : phase_;
fadeDelta = float (1.0f / (sampleRate * parameters.fade));
delaySteps = juce::roundToInt (sampleRate * parameters.delay);

float maxPhase = 1.0f;
float newCurPhase = std::fmod (phase + parameters.phase, maxPhase);
if (newCurPhase < 0) newCurPhase += maxPhase;

updateCurrentValue();
}

Expand All @@ -153,26 +158,29 @@ class MSEG
{
curFade = juce::jlimit (0.0f, 1.0f, curFade + fadeDelta);

float maxPhase = 1.0f;

phase += step;

if (parameters.loop)
{
while (phase >= maxPhase)
phase -= maxPhase;
auto pStart = data.points[data.startIndex].time;
auto pEnd = data.points[data.endIndex].time;

if (pEnd - pStart < 0.0001)
{
if (phase > pEnd)
phase = pEnd;
}
else
{
while (phase >= pEnd)
phase -= pEnd - pStart;
}
}
else
{
if (phase >= maxPhase)
if (phase >= 1.0f)
phase = 1.0f;
}

float newCurPhase = std::fmod (phase + parameters.phase, maxPhase);
if (newCurPhase < 0)
newCurPhase += maxPhase;

curPhase = newCurPhase;
}
}

Expand Down Expand Up @@ -221,11 +229,11 @@ class MSEG
const auto& p1 = data.points.getReference (i + 0);
const auto& p2 = data.points.getReference (i + 1);

if (curPhase >= p1.time && curPhase < p2.time)
if (phase >= p1.time && phase < p2.time)
{
auto dy = p2.value - p1.value;
auto dx = p2.time - p1.time;
auto fr = (dx > 0.0f) ? ((curPhase - p1.time) / dx) : 1.0f;
auto fr = (dx > 0.0f) ? ((phase - p1.time) / dx) : 1.0f;

output = dy * curve (fr, p1.curve) + p1.value;
break;
Expand All @@ -247,6 +255,6 @@ class MSEG
Parameters parameters;

double sampleRate = 0.0;
float phase = 0.0f, curPhase = 0.0f, output = 0.0f, fadeDelta = 0.0f, curFade = 1.0f;
float phase = 0.0f, output = 0.0f, fadeDelta = 0.0f, curFade = 1.0f;
int delaySteps = 0;
};
85 changes: 65 additions & 20 deletions modules/gin_plugin/components/gin_msegcomponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void MSEGComponent::resized()
void MSEGComponent::setParams (Parameter::Ptr wave_, Parameter::Ptr sync_, Parameter::Ptr rate_,
Parameter::Ptr beat_, Parameter::Ptr depth_, Parameter::Ptr offset_,
Parameter::Ptr phase_, Parameter::Ptr enable_, Parameter::Ptr xgrid_,
Parameter::Ptr ygrid_)
Parameter::Ptr ygrid_, Parameter::Ptr loop_)
{
unwatchParams();

Expand All @@ -26,6 +26,7 @@ void MSEGComponent::setParams (Parameter::Ptr wave_, Parameter::Ptr sync_, Param
watchParam (enable = enable_);
watchParam (xgrid = xgrid_);
watchParam (ygrid = ygrid_);
watchParam (loop = loop_);

startTimerHz (30);
}
Expand All @@ -38,7 +39,7 @@ void MSEGComponent::paramChanged ()

void MSEGComponent::createPath (juce::Rectangle<float> area)
{
mseg.setSampleRate ((double) area.getWidth());
mseg.setSampleRate (44100.0);

MSEG::Parameters p;
p.frequency = 1.0f;
Expand All @@ -59,25 +60,25 @@ void MSEGComponent::createPath (juce::Rectangle<float> area)
mseg.setParameters (p);
mseg.reset();

curve.clear();
path.clear();

for (int x = int (area.getX()); x <= area.getRight(); x++)
path.startNewSubPath (timeToX (0), valueToY (data.points[0].value));

for (auto i = 0; i < data.numPoints - 1; i++)
{
auto v = mseg.process (1);
auto p1 = data.points[i + 0];
auto p2 = data.points[i + 1];

if (x == int (area.getX()))
path.startNewSubPath ({float (area.getX()), valueToY (v)});
else
path.lineTo ({float (x), valueToY (v)});
for (auto x = timeToX (p1.time); x < timeToX (p2.time); x++)
path.lineTo ({x, valueToY (mseg.getValueAt (xToTime (x))) });

curve[x - int (area.getX())] = valueToY (v);
path.lineTo ({timeToX (p2.time), valueToY (p2.value) });
}
}

void MSEGComponent::paint (juce::Graphics& g)
{
auto rc = getLocalBounds().toFloat().reduced (2);
auto rc = getArea();

if (dirty)
{
Expand All @@ -89,6 +90,7 @@ void MSEGComponent::paint (juce::Graphics& g)

juce::RectangleList<float> rects;

// Draw grid
if (editable)
{
for (int i = 0; i <= ygrid->getUserValueInt(); i++)
Expand All @@ -111,32 +113,35 @@ void MSEGComponent::paint (juce::Graphics& g)

if (isEnabled())
{
auto lerp = [] (float t, float a, float b) { return a + t * (b - a); };

for (auto curPhase : curPhases)
{
float x = curPhase * rc.getWidth();
float t = x - int (x);
float y = lerp (t, curve[int(x)], curve[int(x) + 1]);
float x = timeToX (curPhase);
float y = valueToY (mseg.getValueAt (curPhase));

g.setColour (dimIfNeeded (findColour (GinLookAndFeel::whiteColourId).withAlpha (0.9f)));
g.fillEllipse (rc.getX() + x - 2, y - 2, 4, 4);
g.fillEllipse (x - 2, y - 2, 4, 4);
}
}

if (editable && isMouseOverOrDragging())
if (editable)
{
for (auto i = 0; i < data.numPoints; i++)
{
auto r = juce::Rectangle (timeToX (data.points[i].time) - 2.0f, valueToY (data.points[i].value) - 2.0f, 4.0f, 4.0f);
auto r = juce::Rectangle (timeToX (data.points[i].time) - 2.5f, valueToY (data.points[i].value) - 2.5f, 5.0f, 5.0f);

if (draggingPoint == i || getPointAt (getMouseXYRelative().toFloat()) == i)
{
g.setColour (dimIfNeeded (juce::Colours::white).withAlpha (0.3f));
g.fillEllipse (r.expanded (4));
}

g.setColour (dimIfNeeded (findColour (GinLookAndFeel::accentColourId).withAlpha (0.7f)));
if (loop->getUserValueInt() == 1 && i == data.startIndex)
g.setColour (dimIfNeeded (juce::Colours::green).withAlpha (1.0f));
else if (loop->getUserValueInt() == 1 && i == data.endIndex)
g.setColour (dimIfNeeded (juce::Colours::red).withAlpha (1.0f));
else
g.setColour (dimIfNeeded (findColour (GinLookAndFeel::accentColourId).withAlpha (0.7f)));

g.fillEllipse (r);
}

Expand Down Expand Up @@ -245,6 +250,12 @@ void MSEGComponent::mouseDown (const juce::MouseEvent& e)

data.numPoints--;

if (data.startIndex >= draggingPoint)
data.startIndex = std::max (0, data.startIndex - 1);

if (data.endIndex >= draggingPoint)
data.endIndex = std::max (1, data.startIndex - 1);

dirty = true;
repaint();
}
Expand All @@ -270,6 +281,12 @@ void MSEGComponent::mouseDown (const juce::MouseEvent& e)
data.points.getReference (i + 1) = { t, v, 0.0f };
data.numPoints++;

if (data.startIndex >= i + 1)
data.startIndex++;

if (data.endIndex >= i + 1)
data.endIndex++;

break;
}
}
Expand Down Expand Up @@ -376,6 +393,34 @@ void MSEGComponent::mouseUp (const juce::MouseEvent& e)
if (! editable)
return;

if (e.mods.isPopupMenu())
{
if (draggingPoint >= 0 && loop->getUserValueInt() == 1)
{
juce::PopupMenu m;
m.addItem ("Set Loop Start", draggingPoint < data.numPoints - 1, false, [this, dp = draggingPoint]
{
data.startIndex = dp;

if (data.endIndex <= dp)
data.endIndex = dp + 1;

repaint();
});
m.addItem ("Set Loop End", draggingPoint > 0, false, [this, dp = draggingPoint]
{
data.endIndex = dp;

if (data.startIndex >= dp)
data.startIndex = dp - 1;

repaint();
});

m.showMenuAsync ({});
}
}

draggingPoint = -1;
draggingCurve = -1;
repaint ();
Expand Down
7 changes: 3 additions & 4 deletions modules/gin_plugin/components/gin_msegcomponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class MSEGComponent : public MultiParamComponent,
void setParams (Parameter::Ptr wave, Parameter::Ptr sync, Parameter::Ptr rate,
Parameter::Ptr beat, Parameter::Ptr depth, Parameter::Ptr offset,
Parameter::Ptr phase, Parameter::Ptr enable, Parameter::Ptr xgrid,
Parameter::Ptr ygrid);
Parameter::Ptr ygrid, Parameter::Ptr loop);

void setEditable (bool e) { editable = e; }

Expand Down Expand Up @@ -43,23 +43,22 @@ class MSEGComponent : public MultiParamComponent,
void createPath (juce::Rectangle<float> area);
float getSample (float phase);

Parameter::Ptr wave, sync, rate, beat, depth, offset, phase, enable, xgrid, ygrid;
Parameter::Ptr wave, sync, rate, beat, depth, offset, phase, enable, xgrid, ygrid, loop;

MSEG::Data& data;
MSEG mseg {data};

juce::Path path;
bool dirty = true;
std::vector<float> curPhases;
std::map<int,float> curve;

int draggingPoint = -1;
int draggingCurve = -1;

float lastY = 0.0f;
bool editable = false;

juce::Rectangle<float> getArea() { return getLocalBounds().toFloat().reduced (2.0f); }
juce::Rectangle<float> getArea() { return getLocalBounds().toFloat().reduced (editable ? 4.0f : 2.0f); }

int getPointAt (juce::Point<float> p);
int getCurveAt (juce::Point<float> p);
Expand Down

0 comments on commit b4c2f1f

Please sign in to comment.