Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add several clipping options to Delay Feedback parameter (including none) #5926

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/common/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ bool Parameter::has_deformoptions() const
case ct_modern_trimix:
case ct_alias_mask:
case ct_tape_drive:
case ct_dly_fb_clippingmodes:
return true;
default:
break;
Expand Down Expand Up @@ -961,6 +962,7 @@ void Parameter::set_type(int ctrltype)
break;
case ct_percent:
case ct_percent_deactivatable:
case ct_dly_fb_clippingmodes:
case ct_percent_oscdrift:
val_min.f = 0;
val_max.f = 1;
Expand Down Expand Up @@ -1300,6 +1302,7 @@ void Parameter::set_type(int ctrltype)
switch (ctrltype)
{
case ct_percent:
case ct_dly_fb_clippingmodes:
case ct_percent_deactivatable:
case ct_percent_oscdrift:
case ct_percent200:
Expand Down Expand Up @@ -1622,6 +1625,7 @@ void Parameter::bound_value(bool force_integer)
{
case ct_percent:
case ct_percent_deactivatable:
case ct_dly_fb_clippingmodes:
case ct_percent_oscdrift:
case ct_percent200:
case ct_percent_bipolar:
Expand Down Expand Up @@ -3868,6 +3872,7 @@ bool Parameter::can_setvalue_from_string() const
{
case ct_percent:
case ct_percent_deactivatable:
case ct_dly_fb_clippingmodes:
case ct_percent_oscdrift:
case ct_percent200:
case ct_percent_bipolar:
Expand Down
1 change: 1 addition & 0 deletions src/common/Parameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum ctrltypes
ct_none,
ct_percent,
ct_percent_deactivatable,
ct_dly_fb_clippingmodes,
ct_percent_bipolar,
ct_percent_bipolar_stereo, // bipolar with special text strings at -100% +100% and 0%
ct_percent_bipolar_stringbal, // bipolar with special text strings
Expand Down
3 changes: 2 additions & 1 deletion src/common/SurgeStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ const int FIRoffsetI16 = FIRipolI16_N >> 1;
// added (a lot of) new waveshapers
// added two additional FX slots to all FX chains
// added new Conditioner parameter (Side Low Cut)
// 17 -> 18 (XT 1.1 release) added clipping options to Delay Feedback parameter (via deform)

const int ff_revision = 17;
const int ff_revision = 18;

extern float sinctable alignas(16)[(FIRipol_M + 1) * FIRipol_N * 2];
extern float sinctable1X alignas(16)[(FIRipol_M + 1) * FIRipol_N];
Expand Down
33 changes: 30 additions & 3 deletions src/common/dsp/effects/DelayEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,28 @@ void DelayEffect::process(float *dataL, float *dataR)
_mm_store_ss(&tbufferR[k], R);
}

softclip_block(tbufferL, BLOCK_SIZE_QUAD);
softclip_block(tbufferR, BLOCK_SIZE_QUAD);
switch (fxdata->p[dly_feedback].deform_type)
{
case dly_clipping_soft:
softclip_block(tbufferL, BLOCK_SIZE_QUAD);
softclip_block(tbufferR, BLOCK_SIZE_QUAD);
break;
case dly_clipping_tanh:
tanh7_block(tbufferL, BLOCK_SIZE_QUAD);
tanh7_block(tbufferR, BLOCK_SIZE_QUAD);
break;
case dly_clipping_hard:
hardclip_block(tbufferL, BLOCK_SIZE_QUAD);
hardclip_block(tbufferR, BLOCK_SIZE_QUAD);
break;
case dly_clipping_hard18:
hardclip_block8(tbufferL, BLOCK_SIZE_QUAD);
hardclip_block8(tbufferR, BLOCK_SIZE_QUAD);
break;
case dly_clipping_off:
default:
break;
}

if (!fxdata->p[dly_highcut].deactivated)
{
Expand Down Expand Up @@ -266,7 +286,8 @@ void DelayEffect::init_ctrltypes()
fxdata->p[dly_time_right].set_name("Right");
fxdata->p[dly_time_right].set_type(ct_envtime_linkable_delay);
fxdata->p[dly_feedback].set_name("Feedback");
fxdata->p[dly_feedback].set_type(ct_percent);
fxdata->p[dly_feedback].set_type(ct_dly_fb_clippingmodes);
fxdata->p[dly_feedback].deform_type = 1;
fxdata->p[dly_crossfeed].set_name("Crossfeed");
fxdata->p[dly_crossfeed].set_type(ct_percent);
fxdata->p[dly_lowcut].set_name("Low Cut");
Expand Down Expand Up @@ -307,6 +328,7 @@ void DelayEffect::init_default_values()
fxdata->p[dly_time_right].val.f = -2.f;
fxdata->p[dly_time_right].deactivated = false;
fxdata->p[dly_feedback].val.f = 0.0f;
fxdata->p[dly_feedback].deform_type = 1;
fxdata->p[dly_crossfeed].val.f = 0.0f;

fxdata->p[dly_lowcut].val.f = -24.f;
Expand All @@ -331,4 +353,9 @@ void DelayEffect::handleStreamingMismatches(int streamingRevision,
fxdata->p[dly_highcut].deactivated = false;
fxdata->p[dly_time_right].deactivated = false;
}

if (streamingRevision <= 17)
{
fxdata->p[dly_feedback].deform_type = 1;
}
}
11 changes: 11 additions & 0 deletions src/common/dsp/effects/DelayEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ class DelayEffect : public Effect
dly_width,
};

enum delay_clipping_modes
{
dly_clipping_off,
dly_clipping_soft,
dly_clipping_tanh,
dly_clipping_hard,
dly_clipping_hard18,

num_dly_clipping_modes,
};

private:
lag<float, true> timeL, timeR;
bool inithadtempo;
Expand Down
39 changes: 33 additions & 6 deletions src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1821,16 +1821,42 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c
{
contextMenu.addSeparator();

juce::StringArray tapeHysteresisModes{"Normal", "Medium", "High",
"Very High"};
std::vector<std::string> tapeHysteresisModes = {"Normal", "Medium", "High",
"Very High"};

contextMenu.addSectionHeader("PRECISION");

for (int i = 0; i < tapeHysteresisModes.size(); ++i)
{
bool isChecked = p->deform_type == i;

contextMenu.addItem(tapeHysteresisModes[i].toStdString(), true,
contextMenu.addItem(Surge::GUI::toOSCaseForMenu(tapeHysteresisModes[i]),
true, isChecked, [this, isChecked, p, i]() {
p->deform_type = i;
if (!isChecked)
{
synth->storage.getPatch().isDirty = true;
}
});
}

break;
}
case ct_dly_fb_clippingmodes:
{
contextMenu.addSeparator();

std::vector<std::string> fbClipModes = {
"Disabled (DANGER!)", "Soft Clip (cubic)", "Soft Clip (tanh)",
"Hard Clip at 0 dBFS", "Hard Clip at +18 dBFS"};

contextMenu.addSectionHeader("LIMITING");

for (int i = 0; i < fbClipModes.size(); ++i)
{
bool isChecked = p->deform_type == i;

contextMenu.addItem(Surge::GUI::toOSCaseForMenu(fbClipModes[i]), true,
isChecked, [this, isChecked, p, i]() {
p->deform_type = i;
if (!isChecked)
Expand Down Expand Up @@ -2120,8 +2146,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c

contextMenu.addSeparator();

// see if we have any modulators that are unassigned, then create "Add Modulation
// from..." menu
// see if we have any modulators that are unassigned, then create "Add
// Modulation from..." menu
if (n_ms != n_modsources)
{
auto addModSub = juce::PopupMenu();
Expand Down Expand Up @@ -2373,7 +2399,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c
case ct_lfotype:
/*
** This code resets you to default if you double-click on control,
** but on the LFO type widget this is undesirable; it means if you accidentally
** but on the LFO type widget this is undesirable; it means if you
*accidentally
** Control-click on step sequencer, say, you go back to Sine and lose your
** edits. So suppress it!
*/
Expand Down