diff --git a/MicroDexed.ino b/MicroDexed.ino index 120913b..a115f7c 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -241,6 +241,8 @@ char g_voice_name[NUM_DEXED][VOICE_NAME_LEN]; char g_bank_name[NUM_DEXED][BANK_NAME_LEN]; char receive_bank_filename[FILENAME_LEN]; uint8_t selected_instance_id = 0; +int perform_attack_mod = 0; +int perform_release_mod = 0; #ifdef TEENSY4 #if NUM_DEXED>1 int8_t midi_decay[NUM_DEXED] = { -1, -1}; diff --git a/UI.hpp b/UI.hpp index 9b4d0a9..c13e298 100644 --- a/UI.hpp +++ b/UI.hpp @@ -101,14 +101,16 @@ extern AudioAnalyzePeak master_peak_l; extern char sd_string[LCD_cols + 1]; extern char g_voice_name[NUM_DEXED][VOICE_NAME_LEN]; extern char g_bank_name[NUM_DEXED][BANK_NAME_LEN]; - - +extern int perform_attack_mod; +extern int perform_release_mod; /*********************************************************************** GLOBAL ************************************************************************/ elapsedMillis back_from_volume; uint8_t instance_num[8][8]; const char accepted_chars[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-abcdefghijklmnopqrstuvwxyz"; +uint8_t active_perform_page = 1; + #ifdef I2C_DISPLAY #include @@ -3763,6 +3765,11 @@ void UI_func_voice_select(uint8_t param) uint8_t bank_tmp; int8_t voice_tmp; + // Reset Performance Modifiers to 0 after every preset change + perform_attack_mod=0; + perform_release_mod=0; + active_perform_page = 1; + if (LCDML.BT_checkUp()) { //start : show all presets @@ -3973,6 +3980,7 @@ void UI_func_voice_select(uint8_t param) lcd.show(1, 0, 2, configuration.performance.voice[selected_instance_id] + 1); string_toupper(bank_name); lcd.show(0, 3, 8, bank_name); + lcd.show(0, 12, 1, " "); //forced because this char does not clear after fav-search (because the bank name is one char to short to do it). string_toupper(voice_name); lcd.show(1, 3, 10, voice_name); @@ -4018,34 +4026,140 @@ void UI_func_voice_select(uint8_t param) void UI_func_volume(uint8_t param) { + char tmp[6]; if (LCDML.FUNC_setup()) // ****** SETUP ********* { encoderDir[ENC_L].reset(); - lcd_special_chars(BLOCKBAR); - lcd_display_bar_int("Master Vol.", configuration.sys.vol, 1.0, VOLUME_MIN, VOLUME_MAX, 3, false, false, true); + if (active_perform_page == 1) + { //Master Volume + lcd_special_chars(BLOCKBAR); + lcd_display_bar_int("Master Vol.", configuration.sys.vol, 1.0, VOLUME_MIN, VOLUME_MAX, 3, false, false, true); + back_from_volume = 0; + } + + else if (active_perform_page == 2) + { // Live Performance Mod - Attack + lcd.setCursor(0, 0); + lcd.print("Live Modify"); + lcd.setCursor(0, 1); + lcd.print("Attack = "); + lcd.setCursor(13, 1); + sprintf(tmp, "%03d", perform_attack_mod); + lcd.print(tmp); + back_from_volume = 0; + } + + else if (active_perform_page == 3) + { // Live Performance Mod - Release + lcd.setCursor(0, 0); + lcd.print("Live Modify"); + lcd.setCursor(11, 1); + lcd.print("Release = "); + lcd.setCursor(13, 1); + sprintf(tmp, "%03d", perform_release_mod); + lcd.print(tmp); + back_from_volume = 0; + } + + lcd.setCursor(12, 0); + lcd.print("P"); + lcd.setCursor(13, 0); + lcd.print(active_perform_page); + lcd.setCursor(14, 0); + lcd.print("/3"); - back_from_volume = 0; } if (LCDML.FUNC_loop()) // ****** LOOP ********* { - if ((LCDML.BT_checkDown() && encoderDir[ENC_L].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_L].Up())) + + if ( LCDML.BT_checkDown() && encoderDir[ENC_R].Down() ) { back_from_volume = 0; + active_perform_page++; + if (active_perform_page > 3)active_perform_page = 1; + } + else if ( LCDML.BT_checkUp() && encoderDir[ENC_R].Up() ) + { + back_from_volume = 0; + active_perform_page--; + if (active_perform_page < 1)active_perform_page = 3; + } - if (LCDML.BT_checkDown()) - { - configuration.sys.vol = constrain(configuration.sys.vol + ENCODER[ENC_L].speed(), VOLUME_MIN, VOLUME_MAX); + if ((LCDML.BT_checkDown() && encoderDir[ENC_L].Down() ) || (LCDML.BT_checkUp() && encoderDir[ENC_L].Up() )) + { + if (active_perform_page == 1) { + back_from_volume = 0; + + if (LCDML.BT_checkDown() ) + { + configuration.sys.vol = constrain(configuration.sys.vol + ENCODER[ENC_L].speed(), VOLUME_MIN, VOLUME_MAX); + } + else if (LCDML.BT_checkUp() ) + { + configuration.sys.vol = constrain(configuration.sys.vol - ENCODER[ENC_L].speed(), VOLUME_MIN, VOLUME_MAX); + } } - else if (LCDML.BT_checkUp()) - { - configuration.sys.vol = constrain(configuration.sys.vol - ENCODER[ENC_L].speed(), VOLUME_MIN, VOLUME_MAX); + + else if ( active_perform_page == 2) + { //Attack + + if (LCDML.BT_checkDown() ) + { + perform_attack_mod = constrain(perform_attack_mod + ENCODER[ENC_L].speed(), -MAX_PERF_MOD, MAX_PERF_MOD); + } + else if (LCDML.BT_checkUp() ) + { + perform_attack_mod = constrain(perform_attack_mod - ENCODER[ENC_L].speed(), -MAX_PERF_MOD, MAX_PERF_MOD); + } + + + } + else if (active_perform_page == 3) + { //Release + + if (LCDML.BT_checkDown() ) + { + perform_release_mod = constrain(perform_release_mod + ENCODER[ENC_L].speed(), -MAX_PERF_MOD, MAX_PERF_MOD); + } + else if (LCDML.BT_checkUp() ) + { + perform_release_mod = constrain(perform_release_mod - ENCODER[ENC_L].speed(), -MAX_PERF_MOD, MAX_PERF_MOD); + } } } - lcd_display_bar_int("Master Vol.", configuration.sys.vol, 1.0, VOLUME_MIN, VOLUME_MAX, 3, false, false, false); - set_volume(configuration.sys.vol, configuration.sys.mono); + lcd.setCursor(13, 0); + lcd.print(active_perform_page); + + if (active_perform_page == 1) { //Master Volume + lcd.setCursor(0, 0); + lcd.print("Master Vol. "); + lcd_special_chars(BLOCKBAR); + lcd_display_bar_int("Master Vol.", configuration.sys.vol, 1.0, VOLUME_MIN, VOLUME_MAX, 3, false, false, false); + set_volume(configuration.sys.vol, configuration.sys.mono); + } + else if (active_perform_page == 2) { //Attack + lcd.setCursor(0, 0); + lcd.print("Live Modify"); + lcd.setCursor(0, 1); + lcd.print("Attack = "); + lcd.setCursor(13, 1); + sprintf(tmp, "%03d", perform_attack_mod); + lcd.print(tmp); + back_from_volume = 0; + } + else if (active_perform_page == 3) { //Release + lcd.setCursor(0, 0); + lcd.print("Live Modify"); + lcd.setCursor(0, 1); + lcd.print("Release = "); + lcd.setCursor(13, 1); + sprintf(tmp, "%03d", perform_release_mod); + lcd.print(tmp); + back_from_volume = 0; + } } if (LCDML.FUNC_close()) // ****** STABLE END ********* diff --git a/config.h b/config.h index 2bbc07d..d4a9c29 100644 --- a/config.h +++ b/config.h @@ -284,6 +284,7 @@ #define FAV_CONFIG_PATH "FAVCFG" #define FAV_CONFIG_NAME "FAVCFG" +#define MAX_PERF_MOD 30 //************************************************************************************************* //* DO NO CHANGE ANYTHING BEYOND IF YOU DON'T KNOW WHAT YOU ARE DOING !!! diff --git a/synth_dexed.cpp b/synth_dexed.cpp index 519fe7c..47403d4 100644 --- a/synth_dexed.cpp +++ b/synth_dexed.cpp @@ -23,6 +23,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +extern int perform_attack_mod; +extern int perform_release_mod; const float dc = 1e-18; @@ -1248,6 +1250,18 @@ void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity, int src rates[i] = patch[off + i]; levels[i] = patch[off + 4 + i]; } + + // Live Modifiers for Attack and Release + // So far no sanity checks for <0 or similar since i have not experienced any problems without them. + // The macro itself is still work to do - finding the best working relation for most of the presets. + if (perform_attack_mod != 0 || perform_release_mod != 0) + { + rates[1] = rates[1] - perform_attack_mod; + rates[2] = rates[2] - perform_release_mod * 2; + rates[3] = rates[3] - perform_release_mod; + } + // Modifiers End + int outlevel = patch[off + 16]; outlevel = Env::scaleoutlevel(outlevel); int level_scaling = ScaleLevel(midinote, patch[off + 8], patch[off + 9],