Skip to content

Commit

Permalink
First pass of tuning-aware filters (#3866)
Browse files Browse the repository at this point in the history
Tuning aware filters read the SCL/KBM for setting cutoff frequency.
This is a first incomplete checkpoint towards the feature. It is
incomplete because

1. Primarily I am not 100% sure it is correct, but also
2. The display of filter values is still 12-TET

Addresses #3827
  • Loading branch information
baconpaul authored Feb 10, 2021
1 parent 7ba38d9 commit 8112ecf
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 12 deletions.
6 changes: 6 additions & 0 deletions src/common/Parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ bool Parameter::can_extend_range()
case ct_lfoamplitude:
case ct_fmratio:
case ct_reson_res_extendable:
case ct_freq_audible_with_tunability:
case ct_freq_audible_with_very_low_lowerbound:
return true;
}
return false;
Expand Down Expand Up @@ -419,6 +421,7 @@ void Parameter::set_type(int ctrltype)
break;
case ct_freq_audible:
case ct_freq_audible_deactivatable:
case ct_freq_audible_with_tunability:
valtype = vt_float;
val_min.f = -60;
val_max.f = 70;
Expand Down Expand Up @@ -1020,6 +1023,7 @@ void Parameter::set_type(int ctrltype)
case ct_freq_hpf:
case ct_freq_audible:
case ct_freq_audible_deactivatable:
case ct_freq_audible_with_tunability:
case ct_freq_audible_with_very_low_lowerbound:
case ct_freq_reson_band1:
case ct_freq_reson_band2:
Expand Down Expand Up @@ -2198,6 +2202,7 @@ void Parameter::get_display_alt(char *txt, bool external, float ef)
case ct_freq_hpf:
case ct_freq_audible:
case ct_freq_audible_deactivatable:
case ct_freq_audible_with_tunability:
case ct_freq_audible_with_very_low_lowerbound:
case ct_freq_reson_band1:
case ct_freq_reson_band2:
Expand Down Expand Up @@ -3064,6 +3069,7 @@ bool Parameter::can_setvalue_from_string()
case ct_envtime_linkable_delay:
case ct_freq_audible:
case ct_freq_audible_deactivatable:
case ct_freq_audible_with_tunability:
case ct_freq_audible_with_very_low_lowerbound:
case ct_freq_reson_band1:
case ct_freq_reson_band2:
Expand Down
1 change: 1 addition & 0 deletions src/common/Parameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ enum ctrltypes
ct_decibel_deactivatable,
ct_freq_audible,
ct_freq_audible_deactivatable,
ct_freq_audible_with_tunability, // we abuse 'extended' to mean 'use SCL tunign'
ct_freq_audible_with_very_low_lowerbound,
ct_freq_mod,
ct_freq_hpf,
Expand Down
2 changes: 1 addition & 1 deletion src/common/SurgePatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ SurgePatch::SurgePatch(SurgeStorage *storage)
Surge::Skin::Connector::connectorByID("filter.subtype_" + std::to_string(f + 1)),
sc_id, cg_FILTER, f, false));
a->push_back(scene[sc].filterunit[f].cutoff.assign(
p_id.next(), id_s++, "cutoff", "Cutoff", ct_freq_audible,
p_id.next(), id_s++, "cutoff", "Cutoff", ct_freq_audible_with_tunability,
Surge::Skin::Connector::connectorByID("filter.cutoff_" + std::to_string(f + 1)),
sc_id, cg_FILTER, f, true, sceasy));
if (f == 1)
Expand Down
1 change: 1 addition & 0 deletions src/common/SurgeStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,7 @@ class alignas(16) SurgeStorage
bool retuneToStandardTuning()
{
init_tables();
currentTuning = twelveToneStandardMapping;
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/common/SurgeSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2074,7 +2074,8 @@ bool SurgeSynthesizer::setParameter01(long index, float value, bool external, bo
}
else
{
storage.getPatch().scene[s].filterunit[1].cutoff.set_type(ct_freq_audible);
storage.getPatch().scene[s].filterunit[1].cutoff.set_type(
ct_freq_audible_with_tunability);
storage.getPatch().scene[s].filterunit[1].cutoff.set_name("Cutoff");
}
need_refresh = true;
Expand Down
19 changes: 18 additions & 1 deletion src/common/dsp/FilterCoefficientMaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,33 @@
#include "filters/NonlinearFeedback.h"
#include "filters/NonlinearStates.h"

#include "DebugHelpers.h"

using namespace std;

const float smooth = 0.2f;

FilterCoefficientMaker::FilterCoefficientMaker() { Reset(); }

void FilterCoefficientMaker::MakeCoeffs(float Freq, float Reso, int Type, int SubType,
SurgeStorage *storageI)
SurgeStorage *storageI, bool tuningAdjusted)
{
storage = storageI;
if (tuningAdjusted && storage)
{
/*
* Alright frequency comes in in units of semitones from 440 / Midi Note 69.
*/
auto idx = (int)floor(Freq + 69);
float frac = (Freq + 69) - idx; // frac is 0 means use idx; frac is 1 means use idx+1

float b0 = storage->currentTuning.logScaledFrequencyForMidiNote(idx) * 12;
float b1 = storage->currentTuning.logScaledFrequencyForMidiNote(idx + 1) * 12;

auto q = (1.f - frac) * b0 + frac * b1;

Freq = q - 69;
}

// Force compiler to error out if I miss one
fu_type fType = (fu_type)Type;
Expand Down
3 changes: 2 additions & 1 deletion src/common/dsp/FilterCoefficientMaker.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const int n_cm_coeffs = 8;
class FilterCoefficientMaker
{
public:
void MakeCoeffs(float Freq, float Reso, int Type, int SubType, SurgeStorage *storage);
void MakeCoeffs(float Freq, float Reso, int Type, int SubType, SurgeStorage *storage,
bool tuningAdjusted);
void Reset();
FilterCoefficientMaker();
float C[n_cm_coeffs], dC[n_cm_coeffs], tC[n_cm_coeffs]; // K1,K2,Q1,Q2,V1,V2,V3,etc
Expand Down
6 changes: 4 additions & 2 deletions src/common/dsp/SurgeVoice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,10 +1032,12 @@ void SurgeVoice::SetQFB(QuadFilterChainState *Q, int e) // Q == 0 means init(ial
cutoffB += cutoffA;

CM[0].MakeCoeffs(cutoffA, localcopy[id_resoa].f, scene->filterunit[0].type.val.i,
scene->filterunit[0].subtype.val.i, storage);
scene->filterunit[0].subtype.val.i, storage,
scene->filterunit[0].cutoff.extend_range);
CM[1].MakeCoeffs(
cutoffB, scene->f2_link_resonance.val.b ? localcopy[id_resoa].f : localcopy[id_resob].f,
scene->filterunit[1].type.val.i, scene->filterunit[1].subtype.val.i, storage);
scene->filterunit[1].type.val.i, scene->filterunit[1].subtype.val.i, storage,
scene->filterunit[1].cutoff.extend_range);

