Skip to content

Commit

Permalink
Disallow reserved CCs from ever reaching MIDI learn code (#7011)
Browse files Browse the repository at this point in the history
* Disallow reserved CCs to even reach MIDI learn code
Fixes #7010
  • Loading branch information
mkruselj authored May 2, 2023
1 parent 82a5857 commit a89bc17
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 20 deletions.
83 changes: 67 additions & 16 deletions src/common/SurgeSynthesizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,18 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
fx_suspend_bitmask = 0;

for (int i = 0; i < n_fx_slots; ++i)
{
fx[i].reset(nullptr);
}

for (int i = 0; i < disallowedLearnCCs.size(); i++)
{
if (i == 0 || i == 6 || i == 32 || i == 38 || i == 64 || i == 74 || (i >= 98 && i <= 101) ||
i == 120 || i == 123)
{
disallowedLearnCCs[i] = true;
}
}

srand((unsigned)time(nullptr));
// TODO: FIX SCENE ASSUMPTION
Expand Down Expand Up @@ -122,6 +133,7 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
{
scene.modsources[i] = 0;
}

scene.modsources[ms_modwheel] = new ControllerModulationSource(storage.smoothingMode);
scene.modsources[ms_breath] = new ControllerModulationSource(storage.smoothingMode);
scene.modsources[ms_expression] = new ControllerModulationSource(storage.smoothingMode);
Expand All @@ -143,16 +155,16 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl

for (int osc = 0; osc < n_oscs; osc++)
{
// p 5 is unison detune
// p[5] is unison detune
scene.osc[osc].p[5].val.f = 0.1f;
}

for (int i = 0; i < n_filterunits_per_scene; i++)
{
scene.filterunit[i].type.set_user_data(&patch.patchFilterSelectorMapper);
}
scene.wsunit.type.set_user_data(&patch.patchWaveshaperSelectorMapper);

scene.wsunit.type.set_user_data(&patch.patchWaveshaperSelectorMapper);
scene.filterblock_configuration.val.i = fc_wide;

for (int l = 0; l < n_lfos_scene; l++)
Expand All @@ -167,7 +179,9 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
}

for (int k = 0; k < 128; ++k)
{
midiKeyPressedForScene[sc][k] = 0;
}
}

for (int i = 0; i < n_customcontrollers; i++)
Expand All @@ -179,10 +193,17 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
patch.scene[j].modsources[ms_ctrl1 + i] = patch.scene[0].modsources[ms_ctrl1 + i];
}
}

for (int s = 0; s < n_scenes; ++s)
{
for (auto ms : patch.scene[s].modsources)
{
if (ms)
{
ms->set_samplerate(storage.samplerate, storage.samplerate_inv);
}
}
}

amp.set_blocksize(BLOCK_SIZE);
amp_mute.set_blocksize(BLOCK_SIZE);
Expand Down Expand Up @@ -250,6 +271,7 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
patchid_queue = -1;
has_patchid_file = false;
bool lookingForFactory = (storage.initPatchCategoryType == "Factory");

for (auto p : storage.patch_list)
{
if (p.name == storage.initPatchName &&
Expand All @@ -259,10 +281,15 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl
patchid_queue = pid;
break;
}

pid++;
}

if (patchid_queue >= 0)
{
processAudioThreadOpsWhenAudioEngineUnavailable(true); // DANGER MODE IS ON
}

patchid_queue = -1;
has_patchid_file = false;
}
Expand Down Expand Up @@ -2192,9 +2219,11 @@ void SurgeSynthesizer::channelController(char channel, int cc, int value)

int cc_encoded = cc;

