Add delay/reverb dry-wet, granular randomize toggles, rework accent DSP

- Add delay and reverb Dry/Wet parameters and knobs, wired into presets
- Add Accent/Slide/Fine/Rate toggles to the Randomize panel with new
  per-aspect pattern randomizers
- Soften accent: modest volume lift plus small cutoff and filter-attack
  modulation instead of the heavy 5x gain boost
- Halve reverb comb/allpass delays so the wet speaks sooner
- Regenerate a fresh build stamp on every build
This commit is contained in:
Armin 2026-08-06 18:38:32 +02:00
commit 662a1f7383
11 changed files with 310 additions and 97 deletions

View file

@ -14,8 +14,8 @@ static const char* paramId (int index)
"drive", "ringmod", "accent", "fine1",
"filterAttack", "filterDecay", "filterSustain", "filterRelease", "filterEnvAmt",
"seqRetrig",
"delayTime", "delayStrength", "delaySync",
"reverbRoom", "reverbStrength", "reverbDiffusion"
"delayTime", "delayStrength", "delaySync", "delayDryWet",
"reverbRoom", "reverbStrength", "reverbDiffusion", "reverbDryWet"
};
return ids[index];
}
@ -28,8 +28,8 @@ enum ParamIndex
pDrive, pRingMod, pAccent, pFine1,
pFilterAttack, pFilterDecay, pFilterSustain, pFilterRelease, pFilterEnvAmt,
pSeqRetrig,
pDelayTime, pDelayStrength, pDelaySync,
pReverbRoom, pReverbStrength, pReverbDiffusion,
pDelayTime, pDelayStrength, pDelaySync, pDelayDryWet,
pReverbRoom, pReverbStrength, pReverbDiffusion, pReverbDryWet,
numParams
};
@ -72,9 +72,11 @@ MonostepAudioProcessor::MonostepAudioProcessor()
delayTimeParam = apvts.getRawParameterValue (paramId (pDelayTime));
delayStrengthParam = apvts.getRawParameterValue (paramId (pDelayStrength));
delaySyncParam = apvts.getRawParameterValue (paramId (pDelaySync));
delayDryWetParam = apvts.getRawParameterValue (paramId (pDelayDryWet));
reverbRoomParam = apvts.getRawParameterValue (paramId (pReverbRoom));
reverbStrengthParam = apvts.getRawParameterValue (paramId (pReverbStrength));
reverbDiffusionParam = apvts.getRawParameterValue (paramId (pReverbDiffusion));
reverbDryWetParam = apvts.getRawParameterValue (paramId (pReverbDryWet));
setDefaultPattern();
}
@ -186,20 +188,26 @@ juce::AudioProcessorValueTreeState::ParameterLayout MonostepAudioProcessor::crea
"Delay Time", juce::NormalisableRange<float> (0.0f, 1.0f), 0.35f));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pDelayStrength),
"Delay Strength", juce::NormalisableRange<float> (0.0f, 1.0f), 0.0f));
"Delay Feedback", juce::NormalisableRange<float> (0.0f, 1.0f), 0.5f));
layout.add (std::make_unique<juce::AudioParameterBool> (paramId (pDelaySync),
"Delay Sync", true));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pDelayDryWet),
"Delay Dry/Wet", juce::NormalisableRange<float> (0.0f, 1.0f), 0.25f));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbRoom),
"Reverb Roomsize", juce::NormalisableRange<float> (0.0f, 1.0f), 0.5f));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbStrength),
"Reverb Strength", juce::NormalisableRange<float> (0.0f, 1.0f), 0.0f));
"Reverb Strength", juce::NormalisableRange<float> (0.0f, 1.0f), 1.0f));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbDiffusion),
"Reverb Diffusion", juce::NormalisableRange<float> (0.0f, 1.0f), 0.6f));
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbDryWet),
"Reverb Dry/Wet", juce::NormalisableRange<float> (0.0f, 1.0f), 0.25f));
return layout;
}
@ -283,31 +291,39 @@ void MonostepAudioProcessor::applyPreset (int index)
float glide; float gateLen; float swing; int rate; int root; int octave;
float drive; float ring; float accent;
float fAttack; float fDecay; float fSustain; float fRelease; float fAmt;
float delayTime = 0.35f; // only audible when delayWet > 0
float delayFeedback = 0.45f;
bool delaySync = true;
float delayWet = 0.0f;
float reverbRoom = 0.5f; // only audible when reverbWet > 0
float reverbLevel = 0.6f;
float reverbDiff = 0.6f;
float reverbWet = 0.0f;
};
static const Preset presets[] =
{
// --- gritty / glidy -----------------------------------------------------
{ 0, 1, 0, 15.0f, 0.60f, 4200.0f, 0.15f, 0.02f, 0.25f, 0.70f, 0.35f, 0.25f, 0.80f, 0.10f, 2, 0, 3, 0.55f, 0.00f, 0.5f, 0.02f, 0.30f, 0.60f, 0.25f, 1.5f }, // Wet Tape
{ 0, 1, 0, 15.0f, 0.60f, 4200.0f, 0.15f, 0.02f, 0.25f, 0.70f, 0.35f, 0.25f, 0.80f, 0.10f, 2, 0, 3, 0.55f, 0.00f, 0.5f, 0.02f, 0.30f, 0.60f, 0.25f, 1.5f, 0.21f, 0.55f, true, 0.50f, 0.60f, 0.60f, 0.50f, 0.15f }, // Wet Tape
{ 2, 0, -12, -8.0f, 0.45f, 1100.0f, 0.65f, 0.003f, 0.40f, 0.10f, 0.08f, 0.12f, 0.90f, 0.00f, 3, 0, 3, 0.85f, 0.00f, 0.4f, 0.005f, 0.35f, 0.10f, 0.10f, 3.0f }, // Acid Wash
{ 3, 3, 0, 5.0f, 0.50f, 380.0f, 0.30f, 0.005f, 0.10f, 0.40f, 0.10f, 0.20f, 0.95f, 0.05f, 3, 0, 3, 0.60f, 0.00f, 0.3f, 0.005f, 0.15f, 0.30f, 0.15f, 0.5f }, // Tin Can
{ 0, 3, 7, 25.0f, 0.35f, 2500.0f, 0.20f, 0.04f, 0.20f, 0.30f, 0.60f, 0.45f, 0.85f, 0.25f, 2, 0, 3, 0.40f, 0.00f, 0.5f, 0.03f, 0.25f, 0.50f, 0.40f, 1.0f }, // Bent Toy
{ 2, 3, 0, 0.0f, 0.55f, 650.0f, 0.45f, 0.002f, 0.15f, 0.20f, 0.05f, 0.10f, 0.90f, 0.10f, 3, 0, 3, 0.95f, 0.60f, 0.3f, 0.005f, 0.20f, 0.40f, 0.15f, 1.5f }, // Broken Radio
{ 1, 2, 0, 20.0f, 0.50f, 6000.0f, 0.10f, 0.003f, 0.15f, 0.80f, 0.20f, 0.10f, 0.90f, 0.15f, 3, 0, 3, 0.20f, 0.00f, 0.6f, 0.01f, 0.30f, 0.70f, 0.30f, 1.0f }, // Neon Arcade
{ 0, 1, -12, -35.0f, 0.55f, 1800.0f, 0.40f, 0.10f, 0.35f, 0.20f, 0.80f, 0.50f, 0.70f, 0.20f, 2, 0, 3, 0.00f, 0.00f, 0.5f, 0.01f, 0.40f, 0.50f, 0.20f, -1.5f }, // Glitch Garden
{ 2, 2, 5, 10.0f, 0.40f, 3200.0f, 0.35f, 0.002f, 0.20f, 0.60f, 0.12f, 0.15f, 0.95f, 0.40f, 3, 0, 3, 0.70f, 0.20f, 0.5f, 0.01f, 0.25f, 0.60f, 0.20f, 2.0f }, // Robo Funk
{ 1, 1, -7, -15.0f, 0.50f, 2600.0f, 0.20f, 0.03f, 0.30f, 0.35f, 0.60f, 0.60f, 0.80f, 0.05f, 2, 0, 3, 0.10f, 0.00f, 0.4f, 0.02f, 0.30f, 0.50f, 0.30f, -0.5f }, // Lo-Fi Noir
{ 1, 2, 0, 20.0f, 0.50f, 6000.0f, 0.10f, 0.003f, 0.15f, 0.80f, 0.20f, 0.10f, 0.90f, 0.15f, 3, 0, 3, 0.20f, 0.00f, 0.6f, 0.01f, 0.30f, 0.70f, 0.30f, 1.0f, 0.50f, 0.45f, true, 0.30f, 0.50f, 0.50f, 0.60f, 0.30f }, // Neon Arcade
{ 0, 1, -12, -35.0f, 0.55f, 1800.0f, 0.40f, 0.10f, 0.35f, 0.20f, 0.80f, 0.50f, 0.70f, 0.20f, 2, 0, 3, 0.00f, 0.00f, 0.5f, 0.01f, 0.40f, 0.50f, 0.20f, -1.5f, 0.36f, 0.70f, true, 0.50f, 0.50f, 0.60f, 0.60f, 0.00f }, // Glitch Garden
{ 2, 2, 5, 10.0f, 0.40f, 3200.0f, 0.35f, 0.002f, 0.20f, 0.60f, 0.12f, 0.15f, 0.95f, 0.40f, 3, 0, 3, 0.70f, 0.20f, 0.5f, 0.01f, 0.25f, 0.60f, 0.20f, 2.0f, 0.36f, 0.50f, true, 0.40f, 0.50f, 0.60f, 0.60f, 0.00f }, // Robo Funk
{ 1, 1, -7, -15.0f, 0.50f, 2600.0f, 0.20f, 0.03f, 0.30f, 0.35f, 0.60f, 0.60f, 0.80f, 0.05f, 2, 0, 3, 0.10f, 0.00f, 0.4f, 0.02f, 0.30f, 0.50f, 0.30f, -0.5f, 0.21f, 0.40f, true, 0.20f, 0.60f, 0.50f, 0.50f, 0.25f }, // Lo-Fi Noir
{ 0, 2, 0, 8.0f, 0.60f, 7000.0f, 0.08f, 0.01f, 0.20f, 0.90f, 0.25f, 0.30f, 0.75f, 0.00f, 3, 0, 3, 0.35f, 0.35f, 0.6f, 0.01f, 0.30f, 0.20f, 0.30f, 3.5f }, // Spectral Sweep
{ 3, 0, -12, 12.0f, 0.45f, 5000.0f, 0.25f, 0.02f, 0.50f, 0.70f, 0.30f, 0.40f, 0.60f, 0.20f, 2, 0, 3, 0.30f, 0.15f, 0.5f, 0.02f, 0.40f, 0.80f, 0.30f, 0.5f }, // Plasma Organ
{ 0, 0, 0, 0.0f, 0.50f, 900.0f, 0.50f, 0.05f, 0.30f, 0.50f, 0.50f, 0.35f, 0.85f, 0.30f, 2, 0, 3, 0.25f, 0.55f, 0.3f, 0.05f, 0.30f, 0.50f, 0.40f, -2.0f }, // Underwater FM
{ 3, 0, -12, 12.0f, 0.45f, 5000.0f, 0.25f, 0.02f, 0.50f, 0.70f, 0.30f, 0.40f, 0.60f, 0.20f, 2, 0, 3, 0.30f, 0.15f, 0.5f, 0.02f, 0.40f, 0.80f, 0.30f, 0.5f, 0.35f, 0.45f, true, 0.00f, 0.70f, 0.80f, 0.70f, 0.40f }, // Plasma Organ
{ 0, 0, 0, 0.0f, 0.50f, 900.0f, 0.50f, 0.05f, 0.30f, 0.50f, 0.50f, 0.35f, 0.85f, 0.30f, 2, 0, 3, 0.25f, 0.55f, 0.3f, 0.05f, 0.30f, 0.50f, 0.40f, -2.0f, 0.64f, 0.50f, true, 0.35f, 0.90f, 0.70f, 0.90f, 0.35f }, // Underwater FM
// --- clean / no glide / no drive ---------------------------------------
{ 0, 0, 0, 0.0f, 0.50f, 7000.0f, 0.10f, 0.002f, 0.25f, 0.20f, 0.30f, 0.00f, 0.35f, 0.00f, 3, 0, 4, 0.00f, 0.00f, 0.6f, 0.005f, 0.20f, 0.30f, 0.40f, 0.3f }, // Glass Bells
{ 1, 1, 0, 12.0f, 0.60f, 1200.0f, 0.25f, 0.30f, 1.20f, 0.80f, 1.50f, 0.20f, 1.00f, 0.10f, 2, 0, 2, 0.00f, 0.00f, 0.2f, 0.50f, 1.00f, 0.70f, 1.20f, 1.0f }, // Warm Pad
{ 1, 1, 0, 12.0f, 0.60f, 1200.0f, 0.25f, 0.30f, 1.20f, 0.80f, 1.50f, 0.20f, 1.00f, 0.10f, 2, 0, 2, 0.00f, 0.00f, 0.2f, 0.50f, 1.00f, 0.70f, 1.20f, 1.0f, 0.35f, 0.45f, true, 0.00f, 0.80f, 0.90f, 0.80f, 0.45f }, // Warm Pad
{ 2, 2, 0, 5.0f, 0.50f, 2500.0f, 0.15f, 0.002f, 0.20f, 0.30f, 0.12f, 0.00f, 0.50f, 0.30f, 3, 0, 3, 0.00f, 0.00f, 0.5f, 0.01f, 0.25f, 0.40f, 0.20f, 1.5f }, // Pulse Groove
{ 0, 3, 12, 0.0f, 0.40f, 1500.0f, 0.60f, 0.001f, 0.35f, 0.15f, 0.20f, 0.00f, 0.45f, 0.00f, 3, 0, 4, 0.00f, 0.35f, 0.7f, 0.002f, 0.30f, 0.20f, 0.25f, 2.5f }, // Steel Pluck
{ 0, 0, 0, -5.0f, 0.40f, 500.0f, 0.20f, 0.01f, 0.40f, 0.90f, 0.30f, 0.00f, 0.90f, 0.00f, 2, 0, 1, 0.00f, 0.00f, 0.3f, 0.01f, 0.30f, 0.60f, 0.30f, -1.0f }, // Sub Rumble
{ 1, 0, 0, 8.0f, 0.55f, 3000.0f, 0.20f, 0.005f, 0.30f, 0.60f, 0.25f, 0.30f, 0.70f, 0.15f, 2, 0, 3, 0.25f, 0.00f, 0.5f, 0.01f, 0.30f, 0.50f, 0.30f, 1.0f }, // Tape Bounce
{ 1, 0, 0, 8.0f, 0.55f, 3000.0f, 0.20f, 0.005f, 0.30f, 0.60f, 0.25f, 0.30f, 0.70f, 0.15f, 2, 0, 3, 0.25f, 0.00f, 0.5f, 0.01f, 0.30f, 0.50f, 0.30f, 1.0f, 0.64f, 0.60f, true, 0.45f, 0.50f, 0.50f, 0.50f, 0.20f }, // Tape Bounce
};
const auto& pr = presets[juce::jlimit (0, getNumPresets() - 1, index)];
@ -337,6 +353,15 @@ void MonostepAudioProcessor::applyPreset (int index)
applyParamValue ("filterSustain", pr.fSustain);
applyParamValue ("filterRelease", pr.fRelease);
applyParamValue ("filterEnvAmt", pr.fAmt);
applyParamValue ("delayTime", pr.delayTime);
applyParamValue ("delayStrength", pr.delayFeedback);
applyParamValue ("delaySync", pr.delaySync ? 1.0f : 0.0f);
applyParamValue ("delayDryWet", pr.delayWet);
applyParamValue ("reverbRoom", pr.reverbRoom);
applyParamValue ("reverbStrength", pr.reverbLevel);
applyParamValue ("reverbDiffusion", pr.reverbDiff);
applyParamValue ("reverbDryWet", pr.reverbWet);
}
void MonostepAudioProcessor::randomizePattern()
@ -420,11 +445,66 @@ void MonostepAudioProcessor::randomizeFx()
applyParamValue ("drive", random.nextFloat());
applyParamValue ("ringmod", random.nextFloat());
applyParamValue ("delayTime", random.nextFloat());
applyParamValue ("delayStrength", random.nextFloat() * 0.8f);
applyParamValue ("delayStrength", random.nextFloat() * 0.9f);
applyParamValue ("delaySync", random.nextFloat() < 0.8f ? 1.0f : 0.0f);
applyParamValue ("delayDryWet", random.nextFloat() * 0.8f);
applyParamValue ("reverbRoom", 0.2f + random.nextFloat() * 0.7f);
applyParamValue ("reverbStrength", random.nextFloat() * 0.7f);
applyParamValue ("reverbStrength", random.nextFloat());
applyParamValue ("reverbDiffusion", random.nextFloat());
applyParamValue ("reverbDryWet", random.nextFloat() * 0.8f);
}
void MonostepAudioProcessor::randomizeAccent()
{
const int length = juce::roundToInt (seqLenParam->load());
for (int i = 0; i < length; ++i)
{
auto& s = sequencer.step (i);
if (! s.gate)
continue;
s.accent = random.nextFloat() < 0.3f;
}
if (onPatternChanged)
onPatternChanged();
}
void MonostepAudioProcessor::randomizeSlide()
{
const int length = juce::roundToInt (seqLenParam->load());
for (int i = 0; i < length; ++i)
{
auto& s = sequencer.step (i);
if (! s.gate)
continue;
s.slide = random.nextFloat() < 0.25f;
}
if (onPatternChanged)
onPatternChanged();
}
void MonostepAudioProcessor::randomizeFine()
{
const int length = juce::roundToInt (seqLenParam->load());
for (int i = 0; i < length; ++i)
{
auto& s = sequencer.step (i);
if (! s.gate)
continue;
s.cents = random.nextFloat() * 100.0f - 50.0f;
}
if (onPatternChanged)
onPatternChanged();
}
void MonostepAudioProcessor::randomizeRate()
{
applyParamValue ("seqRate", (float) random.nextInt (5));
}
void MonostepAudioProcessor::randomizeParams()
@ -686,8 +766,9 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
}
// Accent tracks the current step (not just gate changes), so it holds for
// the whole step even when the note repeats without retriggering.
voice.setAccentLevel (seqAccent ? 1.0f + accentParam->load() * 4.0f : 1.0f);
// the whole step even when the note repeats without retriggering. Kept
// gentle: a modest volume lift plus a bit of brightness/timing (below).
voice.setAccentLevel (seqAccent ? 1.0f + accentParam->load() * 0.4f : 1.0f);
if (wantGate != lastGateApplied)
{
@ -714,13 +795,15 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
buffer.addFrom (ch, 0, scratch, 0, 0, numSamples);
monostep::FxProcessor::Params fp;
fp.delayTime = delayTimeParam->load();
fp.delayMix = delayStrengthParam->load();
fp.delaySync = delaySyncParam->load() >= 0.5f;
fp.reverbRoom = reverbRoomParam->load();
fp.reverbMix = reverbStrengthParam->load();
fp.reverbDiff = reverbDiffusionParam->load();
fp.bpm = bpm;
fp.delayTime = delayTimeParam->load();
fp.delayFeedback = delayStrengthParam->load();
fp.delaySync = delaySyncParam->load() >= 0.5f;
fp.delayMix = delayDryWetParam->load();
fp.reverbRoom = reverbRoomParam->load();
fp.reverbLevel = reverbStrengthParam->load();
fp.reverbMix = reverbDryWetParam->load();
fp.reverbDiff = reverbDiffusionParam->load();
fp.bpm = bpm;
fx.setParams (fp);
fx.process (buffer, numSamples);
}