diff --git a/MicroDexed.ino b/MicroDexed.ino index 4634cb3..6e61fe0 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -738,7 +738,6 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) Serial.println(F("BREATH CC")); #endif MicroDexed[instance_id]->controllers.breath_cc = inValue; - //MicroDexed[instance_id]->controllers.breath_cc = 100 – BCrange + Output * BCrange * Bcvalue/100 MicroDexed[instance_id]->controllers.refresh(); break; case 4: @@ -810,7 +809,36 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) LCDML.loop_menu(); } break; + case 94: // CC 94: (de)tune + configuration.dexed[selected_instance_id].tune = map(inValue, 0, 0x7f, TUNE_MIN, TUNE_MAX); + MicroDexed[selected_instance_id]->controllers.masterTune = (int((configuration.dexed[selected_instance_id].tune - 100) / 100.0 * 0x4000) << 11) * (1.0 / 12); + MicroDexed[selected_instance_id]->doRefreshVoice(); + if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_tune)) + { + LCDML.OTHER_updateFunc(); + LCDML.loop_menu(); + } + break; #if defined(USE_FX) + case 91: // CC 91: reverb send + configuration.fx.reverb_send[selected_instance_id] = map(inValue, 0, 0x7f, REVERB_SEND_MIN, REVERB_SEND_MAX); + reverb_mixer_r.gain(selected_instance_id, pseudo_log_curve(mapfloat(configuration.fx.reverb_send[selected_instance_id], REVERB_SEND_MIN, REVERB_SEND_MAX, 0.0, 1.0))); + reverb_mixer_l.gain(selected_instance_id, pseudo_log_curve(mapfloat(configuration.fx.reverb_send[selected_instance_id], REVERB_SEND_MIN, REVERB_SEND_MAX, 0.0, 1.0))); + if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_reverb_send)) + { + LCDML.OTHER_updateFunc(); + LCDML.loop_menu(); + } + break; + case 93: // CC 93: chorus level + configuration.fx.chorus_level[selected_instance_id] = map(inValue, 0, 0x7f, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX); + chorus_mixer[selected_instance_id]->gain(1, mapfloat(configuration.fx.chorus_level[selected_instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); + if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_chorus_level)) + { + LCDML.OTHER_updateFunc(); + LCDML.loop_menu(); + } + break; case 103: // CC 103: filter resonance configuration.fx.filter_resonance[instance_id] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); MicroDexed[instance_id]->fx.Reso = mapfloat(configuration.fx.filter_resonance[instance_id], FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 1.0, 0.0); @@ -837,6 +865,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) LCDML.OTHER_updateFunc(); LCDML.loop_menu(); } + break; case 106: // CC 106: delay feedback configuration.fx.delay_feedback[instance_id] = map(inValue, 0, 0x7f, DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX); delay_fb_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_feedback[instance_id], DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); // amount of feedback @@ -1432,6 +1461,9 @@ void init_MIDI_send_CC(void) { MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 7, configuration.dexed[selected_instance_id].sound_intensity); MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, configuration.dexed[selected_instance_id].pan); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 91, configuration.fx.reverb_send[selected_instance_id]); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 93, configuration.fx.chorus_level[selected_instance_id]); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 94, configuration.dexed[selected_instance_id].tune); MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 103, configuration.fx.filter_resonance[selected_instance_id]); MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 104, configuration.fx.filter_cutoff[selected_instance_id]); MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 105, configuration.fx.delay_time[selected_instance_id]); diff --git a/UI.hpp b/UI.hpp index d5dc50c..56dfcb9 100644 --- a/UI.hpp +++ b/UI.hpp @@ -1186,9 +1186,15 @@ void UI_func_chorus_level(uint8_t param) if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) { if (LCDML.BT_checkDown()) + { configuration.fx.chorus_level[selected_instance_id] = constrain(configuration.fx.chorus_level[selected_instance_id] + ENCODER[ENC_R].speed(), CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 93, configuration.fx.chorus_level[selected_instance_id]); + } else if (LCDML.BT_checkUp()) + { configuration.fx.chorus_level[selected_instance_id] = constrain(configuration.fx.chorus_level[selected_instance_id] - ENCODER[ENC_R].speed(), CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 93, configuration.fx.chorus_level[selected_instance_id]); + } #if NUM_DEXED > 1 else if (LCDML.BT_checkEnter()) { @@ -1426,9 +1432,15 @@ void UI_func_reverb_send(uint8_t param) if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) { if (LCDML.BT_checkDown()) + { configuration.fx.reverb_send[selected_instance_id] = constrain(configuration.fx.reverb_send[selected_instance_id] + ENCODER[ENC_R].speed(), REVERB_SEND_MIN, REVERB_SEND_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 91, configuration.fx.reverb_send[selected_instance_id]); + } else if (LCDML.BT_checkUp()) + { configuration.fx.reverb_send[selected_instance_id] = constrain(configuration.fx.reverb_send[selected_instance_id] - ENCODER[ENC_R].speed(), REVERB_SEND_MIN, REVERB_SEND_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 91, configuration.fx.reverb_send[selected_instance_id]); + } #if NUM_DEXED > 1 else if (LCDML.BT_checkEnter()) { @@ -1654,9 +1666,15 @@ void UI_func_tune(uint8_t param) if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())) { if (LCDML.BT_checkDown()) + { configuration.dexed[selected_instance_id].tune = constrain(configuration.dexed[selected_instance_id].tune + ENCODER[ENC_R].speed(), TUNE_MIN, TUNE_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 94, configuration.dexed[selected_instance_id].tune); + } else if (LCDML.BT_checkUp()) + { configuration.dexed[selected_instance_id].tune = constrain(configuration.dexed[selected_instance_id].tune - ENCODER[ENC_R].speed(), TUNE_MIN, TUNE_MAX); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 94, configuration.dexed[selected_instance_id].tune); + } #if NUM_DEXED > 1 else if (LCDML.BT_checkEnter()) { @@ -1965,12 +1983,12 @@ void UI_func_panorama(uint8_t param) if (LCDML.BT_checkDown() && encoderDir[ENC_R].Down() && configuration.sys.mono == 0) { configuration.dexed[selected_instance_id].pan = constrain(configuration.dexed[selected_instance_id].pan + ENCODER[ENC_R].speed(), PANORAMA_MIN, PANORAMA_MAX); - MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, configuration.dexed[selected_instance_id].pan); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, map(configuration.dexed[selected_instance_id].pan, PANORAMA_MIN, PANORAMA_MAX, 0, 127)); } else if (LCDML.BT_checkUp() && encoderDir[ENC_R].Up() && configuration.sys.mono == 0) { configuration.dexed[selected_instance_id].pan = constrain(configuration.dexed[selected_instance_id].pan - ENCODER[ENC_R].speed(), PANORAMA_MIN, PANORAMA_MAX); - MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, configuration.dexed[selected_instance_id].pan); + MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, map(configuration.dexed[selected_instance_id].pan, PANORAMA_MIN, PANORAMA_MAX, 0, 127)); } #if NUM_DEXED > 1 else if (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()) diff --git a/dexed_sd.cpp b/dexed_sd.cpp index a7a4671..d03ea0a 100644 --- a/dexed_sd.cpp +++ b/dexed_sd.cpp @@ -30,6 +30,8 @@ #include "dexed.h" #include "dexed_sd.h" +extern void init_MIDI_send_CC(void); + /****************************************************************************** SD BANK/VOICE LOADING ******************************************************************************/ @@ -83,7 +85,7 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id) uint8_t data_copy[155]; MicroDexed[instance_id]->getVoiceData(data_copy); send_sysex_voice(configuration.dexed[instance_id].midi_channel, data_copy); - + init_MIDI_send_CC(); return (ret); } #ifdef DEBUG @@ -875,7 +877,7 @@ bool get_bank_name(uint8_t b, char* name, uint8_t len) sysex.close(); return (false); } - + strip_extension(entry.name(), name, len); #ifdef DEBUG diff --git a/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.md b/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.md index 0ac3a88..8170b33 100644 --- a/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.md +++ b/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.md @@ -956,15 +956,18 @@ Another way of editing voice presets is to use an editor like Edisyn. For downlo | MIDI-CC# | Target | |:--------:|:-------| | 0 | Bank-Select MSB (currently unused)| -| 1 | Modulation wheel range| -| 2 | Breath controller range| -| 4 | Foot controller range| +| 1 | Modulation wheel | +| 2 | Breath controller | +| 4 | Foot controller | | 5 | Portamento time | | 7 | Volume | | 10 | Panorama (0-62 = left, 63-64 = middle, 65-127 = right)| | 32 | Bank-Select LSB| | 64 | Sustain (0 to 63 = Off, 64 to 127 = On)| | 65 | Portamento (0 to 63 = Off, 64 to 127 = On)| +| 91 | Reverb send | +| 93 | Chorus level | +| 94 | Tune | | 103 | Filter resonance | | 104 | Filter cutoff | | 105 | Delay time | diff --git a/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.pdf b/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.pdf index 706a86f..6454c04 100644 Binary files a/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.pdf and b/doc/manuals/MicroDexed-User_Manual/MicroDexed-User_Manual.pdf differ