monostep/Source/dsp/FxProcessor.h
Armin 662a1f7383 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
2026-08-06 18:38:32 +02:00

77 lines
2.2 KiB
C++

#pragma once
#include <JuceHeader.h>
#include <vector>
namespace monostep
{
// Tempo-synced delay + Schroeder reverb, applied after the voice.
class FxProcessor
{
public:
FxProcessor() = default;
void prepare (double sampleRate, int numChannels);
void reset();
struct Params
{
float delayTime = 0.35f; // normalized knob 0..1
float delayFeedback = 0.45f; // 0..0.9 feedback (repeat density)
bool delaySync = true; // tempo-synced vs. free milliseconds
float delayMix = 0.0f; // 0..1 dry/wet
float reverbRoom = 0.5f; // 0..1
float reverbLevel = 1.0f; // 0..1 wet send gain
float reverbMix = 0.0f; // 0..1 dry/wet
float reverbDiff = 0.6f; // 0..1 allpass diffusion
double bpm = 120.0;
};
void setParams (const Params& p);
void process (juce::AudioBuffer<float>& buffer, int numSamples);
// Shared knob-to-time mapping so the editor displays the same values the DSP uses.
static float delayTimeSeconds (float knobNormalized, bool sync, double bpm);
static juce::String delayTimeLabel (float knobNormalized, bool sync, double bpm);
private:
struct DelayChannel
{
std::vector<float> memory;
int writeIndex = 0;
float smoothedDelay = 0.0f;
float feedbackLp = 0.0f;
};
struct ReverbChannel
{
std::vector<float> combs[4];
std::vector<float> allpasses[2];
int combIndex[4] = {};
int allpassIndex[2] = {};
};
void processDelay (juce::AudioBuffer<float>& buffer, int numSamples);
void processReverb (const juce::AudioBuffer<float>& dryIn, juce::AudioBuffer<float>& buffer, int numSamples);
double sampleRate = 44100.0;
int numChannels = 2;
int maxDelaySamples = 0;
int combDelaySamples[2][4] = {};
int allpassDelaySamples[2][2] = {};
Params params;
float currentDelaySeconds = 0.0f;
// Pre-delay snapshot: the reverb is fed the dry signal (before the delay),
// so delay and reverb run in parallel instead of in series.
juce::AudioBuffer<float> dryScratch;
std::vector<DelayChannel> delays;
std::vector<ReverbChannel> reverbs;
};
} // namespace monostep