if ((cc == 6) || (cc == 38)) // handle RPN/NRPNs (untested)
// handle RPN/NRPNs (untested)
if (cc == 6 || cc == 38)
{
int tv, cnum;

if (channelState[channel].nrpn_last)
{
tv = (channelState[channel].nrpn_v[1] << 7) + channelState[channel].nrpn_v[0];
Expand Down Expand Up @@ -2223,26 +2252,36 @@ void SurgeSynthesizer::channelController(char channel, int cc, int value)

if (learn_param_from_cc >= 0)
{
if (learn_param_from_cc < n_global_params)
if (!disallowedLearnCCs.test(cc))
{
storage.getPatch().param_ptr[learn_param_from_cc]->midictrl = cc_encoded;
}
else
{
int a = learn_param_from_cc;
if (learn_param_from_cc >= (n_global_params + n_scene_params))
a -= n_scene_params;
if (learn_param_from_cc < n_global_params)
{
storage.getPatch().param_ptr[learn_param_from_cc]->midictrl = cc_encoded;
}
else
{
int a = learn_param_from_cc;

storage.getPatch().param_ptr[a]->midictrl = cc_encoded;
storage.getPatch().param_ptr[a + n_scene_params]->midictrl = cc_encoded;
if (learn_param_from_cc >= (n_global_params + n_scene_params))
{
a -= n_scene_params;
}

storage.getPatch().param_ptr[a]->midictrl = cc_encoded;
storage.getPatch().param_ptr[a + n_scene_params]->midictrl = cc_encoded;
}

learn_param_from_cc = -1;
}
learn_param_from_cc = -1;
}

if ((learn_macro_from_cc >= 0) && (learn_macro_from_cc < n_customcontrollers))
{
storage.controllers[learn_macro_from_cc] = cc_encoded;
learn_macro_from_cc = -1;
if (!disallowedLearnCCs.test(cc))
{
storage.controllers[learn_macro_from_cc] = cc_encoded;
learn_macro_from_cc = -1;
}
}

for (int i = 0; i < n_global_params; i++)
Expand All @@ -2251,13 +2290,19 @@ void SurgeSynthesizer::channelController(char channel, int cc, int value)
{
this->setParameterSmoothed(i, fval);
int j = 0;

while (j < 7)
{
if ((refresh_ctrl_queue[j] > -1) && (refresh_ctrl_queue[j] != i))
{
j++;
}
else
{
break;
}
}

refresh_ctrl_queue[j] = i;
refresh_ctrl_queue_value[j] = fval;
}
Expand All @@ -2271,13 +2316,19 @@ void SurgeSynthesizer::channelController(char channel, int cc, int value)
{
this->setParameterSmoothed(i, fval);
int j = 0;

while (j < 7)
{
if ((refresh_ctrl_queue[j] > -1) && (refresh_ctrl_queue[j] != i))
{
j++;
}
else
{
break;
}
}

refresh_ctrl_queue[j] = i;
refresh_ctrl_queue_value[j] = fval;
}
Expand Down
4 changes: 3 additions & 1 deletion src/common/SurgeSynthesizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct QuadFilterChainState;
#include <utility>
#include <atomic>
#include <cstdio>
#include <bitset>

struct timedata
{
Expand Down Expand Up @@ -176,7 +177,7 @@ class alignas(16) SurgeSynthesizer
/*
* So when surge was pre-juce we contemplated writing our own ID remapping between
* internal indices and DAW IDs so put an indirectin and class in place. JUCE obviates
* the need for that by using hash of stremaing name as an ID consistently throuhg its
* the need for that by using hash of stremaing name as an ID consistently through its
* param mechanism. I could, in theory, have gone right back to int as my accessor class
* but there's something compelilng about keeping that indirection I plumbed in just in case
* i need it in the future. So the ID class is now just a simple wrapper on an int which is
Expand Down Expand Up @@ -422,6 +423,7 @@ class alignas(16) SurgeSynthesizer
int mpeVoices = 0;
int mpeGlobalPitchBendRange = 0;

std::bitset<128> disallowedLearnCCs{0};
std::array<uint64_t, 128> midiKeyPressedForScene[n_scenes];
uint64_t orderedMidiKey = 0;
std::atomic<uint64_t> midiNoteEvents{0};
Expand Down
5 changes: 2 additions & 3 deletions src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,8 @@ void SurgeGUIEditor::createMIDILearnMenuEntries(juce::PopupMenu &parentMenu,
bool isEnabled = true;

// these CCs cannot be used for MIDI learn (see SurgeSynthesizer::channelController)
if (mc == 0 || mc == 6 || mc == 32 || mc == 38 || mc == 64 ||
(mc == 74 && synth->mpeEnabled) || (mc >= 98 && mc <= 101) || mc == 120 ||
mc == 123)
if (mc == 0 || mc == 6 || mc == 32 || mc == 38 || mc == 64 || mc == 74 ||
(mc >= 98 && mc <= 101) || mc == 120 || mc == 123)
{
isEnabled = false;
}
Expand Down

0 comments on commit a89bc17

Please sign in to comment.