chore: land janitor round 1 and graft integration
Round 1 findings and fixes, all previously uncommitted: - FXProcessor per-slot DSP history repair (HEAD does not compile without it) - SynthVoice::getModulationValue, editor control-lock guard - ExactCompare.h naming the deliberate exact float comparisons - KnobLookAndFeel replacing the never-installed SerumLookAndFeel - 55 first-party compiler warnings to 0 - AGENT.md renamed to AGENTS.md across Source/ - graft repository context graph and its hooks - JANITOR_TASKS.md and UI_UX_AUDIT.md records
This commit is contained in:
1 parent
5c942cad0c
commit
e4cea300db
63 files changed
+2360
-805
No files matched your search
+29
-33
@@ -1,52 +1,28 @@
|
||||
#include "LFODisplay.h"
|
||||
#include "../ExactCompare.h"
|
||||
|
||||
namespace serum
|
||||
{
|
||||
|
||||
void LFODisplay::setShapeData (const std::vector<float>& data, int s)
|
||||
{
|
||||
const int newSteps = juce::jlimit (2, 64, s);
|
||||
const size_t dataSize = std::min (data.size(), size_t (64));
|
||||
if (steps == newSteps && shapeData.size() == 64
|
||||
const int newSteps = juce::jlimit (2, LFO::kShapePoints, s);
|
||||
const auto dataSize = (std::ptrdiff_t) std::min (data.size(), size_t (LFO::kShapePoints));
|
||||
if (steps == newSteps && (int) shapeData.size() == LFO::kShapePoints
|
||||
&& std::equal (data.begin(), data.begin() + dataSize, shapeData.begin())
|
||||
&& std::all_of (shapeData.begin() + dataSize, shapeData.end(), [] (float v) { return v == 0.0f; }))
|
||||
&& std::all_of (shapeData.begin() + dataSize, shapeData.end(), [] (float v) { return exactly (v, 0.0f); }))
|
||||
return;
|
||||
|
||||
steps = newSteps;
|
||||
shapeData.assign (data.begin(), data.begin() + dataSize);
|
||||
shapeData.resize (64, 0.0f);
|
||||
shapeData.resize ((size_t) LFO::kShapePoints, 0.0f);
|
||||
repaint();
|
||||
}
|
||||
|
||||
float LFODisplay::valueAt (float phase) const noexcept
|
||||
{
|
||||
switch ((LfoShape) shape)
|
||||
{
|
||||
case LfoShape::Sine: return std::sin (phase * 6.2831853f);
|
||||
case LfoShape::Triangle: return 1.0f - 4.0f * std::abs (phase - 0.5f);
|
||||
case LfoShape::Saw: return 2.0f * phase - 1.0f;
|
||||
case LfoShape::Square: return (phase < 0.5f) ? 1.0f : -1.0f;
|
||||
case LfoShape::SampleHold:
|
||||
{
|
||||
const int step = juce::jlimit (0, 15, (int) (phase * 16.0f));
|
||||
return ((step * 2654435761u) & 0xffffu) / 32768.0f - 1.0f;
|
||||
}
|
||||
case LfoShape::StepSeq:
|
||||
{
|
||||
const int idx = juce::jlimit (0, steps - 1, (int) (phase * steps));
|
||||
return shapeData.empty() ? 0.0f : shapeData[(size_t) idx];
|
||||
}
|
||||
case LfoShape::Freehand:
|
||||
{
|
||||
if (shapeData.empty()) return 0.0f;
|
||||
const float pos = phase * (float) (steps - 1);
|
||||
const int i0 = (int) pos;
|
||||
const int i1 = juce::jmin (i0 + 1, steps - 1);
|
||||
const float frac = pos - (float) i0;
|
||||
return shapeData[(size_t) i0] * (1.0f - frac) + shapeData[(size_t) i1] * frac;
|
||||
}
|
||||
default: return 0.0f;
|
||||
}
|
||||
return lfoShapeValue (phase, (LfoShape) shape, steps,
|
||||
shapeData.data(), (int) shapeData.size(), kSampleHoldLevel);
|
||||
}
|
||||
|
||||
void LFODisplay::paint (juce::Graphics& g)
|
||||
@@ -75,6 +51,26 @@ void LFODisplay::paint (juce::Graphics& g)
|
||||
}
|
||||
}
|
||||
|
||||
// Sample and hold is stateful in the audio path, so the preview draws the
|
||||
// held level as a flat schematic with its hold steps marked, and labels it,
|
||||
// rather than inventing a sequence the synth will never play.
|
||||
if (shape == (int) LfoShape::SampleHold)
|
||||
{
|
||||
const float stepW = (b.getWidth() - 8.0f) / (float) steps;
|
||||
g.setColour (theme::outline);
|
||||
for (int i = 1; i < steps; ++i)
|
||||
{
|
||||
const float x = b.getX() + 4.0f + stepW * (float) i;
|
||||
g.drawLine (x, midY - b.getHeight() * 0.28f, x, midY + b.getHeight() * 0.28f, 1.0f);
|
||||
}
|
||||
|
||||
g.setColour (theme::textDim);
|
||||
g.setFont (10.0f);
|
||||
g.drawText ("S&H schematic",
|
||||
juce::Rectangle<float> (b.getX(), b.getY(), b.getWidth(), 14.0f).toNearestInt(),
|
||||
juce::Justification::centred, false);
|
||||
}
|
||||
|
||||
juce::Path path;
|
||||
path.startNewSubPath (b.getX() + 4.0f, midY);
|
||||
const int n = 256;
|
||||
@@ -99,7 +95,7 @@ void LFODisplay::editAt (float x, float y)
|
||||
const float v = juce::jlimit (-1.0f, 1.0f, (midY - y) / (b.getHeight() * 0.42f));
|
||||
|
||||
if (shapeData.empty())
|
||||
shapeData.assign (64, 0.0f);
|
||||
shapeData.assign ((size_t) LFO::kShapePoints, 0.0f);
|
||||
|
||||
if (shape == (int) LfoShape::StepSeq)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user