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

+30 -31
View File
@@ -33,17 +33,18 @@ FXProcessor::~FXProcessor() = default;
void FXProcessor::prepare (double sampleRate, int maxBlockSize)
{
for (auto& slotUnits : units)
for (auto& u : slotUnits)
u->prepare (sampleRate, maxBlockSize);
for (auto& unit : slotUnits)
unit->prepare (sampleRate, maxBlockSize);
wet.setSize (2, maxBlockSize, false, false, true);
reset();
}
void FXProcessor::reset()
{
for (auto& u : units)
u->reset();
dry.clear();
for (auto& slotUnits : units)
for (auto& unit : slotUnits)
unit->reset();
activeTypes.fill ((int) FxType::Off);
wet.clear();
}
@@ -61,52 +62,50 @@ juce::String FXProcessor::fxTypeName (int type)
case FxType::Compressor: return "Compressor";
case FxType::Delay: return "Delay";
case FxType::Reverb: return "Reverb";
case FxType::Count: return {};
default: return {};
}
}
void FXProcessor::process (juce::AudioBuffer<float>& buffer, const FxSlotParams* slots, int numSlots)
{
// The rack is stereo end to end; a mono buffer would read a channel that is not there.
jassert (buffer.getNumChannels() >= 2);
if (buffer.getNumChannels() < 2)
return;
const int n = buffer.getNumSamples();
jassert (n <= wet.getNumSamples());
if (n <= 0)
return;
for (int s = 0; s < numSlots; ++s)
for (int s = 0; s < juce::jmin (numSlots, kNumFxSlots); ++s)
{
const FxSlotParams& slot = slots[s];
if (slot.type == (int) FxType::Off)
continue;
const int unitIdx = slot.type - 1;
if (unitIdx < 0 || unitIdx >= (int) units.size())
if (unitIdx < 0 || unitIdx >= kNumEffectTypes)
{
activeTypes[(size_t) s] = (int) FxType::Off;
continue;
}
dry.copyFrom (0, 0, buffer, 0, 0, n);
dry.copyFrom (1, 1, buffer, 1, 0, n);
auto& unit = *units[(size_t) s][(size_t) unitIdx];
if (activeTypes[(size_t) s] != slot.type)
{
unit.reset();
activeTypes[(size_t) s] = slot.type;
}
wet.copyFrom (0, 0, buffer, 0, 0, n);
wet.copyFrom (1, 1, buffer, 1, 0, n);
units[(size_t) unitIdx]->process (wet.getWritePointer (0), wet.getWritePointer (1), n, slot.p);
wet.copyFrom (1, 0, buffer, 1, 0, n);
unit.process (wet.getWritePointer (0), wet.getWritePointer (1), n, slot.p);
const float mix = juce::jlimit (0.0f, 1.0f, slot.mix);
if (mix >= 1.0f)
for (int ch = 0; ch < 2; ++ch)
{
buffer.copyFrom (0, 0, wet, 0, 0, n);
buffer.copyFrom (1, 0, wet, 1, 0, n);
}
else if (mix > 0.0f)
{
const float* dL = dry.getReadPointer (0);
const float* dR = dry.getReadPointer (1);
const float* wL = wet.getReadPointer (0);
const float* wR = wet.getReadPointer (1);
float* oL = buffer.getWritePointer (0);
float* oR = buffer.getWritePointer (1);
float* out = buffer.getWritePointer (ch);
const float* effect = wet.getReadPointer (ch);
for (int i = 0; i < n; ++i)
{
oL[i] = dL[i] * (1.0f - mix) + wL[i] * mix;
oR[i] = dR[i] * (1.0f - mix) + wR[i] * mix;
}
out[i] = out[i] * (1.0f - mix) + effect[i] * mix;
}
}
}