mirror of
https://codeberg.org/armin/monostep.git
synced 2026-09-01 04:10:46 +02:00
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:
parent
342d413563
commit
662a1f7383
11 changed files with 310 additions and 97 deletions
|
|
@ -89,6 +89,17 @@ target_sources(Monostep PRIVATE
|
||||||
|
|
||||||
target_include_directories(Monostep PRIVATE Source)
|
target_include_directories(Monostep PRIVATE Source)
|
||||||
|
|
||||||
|
# Regenerate BuildStamp.h on every build so the UI's build date is always fresh.
|
||||||
|
set(MONOSTEP_BUILD_STAMP_HEADER "${CMAKE_CURRENT_BINARY_DIR}/generated/BuildStamp.h")
|
||||||
|
add_custom_target(MonostepBuildStamp ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-DMONOSTEP_BUILD_STAMP_HEADER="${MONOSTEP_BUILD_STAMP_HEADER}"
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/WriteBuildStamp.cmake"
|
||||||
|
COMMENT "Writing build stamp"
|
||||||
|
)
|
||||||
|
add_dependencies(Monostep MonostepBuildStamp)
|
||||||
|
target_include_directories(Monostep PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||||
|
|
||||||
target_compile_definitions(Monostep PRIVATE
|
target_compile_definitions(Monostep PRIVATE
|
||||||
JUCE_WEB_BROWSER=0
|
JUCE_WEB_BROWSER=0
|
||||||
JUCE_VST3_CAN_REPLACE_VST2=0
|
JUCE_VST3_CAN_REPLACE_VST2=0
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
|
#include "BuildStamp.h"
|
||||||
|
|
||||||
namespace monostep
|
namespace monostep
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +20,9 @@ inline juce::String gitInfo()
|
||||||
|
|
||||||
inline juce::String buildDateString()
|
inline juce::String buildDateString()
|
||||||
{
|
{
|
||||||
|
#if defined (MONOSTEP_BUILD_DATE)
|
||||||
|
return juce::String (MONOSTEP_BUILD_DATE);
|
||||||
|
#else
|
||||||
static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
|
||||||
|
|
@ -36,6 +40,7 @@ inline juce::String buildDateString()
|
||||||
const int year = d.substring (7).getIntValue();
|
const int year = d.substring (7).getIntValue();
|
||||||
|
|
||||||
return juce::String::formatted ("%04d-%02d-%02d__%s", year, month, day, __TIME__);
|
return juce::String::formatted ("%04d-%02d-%02d__%s", year, month, day, __TIME__);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline juce::String footerText()
|
inline juce::String footerText()
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,14 @@ StepPanel::StepPanel (MonostepAudioProcessor& processorRef)
|
||||||
processor.randomizeSeqSettings();
|
processor.randomizeSeqSettings();
|
||||||
if (randomizeToggles[RandomFx].getToggleState())
|
if (randomizeToggles[RandomFx].getToggleState())
|
||||||
processor.randomizeFx();
|
processor.randomizeFx();
|
||||||
|
if (randomizeToggles[RandomAccent].getToggleState())
|
||||||
|
processor.randomizeAccent();
|
||||||
|
if (randomizeToggles[RandomSlide].getToggleState())
|
||||||
|
processor.randomizeSlide();
|
||||||
|
if (randomizeToggles[RandomFine].getToggleState())
|
||||||
|
processor.randomizeFine();
|
||||||
|
if (randomizeToggles[RandomRate].getToggleState())
|
||||||
|
processor.randomizeRate();
|
||||||
};
|
};
|
||||||
addAndMakeVisible (randomizeButton);
|
addAndMakeVisible (randomizeButton);
|
||||||
|
|
||||||
|
|
@ -513,7 +521,8 @@ StepPanel::StepPanel (MonostepAudioProcessor& processorRef)
|
||||||
randomizeCaption.setColour (juce::Label::textColourId, colours::textDim);
|
randomizeCaption.setColour (juce::Label::textColourId, colours::textDim);
|
||||||
addAndMakeVisible (randomizeCaption);
|
addAndMakeVisible (randomizeCaption);
|
||||||
|
|
||||||
static const char* groupNames[] = { "Pattern", "Osc", "Filter", "Env", "Length", "FX" };
|
static const char* groupNames[] = { "Pattern", "Osc", "Filter", "Env", "Length", "FX",
|
||||||
|
"Accent", "Slide", "Fine", "Rate" };
|
||||||
|
|
||||||
for (int i = 0; i < RandomGroupCount; ++i)
|
for (int i = 0; i < RandomGroupCount; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -590,41 +599,41 @@ void StepPanel::resized()
|
||||||
const int w = getWidth();
|
const int w = getWidth();
|
||||||
|
|
||||||
titleLabel.setBounds (0, 4, w, 16);
|
titleLabel.setBounds (0, 4, w, 16);
|
||||||
noteLabel.setBounds (0, 22, w, 28);
|
noteLabel.setBounds (0, 22, w, 26);
|
||||||
gateLabel.setBounds (0, 50, w, 14);
|
gateLabel.setBounds (0, 50, w, 14);
|
||||||
|
|
||||||
const int knobX = (w - 74) / 2;
|
const int knobX = (w - 74) / 2;
|
||||||
const int knobY = 68;
|
const int knobY = 66;
|
||||||
|
|
||||||
fineKnob.setBounds (knobX, knobY, 74, 94);
|
fineKnob.setBounds (knobX, knobY, 74, 84);
|
||||||
|
|
||||||
const int btnY = knobY + 102;
|
const int btnY = knobY + 84 + 6;
|
||||||
prevButton.setBounds (knobX - 32, btnY, 24, 24);
|
prevButton.setBounds (knobX - 32, btnY, 24, 24);
|
||||||
nextButton.setBounds (knobX + 74 + 8, btnY, 24, 24);
|
nextButton.setBounds (knobX + 74 + 8, btnY, 24, 24);
|
||||||
|
|
||||||
const int shiftW = 22;
|
const int shiftW = 22;
|
||||||
shiftLeftButton.setBounds (10, btnY + 50, shiftW, 26);
|
shiftLeftButton.setBounds (10, btnY + 40, shiftW, 24);
|
||||||
clearButton.setBounds (10 + shiftW + 4, btnY + 50, w - 20 - shiftW * 2 - 8, 26);
|
clearButton.setBounds (10 + shiftW + 4, btnY + 40, w - 20 - shiftW * 2 - 8, 24);
|
||||||
shiftRightButton.setBounds (10 + w - 20 - shiftW, btnY + 50, shiftW, 26);
|
shiftRightButton.setBounds (10 + w - 20 - shiftW, btnY + 40, shiftW, 24);
|
||||||
|
|
||||||
toolsCaption.setBounds (10, btnY + 86, w - 20, 14);
|
toolsCaption.setBounds (10, btnY + 70, w - 20, 12);
|
||||||
presetCombo.setBounds (10, btnY + 102, w - 20, 26);
|
presetCombo.setBounds (10, btnY + 84, w - 20, 24);
|
||||||
randomizeButton.setBounds (10, btnY + 134, w - 20, 26);
|
randomizeButton.setBounds (10, btnY + 112, w - 20, 24);
|
||||||
randomizeCaption.setBounds (10, btnY + 166, w - 20, 12);
|
randomizeCaption.setBounds (10, btnY + 140, w - 20, 12);
|
||||||
|
|
||||||
const int colW = (w - 20 - 4) / 2;
|
const int colW = (w - 20 - 4) / 2;
|
||||||
const int rowH = 20;
|
const int rowH = 18;
|
||||||
|
|
||||||
for (int i = 0; i < RandomGroupCount; ++i)
|
for (int i = 0; i < RandomGroupCount; ++i)
|
||||||
{
|
{
|
||||||
const int col = i / 3;
|
const int col = i % 2;
|
||||||
const int row = i % 3;
|
const int row = i / 2;
|
||||||
randomizeToggles[i].setBounds (10 + col * (colW + 4), btnY + 180 + row * (rowH + 2), colW, rowH);
|
randomizeToggles[i].setBounds (10 + col * (colW + 4), btnY + 154 + row * (rowH + 2), colW, rowH);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int retrigW = 100;
|
const int retrigW = 100;
|
||||||
retrigToggle.setBounds (10, btnY + 252, retrigW, 26);
|
retrigToggle.setBounds (10, btnY + 254, retrigW, 24);
|
||||||
resetFineButton.setBounds (10 + retrigW + 4, btnY + 252, w - 20 - retrigW - 4, 26);
|
resetFineButton.setBounds (10 + retrigW + 4, btnY + 254, w - 20 - retrigW - 4, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -659,10 +668,12 @@ MonostepAudioProcessorEditor::MonostepAudioProcessorEditor (MonostepAudioProcess
|
||||||
driveKnob ("Drive"),
|
driveKnob ("Drive"),
|
||||||
ringKnob ("Ring"),
|
ringKnob ("Ring"),
|
||||||
delayTimeKnob ("Time"),
|
delayTimeKnob ("Time"),
|
||||||
delayStrengthKnob ("Strength"),
|
delayFeedbackKnob ("Feedback"),
|
||||||
|
delayDryWetKnob ("Dry/Wet"),
|
||||||
reverbRoomKnob ("Room"),
|
reverbRoomKnob ("Room"),
|
||||||
reverbStrengthKnob ("Strength"),
|
reverbStrengthKnob ("Level"),
|
||||||
reverbDiffusionKnob ("Diff"),
|
reverbDiffusionKnob ("Diff"),
|
||||||
|
reverbDryWetKnob ("Dry/Wet"),
|
||||||
accentKnob ("Accent"),
|
accentKnob ("Accent"),
|
||||||
rateBar (processor.getAPVTS(), "seqRate", { "1/4", "1/8", "1/8T", "1/16", "1/32" }),
|
rateBar (processor.getAPVTS(), "seqRate", { "1/4", "1/8", "1/8T", "1/16", "1/32" }),
|
||||||
octaveBar (processor.getAPVTS(), "seqOctave", { "-2", "-1", "0", "+1", "+2" }),
|
octaveBar (processor.getAPVTS(), "seqOctave", { "-2", "-1", "0", "+1", "+2" }),
|
||||||
|
|
@ -770,10 +781,12 @@ MonostepAudioProcessorEditor::MonostepAudioProcessorEditor (MonostepAudioProcess
|
||||||
const bool sync = processorRef.getAPVTS().getRawParameterValue ("delaySync")->load() >= 0.5f;
|
const bool sync = processorRef.getAPVTS().getRawParameterValue ("delaySync")->load() >= 0.5f;
|
||||||
return monostep::FxProcessor::delayTimeLabel (v, sync, 120.0);
|
return monostep::FxProcessor::delayTimeLabel (v, sync, 120.0);
|
||||||
});
|
});
|
||||||
addKnob (delayStrengthKnob, "delayStrength", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
addKnob (delayFeedbackKnob, "delayStrength", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
|
addKnob (delayDryWetKnob, "delayDryWet", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
addKnob (reverbRoomKnob, "reverbRoom", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
addKnob (reverbRoomKnob, "reverbRoom", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
addKnob (reverbStrengthKnob, "reverbStrength", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
addKnob (reverbStrengthKnob, "reverbStrength", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
addKnob (reverbDiffusionKnob, "reverbDiffusion", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
addKnob (reverbDiffusionKnob, "reverbDiffusion", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
|
addKnob (reverbDryWetKnob, "reverbDryWet", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
addKnob (accentKnob, "accent", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
addKnob (accentKnob, "accent", [] (float v) { return juce::String (juce::roundToInt (v * 100.0f)) + "%"; });
|
||||||
|
|
||||||
delaySyncToggle.setButtonText ("Sync");
|
delaySyncToggle.setButtonText ("Sync");
|
||||||
|
|
@ -948,10 +961,10 @@ void MonostepAudioProcessorEditor::paintContent (juce::Graphics& g)
|
||||||
drawFrame (glideKnob, accentKnob, 6.0f);
|
drawFrame (glideKnob, accentKnob, 6.0f);
|
||||||
drawPill (glideKnob, accentKnob, "NOTE");
|
drawPill (glideKnob, accentKnob, "NOTE");
|
||||||
|
|
||||||
drawFrame (driveKnob, reverbDiffusionKnob, 6.0f);
|
drawFrame (driveKnob, reverbDryWetKnob, 6.0f);
|
||||||
drawPill (driveKnob, ringKnob, "FX");
|
drawPill (driveKnob, ringKnob, "FX");
|
||||||
drawPill (delayTimeKnob, delaySyncToggle, "DELAY");
|
drawPill (delayTimeKnob, delaySyncToggle, "DELAY");
|
||||||
drawPill (reverbRoomKnob, reverbDiffusionKnob, "REVERB");
|
drawPill (reverbRoomKnob, reverbDryWetKnob, "REVERB");
|
||||||
|
|
||||||
drawFrame (filterTypeBox, resKnob, 6.0f, 6.0f);
|
drawFrame (filterTypeBox, resKnob, 6.0f, 6.0f);
|
||||||
drawPill (filterTypeBox, resKnob, "FILTER", 6.0f);
|
drawPill (filterTypeBox, resKnob, "FILTER", 6.0f);
|
||||||
|
|
@ -1027,7 +1040,7 @@ void MonostepAudioProcessorEditor::resized()
|
||||||
const int oscColW = oscLabelW + oscDropW + oscGapW; // labels + dropdowns + gap to knobs
|
const int oscColW = oscLabelW + oscDropW + oscGapW; // labels + dropdowns + gap to knobs
|
||||||
|
|
||||||
// Both rows are centered over the full bottom bar width.
|
// Both rows are centered over the full bottom bar width.
|
||||||
const int blockW = oscColW + 12 * step + 104; // osc col + FX (8 widgets + subgroup gaps)
|
const int blockW = oscColW + 15 * step + 152; // osc col + FX (9 widgets + sync toggle + subgroup gaps)
|
||||||
const int oscX = pad + ((w - 2 * pad) - blockW) / 2 + oscColW;
|
const int oscX = pad + ((w - 2 * pad) - blockW) / 2 + oscColW;
|
||||||
const int row1Y = bottomY + 24;
|
const int row1Y = bottomY + 24;
|
||||||
const int row2Y = row1Y + knobH + 34; // row 1 + a caption band
|
const int row2Y = row1Y + knobH + 34; // row 1 + a caption band
|
||||||
|
|
@ -1053,9 +1066,9 @@ void MonostepAudioProcessorEditor::resized()
|
||||||
|
|
||||||
const int fxX = oscX + 5 * step + 48;
|
const int fxX = oscX + 5 * step + 48;
|
||||||
placeRow (row1Y, fxX, { &driveKnob, &ringKnob });
|
placeRow (row1Y, fxX, { &driveKnob, &ringKnob });
|
||||||
placeRow (row1Y, fxX + 2 * step + 24, { &delayTimeKnob, &delayStrengthKnob });
|
placeRow (row1Y, fxX + 2 * step + 24, { &delayTimeKnob, &delayFeedbackKnob, &delayDryWetKnob });
|
||||||
placeRow (row1Y, fxX + 5 * step + 48, { &reverbRoomKnob, &reverbStrengthKnob, &reverbDiffusionKnob });
|
placeRow (row1Y, fxX + 6 * step + 46, { &reverbRoomKnob, &reverbStrengthKnob, &reverbDiffusionKnob, &reverbDryWetKnob });
|
||||||
delaySyncToggle.setBounds (fxX + 4 * step + 24, row1Y + (knobH - 24) / 2, knobW, 24);
|
delaySyncToggle.setBounds (fxX + 5 * step + 24, row1Y + (knobH - 24) / 2, knobW, 24);
|
||||||
|
|
||||||
// Row 2: Filter (dropdown + cutoff, res) [gap] Amp Envelope [gap] Filter Env.
|
// Row 2: Filter (dropdown + cutoff, res) [gap] Amp Envelope [gap] Filter Env.
|
||||||
// The three sections are centered as one block with equal frame gaps.
|
// The three sections are centered as one block with equal frame gaps.
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,10 @@ private:
|
||||||
RandomEnv,
|
RandomEnv,
|
||||||
RandomSeq,
|
RandomSeq,
|
||||||
RandomFx,
|
RandomFx,
|
||||||
|
RandomAccent,
|
||||||
|
RandomSlide,
|
||||||
|
RandomFine,
|
||||||
|
RandomRate,
|
||||||
RandomGroupCount
|
RandomGroupCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -194,7 +198,7 @@ private:
|
||||||
|
|
||||||
ContentComponent content;
|
ContentComponent content;
|
||||||
|
|
||||||
static constexpr int baseWidth = 1280;
|
static constexpr int baseWidth = 1360;
|
||||||
static constexpr int baseHeight = 780;
|
static constexpr int baseHeight = 780;
|
||||||
|
|
||||||
float zoomFactor = 1.0f;
|
float zoomFactor = 1.0f;
|
||||||
|
|
@ -230,10 +234,12 @@ private:
|
||||||
Knob driveKnob;
|
Knob driveKnob;
|
||||||
Knob ringKnob;
|
Knob ringKnob;
|
||||||
Knob delayTimeKnob;
|
Knob delayTimeKnob;
|
||||||
Knob delayStrengthKnob;
|
Knob delayFeedbackKnob;
|
||||||
|
Knob delayDryWetKnob;
|
||||||
Knob reverbRoomKnob;
|
Knob reverbRoomKnob;
|
||||||
Knob reverbStrengthKnob;
|
Knob reverbStrengthKnob;
|
||||||
Knob reverbDiffusionKnob;
|
Knob reverbDiffusionKnob;
|
||||||
|
Knob reverbDryWetKnob;
|
||||||
juce::ToggleButton delaySyncToggle;
|
juce::ToggleButton delaySyncToggle;
|
||||||
std::unique_ptr<juce::AudioProcessorValueTreeState::ButtonAttachment> delaySyncAttachment;
|
std::unique_ptr<juce::AudioProcessorValueTreeState::ButtonAttachment> delaySyncAttachment;
|
||||||
Knob accentKnob;
|
Knob accentKnob;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ static const char* paramId (int index)
|
||||||
"drive", "ringmod", "accent", "fine1",
|
"drive", "ringmod", "accent", "fine1",
|
||||||
"filterAttack", "filterDecay", "filterSustain", "filterRelease", "filterEnvAmt",
|
"filterAttack", "filterDecay", "filterSustain", "filterRelease", "filterEnvAmt",
|
||||||
"seqRetrig",
|
"seqRetrig",
|
||||||
"delayTime", "delayStrength", "delaySync",
|
"delayTime", "delayStrength", "delaySync", "delayDryWet",
|
||||||
"reverbRoom", "reverbStrength", "reverbDiffusion"
|
"reverbRoom", "reverbStrength", "reverbDiffusion", "reverbDryWet"
|
||||||
};
|
};
|
||||||
return ids[index];
|
return ids[index];
|
||||||
}
|
}
|
||||||
|
|
@ -28,8 +28,8 @@ enum ParamIndex
|
||||||
pDrive, pRingMod, pAccent, pFine1,
|
pDrive, pRingMod, pAccent, pFine1,
|
||||||
pFilterAttack, pFilterDecay, pFilterSustain, pFilterRelease, pFilterEnvAmt,
|
pFilterAttack, pFilterDecay, pFilterSustain, pFilterRelease, pFilterEnvAmt,
|
||||||
pSeqRetrig,
|
pSeqRetrig,
|
||||||
pDelayTime, pDelayStrength, pDelaySync,
|
pDelayTime, pDelayStrength, pDelaySync, pDelayDryWet,
|
||||||
pReverbRoom, pReverbStrength, pReverbDiffusion,
|
pReverbRoom, pReverbStrength, pReverbDiffusion, pReverbDryWet,
|
||||||
numParams
|
numParams
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -72,9 +72,11 @@ MonostepAudioProcessor::MonostepAudioProcessor()
|
||||||
delayTimeParam = apvts.getRawParameterValue (paramId (pDelayTime));
|
delayTimeParam = apvts.getRawParameterValue (paramId (pDelayTime));
|
||||||
delayStrengthParam = apvts.getRawParameterValue (paramId (pDelayStrength));
|
delayStrengthParam = apvts.getRawParameterValue (paramId (pDelayStrength));
|
||||||
delaySyncParam = apvts.getRawParameterValue (paramId (pDelaySync));
|
delaySyncParam = apvts.getRawParameterValue (paramId (pDelaySync));
|
||||||
|
delayDryWetParam = apvts.getRawParameterValue (paramId (pDelayDryWet));
|
||||||
reverbRoomParam = apvts.getRawParameterValue (paramId (pReverbRoom));
|
reverbRoomParam = apvts.getRawParameterValue (paramId (pReverbRoom));
|
||||||
reverbStrengthParam = apvts.getRawParameterValue (paramId (pReverbStrength));
|
reverbStrengthParam = apvts.getRawParameterValue (paramId (pReverbStrength));
|
||||||
reverbDiffusionParam = apvts.getRawParameterValue (paramId (pReverbDiffusion));
|
reverbDiffusionParam = apvts.getRawParameterValue (paramId (pReverbDiffusion));
|
||||||
|
reverbDryWetParam = apvts.getRawParameterValue (paramId (pReverbDryWet));
|
||||||
|
|
||||||
setDefaultPattern();
|
setDefaultPattern();
|
||||||
}
|
}
|
||||||
|
|
@ -186,20 +188,26 @@ juce::AudioProcessorValueTreeState::ParameterLayout MonostepAudioProcessor::crea
|
||||||
"Delay Time", juce::NormalisableRange<float> (0.0f, 1.0f), 0.35f));
|
"Delay Time", juce::NormalisableRange<float> (0.0f, 1.0f), 0.35f));
|
||||||
|
|
||||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pDelayStrength),
|
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),
|
layout.add (std::make_unique<juce::AudioParameterBool> (paramId (pDelaySync),
|
||||||
"Delay Sync", true));
|
"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),
|
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbRoom),
|
||||||
"Reverb Roomsize", juce::NormalisableRange<float> (0.0f, 1.0f), 0.5f));
|
"Reverb Roomsize", juce::NormalisableRange<float> (0.0f, 1.0f), 0.5f));
|
||||||
|
|
||||||
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbStrength),
|
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),
|
layout.add (std::make_unique<juce::AudioParameterFloat> (paramId (pReverbDiffusion),
|
||||||
"Reverb Diffusion", juce::NormalisableRange<float> (0.0f, 1.0f), 0.6f));
|
"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;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,31 +291,39 @@ void MonostepAudioProcessor::applyPreset (int index)
|
||||||
float glide; float gateLen; float swing; int rate; int root; int octave;
|
float glide; float gateLen; float swing; int rate; int root; int octave;
|
||||||
float drive; float ring; float accent;
|
float drive; float ring; float accent;
|
||||||
float fAttack; float fDecay; float fSustain; float fRelease; float fAmt;
|
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[] =
|
static const Preset presets[] =
|
||||||
{
|
{
|
||||||
// --- gritty / glidy -----------------------------------------------------
|
// --- 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
|
{ 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
|
{ 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
|
{ 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
|
{ 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
|
{ 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 }, // Glitch Garden
|
{ 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 }, // Robo Funk
|
{ 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 }, // Lo-Fi Noir
|
{ 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
|
{ 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
|
{ 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 }, // Underwater FM
|
{ 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 ---------------------------------------
|
// --- 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
|
{ 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
|
{ 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, 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
|
{ 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)];
|
const auto& pr = presets[juce::jlimit (0, getNumPresets() - 1, index)];
|
||||||
|
|
@ -337,6 +353,15 @@ void MonostepAudioProcessor::applyPreset (int index)
|
||||||
applyParamValue ("filterSustain", pr.fSustain);
|
applyParamValue ("filterSustain", pr.fSustain);
|
||||||
applyParamValue ("filterRelease", pr.fRelease);
|
applyParamValue ("filterRelease", pr.fRelease);
|
||||||
applyParamValue ("filterEnvAmt", pr.fAmt);
|
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()
|
void MonostepAudioProcessor::randomizePattern()
|
||||||
|
|
@ -420,11 +445,66 @@ void MonostepAudioProcessor::randomizeFx()
|
||||||
applyParamValue ("drive", random.nextFloat());
|
applyParamValue ("drive", random.nextFloat());
|
||||||
applyParamValue ("ringmod", random.nextFloat());
|
applyParamValue ("ringmod", random.nextFloat());
|
||||||
applyParamValue ("delayTime", 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 ("delaySync", random.nextFloat() < 0.8f ? 1.0f : 0.0f);
|
||||||
|
applyParamValue ("delayDryWet", random.nextFloat() * 0.8f);
|
||||||
applyParamValue ("reverbRoom", 0.2f + random.nextFloat() * 0.7f);
|
applyParamValue ("reverbRoom", 0.2f + random.nextFloat() * 0.7f);
|
||||||
applyParamValue ("reverbStrength", random.nextFloat() * 0.7f);
|
applyParamValue ("reverbStrength", random.nextFloat());
|
||||||
applyParamValue ("reverbDiffusion", 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()
|
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
|
// Accent tracks the current step (not just gate changes), so it holds for
|
||||||
// the whole step even when the note repeats without retriggering.
|
// the whole step even when the note repeats without retriggering. Kept
|
||||||
voice.setAccentLevel (seqAccent ? 1.0f + accentParam->load() * 4.0f : 1.0f);
|
// 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)
|
if (wantGate != lastGateApplied)
|
||||||
{
|
{
|
||||||
|
|
@ -715,10 +796,12 @@ void MonostepAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juc
|
||||||
|
|
||||||
monostep::FxProcessor::Params fp;
|
monostep::FxProcessor::Params fp;
|
||||||
fp.delayTime = delayTimeParam->load();
|
fp.delayTime = delayTimeParam->load();
|
||||||
fp.delayMix = delayStrengthParam->load();
|
fp.delayFeedback = delayStrengthParam->load();
|
||||||
fp.delaySync = delaySyncParam->load() >= 0.5f;
|
fp.delaySync = delaySyncParam->load() >= 0.5f;
|
||||||
|
fp.delayMix = delayDryWetParam->load();
|
||||||
fp.reverbRoom = reverbRoomParam->load();
|
fp.reverbRoom = reverbRoomParam->load();
|
||||||
fp.reverbMix = reverbStrengthParam->load();
|
fp.reverbLevel = reverbStrengthParam->load();
|
||||||
|
fp.reverbMix = reverbDryWetParam->load();
|
||||||
fp.reverbDiff = reverbDiffusionParam->load();
|
fp.reverbDiff = reverbDiffusionParam->load();
|
||||||
fp.bpm = bpm;
|
fp.bpm = bpm;
|
||||||
fx.setParams (fp);
|
fx.setParams (fp);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ public:
|
||||||
void randomizeEnv();
|
void randomizeEnv();
|
||||||
void randomizeSeqSettings();
|
void randomizeSeqSettings();
|
||||||
void randomizeFx();
|
void randomizeFx();
|
||||||
|
void randomizeAccent();
|
||||||
|
void randomizeSlide();
|
||||||
|
void randomizeFine();
|
||||||
|
void randomizeRate();
|
||||||
|
|
||||||
juce::String getStepNoteName (int idx) const;
|
juce::String getStepNoteName (int idx) const;
|
||||||
|
|
||||||
|
|
@ -110,9 +114,11 @@ private:
|
||||||
std::atomic<float>* delayTimeParam = nullptr;
|
std::atomic<float>* delayTimeParam = nullptr;
|
||||||
std::atomic<float>* delayStrengthParam = nullptr;
|
std::atomic<float>* delayStrengthParam = nullptr;
|
||||||
std::atomic<float>* delaySyncParam = nullptr;
|
std::atomic<float>* delaySyncParam = nullptr;
|
||||||
|
std::atomic<float>* delayDryWetParam = nullptr;
|
||||||
std::atomic<float>* reverbRoomParam = nullptr;
|
std::atomic<float>* reverbRoomParam = nullptr;
|
||||||
std::atomic<float>* reverbStrengthParam = nullptr;
|
std::atomic<float>* reverbStrengthParam = nullptr;
|
||||||
std::atomic<float>* reverbDiffusionParam = nullptr;
|
std::atomic<float>* reverbDiffusionParam = nullptr;
|
||||||
|
std::atomic<float>* reverbDryWetParam = nullptr;
|
||||||
|
|
||||||
monostep::StepSequencer sequencer;
|
monostep::StepSequencer sequencer;
|
||||||
monostep::SynthVoice voice;
|
monostep::SynthVoice voice;
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,19 @@ namespace monostep
|
||||||
{
|
{
|
||||||
|
|
||||||
// Freeverb-style comb / allpass sizes, slightly offset per channel so the
|
// Freeverb-style comb / allpass sizes, slightly offset per channel so the
|
||||||
// left and right reverb tails decorrelate.
|
// left and right reverb tails decorrelate. Halved from the classic freeverb
|
||||||
|
// set so the early reflections land ~13 ms after the note instead of ~25 ms:
|
||||||
|
// a 100%-wet reverb keeps its tail but speaks much sooner.
|
||||||
static constexpr int combSizes[2][4] =
|
static constexpr int combSizes[2][4] =
|
||||||
{
|
{
|
||||||
{ 1116, 1188, 1277, 1356 },
|
{ 558, 594, 639, 678 },
|
||||||
{ 1126, 1198, 1287, 1366 }
|
{ 563, 599, 644, 683 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int allpassSizes[2][2] =
|
static constexpr int allpassSizes[2][2] =
|
||||||
{
|
{
|
||||||
{ 225, 556 },
|
{ 113, 278 },
|
||||||
{ 235, 566 }
|
{ 118, 283 }
|
||||||
};
|
};
|
||||||
|
|
||||||
float FxProcessor::delayTimeSeconds (float knob, bool sync, double bpm)
|
float FxProcessor::delayTimeSeconds (float knob, bool sync, double bpm)
|
||||||
|
|
@ -36,7 +38,7 @@ juce::String FxProcessor::delayTimeLabel (float knob, bool sync, double bpm)
|
||||||
{
|
{
|
||||||
if (sync)
|
if (sync)
|
||||||
{
|
{
|
||||||
static const char* names[] = { "1/16", "1/8", "1/8D", "1/4", "1/4D", "1/2", "1/2D", "1W" };
|
static const char* names[] = { "1/16", "1/8", "3/16", "1/4", "3/8", "1/2", "3/4", "1 bar" };
|
||||||
const int idx = juce::roundToInt (juce::jlimit (0.0f, 1.0f, knob) * 7.0f);
|
const int idx = juce::roundToInt (juce::jlimit (0.0f, 1.0f, knob) * 7.0f);
|
||||||
return names[juce::jlimit (0, 7, idx)];
|
return names[juce::jlimit (0, 7, idx)];
|
||||||
}
|
}
|
||||||
|
|
@ -113,9 +115,11 @@ void FxProcessor::reset()
|
||||||
void FxProcessor::setParams (const Params& p)
|
void FxProcessor::setParams (const Params& p)
|
||||||
{
|
{
|
||||||
params.delayTime = juce::jlimit (0.0f, 1.0f, p.delayTime);
|
params.delayTime = juce::jlimit (0.0f, 1.0f, p.delayTime);
|
||||||
params.delayMix = juce::jlimit (0.0f, 1.0f, p.delayMix);
|
params.delayFeedback = juce::jlimit (0.0f, 0.9f, p.delayFeedback);
|
||||||
params.delaySync = p.delaySync;
|
params.delaySync = p.delaySync;
|
||||||
|
params.delayMix = juce::jlimit (0.0f, 1.0f, p.delayMix);
|
||||||
params.reverbRoom = juce::jlimit (0.0f, 1.0f, p.reverbRoom);
|
params.reverbRoom = juce::jlimit (0.0f, 1.0f, p.reverbRoom);
|
||||||
|
params.reverbLevel = juce::jlimit (0.0f, 1.0f, p.reverbLevel);
|
||||||
params.reverbMix = juce::jlimit (0.0f, 1.0f, p.reverbMix);
|
params.reverbMix = juce::jlimit (0.0f, 1.0f, p.reverbMix);
|
||||||
params.reverbDiff = juce::jlimit (0.0f, 1.0f, p.reverbDiff);
|
params.reverbDiff = juce::jlimit (0.0f, 1.0f, p.reverbDiff);
|
||||||
params.bpm = juce::jmax (20.0, p.bpm);
|
params.bpm = juce::jmax (20.0, p.bpm);
|
||||||
|
|
@ -128,8 +132,23 @@ void FxProcessor::process (juce::AudioBuffer<float>& buffer, int numSamples)
|
||||||
if (numSamples <= 0 || buffer.getNumChannels() == 0)
|
if (numSamples <= 0 || buffer.getNumChannels() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// The reverb must feed off the dry (pre-delay) signal, not the delay's
|
||||||
|
// output, so snapshot the incoming buffer before the delay runs.
|
||||||
|
const bool reverbActive = params.reverbMix > 0.0001f && params.reverbLevel > 0.0001f;
|
||||||
|
if (reverbActive)
|
||||||
|
{
|
||||||
|
if (dryScratch.getNumSamples() < numSamples)
|
||||||
|
dryScratch.setSize (buffer.getNumChannels(), numSamples, false, false, true);
|
||||||
|
|
||||||
|
const int n = juce::jmin (buffer.getNumChannels(), dryScratch.getNumChannels());
|
||||||
|
for (int c = 0; c < n; ++c)
|
||||||
|
dryScratch.copyFrom (c, 0, buffer, c, 0, numSamples);
|
||||||
|
}
|
||||||
|
|
||||||
processDelay (buffer, numSamples);
|
processDelay (buffer, numSamples);
|
||||||
processReverb (buffer, numSamples);
|
|
||||||
|
if (reverbActive)
|
||||||
|
processReverb (dryScratch, buffer, numSamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FxProcessor::processDelay (juce::AudioBuffer<float>& buffer, int numSamples)
|
void FxProcessor::processDelay (juce::AudioBuffer<float>& buffer, int numSamples)
|
||||||
|
|
@ -166,7 +185,7 @@ void FxProcessor::processDelay (juce::AudioBuffer<float>& buffer, int numSamples
|
||||||
|
|
||||||
// Feedback with a little high-frequency damping.
|
// Feedback with a little high-frequency damping.
|
||||||
d.feedbackLp += 0.35f * (delayed - d.feedbackLp);
|
d.feedbackLp += 0.35f * (delayed - d.feedbackLp);
|
||||||
d.memory[d.writeIndex] = x + 0.42f * d.feedbackLp;
|
d.memory[d.writeIndex] = x + params.delayFeedback * d.feedbackLp;
|
||||||
|
|
||||||
out[i] = x + delayed * mix;
|
out[i] = x + delayed * mix;
|
||||||
|
|
||||||
|
|
@ -176,24 +195,38 @@ void FxProcessor::processDelay (juce::AudioBuffer<float>& buffer, int numSamples
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FxProcessor::processReverb (juce::AudioBuffer<float>& buffer, int numSamples)
|
void FxProcessor::processReverb (const juce::AudioBuffer<float>& dryIn,
|
||||||
|
juce::AudioBuffer<float>& buffer, int numSamples)
|
||||||
{
|
{
|
||||||
if (params.reverbMix <= 0.0001f)
|
if (params.reverbMix <= 0.0001f || params.reverbLevel <= 0.0001f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int n = juce::jmin (numChannels, buffer.getNumChannels());
|
const int n = juce::jmin (numChannels, juce::jmin (dryIn.getNumChannels(), buffer.getNumChannels()));
|
||||||
const float combGain = 0.70f + 0.28f * params.reverbRoom; // 0.70 .. 0.98
|
const float combGain = 0.70f + 0.28f * params.reverbRoom; // 0.70 .. 0.98
|
||||||
const float allpassGain = 0.75f * params.reverbDiff; // 0 .. 0.75
|
const float allpassGain = 0.75f * params.reverbDiff; // 0 .. 0.75
|
||||||
|
// Room normalisation: the comb network's DC gain is ~4 / (1 - combGain),
|
||||||
|
// so scaling by (1 - combGain) keeps the wet level bounded as the room
|
||||||
|
// (decay length) grows instead of blowing up near oscillation. The 2.5
|
||||||
|
// constant is calibrated (standalone replication of this network): at
|
||||||
|
// room 0.5 it puts the note-off ring ~ +6 dB above the dry and the tail
|
||||||
|
// ~ -6 dB one second in, so the reverb is clearly audible even at modest
|
||||||
|
// dry/wet settings. The wet is intentionally NOT clipped here: any
|
||||||
|
// soft-clip knee far below the signal level pins the wet at a constant
|
||||||
|
// flat value (the early tail stops audibly decaying, which reads as a
|
||||||
|
// "reverb slowly kicking in" plateau) and makes 100% wet sound quiet
|
||||||
|
// next to a hot dry signal.
|
||||||
|
const float wetScale = 2.5f * (1.0f - combGain);
|
||||||
const float mix = params.reverbMix;
|
const float mix = params.reverbMix;
|
||||||
|
|
||||||
for (int ch = 0; ch < n; ++ch)
|
for (int ch = 0; ch < n; ++ch)
|
||||||
{
|
{
|
||||||
auto& r = reverbs[ch];
|
auto& r = reverbs[ch];
|
||||||
|
const float* in = dryIn.getReadPointer (ch);
|
||||||
auto* out = buffer.getWritePointer (ch);
|
auto* out = buffer.getWritePointer (ch);
|
||||||
|
|
||||||
for (int i = 0; i < numSamples; ++i)
|
for (int i = 0; i < numSamples; ++i)
|
||||||
{
|
{
|
||||||
const float x = out[i];
|
const float x = in[i];
|
||||||
|
|
||||||
float combSum = 0.0f;
|
float combSum = 0.0f;
|
||||||
for (int c = 0; c < 4; ++c)
|
for (int c = 0; c < 4; ++c)
|
||||||
|
|
@ -208,7 +241,7 @@ void FxProcessor::processReverb (juce::AudioBuffer<float>& buffer, int numSample
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float wet = combSum * 0.012f;
|
float wet = combSum * wetScale * params.reverbLevel;
|
||||||
|
|
||||||
for (int a = 0; a < 2; ++a)
|
for (int a = 0; a < 2; ++a)
|
||||||
{
|
{
|
||||||
|
|
@ -223,7 +256,7 @@ void FxProcessor::processReverb (juce::AudioBuffer<float>& buffer, int numSample
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out[i] = x * (1.0f - mix) + wet * mix;
|
out[i] += wet * mix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,11 @@ public:
|
||||||
struct Params
|
struct Params
|
||||||
{
|
{
|
||||||
float delayTime = 0.35f; // normalized knob 0..1
|
float delayTime = 0.35f; // normalized knob 0..1
|
||||||
float delayMix = 0.0f; // 0..1 dry/wet
|
float delayFeedback = 0.45f; // 0..0.9 feedback (repeat density)
|
||||||
bool delaySync = true; // tempo-synced vs. free milliseconds
|
bool delaySync = true; // tempo-synced vs. free milliseconds
|
||||||
|
float delayMix = 0.0f; // 0..1 dry/wet
|
||||||
float reverbRoom = 0.5f; // 0..1
|
float reverbRoom = 0.5f; // 0..1
|
||||||
|
float reverbLevel = 1.0f; // 0..1 wet send gain
|
||||||
float reverbMix = 0.0f; // 0..1 dry/wet
|
float reverbMix = 0.0f; // 0..1 dry/wet
|
||||||
float reverbDiff = 0.6f; // 0..1 allpass diffusion
|
float reverbDiff = 0.6f; // 0..1 allpass diffusion
|
||||||
double bpm = 120.0;
|
double bpm = 120.0;
|
||||||
|
|
@ -52,7 +54,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void processDelay (juce::AudioBuffer<float>& buffer, int numSamples);
|
void processDelay (juce::AudioBuffer<float>& buffer, int numSamples);
|
||||||
void processReverb (juce::AudioBuffer<float>& buffer, int numSamples);
|
void processReverb (const juce::AudioBuffer<float>& dryIn, juce::AudioBuffer<float>& buffer, int numSamples);
|
||||||
|
|
||||||
double sampleRate = 44100.0;
|
double sampleRate = 44100.0;
|
||||||
int numChannels = 2;
|
int numChannels = 2;
|
||||||
|
|
@ -64,6 +66,10 @@ private:
|
||||||
Params params;
|
Params params;
|
||||||
float currentDelaySeconds = 0.0f;
|
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<DelayChannel> delays;
|
||||||
std::vector<ReverbChannel> reverbs;
|
std::vector<ReverbChannel> reverbs;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,10 @@ private:
|
||||||
fenvStage = Stage::attack;
|
fenvStage = Stage::attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RC-style (exponential) filter envelope: the cutoff glides smoothly instead
|
||||||
|
// of stepping linearly, so fast filter sweeps sound analog rather than
|
||||||
|
// zippered. Each stage still reaches ~95% within the labelled time, so the
|
||||||
|
// knob values keep their musical meaning.
|
||||||
void updateFilterEnvelope()
|
void updateFilterEnvelope()
|
||||||
{
|
{
|
||||||
const float sr = sampleRate;
|
const float sr = sampleRate;
|
||||||
|
|
@ -144,23 +148,37 @@ private:
|
||||||
switch (fenvStage)
|
switch (fenvStage)
|
||||||
{
|
{
|
||||||
case Stage::attack:
|
case Stage::attack:
|
||||||
fenv += 1.0f / (params.fAttack * sr);
|
{
|
||||||
if (fenv >= 1.0f) { fenv = 1.0f; fenvStage = Stage::decay; }
|
// Accented notes attack the filter ever so slightly faster.
|
||||||
|
const float acc = accentSmooth - 1.0f;
|
||||||
|
const float t = juce::jmax (0.0005f, params.fAttack / (1.0f + acc * 0.5f));
|
||||||
|
const float a = 1.0f - std::exp (-3.0f / (t * sr));
|
||||||
|
fenv += (1.0f - fenv) * a;
|
||||||
|
if (fenv >= 0.999f) { fenv = 1.0f; fenvStage = Stage::decay; }
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Stage::decay:
|
case Stage::decay:
|
||||||
fenv -= (1.0f - params.fSustain) / (params.fDecay * sr);
|
{
|
||||||
if (fenv <= params.fSustain) { fenv = params.fSustain; fenvStage = Stage::sustain; }
|
const float t = juce::jmax (0.0005f, params.fDecay);
|
||||||
|
const float a = 1.0f - std::exp (-3.0f / (t * sr));
|
||||||
|
fenv += (params.fSustain - fenv) * a;
|
||||||
|
if (std::fabs (fenv - params.fSustain) < 0.001f) { fenv = params.fSustain; fenvStage = Stage::sustain; }
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Stage::sustain:
|
case Stage::sustain:
|
||||||
fenv = params.fSustain;
|
fenv = params.fSustain;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Stage::release:
|
case Stage::release:
|
||||||
fenv -= 1.0f / (params.fRelease * sr);
|
{
|
||||||
if (fenv <= 0.0f) { fenv = 0.0f; fenvStage = Stage::idle; }
|
const float t = juce::jmax (0.0005f, params.fRelease);
|
||||||
|
const float a = 1.0f - std::exp (-3.0f / (t * sr));
|
||||||
|
fenv -= fenv * a;
|
||||||
|
if (fenv <= 0.001f) { fenv = 0.0f; fenvStage = Stage::idle; }
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Stage::idle:
|
case Stage::idle:
|
||||||
break;
|
break;
|
||||||
|
|
@ -278,15 +296,18 @@ private:
|
||||||
|
|
||||||
float renderSample()
|
float renderSample()
|
||||||
{
|
{
|
||||||
updateEnvelope();
|
|
||||||
updateFilterEnvelope();
|
|
||||||
updateGlide();
|
|
||||||
|
|
||||||
// Accent gains fast attack / slow release, so the boost fades out smoothly
|
// Accent gains fast attack / slow release, so the boost fades out smoothly
|
||||||
// at the tail of an accented note instead of cutting off hard-edged.
|
// at the tail of an accented note instead of cutting off hard-edged.
|
||||||
accentSmooth += (accentLevel - accentSmooth)
|
accentSmooth += (accentLevel - accentSmooth)
|
||||||
* (accentLevel > accentSmooth ? accentAttackCoef : accentReleaseCoef);
|
* (accentLevel > accentSmooth ? accentAttackCoef : accentReleaseCoef);
|
||||||
|
|
||||||
|
// 0 for unaccented steps, rising with the accent knob on accented ones.
|
||||||
|
const float accBoost = accentSmooth - 1.0f;
|
||||||
|
|
||||||
|
updateEnvelope();
|
||||||
|
updateFilterEnvelope();
|
||||||
|
updateGlide();
|
||||||
|
|
||||||
const float incA = (currentFreq * params.detuneRatioA) / sampleRate;
|
const float incA = (currentFreq * params.detuneRatioA) / sampleRate;
|
||||||
const float incB = (currentFreq * params.detuneRatio) / sampleRate;
|
const float incB = (currentFreq * params.detuneRatio) / sampleRate;
|
||||||
|
|
||||||
|
|
@ -302,14 +323,17 @@ private:
|
||||||
out = (1.0f - params.ringMod) * out + params.ringMod * (a * b);
|
out = (1.0f - params.ringMod) * out + params.ringMod * (a * b);
|
||||||
|
|
||||||
const float preFilter = out;
|
const float preFilter = out;
|
||||||
|
|
||||||
|
// Accented steps open the filter a tiny bit, so they sparkle without
|
||||||
|
// relying on a big volume jump.
|
||||||
const float envCutoff = juce::jlimit (20.0f, 20000.0f,
|
const float envCutoff = juce::jlimit (20.0f, 20000.0f,
|
||||||
params.cutoff * std::pow (2.0f, params.fAmount * fenv));
|
params.cutoff * std::pow (2.0f, params.fAmount * fenv + accBoost * 1.5f));
|
||||||
out = processFilter (out, envCutoff);
|
out = processFilter (out, envCutoff);
|
||||||
|
|
||||||
// Accented steps also get a touch of the unfiltered signal so they cut
|
// Accented steps also get a touch of the unfiltered signal so they cut
|
||||||
// through the mix (presence), not just a volume bump.
|
// through the mix (presence), not just a volume bump.
|
||||||
if (accentSmooth > 1.0f)
|
if (accBoost > 0.0f)
|
||||||
out += (accentSmooth - 1.0f) * 0.2f * preFilter;
|
out += accBoost * 0.2f * preFilter;
|
||||||
|
|
||||||
if (params.drive > 0.0f)
|
if (params.drive > 0.0f)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
22
cmake/WriteBuildStamp.cmake
Normal file
22
cmake/WriteBuildStamp.cmake
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generates BuildStamp.h with the current date/time. Run as a build-time
|
||||||
|
# custom command so the stamp is refreshed on every build (the TU that includes
|
||||||
|
# it is recompiled because the header mtime changes each time).
|
||||||
|
|
||||||
|
if(NOT DEFINED MONOSTEP_BUILD_STAMP_HEADER)
|
||||||
|
message(FATAL_ERROR "MONOSTEP_BUILD_STAMP_HEADER must be set")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(TIMESTAMP STAMP "%Y-%m-%d__%H:%M:%S")
|
||||||
|
|
||||||
|
get_filename_component(MONOSTEP_BUILD_STAMP_DIR "${MONOSTEP_BUILD_STAMP_HEADER}" DIRECTORY)
|
||||||
|
file(MAKE_DIRECTORY "${MONOSTEP_BUILD_STAMP_DIR}")
|
||||||
|
|
||||||
|
file(WRITE "${MONOSTEP_BUILD_STAMP_HEADER}"
|
||||||
|
"// Generated at build time - do not edit.
|
||||||
|
#ifndef MONOSTEP_BUILD_STAMP_H_INCLUDED
|
||||||
|
#define MONOSTEP_BUILD_STAMP_H_INCLUDED
|
||||||
|
|
||||||
|
#define MONOSTEP_BUILD_DATE \"${STAMP}\"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
")
|
||||||
|
|
@ -305,6 +305,8 @@ static int testProcessorRendering()
|
||||||
*processor.getAPVTS().getRawParameterValue ("release") = 0.01f;
|
*processor.getAPVTS().getRawParameterValue ("release") = 0.01f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("delayStrength") = 0.0f;
|
*processor.getAPVTS().getRawParameterValue ("delayStrength") = 0.0f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("reverbStrength") = 0.0f;
|
*processor.getAPVTS().getRawParameterValue ("reverbStrength") = 0.0f;
|
||||||
|
*processor.getAPVTS().getRawParameterValue ("delayDryWet") = 0.0f;
|
||||||
|
*processor.getAPVTS().getRawParameterValue ("reverbDryWet") = 0.0f;
|
||||||
|
|
||||||
const int releaseBlock = numBlocks / 2;
|
const int releaseBlock = numBlocks / 2;
|
||||||
|
|
||||||
|
|
@ -360,9 +362,11 @@ static int testProcessorRendering()
|
||||||
*processor.getAPVTS().getRawParameterValue ("delayStrength") = 0.8f;
|
*processor.getAPVTS().getRawParameterValue ("delayStrength") = 0.8f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("delayTime") = 0.4f;
|
*processor.getAPVTS().getRawParameterValue ("delayTime") = 0.4f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("delaySync") = 1.0f;
|
*processor.getAPVTS().getRawParameterValue ("delaySync") = 1.0f;
|
||||||
|
*processor.getAPVTS().getRawParameterValue ("delayDryWet") = 0.5f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("reverbStrength") = 0.8f;
|
*processor.getAPVTS().getRawParameterValue ("reverbStrength") = 0.8f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("reverbRoom") = 0.9f;
|
*processor.getAPVTS().getRawParameterValue ("reverbRoom") = 0.9f;
|
||||||
*processor.getAPVTS().getRawParameterValue ("reverbDiffusion") = 1.0f;
|
*processor.getAPVTS().getRawParameterValue ("reverbDiffusion") = 1.0f;
|
||||||
|
*processor.getAPVTS().getRawParameterValue ("reverbDryWet") = 0.5f;
|
||||||
|
|
||||||
const double wetTail = renderFxTail();
|
const double wetTail = renderFxTail();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue