From 167f5b01624c4c62ccc42b833d2ac82bc2625af2 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 8 Mar 2023 16:04:09 +0100 Subject: [PATCH] Fixing learning drum notes via MIDI. --- MicroDexed.ino | 116 +++++++++++++++++++++++++++---------------------- UI.hpp | 18 ++++---- config.h | 6 +-- 3 files changed, 75 insertions(+), 65 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index 8eaaa06..7ad7dd1 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -824,7 +824,7 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { // // MIDI learn mode // - if (midi_learn_mode != MIDI_LEARN_MODE_OFF) { + if (midi_learn_mode > MIDI_LEARN_MODE_OFF) { int8_t tmp_channel = handle_midi_learn(inNumber); if (tmp_channel >= 0) inChannel = tmp_channel; @@ -890,19 +890,22 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { if (drum_counter >= NUM_DRUMS) drum_counter = 0; - if (!(midi_learn_mode & 0x80)) { + if (midi_learn_mode > MIDI_LEARN_MODE_OFF) { inNumber = configuration.drums.midinote[active_sample]; - } else { - inNumber = midi_learn_mode & 0x7f; - midi_learn_mode = MIDI_LEARN_MODE_DRUM_NOTE; } #ifdef DEBUG char note_name[4]; getNoteName(note_name, inNumber); + if (midi_learn_mode > MIDI_LEARN_MODE_OFF) { + if (midi_learn_mode & 0x80) + Serial.printf_P(PSTR("MIDI LEARN MODE DRUM (%s) for note (%s)\n"), byte_to_binary(midi_learn_mode), note_name); + else + Serial.printf_P(PSTR("MIDI LEARN MODE NOTE (%s) for note (%s)\n"), byte_to_binary(midi_learn_mode), note_name); + } Serial.print(F("Triggring Drum[")); Serial.print(drum_counter, DEC); - Serial.print(F("]: with note ")); + Serial.print(F("] with note ")); Serial.print(note_name); Serial.print(F("/")); Serial.println(inNumber, DEC); @@ -918,43 +921,45 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { } } - uint8_t slot = drum_get_slot(drum_config[use_drum].drum_class); - float pan = mapfloat(configuration.drums.pan[use_drum], DRUMS_PANORAMA_MIN, DRUMS_PANORAMA_MAX, 0.0, 1.0); - float reverb_send = configuration.drums.reverb_send[use_drum] / 100.0f; - float vol_min = configuration.drums.vol_min[use_drum] / 100.0f; - float vol_max = configuration.drums.vol_max[use_drum] / 100.0f; - - drum_mixer_r.gain(slot, pan * volume_transform(mapfloat(inVelocity, 0, 127, vol_min, vol_max))); - drum_mixer_l.gain(slot, (1.0 - pan) * volume_transform(mapfloat(inVelocity, 0, 127, vol_min, vol_max))); - - drum_reverb_send_mixer_r.gain(slot, pan * volume_transform(reverb_send)); - drum_reverb_send_mixer_l.gain(slot, (1.0 - pan) * volume_transform(reverb_send)); - - if (drum_config[use_drum].drum_data != NULL && drum_config[use_drum].len > 0) { - if (configuration.drums.pitch[use_drum] != 0) { - Drum[slot]->enableInterpolation(true); - Drum[slot]->setPlaybackRate(pow(2, float(configuration.drums.pitch[use_drum]) / 120.0)); - } else { - Drum[slot]->enableInterpolation(false); - Drum[slot]->setPlaybackRate(1.0); - } - Drum[slot]->playRaw((int16_t*)drum_config[use_drum].drum_data, drum_config[use_drum].len, 1); -#ifdef DEBUG - Serial.printf(PSTR("Playing sample [%s][%c%c] on slot [%d] main volume [%d]: drum_data=%p, len=%d\n"), drum_config[use_drum].name, slot, configuration.drums.main_vol, drum_config[use_drum].drum_data, drum_config[use_drum].len); - - Serial.print(F("Drum Slot [")); - Serial.print(slot); - Serial.print(F("]: Velocity=")); - Serial.print(mapfloat(inVelocity, 0, 127, vol_min, vol_max), 2); - Serial.print(F(" Pan=")); - Serial.print(pan, 2); - Serial.print(F(" ReverbSend=")); - Serial.print(reverb_send, 2); - Serial.print(F(" Pitch=")); - Serial.print(configuration.drums.pitch[use_drum] / 10.0f, 1); - Serial.print(F(" Playback speed=")); - Serial.println(pow(2, float(configuration.drums.pitch[use_drum]) / 120.0)); + if (drum_config[use_drum].midinote > 0) { + uint8_t slot = drum_get_slot(drum_config[use_drum].drum_class); + float pan = mapfloat(configuration.drums.pan[use_drum], DRUMS_PANORAMA_MIN, DRUMS_PANORAMA_MAX, 0.0, 1.0); + float reverb_send = configuration.drums.reverb_send[use_drum] / 100.0f; + float vol_min = configuration.drums.vol_min[use_drum] / 100.0f; + float vol_max = configuration.drums.vol_max[use_drum] / 100.0f; + + drum_mixer_r.gain(slot, pan * volume_transform(mapfloat(inVelocity, 0, 127, vol_min, vol_max))); + drum_mixer_l.gain(slot, (1.0 - pan) * volume_transform(mapfloat(inVelocity, 0, 127, vol_min, vol_max))); + + drum_reverb_send_mixer_r.gain(slot, pan * volume_transform(reverb_send)); + drum_reverb_send_mixer_l.gain(slot, (1.0 - pan) * volume_transform(reverb_send)); + + if (drum_config[use_drum].drum_data != NULL && drum_config[use_drum].len > 0) { + if (configuration.drums.pitch[use_drum] != 0) { + Drum[slot]->enableInterpolation(true); + Drum[slot]->setPlaybackRate(pow(2, float(configuration.drums.pitch[use_drum]) / 120.0)); + } else { + Drum[slot]->enableInterpolation(false); + Drum[slot]->setPlaybackRate(1.0); + } + Drum[slot]->playRaw((int16_t*)drum_config[use_drum].drum_data, drum_config[use_drum].len, 1); +#ifdef DEBUG + Serial.printf_P(PSTR("Playing sample [%s] on slot [%d] main volume [%d]: drum_data=%p, len=%d\n"), drum_config[use_drum].name, slot, configuration.drums.main_vol, drum_config[use_drum].drum_data, drum_config[use_drum].len); + + Serial.print(F("Drum Slot [")); + Serial.print(slot); + Serial.print(F("]: Velocity=")); + Serial.print(mapfloat(inVelocity, 0, 127, vol_min, vol_max), 2); + Serial.print(F(" Pan=")); + Serial.print(pan, 2); + Serial.print(F(" ReverbSend=")); + Serial.print(reverb_send, 2); + Serial.print(F(" Pitch=")); + Serial.print(configuration.drums.pitch[use_drum] / 10.0f, 1); + Serial.print(F(" Playback speed=")); + Serial.println(pow(2, float(configuration.drums.pitch[use_drum]) / 120.0)); #endif + } } } #endif @@ -964,7 +969,7 @@ void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { // // MIDI learn mode // - if (midi_learn_mode != MIDI_LEARN_MODE_OFF) { + if (midi_learn_mode > MIDI_LEARN_MODE_OFF) { int8_t tmp_channel = handle_midi_learn(inNumber); if (tmp_channel >= 0) inChannel = tmp_channel; @@ -2215,7 +2220,7 @@ int8_t handle_midi_learn(int8_t note) { int8_t ret_channel = -1; #ifdef DEBUG - Serial.printf(PSTR("MIDI learning for %d with midi learn mode %d\n"), note, midi_learn_mode); + Serial.printf_P(PSTR("MIDI learning for note %d with midi learn mode %d\n"), note, midi_learn_mode); #endif if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_drum_pan)) { @@ -2232,15 +2237,10 @@ int8_t handle_midi_learn(int8_t note) { LCDML.OTHER_jumpToFunc(UI_func_drum_vol_min_max); } else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_drum_midi_note)) { ret_channel = configuration.drums.midi_channel; - if (midi_learn_mode != MIDI_LEARN_MODE_NOTE && midi_learn_mode != MIDI_LEARN_MODE_DRUM_NOTE) + if (midi_learn_mode & 0x80) active_sample = get_drums_id_by_note(note); - else { - if (midi_learn_mode != MIDI_LEARN_MODE_DRUM_NOTE) - midi_learn_mode = note; - else - midi_learn_mode = note & 0x80; - LCDML.OTHER_jumpToFunc(UI_func_drum_midi_note); - } + midi_learn_mode |= note; + LCDML.OTHER_jumpToFunc(UI_func_drum_midi_note); } else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_drum_pitch)) { ret_channel = configuration.drums.midi_channel; active_sample = get_drums_id_by_note(note); @@ -2889,6 +2889,18 @@ void SerialPrintFormatInt3(uint8_t num) { Serial.print(buf); } +const char* byte_to_binary(int x) { + static char b[9]; + b[0] = '\0'; + + int z; + for (z = 128; z > 0; z >>= 1) { + strcat(b, ((x & z) == z) ? "1" : "0"); + } + + return b; +} + #if defined(ARDUINO_TEENSY36) /* From: https://forum.pjrc.com/threads/33443-How-to-display-free-ram */ extern "C" char* sbrk(int incr); diff --git a/UI.hpp b/UI.hpp index baa2c40..17c5e59 100644 --- a/UI.hpp +++ b/UI.hpp @@ -2909,7 +2909,7 @@ void UI_func_note_refresh(uint8_t param) { MicroDexed[selected_instance_id]->setNoteRefreshMode(configuration.dexed[selected_instance_id].note_refresh); #ifdef DEBUG - Serial.printf(PSTR("Note refresh: %d\n"), configuration.dexed[selected_instance_id].note_refresh); + Serial.printf_P(PSTR("Note refresh: %d\n"), configuration.dexed[selected_instance_id].note_refresh); #endif display.setCursor(0, 1); @@ -4440,8 +4440,8 @@ void UI_func_drum_midi_note(uint8_t param) { for (uint8_t i = 0; i < NUM_DRUMSET_CONFIG; i++) midinote_old[i] = configuration.drums.midinote[i]; - if (!display_name) - midi_learn_mode = MIDI_LEARN_MODE_DRUM_NOTE; + if (display_name) + midi_learn_mode = MIDI_LEARN_MODE_ON| 0x80; else midi_learn_mode = MIDI_LEARN_MODE_ON; @@ -4476,8 +4476,8 @@ void UI_func_drum_midi_note(uint8_t param) { } } - if (midi_learn_mode >= DRUMS_MIDI_NOTE_MIN) - configuration.drums.midinote[active_sample] = midi_learn_mode & 0x7f; + // if (midi_learn_mode & 0x80) + // configuration.drums.midinote[active_sample] = midi_learn_mode & 0x7f; 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()) { @@ -4526,8 +4526,8 @@ void UI_func_drum_midi_note(uint8_t param) { } else if (ask_before_quit_mode == 0) { // BACK ask_before_quit_mode = -1; ask_before_quit = false; - if (!display_name) - midi_learn_mode = MIDI_LEARN_MODE_DRUM_NOTE; + if (display_name) + midi_learn_mode = MIDI_LEARN_MODE_ON | 0x80; else midi_learn_mode = MIDI_LEARN_MODE_ON; LCDML.OTHER_updateFunc(); @@ -4550,8 +4550,8 @@ void UI_func_drum_midi_note(uint8_t param) { #endif _check_display_name(display_name, 3); - if (!display_name) - midi_learn_mode = MIDI_LEARN_MODE_DRUM_NOTE; + if (display_name) + midi_learn_mode = MIDI_LEARN_MODE_ON | 0x80; else midi_learn_mode = MIDI_LEARN_MODE_ON; } diff --git a/config.h b/config.h index 014830b..6a509ae 100644 --- a/config.h +++ b/config.h @@ -829,10 +829,8 @@ enum reverb_mixer_ports { enum midi_learn_modes { MIDI_LEARN_MODE_OFF, - MIDI_LEARN_MODE_ON, - MIDI_LEARN_MODE_NOTE, - MIDI_LEARN_MODE_DRUM_NOTE - }; + MIDI_LEARN_MODE_ON +}; #ifndef _MAPFLOAT #define _MAPFLOAT