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:
biggy committed 2026-10-06 08:50:45 +02:00
1 parent 5c942cad0c
commit e4cea300db
63 files changed
+2360 -805

No files matched your search

+39 -39
View File
@@ -1,6 +1,7 @@
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "Presets/FactoryPresets.h"
#include "ExactCompare.h"
namespace serum
{
@@ -98,12 +99,12 @@ juce::AudioProcessorValueTreeState::ParameterLayout SerumAltAudioProcessor::crea
params.push_back (f (ids::fMix, "Filter Mix", 0.5f));
params.push_back (f (ids::fOut, "Filter Out", 0.667f));
// Envelopes 1..4
const char* envA[4] = { ids::env1A, ids::env2A, ids::env3A, ids::env4A };
const char* envD[4] = { ids::env1D, ids::env2D, ids::env3D, ids::env4D };
const char* envS[4] = { ids::env1S, ids::env2S, ids::env3S, ids::env4S };
const char* envR[4] = { ids::env1R, ids::env2R, ids::env3R, ids::env4R };
const char* envC[4] = { ids::env1Curve, ids::env2Curve, ids::env3Curve, ids::env4Curve };
// Envelopes 1..4 (IDs come from the shared paramIds groups)
constexpr auto& envA = paramIds::envAttack;
constexpr auto& envD = paramIds::envDecay;
constexpr auto& envS = paramIds::envSustain;
constexpr auto& envR = paramIds::envRelease;
constexpr auto& envC = paramIds::envCurve;
const float envADef[4] = { 0.05f, 0.1f, 0.2f, 0.2f };
const float envDDef[4] = { 0.25f, 0.3f, 0.3f, 0.3f };
const float envSDef[4] = { 0.8f, 0.5f, 0.5f, 0.5f };
@@ -117,14 +118,14 @@ juce::AudioProcessorValueTreeState::ParameterLayout SerumAltAudioProcessor::crea
params.push_back (f (envC[i], juce::String ("Env ") + juce::String (i + 1) + " Curve", 0.5f));
}
// LFOs 1..4
const char* lfoRate[4] = { ids::lfo1Rate, ids::lfo2Rate, ids::lfo3Rate, ids::lfo4Rate };
const char* lfoSync[4] = { ids::lfo1Sync, ids::lfo2Sync, ids::lfo3Sync, ids::lfo4Sync };
const char* lfoBeat[4] = { ids::lfo1Beat, ids::lfo2Beat, ids::lfo3Beat, ids::lfo4Beat };
const char* lfoShape[4] = { ids::lfo1Shape, ids::lfo2Shape, ids::lfo3Shape, ids::lfo4Shape };
const char* lfoPhase[4] = { ids::lfo1Phase, ids::lfo2Phase, ids::lfo3Phase, ids::lfo4Phase };
const char* lfoFade[4] = { ids::lfo1Fade, ids::lfo2Fade, ids::lfo3Fade, ids::lfo4Fade };
const char* lfoDelay[4] = { ids::lfo1Delay, ids::lfo2Delay, ids::lfo3Delay, ids::lfo4Delay };
// LFOs 1..4 (IDs come from the shared paramIds groups)
constexpr auto& lfoRate = paramIds::lfoRate;
constexpr auto& lfoSync = paramIds::lfoSync;
constexpr auto& lfoBeat = paramIds::lfoBeat;
constexpr auto& lfoShape = paramIds::lfoShape;
constexpr auto& lfoPhase = paramIds::lfoPhase;
constexpr auto& lfoFade = paramIds::lfoFade;
constexpr auto& lfoDelay = paramIds::lfoDelay;
const float lfoShapeDef[4] = { 0.0f, 1.0f / 6.0f, 2.0f / 6.0f, 3.0f / 6.0f };
for (int i = 0; i < 4; ++i)
{
@@ -138,37 +139,31 @@ juce::AudioProcessorValueTreeState::ParameterLayout SerumAltAudioProcessor::crea
params.push_back (f (lfoDelay[i], n + " Delay", 0.0f));
}
// FX slots 1..8
const char* fxType[8] = { ids::fx1Type, ids::fx2Type, ids::fx3Type, ids::fx4Type,
ids::fx5Type, ids::fx6Type, ids::fx7Type, ids::fx8Type };
const char* fxMix[8] = { ids::fx1Mix, ids::fx2Mix, ids::fx3Mix, ids::fx4Mix,
ids::fx5Mix, ids::fx6Mix, ids::fx7Mix, ids::fx8Mix };
const char* fxP[8][4] = {
{ ids::fx1P1, ids::fx1P2, ids::fx1P3, ids::fx1P4 },
{ ids::fx2P1, ids::fx2P2, ids::fx2P3, ids::fx2P4 },
{ ids::fx3P1, ids::fx3P2, ids::fx3P3, ids::fx3P4 },
{ ids::fx4P1, ids::fx4P2, ids::fx4P3, ids::fx4P4 },
{ ids::fx5P1, ids::fx5P2, ids::fx5P3, ids::fx5P4 },
{ ids::fx6P1, ids::fx6P2, ids::fx6P3, ids::fx6P4 },
{ ids::fx7P1, ids::fx7P2, ids::fx7P3, ids::fx7P4 },
{ ids::fx8P1, ids::fx8P2, ids::fx8P3, ids::fx8P4 }
};
// FX slots 1..8 (IDs come from the shared paramIds groups)
constexpr auto& fxType = paramIds::fxType;
constexpr auto& fxMix = paramIds::fxMix;
const char* const fxP[4][8] = { { paramIds::fxP1[0], paramIds::fxP1[1], paramIds::fxP1[2], paramIds::fxP1[3],
paramIds::fxP1[4], paramIds::fxP1[5], paramIds::fxP1[6], paramIds::fxP1[7] },
{ paramIds::fxP2[0], paramIds::fxP2[1], paramIds::fxP2[2], paramIds::fxP2[3],
paramIds::fxP2[4], paramIds::fxP2[5], paramIds::fxP2[6], paramIds::fxP2[7] },
{ paramIds::fxP3[0], paramIds::fxP3[1], paramIds::fxP3[2], paramIds::fxP3[3],
paramIds::fxP3[4], paramIds::fxP3[5], paramIds::fxP3[6], paramIds::fxP3[7] },
{ paramIds::fxP4[0], paramIds::fxP4[1], paramIds::fxP4[2], paramIds::fxP4[3],
paramIds::fxP4[4], paramIds::fxP4[5], paramIds::fxP4[6], paramIds::fxP4[7] } };
for (int i = 0; i < 8; ++i)
{
const juce::String n = juce::String ("FX ") + juce::String (i + 1);
params.push_back (f (fxType[i], n + " Type", 0.0f));
params.push_back (f (fxMix[i], n + " Mix", 0.5f));
params.push_back (f (fxP[i][0], n + " P1", 0.5f));
params.push_back (f (fxP[i][1], n + " P2", 0.5f));
params.push_back (f (fxP[i][2], n + " P3", 0.5f));
params.push_back (f (fxP[i][3], n + " P4", 0.5f));
params.push_back (f (fxP[0][i], n + " P1", 0.5f));
params.push_back (f (fxP[1][i], n + " P2", 0.5f));
params.push_back (f (fxP[2][i], n + " P3", 0.5f));
params.push_back (f (fxP[3][i], n + " P4", 0.5f));
}
// Macros
params.push_back (f (ids::macro1, "Macro 1", 0.0f));
params.push_back (f (ids::macro2, "Macro 2", 0.0f));
params.push_back (f (ids::macro3, "Macro 3", 0.0f));
params.push_back (f (ids::macro4, "Macro 4", 0.0f));
// Macros (display names come from MacroControls::macroName, the single source)
for (int i = 0; i < kNumMacros; ++i)
params.push_back (f (paramIds::macros[i], MacroControls::macroName (i), 0.0f));
return { params.begin(), params.end() };
}
@@ -266,6 +261,9 @@ void SerumAltAudioProcessor::loadFactoryPreset (int index)
continue;
restoreLfoShapesFromState ({});
// A preset starts from clean DSP state, so the previous preset's filter,
// delay and reverb tails cannot bleed into the new one.
engine.requestReset();
currentProgram.store (index);
}
@@ -356,6 +354,8 @@ void SerumAltAudioProcessor::setStateInformation (const void* data, int sizeInBy
engine.getMatrix().fromValueTree (state.getChildWithName ("MODMATRIX"));
engine.getMacros().fromValueTree (state.getChildWithName ("MACROS"));
restoreLfoShapesFromState (state);
// Loading a saved project is a patch change too: start from clean state.
engine.requestReset();
const double savedProgram = (double) state.getProperty ("currentProgram", 0);
currentProgram.store (std::isfinite (savedProgram)
@@ -406,7 +406,7 @@ void SerumAltAudioProcessor::restoreLfoShapesFromState (const juce::ValueTree& s
continue;
const double savedIndex = (double) lfo.getProperty ("index", -1);
if (! std::isfinite (savedIndex) || savedIndex < 0.0 || savedIndex >= kNumLfos
|| std::floor (savedIndex) != savedIndex)
|| ! isWholeNumber (savedIndex))
continue;
const int index = (int) savedIndex;
if (restored[(size_t) index])