for (int u = 0; u < n_filterunits_per_scene; u++)
{
Expand Down
3 changes: 2 additions & 1 deletion src/common/dsp/effect/CombulatorEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,13 @@ void CombulatorEffect::process(float *dataL, float *dataR)
/*
* So now set up across the voices (e for 'entry' to match SurgeVoice) and the channels (c)
*/
bool useTuning = fxdata->p[combulator_freq1].extend_range;
for (int e = 0; e < 3; ++e)
{
for (int c = 0; c < 2; ++c)
{
coeff[e][c].MakeCoeffs(freq[e].v, fbscaled, type,
subtype | QFUSubtypeMasks::EXTENDED_COMB, storage);
subtype | QFUSubtypeMasks::EXTENDED_COMB, storage, useTuning);

for (int i = 0; i < n_cm_coeffs; i++)
{
Expand Down
2 changes: 1 addition & 1 deletion src/common/dsp/effect/ResonatorEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void ResonatorEffect::process(float *dataL, float *dataR)
for (int c = 0; c < 2; ++c)
{
coeff[e][c].MakeCoeffs(cutoff[e].v, resonance[e].v * rescomp[whichModel], type, subtype,
storage);
storage, false);

for (int i = 0; i < n_cm_coeffs; i++)
{
Expand Down
18 changes: 14 additions & 4 deletions src/common/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3430,9 +3430,19 @@ int32_t SurgeGUIEditor::controlModifierClicked(CControl *control, CButtonState b
{
if (!(p->ctrltype == ct_fmratio && p->can_be_absolute() && p->absolute))
{
std::string txt = p->ctrltype == ct_reson_res_extendable
? "Modulation Extends into Self-oscillation"
: "Extend Range";
std::string txt = "Extend Range";
switch (p->ctrltype)
{
case ct_reson_res_extendable:
txt = "Modulation Extends into Self-oscillation";
break;
case ct_freq_audible_with_tunability:
case ct_freq_audible_with_very_low_lowerbound:
txt = "Filter Uses SCL/KBM Tuning";
break;
default:
break;
}

addCallbackMenu(contextMenu, Surge::UI::toOSCaseForMenu(txt), [this, p]() {
p->extend_range = !p->extend_range;
Expand Down Expand Up @@ -5044,7 +5054,7 @@ void SurgeGUIEditor::toggleTuning()
mappingCacheForToggle = this->synth->storage.currentMapping.rawText;
}
this->synth->storage.remapToStandardKeyboard();
this->synth->storage.init_tables();
this->synth->storage.retuneToStandardTuning();
}

if (statusTune)
Expand Down

0 comments on commit 8112ecf

Please sign in to comment.