From bb0bcb5b241a80b7de6a335900ead4263de6123e Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Mon, 4 Nov 2019 16:16:20 +0100 Subject: [PATCH] Several additions for multi-instance handling. Next additions for setup menus. --- MicroDexed.ino | 724 ++++++++++++++++++++++++++---------------------- UI.hpp | 190 ++++++++++--- config.h | 2 +- dexed.cpp | 125 +++++++-- dexed.h | 9 +- dexed_sysex.cpp | 34 +-- dexed_sysex.h | 14 +- 7 files changed, 684 insertions(+), 414 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index 82e5b0e..82fecba 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -138,10 +138,10 @@ void create_audio_connections(AudioSourceMicroDexed &d) bool sd_card_available = false; uint8_t max_loaded_banks = 0; -char bank_name[BANK_NAME_LEN]; -char voice_name[VOICE_NAME_LEN]; -char bank_names[MAX_BANKS][BANK_NAME_LEN]; -char voice_names[MAX_VOICES][VOICE_NAME_LEN]; +char bank_name[NUM_DEXED][BANK_NAME_LEN]; +char voice_name[NUM_DEXED][VOICE_NAME_LEN]; +char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN]; +char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN]; elapsedMillis autostore; uint8_t midi_timing_counter = 0; // 24 per qarter elapsedMillis midi_timing_timestep; @@ -279,41 +279,47 @@ void setup() if (!SD.begin(SDCARD_CS_PIN)) { Serial.println(F("SD card not accessable.")); - strcpy(bank_name, "Default"); - strcpy(voice_name, "Default"); + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { + strcpy(bank_name[instance_id], "Default"); + strcpy(voice_name[instance_id], "Default"); + } } else { Serial.println(F("SD card found.")); sd_card_available = true; + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { + // read all bank names + max_loaded_banks = get_bank_names(instance_id); + strip_extension(bank_names[instance_id][configuration.bank[instance_id]], bank_name[instance_id]); - // read all bank names - max_loaded_banks = get_bank_names(); - strip_extension(bank_names[configuration.bank[0]], bank_name); - - // read all voice name for actual bank - get_voice_names_from_bank(configuration.bank[0]); + // read all voice name for actual bank + get_voice_names_from_bank(configuration.bank[instance_id], instance_id); #ifdef DEBUG - Serial.print(F("Bank [")); - Serial.print(bank_names[configuration.bank[0]]); - Serial.print(F("/")); - Serial.print(bank_name); - Serial.println(F("]")); - for (uint8_t n = 0; n < MAX_VOICES; n++) - { - if (n < 10) - Serial.print(F(" ")); - Serial.print(F(" ")); - Serial.print(n, DEC); - Serial.print(F("[")); - Serial.print(voice_names[n]); + Serial.print(F("Bank [")); + Serial.print(bank_names[instance_id][configuration.bank[instance_id]]); + Serial.print(F("/")); + Serial.print(bank_name[instance_id]); Serial.println(F("]")); - } + for (uint8_t n = 0; n < MAX_VOICES; n++) + { + if (n < 10) + Serial.print(F(" ")); + Serial.print(F(" ")); + Serial.print(n, DEC); + Serial.print(F("[")); + Serial.print(voice_names[instance_id][n]); + Serial.println(F("]")); + } #endif - // load default SYSEX data - load_sysex(configuration.bank[0], configuration.voice[0]); + // load default SYSEX data + load_sysex(configuration.bank[0], configuration.voice[0], instance_id); + } } + #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -399,14 +405,17 @@ void setup() AudioMemoryUsageMaxReset(); #endif + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { #ifdef DEBUG - Serial.print(F("Bank/Voice from EEPROM [")); - Serial.print(configuration.bank[0], DEC); - Serial.print(F("/")); - Serial.print(configuration.voice[0], DEC); - Serial.println(F("]")); - show_patch(); + Serial.print(F("Bank/Voice from EEPROM [")); + Serial.print(configuration.bank[instance_id], DEC); + Serial.print(F("/")); + Serial.print(configuration.voice[instance_id], DEC); + Serial.println(F("]")); + show_patch(instance_id); #endif + } Serial.print(F("AUDIO_BLOCK_SAMPLES=")); Serial.print(AUDIO_BLOCK_SAMPLES); @@ -556,173 +565,163 @@ void loop() ******************************************************************************/ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { - if (checkMidiChannel(inChannel)) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { - MicroDexed[0]->keydown(inNumber, inVelocity); + if (checkMidiChannel(inChannel, instance_id)) + { + MicroDexed[instance_id]->keydown(inNumber, inVelocity); + } } } void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { - if (checkMidiChannel(inChannel)) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { - MicroDexed[0]->keyup(inNumber); + if (checkMidiChannel(inChannel, instance_id)) + { + MicroDexed[instance_id]->keyup(inNumber); + } } } void handleControlChange(byte inChannel, byte inCtrl, byte inValue) { - if (checkMidiChannel(inChannel)) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { + if (checkMidiChannel(inChannel, instance_id)) + { #ifdef DEBUG - Serial.print(F("CC#")); - Serial.print(inCtrl, DEC); - Serial.print(F(":")); - Serial.println(inValue, DEC); + Serial.print(F("INSTANCE ")); + Serial.print(instance_id, DEC); + Serial.print(F(": CC#")); + Serial.print(inCtrl, DEC); + Serial.print(F(":")); + Serial.println(inValue, DEC); #endif - switch (inCtrl) { - case 0: - if (inValue < MAX_BANKS) - { - configuration.bank[0] = inValue; - } - break; - case 1: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->controllers.modwheel_cc = inValue; - MicroDexed[i]->controllers.refresh(); - } - break; - case 2: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->controllers.breath_cc = inValue; - MicroDexed[i]->controllers.refresh(); - } - break; - case 4: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->controllers.foot_cc = inValue; - MicroDexed[i]->controllers.refresh(); - } - break; - case 7: // Volume - configuration.vol = map(inValue, 0, 0x7f, VOLUME_MIN, VOLUME_MAX); - soften_volume.update(configuration.vol, SOFTEN_VALUE_CHANGE_STEPS); - break; - case 10: // Pan - configuration.pan[0] = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX); - set_volume(configuration.vol, configuration.pan[0], configuration.mono); - break; - case 32: // BankSelect LSB - configuration.bank[0] = inValue; - break; - case 64: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->setSustain(inValue > 63); - if (!MicroDexed[i]->getSustain()) { - for (uint8_t note = 0; note < MicroDexed[0]->getMaxNotes(); note++) { - if (MicroDexed[i]->voices[note].sustained && !MicroDexed[i]->voices[note].keydown) { - MicroDexed[i]->voices[note].dx7_note->keyup(); - MicroDexed[i]->voices[note].sustained = false; + switch (inCtrl) { + case 0: + if (inValue < MAX_BANKS) + { + configuration.bank[instance_id] = inValue; + } + break; + case 1: + MicroDexed[instance_id]->controllers.modwheel_cc = inValue; + MicroDexed[instance_id]->controllers.refresh(); + break; + case 2: + MicroDexed[instance_id]->controllers.breath_cc = inValue; + MicroDexed[instance_id]->controllers.refresh(); + break; + case 4: + MicroDexed[instance_id]->controllers.foot_cc = inValue; + MicroDexed[instance_id]->controllers.refresh(); + break; + case 7: // Volume + configuration.vol = map(inValue, 0, 0x7f, VOLUME_MIN, VOLUME_MAX); + soften_volume.update(configuration.vol, SOFTEN_VALUE_CHANGE_STEPS); + break; + case 10: // Pan + configuration.pan[instance_id] = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX); + set_volume(configuration.vol, configuration.pan[instance_id], configuration.mono); + break; + case 32: // BankSelect LSB + configuration.bank[instance_id] = inValue; + break; + case 64: + MicroDexed[instance_id]->setSustain(inValue > 63); + if (!MicroDexed[instance_id]->getSustain()) { + for (uint8_t note = 0; note < MicroDexed[instance_id]->getMaxNotes(); note++) { + if (MicroDexed[instance_id]->voices[note].sustained && !MicroDexed[instance_id]->voices[note].keydown) { + MicroDexed[instance_id]->voices[note].dx7_note->keyup(); + MicroDexed[instance_id]->voices[note].sustained = false; } } } - } - break; - case 103: // CC 103: filter resonance - configuration.filter_resonance[0] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->fx.Reso = configuration.filter_resonance[i] / 100.0; - } - break; - case 104: // CC 104: filter cutoff - configuration.filter_cutoff[0] = map(inValue, 0, 0x7f, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX); - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff[i] / 100.0; - } - break; - case 105: // CC 105: delay time - configuration.delay_time = map(inValue, 0, 0x7f, DELAY_TIME_MIN, DELAY_TIME_MAX); - delay1.delay(0, configuration.delay_time * 10); - case 106: // CC 106: delay feedback - configuration.delay_feedback = map(inValue, 0, 0x7f, DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX); - delay_fb_mixer.gain(1, configuration.delay_feedback / 100.0 ); // amount of feedback - delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signalbreak; - break; - case 107: // CC 107: delay volume - configuration.delay_level[0] = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX); - master_mixer_r.gain(DELAY, configuration.delay_level[0] / 100.0); - master_mixer_l.gain(2, configuration.delay_level[0] / 100.0); - break; - case 120: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->panic(); - } - break; - case 121: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->resetControllers(); - } - break; - case 123: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->notesOff(); - } - break; - case 126: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->setMonoMode(true); - } - break; - case 127: - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - MicroDexed[i]->setMonoMode(false); - } - break; + break; + case 103: // CC 103: filter resonance + configuration.filter_resonance[instance_id] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); + MicroDexed[instance_id]->fx.Reso = configuration.filter_resonance[instance_id] / 100.0; + break; + case 104: // CC 104: filter cutoff + configuration.filter_cutoff[instance_id] = map(inValue, 0, 0x7f, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX); + MicroDexed[instance_id]->fx.Cutoff = configuration.filter_cutoff[instance_id] / 100.0; + break; + case 105: // CC 105: delay time + configuration.delay_time = map(inValue, 0, 0x7f, DELAY_TIME_MIN, DELAY_TIME_MAX); + delay1.delay(0, configuration.delay_time * 10); + case 106: // CC 106: delay feedback + configuration.delay_feedback = map(inValue, 0, 0x7f, DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX); + delay_fb_mixer.gain(1, configuration.delay_feedback / 100.0 ); // amount of feedback + delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signalbreak; + break; + case 107: // CC 107: delay volume + configuration.delay_level[instance_id] = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX); + master_mixer_r.gain(DELAY, configuration.delay_level[instance_id] / 100.0); + master_mixer_l.gain(2, configuration.delay_level[instance_id] / 100.0); + break; + case 120: + MicroDexed[instance_id]->panic(); + break; + case 121: + MicroDexed[instance_id]->resetControllers(); + break; + case 123: + MicroDexed[instance_id]->notesOff(); + break; + case 126: + MicroDexed[instance_id]->setMonoMode(true); + break; + case 127: + MicroDexed[instance_id]->setMonoMode(false); + break; + } } } } void handleAfterTouch(byte inChannel, byte inPressure) { - for (uint8_t i = 0; i < NUM_DEXED; i++) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { - MicroDexed[i]->controllers.aftertouch_cc = inPressure; - MicroDexed[i]->controllers.refresh(); + if (checkMidiChannel(inChannel, instance_id)) + { + MicroDexed[instance_id]->controllers.aftertouch_cc = inPressure; + MicroDexed[instance_id]->controllers.refresh(); + } } } void handlePitchBend(byte inChannel, int inPitch) { - for (uint8_t i = 0; i < NUM_DEXED; i++) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { - MicroDexed[i]->controllers.values_[kControllerPitch] = inPitch + 0x2000; // -8192 to +8191 --> 0 to 16383 + if (checkMidiChannel(inChannel, instance_id)) + { + MicroDexed[instance_id]->controllers.values_[kControllerPitch] = inPitch + 0x2000; // -8192 to +8191 --> 0 to 16383 + } } } void handleProgramChange(byte inChannel, byte inProgram) { - if (inProgram < MAX_VOICES) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { + if (checkMidiChannel(inChannel, instance_id)) + { + if (inProgram < MAX_VOICES) + { #ifdef DISPLAY_LCD_SPI - change_disp_sd(false); + change_disp_sd(false); #endif - load_sysex(configuration.bank[0], inProgram); + load_sysex(configuration.bank[instance_id], inProgram, instance_id); #ifdef DISPLAY_LCD_SPI - change_disp_sd(true); + change_disp_sd(true); #endif + } + } } } @@ -746,166 +745,172 @@ void handleSystemExclusive(byte * sysex, uint len) 11110111 F7 Status - end sysex */ -#ifdef DEBUG - Serial.print(F("SYSEX-Data[")); - Serial.print(len, DEC); - Serial.print(F("]")); - for (uint8_t i = 0; i < len; i++) + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { - Serial.print(F(" ")); - Serial.print(sysex[i], DEC); - } - Serial.println(); + if (!checkMidiChannel((sysex[2] & 0x0f) + 1 , instance_id)) + { +#ifdef DEBUG + Serial.print(F("INSTANCE ")); + Serial.print(instance_id, DEC); + Serial.println(F(": SYSEX-MIDI-Channel mismatch")); #endif - - if (!checkMidiChannel((sysex[2] & 0x0f) + 1 )) - { + return; + } #ifdef DEBUG - Serial.println(F("SYSEX-MIDI-Channel mismatch")); + Serial.print(F("INSTANCE ")); + Serial.print(instance_id, DEC); + Serial.print(F(": SYSEX-Data[")); + Serial.print(len, DEC); + Serial.print(F("]")); + for (uint8_t i = 0; i < len; i++) + { + Serial.print(F(" ")); + Serial.print(sysex[i], DEC); + } + Serial.println(); #endif - return; - } - if (sysex[1] != 0x43) // check for Yamaha sysex - { + if (sysex[1] != 0x43) // check for Yamaha sysex + { #ifdef DEBUG - Serial.println(F("E: SysEx vendor not Yamaha.")); + Serial.println(F("E: SysEx vendor not Yamaha.")); #endif - return; - } + return; + } #ifdef DEBUG - Serial.print(F("Substatus: [")); - Serial.print((sysex[2] & 0x70) >> 4); - Serial.println(F("]")); + Serial.print(F("Substatus: [")); + Serial.print((sysex[2] & 0x70) >> 4); + Serial.println(F("]")); #endif - // parse parameter change - if (len == 7) - { - if (((sysex[3] & 0x7c) >> 2) != 0 && ((sysex[3] & 0x7c) >> 2) != 2) + // parse parameter change + if (len == 7) { + if (((sysex[3] & 0x7c) >> 2) != 0 && ((sysex[3] & 0x7c) >> 2) != 2) + { #ifdef DEBUG - Serial.println(F("E: Not a SysEx parameter or function parameter change.")); + Serial.println(F("E: Not a SysEx parameter or function parameter change.")); #endif - return; - } - if (sysex[6] != 0xf7) - { + return; + } + if (sysex[6] != 0xf7) + { #ifdef DEBUG - Serial.println(F("E: SysEx end status byte not detected.")); + Serial.println(F("E: SysEx end status byte not detected.")); #endif - return; - } + return; + } - sysex[4] &= 0x7f; - sysex[5] &= 0x7f; + sysex[4] &= 0x7f; + sysex[5] &= 0x7f; - uint8_t data_index; + uint8_t data_index; - if (((sysex[3] & 0x7c) >> 2) == 0) - { - MicroDexed[0]->notesOff(); - MicroDexed[0]->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter - MicroDexed[0]->doRefreshVoice(); - data_index = sysex[4] + ((sysex[3] & 0x03) * 128); - } - else - { - MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set function parameter - MicroDexed[0]->controllers.values_[kControllerPitchRange] = MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; - MicroDexed[0]->controllers.values_[kControllerPitchStep] = MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; - MicroDexed[0]->controllers.wheel.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); - MicroDexed[0]->controllers.wheel.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); - MicroDexed[0]->controllers.foot.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); - MicroDexed[0]->controllers.foot.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); - MicroDexed[0]->controllers.breath.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); - MicroDexed[0]->controllers.breath.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); - MicroDexed[0]->controllers.at.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); - MicroDexed[0]->controllers.at.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); - MicroDexed[0]->controllers.masterTune = (MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); - MicroDexed[0]->controllers.refresh(); - data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]; - } + if (((sysex[3] & 0x7c) >> 2) == 0) + { + MicroDexed[instance_id]->notesOff(); + MicroDexed[instance_id]->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter + MicroDexed[instance_id]->doRefreshVoice(); + data_index = sysex[4] + ((sysex[3] & 0x03) * 128); + } + else + { + MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set function parameter + MicroDexed[instance_id]->controllers.values_[kControllerPitchRange] = MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; + MicroDexed[instance_id]->controllers.values_[kControllerPitchStep] = MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; + MicroDexed[instance_id]->controllers.wheel.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); + MicroDexed[instance_id]->controllers.wheel.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); + MicroDexed[instance_id]->controllers.foot.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); + MicroDexed[instance_id]->controllers.foot.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); + MicroDexed[instance_id]->controllers.breath.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); + MicroDexed[instance_id]->controllers.breath.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); + MicroDexed[instance_id]->controllers.at.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); + MicroDexed[instance_id]->controllers.at.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); + MicroDexed[instance_id]->controllers.masterTune = (MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); + MicroDexed[instance_id]->controllers.refresh(); + data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]; + } #ifdef DEBUG - Serial.print(F("SysEx")); - if (((sysex[3] & 0x7c) >> 2) == 0) - Serial.print(F(" function")); - Serial.print(F(" parameter ")); - Serial.print(sysex[4], DEC); - Serial.print(F(" = ")); - Serial.print(sysex[5], DEC); - Serial.print(F(", data_index = ")); - Serial.println(data_index, DEC); + Serial.print(F("SysEx")); + if (((sysex[3] & 0x7c) >> 2) == 0) + Serial.print(F(" function")); + Serial.print(F(" parameter ")); + Serial.print(sysex[4], DEC); + Serial.print(F(" = ")); + Serial.print(sysex[5], DEC); + Serial.print(F(", data_index = ")); + Serial.println(data_index, DEC); #endif - } - else if (len == 163) - { - int32_t bulk_checksum_calc = 0; - int8_t bulk_checksum = sysex[161]; + } + else if (len == 163) + { + int32_t bulk_checksum_calc = 0; + int8_t bulk_checksum = sysex[161]; - // 1 Voice bulk upload + // 1 Voice bulk upload #ifdef DEBUG - Serial.println(F("One Voice bulk upload")); + Serial.println(F("One Voice bulk upload")); #endif - if (sysex[162] != 0xf7) - { + if (sysex[162] != 0xf7) + { #ifdef DEBUG - Serial.println(F("E: Found no SysEx end marker.")); + Serial.println(F("E: Found no SysEx end marker.")); #endif - return; - } + return; + } - if ((sysex[3] & 0x7f) != 0) - { + if ((sysex[3] & 0x7f) != 0) + { #ifdef DEBUG - Serial.println(F("E: Not a SysEx voice bulk upload.")); + Serial.println(F("E: Not a SysEx voice bulk upload.")); #endif - return; - } + return; + } - if (((sysex[4] << 7) | sysex[5]) != 0x9b) - { + if (((sysex[4] << 7) | sysex[5]) != 0x9b) + { #ifdef DEBUG - Serial.println(F("E: Wrong length for SysEx voice bulk upload (not 155).")); + Serial.println(F("E: Wrong length for SysEx voice bulk upload (not 155).")); #endif - return; - } + return; + } - // checksum calculation - for (uint8_t i = 0; i < 155 ; i++) - { - bulk_checksum_calc -= sysex[i + 6]; - } - bulk_checksum_calc &= 0x7f; + // checksum calculation + for (uint8_t i = 0; i < 155 ; i++) + { + bulk_checksum_calc -= sysex[i + 6]; + } + bulk_checksum_calc &= 0x7f; - if (bulk_checksum_calc != bulk_checksum) - { + if (bulk_checksum_calc != bulk_checksum) + { #ifdef DEBUG - Serial.print(F("E: Checksum error for one voice [0x")); - Serial.print(bulk_checksum, HEX); - Serial.print(F("/0x")); - Serial.print(bulk_checksum_calc, HEX); - Serial.println(F("]")); + Serial.print(F("E: Checksum error for one voice [0x")); + Serial.print(bulk_checksum, HEX); + Serial.print(F("/0x")); + Serial.print(bulk_checksum_calc, HEX); + Serial.println(F("]")); #endif - return; - } + return; + } - // load sysex-data into voice memory - MicroDexed[0]->loadVoiceParameters(&sysex[6]); - //MicroDexed[0]->initGlobalParameters(); + // load sysex-data into voice memory + MicroDexed[instance_id]->loadVoiceParameters(&sysex[6]); + //MicroDexed[instance_id]->initGlobalParameters(); - // manipulate UI names and numbers - strncpy(voice_name, (char *)&sysex[151], sizeof(voice_name) - 1); - Serial.print(F("Got voice [")); - Serial.print(voice_name); - Serial.println(F("].")); - } + // manipulate UI names and numbers + strncpy(voice_name[instance_id], (char *)&sysex[151], sizeof(voice_name[instance_id]) - 1); + Serial.print(F("Got voice [")); + Serial.print(voice_name[instance_id]); + Serial.println(F("].")); + } #ifdef DEBUG - else - Serial.println(F("E: SysEx parameter length wrong.")); + else + Serial.println(F("E: SysEx parameter length wrong.")); #endif + } } void handleTimeCodeQuarterFrame(byte data) @@ -969,31 +974,36 @@ void handleActiveSensing(void) void handleSystemReset(void) { + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { #ifdef DEBUG - Serial.println(F("MIDI SYSEX RESET")); + Serial.println(F("MIDI SYSEX RESET")); #endif - MicroDexed[0]->notesOff(); - MicroDexed[0]->panic(); - MicroDexed[0]->resetControllers(); + MicroDexed[instance_id]->notesOff(); + MicroDexed[instance_id]->panic(); + MicroDexed[instance_id]->resetControllers(); + } } /****************************************************************************** MIDI HELPER ******************************************************************************/ -bool checkMidiChannel(byte inChannel) +bool checkMidiChannel(byte inChannel, uint8_t instance_id) { // check for MIDI channel - if (configuration.midi_channel[0] == MIDI_CHANNEL_OMNI) + if (configuration.midi_channel[instance_id] == MIDI_CHANNEL_OMNI) { return (true); } - else if (inChannel != configuration.midi_channel[0]) + else if (inChannel != configuration.midi_channel[instance_id]) { #ifdef DEBUG - Serial.print(F("Ignoring MIDI data on channel ")); + Serial.print(F("INSTANCE ")); + Serial.print(instance_id, DEC); + Serial.print(F(": Ignoring MIDI data on channel ")); Serial.print(inChannel); Serial.print(F("(listening on ")); - Serial.print(configuration.midi_channel[0]); + Serial.print(configuration.midi_channel[instance_id]); Serial.println(F(")")); #endif return (false); @@ -1132,13 +1142,56 @@ void initial_values_from_eeprom(void) configuration.at_assign[i] = AT_ASSIGN_DEFAULT; configuration.op_enabled[i] = OP_ENABLED_DEFAULT; } - eeprom_update(); } else { EEPROM_readAnything(EEPROM_START_ADDRESS, configuration); + + configuration.instances %= INSTANCES_MAX; + configuration.instance_mode %= INSTANCE_MODE_MAX; + configuration.instance_splitpoint %= INSTANCE_SPLITPOINT_MAX; + configuration.vol %= VOLUME_MAX; + configuration.mono %= MONO_MAX; + configuration.reverb_roomsize %= REVERB_ROOMSIZE_MAX; + configuration.reverb_damping %= REVERB_DAMPING_MAX; + configuration.chorus_frequency %= CHORUS_FREQUENCY_MAX; + configuration.chorus_waveform %= CHORUS_WAVEFORM_MAX; + configuration.chorus_depth %= CHORUS_DEPTH_MAX; + configuration.delay_time %= DELAY_TIME_MAX; + configuration.delay_feedback %= DELAY_FEEDBACK_MAX; + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + configuration.midi_channel[i] %= MIDI_CHANNEL_MAX; + configuration.bank[i] %= MAX_BANKS; + configuration.voice[i] %= MAX_VOICES; + configuration.pan[i] %= PANORAMA_MAX; + configuration.reverb_level[i] %= REVERB_LEVEL_MAX; + configuration.chorus_level[i] %= CHORUS_LEVEL_MAX; + configuration.delay_level[i] %= DELAY_LEVEL_MAX; + configuration.filter_cutoff[i] %= FILTER_CUTOFF_MAX; + configuration.filter_resonance[i] %= FILTER_RESONANCE_MAX; + configuration.loudness[i] %= LOUDNESS_MAX; + configuration.polyphony[i] %= POLYPHONY_MAX; + configuration.engine[i] %= ENGINE_MAX; + configuration.monopoly[i] %= MONOPOLY_MAX; + configuration.pb_range[i] %= PB_RANGE_MAX; + configuration.pb_step[i] %= PB_STEP_MAX; + configuration.mw_range[i] %= MW_RANGE_MAX; + configuration.mw_assign[i] %= MW_ASSIGN_MAX; + configuration.fc_range[i] %= FC_RANGE_MAX; + configuration.fc_assign[i] %= FC_ASSIGN_MAX; + configuration.bc_range[i] %= BC_RANGE_MAX; + configuration.bc_assign[i] %= BC_ASSIGN_MAX; + configuration.at_range[i] %= AT_RANGE_MAX; + configuration.at_assign[i] %= AT_ASSIGN_MAX; + configuration.op_enabled[i] %= 0x3f; + + //MicroDexed[i]->setControllers(configuration.pb_range[i], configuration.pb_step[i], configuration.mw_range[i], configuration.mw_assign[i], configuration.fc_range[i], configuration.fc_assign[i], configuration.bc_range[i], configuration.bc_assign[i], configuration.at_range[i], configuration.at_assign[i]); + } Serial.print(F(" - OK, loading!")); } + eeprom_update(); + #ifdef DEBUG Serial.println(); show_configuration(); @@ -1190,6 +1243,17 @@ uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https:/ #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) void show_cpu_and_mem_usage(void) { + uint32_t sum_xrun = 0; + uint16_t sum_render_time_max = 0; + uint32_t sum_overload = 0; + + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { + sum_xrun += MicroDexed[instance_id]->xrun; + sum_render_time_max += MicroDexed[instance_id]->render_time_max; + sum_overload += MicroDexed[instance_id]->overload; + MicroDexed[instance_id]->render_time_max = 0; + } Serial.print(F("CPU: ")); Serial.print(AudioProcessorUsage(), 2); Serial.print(F("% CPU MAX: ")); @@ -1199,11 +1263,11 @@ void show_cpu_and_mem_usage(void) Serial.print(F(" MEM MAX: ")); Serial.print(AudioMemoryUsageMax(), DEC); Serial.print(F(" RENDER_TIME_MAX: ")); - Serial.print(MicroDexed[0]->render_time_max, DEC); + Serial.print(sum_render_time_max, DEC); Serial.print(F(" XRUN: ")); - Serial.print(MicroDexed[0]->xrun, DEC); + Serial.print(sum_xrun, DEC); Serial.print(F(" OVERLOAD: ")); - Serial.print(MicroDexed[0]->overload, DEC); + Serial.print(sum_overload, DEC); Serial.print(F(" PEAK: ")); Serial.print(peak, DEC); Serial.print(F(" BLOCKSIZE: ")); @@ -1213,7 +1277,6 @@ void show_cpu_and_mem_usage(void) Serial.println(); AudioProcessorUsageMaxReset(); AudioMemoryUsageMaxReset(); - MicroDexed[0]->render_time_max = 0; } #endif @@ -1237,7 +1300,7 @@ void show_configuration(void) Serial.print(F("Delay Feedback ")); Serial.println(configuration.delay_feedback, DEC); for (uint8_t i = 0; i < NUM_DEXED; i++) { - Serial.print(F("=== DEXED Instance ")); + Serial.print(F("=== DEXED INSTANCE ")); Serial.print(i, DEC); Serial.println(" ==="); Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.midi_channel[i], DEC); @@ -1268,11 +1331,14 @@ void show_configuration(void) Serial.println(); } -void show_patch(void) +void show_patch(uint8_t instance_id) { uint8_t i; char voicename[VOICE_NAME_LEN]; + Serial.print(F("INSTANCE ")); + Serial.println(instance_id, DEC); + memset(voicename, 0, sizeof(voicename)); for (i = 0; i < 6; i++) { @@ -1280,81 +1346,81 @@ void show_patch(void) Serial.print(6 - i, DEC); Serial.println(F(": ")); Serial.println(F("R1 | R2 | R3 | R4 | L1 | L2 | L3 | L4 LEV_SCL_BRK_PT | SCL_LEFT_DEPTH | SCL_RGHT_DEPTH")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R1], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_R1], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R2], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_R2], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R3], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_R3], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R4], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_R4], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L1], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_L1], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L2], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_L2], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L3], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_L3], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L4], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_EG_L4], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_LEV_SCL_BRK_PT], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_LEV_SCL_BRK_PT], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_LEFT_DEPTH], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_SCL_LEFT_DEPTH], DEC); Serial.print(F(" ")); - Serial.println(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_RGHT_DEPTH], DEC); + Serial.println(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_SCL_RGHT_DEPTH], DEC); Serial.println(F("SCL_L_CURVE | SCL_R_CURVE | RT_SCALE | AMS | KVS | OUT_LEV | OP_MOD | FRQ_C | FRQ_F | DETUNE")); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_LEFT_CURVE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_SCL_LEFT_CURVE], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_RGHT_CURVE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_SCL_RGHT_CURVE], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_RATE_SCALE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_OSC_RATE_SCALE], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_AMP_MOD_SENS], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_AMP_MOD_SENS], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_KEY_VEL_SENS], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_KEY_VEL_SENS], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OUTPUT_LEV], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_OUTPUT_LEV], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_MODE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_OSC_MODE], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_FREQ_COARSE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_FREQ_COARSE], DEC); Serial.print(F(" ")); - Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_FREQ_FINE], DEC); + Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_FREQ_FINE], DEC); Serial.print(F(" ")); - Serial.println(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_DETUNE], DEC); + Serial.println(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_OSC_DETUNE], DEC); } Serial.println(F("PR1 | PR2 | PR3 | PR4 | PL1 | PL2 | PL3 | PL4")); Serial.print(F(" ")); for (i = 0; i < 8; i++) { - Serial.print(MicroDexed[0]->data[DEXED_VOICE_OFFSET + i], DEC); + Serial.print(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + i], DEC); Serial.print(F(" ")); } Serial.println(); Serial.print(F("ALG: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_ALGORITHM], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_ALGORITHM], DEC); Serial.print(F("FB: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_FEEDBACK], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_FEEDBACK], DEC); Serial.print(F("OKS: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC], DEC); Serial.print(F("LFO SPD: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], DEC); Serial.print(F("LFO_DLY: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_DELAY], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_DELAY], DEC); Serial.print(F("LFO PMD: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_DEP], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_DEP], DEC); Serial.print(F("LFO_AMD: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_AMP_MOD_DEP], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_AMP_MOD_DEP], DEC); Serial.print(F("LFO_SYNC: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SYNC], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SYNC], DEC); Serial.print(F("LFO_WAVEFRM: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_WAVE], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_WAVE], DEC); Serial.print(F("LFO_PMS: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS], DEC); Serial.print(F("TRNSPSE: ")); - Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_TRANSPOSE], DEC); + Serial.println(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_TRANSPOSE], DEC); Serial.print(F("NAME: ")); - strncpy(voicename, (char *)&MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_NAME], sizeof(voicename) - 1); + strncpy(voicename, (char *)&MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + DEXED_NAME], sizeof(voicename) - 1); Serial.print(F("[")); Serial.print(voicename); Serial.println(F("]")); @@ -1362,7 +1428,7 @@ void show_patch(void) { Serial.print(i, DEC); Serial.print(F(": ")); - Serial.println(MicroDexed[0]->data[i]); + Serial.println(MicroDexed[instance_id]->data[i]); } Serial.println(); diff --git a/UI.hpp b/UI.hpp index 61953c0..ad21d9d 100644 --- a/UI.hpp +++ b/UI.hpp @@ -48,13 +48,13 @@ extern config_t configuration; extern void set_volume(uint8_t v, int8_t p, uint8_t m); -extern char bank_names[MAX_BANKS][BANK_NAME_LEN]; -extern char bank_name[BANK_NAME_LEN]; -extern char voice_name[VOICE_NAME_LEN]; -extern char voice_names[MAX_VOICES][VOICE_NAME_LEN]; +extern char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN]; +extern char bank_name[NUM_DEXED][BANK_NAME_LEN]; +extern char voice_name[NUM_DEXED][VOICE_NAME_LEN]; +extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN]; extern void strip_extension(char* s, char *target); extern void eeprom_write(void); -extern bool get_voice_names_from_bank(uint8_t b); +extern bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id); extern bool load_sysex(uint8_t b, uint8_t v); #ifdef DISPLAY_LCD_SPI extern void change_disp_sd(bool d); @@ -148,11 +148,11 @@ void UI_func_mono_poly(uint8_t param); void UI_func_pb_range(uint8_t param); void UI_func_pb_step(uint8_t param); void UI_func_mw_range(uint8_t param); -void UI_func_mw_step(uint8_t param); +void UI_func_mw_assign(uint8_t param); void UI_func_fc_range(uint8_t param); -void UI_func_fc_step(uint8_t param); +void UI_func_fc_assign(uint8_t param); void UI_func_at_range(uint8_t param); -void UI_func_at_step(uint8_t param); +void UI_func_at_assign(uint8_t param); void UI_func_information(uint8_t param); void UI_func_voice_selection(uint8_t param); void UI_func_volume(uint8_t param); @@ -183,8 +183,8 @@ LCDML_add(12, LCDML_0_1_2, 10, "Pitchbend 1", NULL); LCDML_add(13, LCDML_0_1_2_7, 1, "PB Range 1", UI_func_pb_range); LCDML_add(14, LCDML_0_1_2_7, 2, "PB Step 1", UI_func_pb_step); LCDML_add(15, LCDML_0_1_2, 11, "Mod Wheel 1", NULL); -LCDML_add(16, LCDML_0_1_2_8, 1, "MW Range 1", UI_function_not_implemented); -LCDML_add(17, LCDML_0_1_2_8, 2, "MW Assign 1", UI_function_not_implemented); +LCDML_add(16, LCDML_0_1_2_8, 1, "MW Range 1", UI_func_mw_range); +LCDML_add(17, LCDML_0_1_2_8, 2, "MW Assign 1", UI_func_mw_assign); LCDML_add(18, LCDML_0_1_2, 12, "Foot Ctrl 1", NULL); LCDML_add(19, LCDML_0_1_2_9, 1, "FC Range 1", UI_function_not_implemented); LCDML_add(20, LCDML_0_1_2_9, 2, "FC Assign 1", UI_function_not_implemented); @@ -276,8 +276,8 @@ LCDML_add(10, LCDML_0_1, 10, "Pitchbend", NULL); LCDML_add(11, LCDML_0_1_10, 1, "PB Range", UI_func_pb_range); LCDML_add(12, LCDML_0_1_10, 2, "PB Step", UI_func_pb_step); LCDML_add(13, LCDML_0_1, 11, "Mod Wheel", NULL); -LCDML_add(14, LCDML_0_1_11, 1, "MW Range", UI_function_not_implemented); -LCDML_add(15, LCDML_0_1_11, 2, "MW Assign", UI_function_not_implemented); +LCDML_add(14, LCDML_0_1_11, 1, "MW Range", UI_func_mw_range); +LCDML_add(15, LCDML_0_1_11, 2, "MW Assign", UI_func_mw_assign); LCDML_add(16, LCDML_0_1, 12, "Foot Ctrl", NULL); LCDML_add(17, LCDML_0_1_12, 1, "FC Range", UI_function_not_implemented); LCDML_add(18, LCDML_0_1_12, 2, "FC Assign", UI_function_not_implemented); @@ -560,8 +560,8 @@ void encoder_right_up(void) #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); - get_voice_names_from_bank(configuration.bank[instance_id]); + load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -582,8 +582,8 @@ void encoder_right_up(void) #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); - get_voice_names_from_bank(configuration.bank[instance_id]); + load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -623,8 +623,8 @@ void encoder_right_down(void) change_disp_sd(false); #endif - load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); - get_voice_names_from_bank(configuration.bank[instance_id]); + load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -645,8 +645,8 @@ void encoder_right_down(void) #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); - get_voice_names_from_bank(configuration.bank[instance_id]); + load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -1409,13 +1409,13 @@ void UI_func_filter_cutoff(uint8_t param) lcd.setCursor(0, 1); lcd_display_int(configuration.filter_cutoff[instance_id], 3, true, true, false); - Serial.print(LCDML.FUNC_getID(),DEC); + Serial.print(LCDML.FUNC_getID(), DEC); Serial.print(" "); - Serial.print(MENU_ID_OF_INSTANCE_2,DEC); -Serial.print(" INSTANCE: "); -Serial.print(instance_id,DEC); -Serial.print(" value: "); -Serial.println(configuration.filter_cutoff[instance_id] / 100.0,3); + Serial.print(MENU_ID_OF_INSTANCE_2, DEC); + Serial.print(" INSTANCE: "); + Serial.print(instance_id, DEC); + Serial.print(" value: "); + Serial.println(configuration.filter_cutoff[instance_id] / 100.0, 3); MicroDexed[instance_id]->fx.Cutoff = configuration.filter_cutoff[instance_id] / 100.0; } @@ -1897,7 +1897,7 @@ void UI_func_pb_range(uint8_t param) lcd.setCursor(0, 1); lcd_display_int(configuration.pb_range[instance_id], 2, false, true, false); - MicroDexed[instance_id]->setControllers(configuration.pb_range[instance_id], configuration.pb_step[instance_id], configuration.mw_range[instance_id], configuration.mw_assign[instance_id], configuration.fc_range[instance_id], configuration.fc_assign[instance_id], configuration.bc_range[instance_id], configuration.bc_assign[instance_id], configuration.at_range[instance_id], configuration.at_assign[instance_id]); + MicroDexed[instance_id]->setPBController(configuration.pb_range[instance_id], configuration.pb_step[instance_id]); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1945,7 +1945,7 @@ void UI_func_pb_step(uint8_t param) lcd.setCursor(0, 1); lcd_display_int(configuration.pb_step[instance_id], 2, false, true, false); - MicroDexed[instance_id]->setControllers(configuration.pb_range[instance_id], configuration.pb_step[instance_id], configuration.mw_range[instance_id], configuration.mw_assign[instance_id], configuration.fc_range[instance_id], configuration.fc_assign[instance_id], configuration.bc_range[instance_id], configuration.bc_assign[instance_id], configuration.at_range[instance_id], configuration.at_assign[instance_id]); + MicroDexed[instance_id]->setPBController(configuration.pb_range[instance_id], configuration.pb_step[instance_id]); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1957,12 +1957,125 @@ void UI_func_pb_step(uint8_t param) void UI_func_mw_range(uint8_t param) { + uint8_t instance_id = 0; + + if (LCDML.FUNC_getID() < MENU_ID_OF_INSTANCE_2) + instance_id = 1; + + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + // setup function + lcd.setCursor(0, 0); + lcd.print(F("MW Range")); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if (LCDML.BT_checkEnter()) + { + LCDML.FUNC_goBackToMenu(); + } + else if (LCDML.BT_checkDown()) + { + if (configuration.mw_range[instance_id] < MW_RANGE_MAX) + { + configuration.mw_range[instance_id]++; + } + } + else if (LCDML.BT_checkUp()) + { + if (configuration.mw_range[instance_id] > MW_RANGE_MIN) + { + configuration.mw_range[instance_id]--; + } + } + + lcd.setCursor(0, 1); + lcd_display_int(configuration.mw_range[instance_id], 2, false, true, false); + MicroDexed[instance_id]->setMWController(configuration.mw_range[instance_id], configuration.mw_assign[instance_id]); + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + // you can here reset some global vars or do nothing + eeprom_write(); + } } -void UI_func_mw_step(uint8_t param) +void UI_func_mw_assign(uint8_t param) { + uint8_t instance_id = 0; + + if (LCDML.FUNC_getID() < MENU_ID_OF_INSTANCE_2) + instance_id = 1; + + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + // setup function + lcd.setCursor(0, 0); + lcd.print(F("MW Assign")); + } + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if (LCDML.BT_checkEnter()) + { + LCDML.FUNC_goBackToMenu(); + } + else if (LCDML.BT_checkDown()) + { + if (configuration.mw_assign[instance_id] < MW_ASSIGN_MAX) + { + configuration.mw_assign[instance_id]++; + } + } + else if (LCDML.BT_checkUp()) + { + if (configuration.mw_assign[instance_id] > MW_ASSIGN_MIN) + { + configuration.mw_assign[instance_id]--; + } + } + + lcd.setCursor(0, 1); + switch (configuration.mw_assign[instance_id]) + { + default: + case 0: + lcd.print(F("[ NONE ]")); + break; + case 1: + lcd.print(F("[PTCH ]")); + break; + case 2: + lcd.print(F("[ AMP ]")); + break; + case 3: + lcd.print(F("[PTCH AMP ]")); + break; + case 4: + lcd.print(F("[ EG-BS]")); + break; + case 5: + lcd.print(F("[PTCH EG-BS]")); + break; + case 6: + lcd.print(F("[ AMP EG-BS]")); + break; + case 7: + lcd.print(F("[PTCH AMP EG-BS]")); + break; + } + + MicroDexed[instance_id]->setMWController(configuration.mw_range[instance_id], configuration.mw_assign[instance_id]); + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + // you can here reset some global vars or do nothing + eeprom_write(); + } } void UI_func_fc_range(uint8_t param) @@ -1970,7 +2083,7 @@ void UI_func_fc_range(uint8_t param) } -void UI_func_fc_step(uint8_t param) +void UI_func_fc_assign(uint8_t param) { } @@ -1980,7 +2093,7 @@ void UI_func_at_range(uint8_t param) } -void UI_func_at_step(uint8_t param) +void UI_func_at_assign(uint8_t param) { } @@ -2014,28 +2127,23 @@ void UI_func_information(uint8_t param) void UI_func_voice_selection(uint8_t param) { - uint8_t instance_id = 0; - - if (LCDML.FUNC_getID() < MENU_ID_OF_INSTANCE_2) - instance_id = 1; - #ifdef DEBUG Serial.println(F("UI_func_voice_selection()")); #endif menu_state = MENU_VOICE; - strip_extension(bank_names[configuration.bank[instance_id]], bank_name); + strip_extension(bank_names[selected_dexed_instance][configuration.bank[selected_dexed_instance]], bank_name[selected_dexed_instance]); //LCDML.DISP_clear(); // display bank and voice number - lcd.show(0, 0, 2, configuration.bank[instance_id]); - lcd.show(1, 0, 2, configuration.voice[instance_id] + 1); + lcd.show(0, 0, 2, configuration.bank[selected_dexed_instance]); + lcd.show(1, 0, 2, configuration.voice[selected_dexed_instance] + 1); // display names - lcd.show(0, 4, 10, bank_name); - lcd.show(1, 4, 10, voice_names[configuration.voice[instance_id]]); + lcd.show(0, 4, 10, bank_name[selected_dexed_instance]); + lcd.show(1, 4, 10, voice_names[selected_dexed_instance][configuration.voice[selected_dexed_instance]]); // display selected Dexed instance if (selected_dexed_instance == 1) diff --git a/config.h b/config.h index c0fc1ad..40a8d6d 100644 --- a/config.h +++ b/config.h @@ -358,7 +358,7 @@ enum { DEXED, REVERB, DELAY, CHORUS }; #define MW_RANGE_MAX 12 #define MW_RANGE_DEFAULT 12 -#define MW_ASIGN_MIN 0 +#define MW_ASSIGN_MIN 0 #define MW_ASSIGN_MAX 7 #define MW_ASSIGN_DEFAULT 0 // Bitmapped: 0: Pitch, 1: Amp, 2: Bias diff --git a/dexed.cpp b/dexed.cpp index 34e9fe9..83fb6e7 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -172,8 +172,12 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer) fx.process(sumbuf, n_samples); +#ifdef USE_TEENSY_DSP + arm_float_to_q15(sumbuf, buffer, AUDIO_BLOCK_SAMPLES); +#else for (i = 0; i < n_samples; ++i) buffer[i] = static_cast(sumbuf[i] * 0x7fff); +#endif } void Dexed::keydown(uint8_t pitch, uint8_t velo) { @@ -430,6 +434,7 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) uint8_t* p_data = data; uint8_t op; uint8_t tmp; + char dexed_voice_name[11]; notesOff(); @@ -492,11 +497,11 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) doRefreshVoice(); //activate(); - strncpy(voice_name, (char *)&new_data[118], sizeof(voice_name) - 1); - voice_name[10] = '\0'; + strncpy(dexed_voice_name, (char *)&new_data[118], sizeof(dexed_voice_name) - 1); + dexed_voice_name[10] = '\0'; #ifdef DEBUG Serial.print(F("Voice [")); - Serial.print(voice_name); + Serial.print(dexed_voice_name); Serial.println(F("] loaded.")); #endif @@ -505,6 +510,8 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) bool Dexed::loadVoiceParameters(uint8_t* new_data) { + char dexed_voice_name[11]; + notesOff(); memcpy(&data, new_data, 155); @@ -513,11 +520,11 @@ bool Dexed::loadVoiceParameters(uint8_t* new_data) doRefreshVoice(); //activate(); - strncpy(voice_name, (char *)&new_data[145], sizeof(voice_name) - 1); - voice_name[10] = '\0'; + strncpy(dexed_voice_name, (char *)&new_data[145], sizeof(dexed_voice_name) - 1); + dexed_voice_name[10] = '\0'; #ifdef DEBUG Serial.print(F("Voice [")); - Serial.print(voice_name); + Serial.print(dexed_voice_name); Serial.println(F("] loaded.")); #endif @@ -592,30 +599,116 @@ bool Dexed::initGlobalParameters(void) return (true); } -void Dexed::setControllers(uint8_t pb_range, uint8_t pb_step, uint8_t mw_range, uint8_t mw_assign, uint8_t fc_range, uint8_t fc_assign, uint8_t bc_range, uint8_t bc_assign, uint8_t at_range, uint8_t at_assign) +void Dexed::setPBController(uint8_t pb_range, uint8_t pb_step) { +#ifdef DEBUG + Serial.println(F("Dexed::setPBController")); +#endif + pb_range %= PB_RANGE_MAX; pb_step %= PB_STEP_MAX; + +#ifdef DEBUG + Serial.print(F("pb_range=")); + Serial.println(pb_range, DEC); + Serial.print(F("pb_step=")); + Serial.println(pb_step, DEC); +#endif + + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE] = pb_range; + controllers.values_[kControllerPitchRange] = pb_range; + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP] = pb_step; + controllers.values_[kControllerPitchStep] = pb_step; + + controllers.refresh(); +} + +void Dexed::setMWController(uint8_t mw_range, uint8_t mw_assign) +{ +#ifdef DEBUG + Serial.println(F("Dexed::setMWController")); +#endif + mw_range %= MW_RANGE_MAX; mw_assign %= MW_ASSIGN_MAX; - fc_range %= FC_RANGE_MAX; - fc_assign %= FC_ASSIGN_MAX; - bc_range %= BC_RANGE_MAX; - bc_assign %= BC_ASSIGN_MAX; - at_range %= AT_RANGE_MAX; - at_assign %= AT_ASSIGN_MAX; - data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE] = controllers.values_[kControllerPitchRange] = pb_range; - data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP] = controllers.values_[kControllerPitchStep] = pb_step; +#ifdef DEBUG + Serial.print(F("mw_range=")); + Serial.println(mw_range, DEC); + Serial.print(F("mw_assign=")); + Serial.println(mw_assign, DEC); +#endif + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE] = mw_range; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN] = mw_assign; controllers.wheel.setTarget(mw_assign); + + controllers.refresh(); +} + +void Dexed::setFCController(uint8_t fc_range, uint8_t fc_assign) +{ +#ifdef DEBUG + Serial.println(F("Dexed::setFCController")); +#endif + + fc_range %= FC_RANGE_MAX; + fc_assign %= FC_ASSIGN_MAX; + +#ifdef DEBUG + Serial.print(F("fc_range=")); + Serial.println(fc_range, DEC); + Serial.print(F("fc_assign=")); + Serial.println(fc_assign, DEC); +#endif + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE] = fc_range; - data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN] = fc_assign; + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN] = fc_assign; + controllers.foot.setTarget(fc_assign); + + controllers.refresh(); +} + +void Dexed::setBCController(uint8_t bc_range, uint8_t bc_assign) +{ +#ifdef DEBUG + Serial.println(F("Dexed::setBCController")); +#endif + + bc_range %= BC_RANGE_MAX; + bc_assign %= BC_ASSIGN_MAX; + +#ifdef DEBUG + Serial.print(F("bc_range=")); + Serial.println(bc_range, DEC); + Serial.print(F("bc_assign=")); + Serial.println(bc_assign, DEC); +#endif + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE] = bc_range; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN] = bc_assign; controllers.breath.setTarget(bc_assign); + + controllers.refresh(); +} + +void Dexed::setATController(uint8_t at_range, uint8_t at_assign) +{ +#ifdef DEBUG + Serial.println(F("Dexed::setATController")); +#endif + + at_range %= AT_RANGE_MAX; + at_assign %= AT_ASSIGN_MAX; + +#ifdef DEBUG + Serial.print(F("at_range=")); + Serial.println(at_range, DEC); + Serial.print(F("at_assign=")); + Serial.println(at_assign, DEC); +#endif + data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE] = at_range; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN] = at_assign; controllers.at.setTarget(at_assign); diff --git a/dexed.h b/dexed.h index 6e039e2..5174f69 100644 --- a/dexed.h +++ b/dexed.h @@ -44,7 +44,6 @@ extern AudioControlSGTL5000 sgtl5000_1; extern float vol; extern float vol_right; extern float vol_left; -extern char voice_name[11]; struct ProcessorVoice { uint8_t midi_note; @@ -164,7 +163,11 @@ class Dexed void setSustain(bool sustain); bool getSustain(void); uint8_t getNumNotesPlaying(void); - void setControllers(uint8_t pb_range, uint8_t pb_Step, uint8_t mw_range, uint8_t mw_assign, uint8_t fc_range, uint8_t fw_assign, uint8_t bc_range, uint8_t bc_assign, uint8_t at_range, uint8_t at_assign); + void setPBController(uint8_t pb_range, uint8_t pb_step); + void setMWController(uint8_t mw_range, uint8_t mw_assign); + void setFCController(uint8_t fc_range, uint8_t fc_assign); + void setBCController(uint8_t bc_range, uint8_t bc_assign); + void setATController(uint8_t at_range, uint8_t pb_assign); ProcessorVoice voices[MAX_NOTES]; Controllers controllers; @@ -185,7 +188,7 @@ class Dexed 01, 00, 99, 00, 99, 00, 99, 00, 99, 00, // pitch_bend_range, pitch_bend_step, mod_wheel_range, mod_wheel_assign, foot_ctrl_range, foot_ctrl_assign, breath_ctrl_range, breath_ctrl_assign, aftertouch_range, aftertouch_assign 00, // master tune 01, 01, 01, 01, 01, 01, // OP1-6 enable - 16 // number of voices + MAX_NOTES // number of voices }; // FM-Piano uint32_t overload = 0; diff --git a/dexed_sysex.cpp b/dexed_sysex.cpp index cbe84e3..6175078 100644 --- a/dexed_sysex.cpp +++ b/dexed_sysex.cpp @@ -33,19 +33,19 @@ extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; -void create_sysex_filename(uint8_t b, char* sysex_file_name) +void create_sysex_filename(uint8_t b, char* sysex_file_name, uint8_t instance_id) { // init and set name for actual bank memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN); sysex_file_name[0] = '/'; itoa(b, &sysex_file_name[1], 10); strcat(sysex_file_name, "/"); - strcat(sysex_file_name, bank_names[b]); + strcat(sysex_file_name, bank_names[instance_id][b]); #ifdef DEBUG Serial.print(F("Created sysex_filename from bank ")); Serial.print(b, DEC); Serial.print(F(" and name ")); - Serial.print(bank_names[b]); + Serial.print(bank_names[instance_id][b]); Serial.print(F(": [")); Serial.print(sysex_file_name); Serial.println(F("]")); @@ -65,7 +65,7 @@ void strip_extension(char* s, char* target) strcpy(target, token); } -bool get_voice_names_from_bank(uint8_t b) +bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id) { File sysex; uint8_t voice_counter = 0; @@ -75,14 +75,14 @@ bool get_voice_names_from_bank(uint8_t b) b %= MAX_BANKS; // erase all data for voice names - memset(voice_names, 0, MAX_VOICES * VOICE_NAME_LEN); + memset(voice_names[instance_id], 0, MAX_VOICES * VOICE_NAME_LEN); if (sd_card_available) { char sysex_file_name[4 + VOICE_NAME_LEN]; // init and set name for actual bank - create_sysex_filename(b, sysex_file_name); + create_sysex_filename(b, sysex_file_name, instance_id); #ifdef DEBUG Serial.print(F("Reading voice names for bank [")); @@ -143,7 +143,7 @@ bool get_voice_names_from_bank(uint8_t b) if ((n % 128) >= 118 && (n % 128) < 128) // found the start of the voicename { - voice_names[voice_counter][(n % 128) - 118] = d; + voice_names[instance_id][voice_counter][(n % 128) - 118] = d; } if (n % 128 == 127) voice_counter++; @@ -174,13 +174,13 @@ bool get_voice_names_from_bank(uint8_t b) return (false); } -uint8_t get_bank_names(void) +uint8_t get_bank_names(uint8_t instance_id) { File root; uint8_t bank_counter = 0; // erase all data for bank names - memset(bank_names, 0, MAX_BANKS * BANK_NAME_LEN); + memset(bank_names[instance_id], 0, MAX_BANKS * BANK_NAME_LEN); if (sd_card_available) { @@ -202,10 +202,10 @@ uint8_t get_bank_names(void) File entry = root.openNextFile(); if (!entry.isDirectory()) { - strcpy(bank_names[bank_counter], entry.name()); + strcpy(bank_names[instance_id][bank_counter], entry.name()); #ifdef DEBUG Serial.print(F("Found bank [")); - Serial.print(bank_names[bank_counter]); + Serial.print(bank_names[instance_id][bank_counter]); Serial.println(F("]")); #endif bank_counter++; @@ -218,7 +218,7 @@ uint8_t get_bank_names(void) return (bank_counter); } -bool load_sysex(uint8_t b, uint8_t v) +bool load_sysex(uint8_t b, uint8_t v, uint8_t instance_id) { #if DEBUG bool found = false; @@ -232,7 +232,7 @@ bool load_sysex(uint8_t b, uint8_t v) char sysex_file_name[4 + VOICE_NAME_LEN]; uint8_t data[128]; - create_sysex_filename(b, sysex_file_name); + create_sysex_filename(b, sysex_file_name, instance_id); sysex = SD.open(sysex_file_name); if (!sysex) @@ -251,10 +251,10 @@ bool load_sysex(uint8_t b, uint8_t v) Serial.print(F("Loading sysex ")); Serial.print(sysex_file_name); Serial.print(F(" [")); - Serial.print(voice_names[v]); + Serial.print(voice_names[instance_id][v]); Serial.println(F("]")); #endif - return (MicroDexed[0]->loadPackedVoiceParameters(data)); + return (MicroDexed[instance_id]->loadPackedVoiceParameters(data)); } #ifdef DEBUG else @@ -452,7 +452,7 @@ bool get_sysex_setup(File sysex, config_t configuration) return (true); } -bool load_sysex_setup(uint8_t b, uint8_t v) +bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id) { #if DEBUG bool found = false; @@ -484,7 +484,7 @@ bool load_sysex_setup(uint8_t b, uint8_t v) Serial.print(F("Loading sysex setup ")); Serial.print(sysex_setup_file_name); Serial.print(F(" [")); - Serial.print(voice_names[v]); + Serial.print(voice_names[instance_id][v]); Serial.println(F("]")); #endif return (true); diff --git a/dexed_sysex.h b/dexed_sysex.h index c66f4f4..f3000ef 100644 --- a/dexed_sysex.h +++ b/dexed_sysex.h @@ -35,10 +35,10 @@ extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; //extern uint16_t render_time_max; extern uint8_t bank; extern uint8_t voice; -extern char bank_name[BANK_NAME_LEN]; -extern char voice_name[VOICE_NAME_LEN]; -extern char bank_names[MAX_BANKS][BANK_NAME_LEN]; -extern char voice_names[MAX_VOICES][VOICE_NAME_LEN]; +extern char bank_name[NUM_DEXED][BANK_NAME_LEN]; +extern char voice_name[NUM_DEXED][VOICE_NAME_LEN]; +extern char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN]; +extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN]; extern uint8_t ui_state; extern uint8_t ui_main_state; extern config_t configuration; @@ -46,12 +46,12 @@ extern config_t configuration; void create_sysex_filename(uint8_t b, char* sysex_file_name); void strip_extension(char* s, char *target); bool get_voice_names_from_bank(uint8_t b); -uint8_t get_bank_names(void); +uint8_t get_bank_names(uint8_t instance_id); bool get_bank_voice_name(uint8_t b, uint8_t v); -bool load_sysex(uint8_t b, uint8_t v); +bool load_sysex(uint8_t b, uint8_t v, uint8_t instance_id); bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data); void create_sysex_setup_filename(uint8_t b, uint8_t v, char* sysex_setup_file_name); bool get_sysex_setup(File sysex, uint8_t voice_number, uint8_t* data); -bool load_sysex_setup(uint8_t b, uint8_t v); +bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id); #endif