mirror of
https://codeberg.org/armin/monostep.git
synced 2026-09-01 04:10:46 +02:00
Polish GUI, add pattern retrig option, and rework voice DSP
This commit is contained in:
parent
8ed279e84c
commit
4732240cc7
7 changed files with 546 additions and 129 deletions
|
|
@ -9,9 +9,11 @@ static const char* paramId (int index)
|
|||
static const char* ids[] =
|
||||
{
|
||||
"osc1Wave", "osc2Wave", "osc1Coarse", "osc2Coarse", "detune", "mix",
|
||||
"cutoff", "res", "attack", "decay", "sustain", "release", "glide", "master",
|
||||
"cutoff", "res", "filterType", "attack", "decay", "sustain", "release", "glide", "master",
|
||||
"seqLen", "seqRate", "seqRoot", "seqOctave", "seqSwing", "seqGateLen",
|
||||
"drive", "ringmod", "accent", "fine1"
|
||||
"drive", "ringmod", "accent", "fine1",
|
||||
"filterAttack", "filterDecay", "filterSustain", "filterRelease", "filterEnvAmt",
|
||||
"seqRetrig"
|
||||
};
|
||||
return ids[index];
|
||||
}
|
||||
|
|
@ -19,9 +21,11 @@ static const char* paramId (int index)
|
|||
enum ParamIndex
|
||||
{
|
||||
pOsc1Wave, pOsc2Wave, pOsc1Coarse, pOsc2Coarse, pDetune, pMix,
|
||||
pCutoff, pRes, pAttack, pDecay, pSustain, pRelease, pGlide, pMaster,
|
||||
pCutoff, pRes, pFilterType, pAttack, pDecay, pSustain, pRelease, pGlide, pMaster,
|
||||
pSeqLen, pSeqRate, pSeqRoot, pSeqOctave, pSeqSwing, pSeqGateLen,
|
||||
pDrive, pRingMod, pAccent, pFine1,
|
||||
pFilterAttack, pFilterDecay, pFilterSustain, pFilterRelease, pFilterEnvAmt,
|
||||
pSeqRetrig,
|
||||
numParams
|
||||
};
|
||||
|
||||
|
|
@ -39,10 +43,16 @@ MonostepAudioProcessor::MonostepAudioProcessor()
|
|||
osc1PhaseParam = apvts.getRawParameterValue (paramId (pFine1));
|
||||
cutoffParam = apvts.getRawParameterValue (paramId (pCutoff));
|
||||
resParam = apvts.getRawParameterValue (paramId (pRes));
|
||||
filterTypeParam = apvts.getRawParameterValue (paramId (pFilterType));
|
||||
attackParam = apvts.getRawParameterValue (paramId (pAttack));
|
||||
decayParam = apvts.getRawParameterValue (paramId (pDecay));
|
||||
sustainParam = apvts.getRawParameterValue (paramId (pSustain));
|
||||
releaseParam = apvts.getRawParameterValue (paramId (pRelease));
|
||||
filterAttackParam = apvts.getRawParameterValue (paramId (pFilterAttack));
|
||||
filterDecayParam = apvts.getRawParameterValue (paramId (pFilterDecay));
|
||||
filterSustainParam = apvts.getRawParameterValue (paramId (pFilterSustain));
|
||||
filterReleaseParam = apvts.getRawParameterValue (paramId (pFilterRelease));
|
||||
filterEnvAmtParam = apvts.getRawParameterValue (paramId (pFilterEnvAmt));
|
||||
glideParam = apvts.getRawParameterValue (paramId (pGlide));
|
||||
masterParam = apvts.getRawParameterValue (paramId (pMaster));
|
||||
seqLenParam = apvts.getRawParameterValue (paramId (pSeqLen));
|
||||
|
|
@ -54,6 +64,7 @@ MonostepAudioProcessor::MonostepAudioProcessor()
|
|||
driveParam = apvts.getRawParameterValue (paramId (pDrive));
|
||||
ringModParam = apvts.getRawParameterValue (paramId (pRingMod));
|
||||
accentParam = apvts.getRawParameterValue (paramId (pAccent));
|
||||
seqRetrigParam = apvts.getRawParameterValue (paramId (pSeqRetrig));
|
||||
|
||||
setDefaultPattern();
|
||||
}
|
||||
|
|
@ -84,7 +95,13 @@ juce::AudioProcessorValueTreeState::ParameterLayout MonostepAudioProcessor::crea
|
|||
juce::AudioParameterFloatAttributes().withLabel ("Hz")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pRes),
|
||||
"Filter Res", juce::NormalisableRange<float> (0.0f, 1.0f), 0.15f));
|
||||
"Filter Res", juce::NormalisableRange<float> (0.0f, 1.0f), 0.15f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterInt> (paramId (pFilterType),
|
||||
"Filter Type", 0,
|
||||
(int) monostep::SynthVoice::FilterType::numFilterTypes - 1,
|
||||
0));
|
||||
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pAttack),
|
||||
"Attack", juce::NormalisableRange<float> (0.001f, 2.0f, 0.001f, 0.3f), 0.005f,
|
||||
|
|
@ -101,6 +118,25 @@ juce::AudioProcessorValueTreeState::ParameterLayout MonostepAudioProcessor::crea
|
|||
"Release", juce::NormalisableRange<float> (0.01f, 4.0f, 0.001f, 0.3f), 0.4f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("s")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pFilterAttack),
|
||||
"Filter Env Attack", juce::NormalisableRange<float> (0.001f, 2.0f, 0.001f, 0.3f), 0.005f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("s")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pFilterDecay),
|
||||
"Filter Env Decay", juce::NormalisableRange<float> (0.001f, 3.0f, 0.001f, 0.3f), 0.3f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("s")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pFilterSustain),
|
||||
"Filter Env Sustain", juce::NormalisableRange<float> (0.0f, 1.0f), 0.7f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pFilterRelease),
|
||||
"Filter Env Release", juce::NormalisableRange<float> (0.01f, 4.0f, 0.001f, 0.3f), 0.4f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("s")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pFilterEnvAmt),
|
||||
"Filter Env Amount", juce::NormalisableRange<float> (-4.0f, 4.0f), 1.0f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("oct")));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pGlide),
|
||||
"Glide", juce::NormalisableRange<float> (0.0f, 1.0f, 0.001f, 0.5f), 0.12f,
|
||||
juce::AudioParameterFloatAttributes().withLabel ("s")));
|
||||
|
|
@ -124,6 +160,9 @@ juce::AudioProcessorValueTreeState::ParameterLayout MonostepAudioProcessor::crea
|
|||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pSeqGateLen),
|
||||
"Gate Length", juce::NormalisableRange<float> (0.05f, 1.0f), 0.8f));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterBool> (paramId (pSeqRetrig),
|
||||
"Restart Pattern on Note", false));
|
||||
|
||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pDrive),
|
||||
"Distortion Drive", juce::NormalisableRange<float> (0.0f, 1.0f), 0.0f));
|
||||
|
||||
|
|
@ -215,31 +254,32 @@ void MonostepAudioProcessor::applyPreset (int index)
|
|||
float cutoff; float res; float attack; float decay; float sustain; float release;
|
||||
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;
|
||||
};
|
||||
|
||||
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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // Underwater FM
|
||||
{ 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
|
||||
{ 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
|
||||
{ 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
|
||||
|
||||
// --- 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // 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 }, // Tape Bounce
|
||||
{ 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
|
||||
{ 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
|
||||
};
|
||||
|
||||
const auto& pr = presets[juce::jlimit (0, getNumPresets() - 1, index)];
|
||||
|
|
@ -264,6 +304,11 @@ void MonostepAudioProcessor::applyPreset (int index)
|
|||
applyParamValue ("drive", pr.drive);
|
||||
applyParamValue ("ringmod", pr.ring);
|
||||
applyParamValue ("accent", pr.accent);
|
||||
applyParamValue ("filterAttack", pr.fAttack);
|
||||
applyParamValue ("filterDecay", pr.fDecay);
|
||||
applyParamValue ("filterSustain", pr.fSustain);
|
||||
applyParamValue ("filterRelease", pr.fRelease);
|
||||
applyParamValue ("filterEnvAmt", pr.fAmt);
|
||||
}
|
||||
|
||||
void MonostepAudioProcessor::randomizePattern()
|
||||
|
|
@ -318,6 +363,11 @@ void MonostepAudioProcessor::randomizeFilter()
|
|||
{
|
||||
applyParamValue ("cutoff", 200.0f * std::pow (2.0f, random.nextFloat() * 5.0f));
|
||||
applyParamValue ("res", random.nextFloat() * 0.8f);
|
||||
applyParamValue ("filterEnvAmt", -3.0f + random.nextFloat() * 6.0f);
|
||||
applyParamValue ("filterAttack", 0.001f * std::pow (500.0f, random.nextFloat()));
|
||||
applyParamValue ("filterDecay", 0.05f * std::pow (30.0f, random.nextFloat()));
|
||||
applyParamValue ("filterSustain", random.nextFloat());
|
||||
applyParamValue ("filterRelease", 0.05f * std::pow (40.0f, random.nextFloat()));
|
||||
}
|
||||
|
||||
void MonostepAudioProcessor::randomizeEnv()
|
||||
|
|
@ -375,15 +425,22 @@ void MonostepAudioProcessor::updateVoiceParams()
|
|||
monostep::SynthVoice::Params p;
|
||||
p.waveA = (monostep::Waveform) (int) osc1WaveParam->load();
|
||||
p.waveB = (monostep::Waveform) (int) osc2WaveParam->load();
|
||||
p.detuneRatio = std::pow (2.0f, osc2CoarseParam->load() / 12.0f)
|
||||
* std::pow (2.0f, detuneParam->load() / 1200.0f);
|
||||
p.detuneRatioA = std::pow (2.0f, detuneParam->load() / 1200.0f); // OSC1: follows the knob
|
||||
p.detuneRatio = std::pow (2.0f, osc2CoarseParam->load() / 12.0f) // OSC2: coarse
|
||||
* std::pow (2.0f, -detuneParam->load() / 1200.0f); // OSC2: detune inverted
|
||||
p.mix = mixParam->load();
|
||||
p.cutoff = cutoffParam->load();
|
||||
p.cutoff = cutoffParam->load();
|
||||
p.resonance = resParam->load();
|
||||
p.filterType = (monostep::SynthVoice::FilterType) (int) filterTypeParam->load();
|
||||
p.attack = attackParam->load();
|
||||
p.decay = decayParam->load();
|
||||
p.sustain = sustainParam->load();
|
||||
p.release = releaseParam->load();
|
||||
p.fAttack = filterAttackParam->load();
|
||||
p.fDecay = filterDecayParam->load();
|
||||
p.fSustain = filterSustainParam->load();
|
||||
p.fRelease = filterReleaseParam->load();
|
||||
p.fAmount = filterEnvAmtParam->load();
|
||||
p.glide = glideParam->load();
|
||||
p.master = masterParam->load();
|
||||
p.drive = driveParam->load();
|
||||
|
|
@ -419,6 +476,7 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
|
|||
const float cyclePpq = (float) seqLen * stepLen;
|
||||
|
||||
// --- MIDI notes (gate/trigger for the sequencer) -------------------------
|
||||
bool noteOnSeen = false;
|
||||
for (const auto metadata : midiMessages)
|
||||
{
|
||||
const auto msg = metadata.getMessage();
|
||||
|
|
@ -426,6 +484,7 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
|
|||
if (msg.isNoteOn())
|
||||
{
|
||||
midiHeld = true;
|
||||
noteOnSeen = true;
|
||||
lastMidiNote = msg.getNoteNumber();
|
||||
}
|
||||
else if (msg.isNoteOff())
|
||||
|
|
@ -477,6 +536,16 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
|
|||
lastGateApplied = false;
|
||||
}
|
||||
|
||||
// Optional retrigger: a fresh note-on restarts the pattern from
|
||||
// step 1. Only honoured in free-run mode; while the host transport
|
||||
// is running, the pattern follows the host grid instead.
|
||||
if (noteOnSeen && seqRetrigParam->load() >= 0.5f)
|
||||
{
|
||||
freePpq = 0.0;
|
||||
lastStep = -1;
|
||||
lastGateApplied = false;
|
||||
}
|
||||
|
||||
freePpq += ppqPerSample * numSamples;
|
||||
}
|
||||
}
|
||||
|
|
@ -742,6 +811,7 @@ void MonostepAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
|
|||
juce::ValueTree state = apvts.copyState();
|
||||
juce::ValueTree seq = state.getOrCreateChildWithName ("SEQ", nullptr);
|
||||
storeSequence (seq);
|
||||
state.setProperty ("zoom", zoomIndex, nullptr);
|
||||
|
||||
std::unique_ptr<juce::XmlElement> xml (state.createXml());
|
||||
copyXmlToBinary (*xml, destData);
|
||||
|
|
@ -760,6 +830,8 @@ void MonostepAudioProcessor::setStateInformation (const void* data, int sizeInBy
|
|||
if (auto seq = state.getChildWithName ("SEQ"); seq.isValid())
|
||||
loadSequence (seq);
|
||||
|
||||
zoomIndex = juce::jlimit (0, 4, (int) state.getProperty ("zoom", 0));
|
||||
|
||||
if (onPatternChanged)
|
||||
onPatternChanged();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue