Several additions for multi-instance handling.

Next additions for setup menus.
pull/15/head
Holger Wirtz 5 years ago
parent 64fdee843d
commit bb0bcb5b24
  1. 724
      MicroDexed.ino
  2. 190
      UI.hpp
  3. 2
      config.h
  4. 125
      dexed.cpp
  5. 9
      dexed.h
  6. 34
      dexed_sysex.cpp
  7. 14
      dexed_sysex.h

@ -138,10 +138,10 @@ void create_audio_connections(AudioSourceMicroDexed &d)
bool sd_card_available = false; bool sd_card_available = false;
uint8_t max_loaded_banks = 0; uint8_t max_loaded_banks = 0;
char bank_name[BANK_NAME_LEN]; char bank_name[NUM_DEXED][BANK_NAME_LEN];
char voice_name[VOICE_NAME_LEN]; char voice_name[NUM_DEXED][VOICE_NAME_LEN];
char bank_names[MAX_BANKS][BANK_NAME_LEN]; char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
char voice_names[MAX_VOICES][VOICE_NAME_LEN]; char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
elapsedMillis autostore; elapsedMillis autostore;
uint8_t midi_timing_counter = 0; // 24 per qarter uint8_t midi_timing_counter = 0; // 24 per qarter
elapsedMillis midi_timing_timestep; elapsedMillis midi_timing_timestep;
@ -279,41 +279,47 @@ void setup()
if (!SD.begin(SDCARD_CS_PIN)) if (!SD.begin(SDCARD_CS_PIN))
{ {
Serial.println(F("SD card not accessable.")); Serial.println(F("SD card not accessable."));
strcpy(bank_name, "Default"); for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
strcpy(voice_name, "Default"); {
strcpy(bank_name[instance_id], "Default");
strcpy(voice_name[instance_id], "Default");
}
} }
else else
{ {
Serial.println(F("SD card found.")); Serial.println(F("SD card found."));
sd_card_available = true; 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 // read all voice name for actual bank
max_loaded_banks = get_bank_names(); get_voice_names_from_bank(configuration.bank[instance_id], instance_id);
strip_extension(bank_names[configuration.bank[0]], bank_name);
// read all voice name for actual bank
get_voice_names_from_bank(configuration.bank[0]);
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Bank [")); Serial.print(F("Bank ["));
Serial.print(bank_names[configuration.bank[0]]); Serial.print(bank_names[instance_id][configuration.bank[instance_id]]);
Serial.print(F("/")); Serial.print(F("/"));
Serial.print(bank_name); 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[n]);
Serial.println(F("]")); 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 #endif
// load default SYSEX data // load default SYSEX data
load_sysex(configuration.bank[0], configuration.voice[0]); load_sysex(configuration.bank[0], configuration.voice[0], instance_id);
}
} }
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -399,14 +405,17 @@ void setup()
AudioMemoryUsageMaxReset(); AudioMemoryUsageMaxReset();
#endif #endif
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Bank/Voice from EEPROM [")); Serial.print(F("Bank/Voice from EEPROM ["));
Serial.print(configuration.bank[0], DEC); Serial.print(configuration.bank[instance_id], DEC);
Serial.print(F("/")); Serial.print(F("/"));
Serial.print(configuration.voice[0], DEC); Serial.print(configuration.voice[instance_id], DEC);
Serial.println(F("]")); Serial.println(F("]"));
show_patch(); show_patch(instance_id);
#endif #endif
}
Serial.print(F("AUDIO_BLOCK_SAMPLES=")); Serial.print(F("AUDIO_BLOCK_SAMPLES="));
Serial.print(AUDIO_BLOCK_SAMPLES); Serial.print(AUDIO_BLOCK_SAMPLES);
@ -556,173 +565,163 @@ void loop()
******************************************************************************/ ******************************************************************************/
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) 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) 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) 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 #ifdef DEBUG
Serial.print(F("CC#")); Serial.print(F("INSTANCE "));
Serial.print(inCtrl, DEC); Serial.print(instance_id, DEC);
Serial.print(F(":")); Serial.print(F(": CC#"));
Serial.println(inValue, DEC); Serial.print(inCtrl, DEC);
Serial.print(F(":"));
Serial.println(inValue, DEC);
#endif #endif
switch (inCtrl) { switch (inCtrl) {
case 0: case 0:
if (inValue < MAX_BANKS) if (inValue < MAX_BANKS)
{ {
configuration.bank[0] = inValue; configuration.bank[instance_id] = inValue;
} }
break; break;
case 1: case 1:
for (uint8_t i = 0; i < NUM_DEXED; i++) MicroDexed[instance_id]->controllers.modwheel_cc = inValue;
{ MicroDexed[instance_id]->controllers.refresh();
MicroDexed[i]->controllers.modwheel_cc = inValue; break;
MicroDexed[i]->controllers.refresh(); case 2:
} MicroDexed[instance_id]->controllers.breath_cc = inValue;
break; MicroDexed[instance_id]->controllers.refresh();
case 2: break;
for (uint8_t i = 0; i < NUM_DEXED; i++) case 4:
{ MicroDexed[instance_id]->controllers.foot_cc = inValue;
MicroDexed[i]->controllers.breath_cc = inValue; MicroDexed[instance_id]->controllers.refresh();
MicroDexed[i]->controllers.refresh(); break;
} case 7: // Volume
break; configuration.vol = map(inValue, 0, 0x7f, VOLUME_MIN, VOLUME_MAX);
case 4: soften_volume.update(configuration.vol, SOFTEN_VALUE_CHANGE_STEPS);
for (uint8_t i = 0; i < NUM_DEXED; i++) break;
{ case 10: // Pan
MicroDexed[i]->controllers.foot_cc = inValue; configuration.pan[instance_id] = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX);
MicroDexed[i]->controllers.refresh(); set_volume(configuration.vol, configuration.pan[instance_id], configuration.mono);
} break;
break; case 32: // BankSelect LSB
case 7: // Volume configuration.bank[instance_id] = inValue;
configuration.vol = map(inValue, 0, 0x7f, VOLUME_MIN, VOLUME_MAX); break;
soften_volume.update(configuration.vol, SOFTEN_VALUE_CHANGE_STEPS); case 64:
break; MicroDexed[instance_id]->setSustain(inValue > 63);
case 10: // Pan if (!MicroDexed[instance_id]->getSustain()) {
configuration.pan[0] = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX); for (uint8_t note = 0; note < MicroDexed[instance_id]->getMaxNotes(); note++) {
set_volume(configuration.vol, configuration.pan[0], configuration.mono); if (MicroDexed[instance_id]->voices[note].sustained && !MicroDexed[instance_id]->voices[note].keydown) {
break; MicroDexed[instance_id]->voices[note].dx7_note->keyup();
case 32: // BankSelect LSB MicroDexed[instance_id]->voices[note].sustained = false;
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;
} }
} }
} }
} break;
break; case 103: // CC 103: filter resonance
case 103: // CC 103: filter resonance configuration.filter_resonance[instance_id] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX);
configuration.filter_resonance[0] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); MicroDexed[instance_id]->fx.Reso = configuration.filter_resonance[instance_id] / 100.0;
for (uint8_t i = 0; i < NUM_DEXED; i++) break;
{ case 104: // CC 104: filter cutoff
MicroDexed[i]->fx.Reso = configuration.filter_resonance[i] / 100.0; 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; break;
case 104: // CC 104: filter cutoff case 105: // CC 105: delay time
configuration.filter_cutoff[0] = map(inValue, 0, 0x7f, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX); configuration.delay_time = map(inValue, 0, 0x7f, DELAY_TIME_MIN, DELAY_TIME_MAX);
for (uint8_t i = 0; i < NUM_DEXED; i++) delay1.delay(0, configuration.delay_time * 10);
{ case 106: // CC 106: delay feedback
MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff[i] / 100.0; 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
break; delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signalbreak;
case 105: // CC 105: delay time break;
configuration.delay_time = map(inValue, 0, 0x7f, DELAY_TIME_MIN, DELAY_TIME_MAX); case 107: // CC 107: delay volume
delay1.delay(0, configuration.delay_time * 10); configuration.delay_level[instance_id] = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX);
case 106: // CC 106: delay feedback master_mixer_r.gain(DELAY, configuration.delay_level[instance_id] / 100.0);
configuration.delay_feedback = map(inValue, 0, 0x7f, DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX); master_mixer_l.gain(2, configuration.delay_level[instance_id] / 100.0);
delay_fb_mixer.gain(1, configuration.delay_feedback / 100.0 ); // amount of feedback break;
delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signalbreak; case 120:
break; MicroDexed[instance_id]->panic();
case 107: // CC 107: delay volume break;
configuration.delay_level[0] = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX); case 121:
master_mixer_r.gain(DELAY, configuration.delay_level[0] / 100.0); MicroDexed[instance_id]->resetControllers();
master_mixer_l.gain(2, configuration.delay_level[0] / 100.0); break;
break; case 123:
case 120: MicroDexed[instance_id]->notesOff();
for (uint8_t i = 0; i < NUM_DEXED; i++) break;
{ case 126:
MicroDexed[i]->panic(); MicroDexed[instance_id]->setMonoMode(true);
} break;
break; case 127:
case 121: MicroDexed[instance_id]->setMonoMode(false);
for (uint8_t i = 0; i < NUM_DEXED; i++) break;
{ }
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;
} }
} }
} }
void handleAfterTouch(byte inChannel, byte inPressure) 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; if (checkMidiChannel(inChannel, instance_id))
MicroDexed[i]->controllers.refresh(); {
MicroDexed[instance_id]->controllers.aftertouch_cc = inPressure;
MicroDexed[instance_id]->controllers.refresh();
}
} }
} }
void handlePitchBend(byte inChannel, int inPitch) 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) 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 #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
load_sysex(configuration.bank[0], inProgram); load_sysex(configuration.bank[instance_id], inProgram, instance_id);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
}
}
} }
} }
@ -746,166 +745,172 @@ void handleSystemExclusive(byte * sysex, uint len)
11110111 F7 Status - end sysex 11110111 F7 Status - end sysex
*/ */
#ifdef DEBUG for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
Serial.print(F("SYSEX-Data["));
Serial.print(len, DEC);
Serial.print(F("]"));
for (uint8_t i = 0; i < len; i++)
{ {
Serial.print(F(" ")); if (!checkMidiChannel((sysex[2] & 0x0f) + 1 , instance_id))
Serial.print(sysex[i], DEC); {
} #ifdef DEBUG
Serial.println(); Serial.print(F("INSTANCE "));
Serial.print(instance_id, DEC);
Serial.println(F(": SYSEX-MIDI-Channel mismatch"));
#endif #endif
return;
if (!checkMidiChannel((sysex[2] & 0x0f) + 1 )) }
{
#ifdef DEBUG #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 #endif
return;
}
if (sysex[1] != 0x43) // check for Yamaha sysex if (sysex[1] != 0x43) // check for Yamaha sysex
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E: SysEx vendor not Yamaha.")); Serial.println(F("E: SysEx vendor not Yamaha."));
#endif #endif
return; return;
} }
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Substatus: [")); Serial.print(F("Substatus: ["));
Serial.print((sysex[2] & 0x70) >> 4); Serial.print((sysex[2] & 0x70) >> 4);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
// parse parameter change // parse parameter change
if (len == 7) if (len == 7)
{
if (((sysex[3] & 0x7c) >> 2) != 0 && ((sysex[3] & 0x7c) >> 2) != 2)
{ {
if (((sysex[3] & 0x7c) >> 2) != 0 && ((sysex[3] & 0x7c) >> 2) != 2)
{
#ifdef DEBUG #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 #endif
return; return;
} }
if (sysex[6] != 0xf7) if (sysex[6] != 0xf7)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E: SysEx end status byte not detected.")); Serial.println(F("E: SysEx end status byte not detected."));
#endif #endif
return; return;
} }
sysex[4] &= 0x7f; sysex[4] &= 0x7f;
sysex[5] &= 0x7f; sysex[5] &= 0x7f;
uint8_t data_index; uint8_t data_index;
if (((sysex[3] & 0x7c) >> 2) == 0) if (((sysex[3] & 0x7c) >> 2) == 0)
{ {
MicroDexed[0]->notesOff(); MicroDexed[instance_id]->notesOff();
MicroDexed[0]->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter MicroDexed[instance_id]->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter
MicroDexed[0]->doRefreshVoice(); MicroDexed[instance_id]->doRefreshVoice();
data_index = sysex[4] + ((sysex[3] & 0x03) * 128); data_index = sysex[4] + ((sysex[3] & 0x03) * 128);
} }
else else
{ {
MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set function parameter MicroDexed[instance_id]->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[instance_id]->controllers.values_[kControllerPitchRange] = MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE];
MicroDexed[0]->controllers.values_[kControllerPitchStep] = MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; MicroDexed[instance_id]->controllers.values_[kControllerPitchStep] = MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP];
MicroDexed[0]->controllers.wheel.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); MicroDexed[instance_id]->controllers.wheel.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]);
MicroDexed[0]->controllers.wheel.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); MicroDexed[instance_id]->controllers.wheel.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]);
MicroDexed[0]->controllers.foot.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); MicroDexed[instance_id]->controllers.foot.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]);
MicroDexed[0]->controllers.foot.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); MicroDexed[instance_id]->controllers.foot.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]);
MicroDexed[0]->controllers.breath.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); MicroDexed[instance_id]->controllers.breath.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]);
MicroDexed[0]->controllers.breath.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); MicroDexed[instance_id]->controllers.breath.setTarget(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]);
MicroDexed[0]->controllers.at.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); MicroDexed[instance_id]->controllers.at.setRange(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]);
MicroDexed[0]->controllers.at.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); MicroDexed[instance_id]->controllers.at.setTarget(MicroDexed[instance_id]->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[instance_id]->controllers.masterTune = (MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12);
MicroDexed[0]->controllers.refresh(); MicroDexed[instance_id]->controllers.refresh();
data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]; data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4];
} }
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("SysEx")); Serial.print(F("SysEx"));
if (((sysex[3] & 0x7c) >> 2) == 0) if (((sysex[3] & 0x7c) >> 2) == 0)
Serial.print(F(" function")); Serial.print(F(" function"));
Serial.print(F(" parameter ")); Serial.print(F(" parameter "));
Serial.print(sysex[4], DEC); Serial.print(sysex[4], DEC);
Serial.print(F(" = ")); Serial.print(F(" = "));
Serial.print(sysex[5], DEC); Serial.print(sysex[5], DEC);
Serial.print(F(", data_index = ")); Serial.print(F(", data_index = "));
Serial.println(data_index, DEC); Serial.println(data_index, DEC);
#endif #endif
} }
else if (len == 163) else if (len == 163)
{ {
int32_t bulk_checksum_calc = 0; int32_t bulk_checksum_calc = 0;
int8_t bulk_checksum = sysex[161]; int8_t bulk_checksum = sysex[161];
// 1 Voice bulk upload // 1 Voice bulk upload
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("One Voice bulk upload")); Serial.println(F("One Voice bulk upload"));
#endif #endif
if (sysex[162] != 0xf7) if (sysex[162] != 0xf7)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E: Found no SysEx end marker.")); Serial.println(F("E: Found no SysEx end marker."));
#endif #endif
return; return;
} }
if ((sysex[3] & 0x7f) != 0) if ((sysex[3] & 0x7f) != 0)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E: Not a SysEx voice bulk upload.")); Serial.println(F("E: Not a SysEx voice bulk upload."));
#endif #endif
return; return;
} }
if (((sysex[4] << 7) | sysex[5]) != 0x9b) if (((sysex[4] << 7) | sysex[5]) != 0x9b)
{ {
#ifdef DEBUG #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 #endif
return; return;
} }
// checksum calculation // checksum calculation
for (uint8_t i = 0; i < 155 ; i++) for (uint8_t i = 0; i < 155 ; i++)
{ {
bulk_checksum_calc -= sysex[i + 6]; bulk_checksum_calc -= sysex[i + 6];
} }
bulk_checksum_calc &= 0x7f; bulk_checksum_calc &= 0x7f;
if (bulk_checksum_calc != bulk_checksum) if (bulk_checksum_calc != bulk_checksum)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("E: Checksum error for one voice [0x")); Serial.print(F("E: Checksum error for one voice [0x"));
Serial.print(bulk_checksum, HEX); Serial.print(bulk_checksum, HEX);
Serial.print(F("/0x")); Serial.print(F("/0x"));
Serial.print(bulk_checksum_calc, HEX); Serial.print(bulk_checksum_calc, HEX);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
return; return;
} }
// load sysex-data into voice memory // load sysex-data into voice memory
MicroDexed[0]->loadVoiceParameters(&sysex[6]); MicroDexed[instance_id]->loadVoiceParameters(&sysex[6]);
//MicroDexed[0]->initGlobalParameters(); //MicroDexed[instance_id]->initGlobalParameters();
// manipulate UI names and numbers // manipulate UI names and numbers
strncpy(voice_name, (char *)&sysex[151], sizeof(voice_name) - 1); strncpy(voice_name[instance_id], (char *)&sysex[151], sizeof(voice_name[instance_id]) - 1);
Serial.print(F("Got voice [")); Serial.print(F("Got voice ["));
Serial.print(voice_name); Serial.print(voice_name[instance_id]);
Serial.println(F("].")); Serial.println(F("]."));
} }
#ifdef DEBUG #ifdef DEBUG
else else
Serial.println(F("E: SysEx parameter length wrong.")); Serial.println(F("E: SysEx parameter length wrong."));
#endif #endif
}
} }
void handleTimeCodeQuarterFrame(byte data) void handleTimeCodeQuarterFrame(byte data)
@ -969,31 +974,36 @@ void handleActiveSensing(void)
void handleSystemReset(void) void handleSystemReset(void)
{ {
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("MIDI SYSEX RESET")); Serial.println(F("MIDI SYSEX RESET"));
#endif #endif
MicroDexed[0]->notesOff(); MicroDexed[instance_id]->notesOff();
MicroDexed[0]->panic(); MicroDexed[instance_id]->panic();
MicroDexed[0]->resetControllers(); MicroDexed[instance_id]->resetControllers();
}
} }
/****************************************************************************** /******************************************************************************
MIDI HELPER MIDI HELPER
******************************************************************************/ ******************************************************************************/
bool checkMidiChannel(byte inChannel) bool checkMidiChannel(byte inChannel, uint8_t instance_id)
{ {
// check for MIDI channel // check for MIDI channel
if (configuration.midi_channel[0] == MIDI_CHANNEL_OMNI) if (configuration.midi_channel[instance_id] == MIDI_CHANNEL_OMNI)
{ {
return (true); return (true);
} }
else if (inChannel != configuration.midi_channel[0]) else if (inChannel != configuration.midi_channel[instance_id])
{ {
#ifdef DEBUG #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(inChannel);
Serial.print(F("(listening on ")); Serial.print(F("(listening on "));
Serial.print(configuration.midi_channel[0]); Serial.print(configuration.midi_channel[instance_id]);
Serial.println(F(")")); Serial.println(F(")"));
#endif #endif
return (false); return (false);
@ -1132,13 +1142,56 @@ void initial_values_from_eeprom(void)
configuration.at_assign[i] = AT_ASSIGN_DEFAULT; configuration.at_assign[i] = AT_ASSIGN_DEFAULT;
configuration.op_enabled[i] = OP_ENABLED_DEFAULT; configuration.op_enabled[i] = OP_ENABLED_DEFAULT;
} }
eeprom_update();
} }
else else
{ {
EEPROM_readAnything(EEPROM_START_ADDRESS, configuration); 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!")); Serial.print(F(" - OK, loading!"));
} }
eeprom_update();
#ifdef DEBUG #ifdef DEBUG
Serial.println(); Serial.println();
show_configuration(); 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) #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
void show_cpu_and_mem_usage(void) 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(F("CPU: "));
Serial.print(AudioProcessorUsage(), 2); Serial.print(AudioProcessorUsage(), 2);
Serial.print(F("% CPU MAX: ")); Serial.print(F("% CPU MAX: "));
@ -1199,11 +1263,11 @@ void show_cpu_and_mem_usage(void)
Serial.print(F(" MEM MAX: ")); Serial.print(F(" MEM MAX: "));
Serial.print(AudioMemoryUsageMax(), DEC); Serial.print(AudioMemoryUsageMax(), DEC);
Serial.print(F(" RENDER_TIME_MAX: ")); 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(F(" XRUN: "));
Serial.print(MicroDexed[0]->xrun, DEC); Serial.print(sum_xrun, DEC);
Serial.print(F(" OVERLOAD: ")); Serial.print(F(" OVERLOAD: "));
Serial.print(MicroDexed[0]->overload, DEC); Serial.print(sum_overload, DEC);
Serial.print(F(" PEAK: ")); Serial.print(F(" PEAK: "));
Serial.print(peak, DEC); Serial.print(peak, DEC);
Serial.print(F(" BLOCKSIZE: ")); Serial.print(F(" BLOCKSIZE: "));
@ -1213,7 +1277,6 @@ void show_cpu_and_mem_usage(void)
Serial.println(); Serial.println();
AudioProcessorUsageMaxReset(); AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset(); AudioMemoryUsageMaxReset();
MicroDexed[0]->render_time_max = 0;
} }
#endif #endif
@ -1237,7 +1300,7 @@ void show_configuration(void)
Serial.print(F("Delay Feedback ")); Serial.println(configuration.delay_feedback, DEC); Serial.print(F("Delay Feedback ")); Serial.println(configuration.delay_feedback, DEC);
for (uint8_t i = 0; i < NUM_DEXED; i++) for (uint8_t i = 0; i < NUM_DEXED; i++)
{ {
Serial.print(F("=== DEXED Instance ")); Serial.print(F("=== DEXED INSTANCE "));
Serial.print(i, DEC); Serial.print(i, DEC);
Serial.println(" ==="); Serial.println(" ===");
Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.midi_channel[i], DEC); Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.midi_channel[i], DEC);
@ -1268,11 +1331,14 @@ void show_configuration(void)
Serial.println(); Serial.println();
} }
void show_patch(void) void show_patch(uint8_t instance_id)
{ {
uint8_t i; uint8_t i;
char voicename[VOICE_NAME_LEN]; char voicename[VOICE_NAME_LEN];
Serial.print(F("INSTANCE "));
Serial.println(instance_id, DEC);
memset(voicename, 0, sizeof(voicename)); memset(voicename, 0, sizeof(voicename));
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
{ {
@ -1280,81 +1346,81 @@ void show_patch(void)
Serial.print(6 - i, DEC); Serial.print(6 - i, DEC);
Serial.println(F(": ")); 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.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(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(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(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(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(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(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(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(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(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.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.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(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(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(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(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(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(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(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(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(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.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.println(F("PR1 | PR2 | PR3 | PR4 | PL1 | PL2 | PL3 | PL4"));
Serial.print(F(" ")); Serial.print(F(" "));
for (i = 0; i < 8; i++) 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.print(F(" "));
} }
Serial.println(); Serial.println();
Serial.print(F("ALG: ")); 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.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.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.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.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.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.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.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.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.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.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: ")); 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(F("["));
Serial.print(voicename); Serial.print(voicename);
Serial.println(F("]")); Serial.println(F("]"));
@ -1362,7 +1428,7 @@ void show_patch(void)
{ {
Serial.print(i, DEC); Serial.print(i, DEC);
Serial.print(F(": ")); Serial.print(F(": "));
Serial.println(MicroDexed[0]->data[i]); Serial.println(MicroDexed[instance_id]->data[i]);
} }
Serial.println(); Serial.println();

190
UI.hpp

@ -48,13 +48,13 @@
extern config_t configuration; extern config_t configuration;
extern void set_volume(uint8_t v, int8_t p, uint8_t m); 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_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
extern char bank_name[BANK_NAME_LEN]; extern char bank_name[NUM_DEXED][BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN]; extern char voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char voice_names[MAX_VOICES][VOICE_NAME_LEN]; extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
extern void strip_extension(char* s, char *target); extern void strip_extension(char* s, char *target);
extern void eeprom_write(void); 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); extern bool load_sysex(uint8_t b, uint8_t v);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
extern void change_disp_sd(bool d); 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_range(uint8_t param);
void UI_func_pb_step(uint8_t param); void UI_func_pb_step(uint8_t param);
void UI_func_mw_range(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_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_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_information(uint8_t param);
void UI_func_voice_selection(uint8_t param); void UI_func_voice_selection(uint8_t param);
void UI_func_volume(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(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(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(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(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_function_not_implemented); 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(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(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); 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(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(12, LCDML_0_1_10, 2, "PB Step", UI_func_pb_step);
LCDML_add(13, LCDML_0_1, 11, "Mod Wheel", NULL); 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(14, LCDML_0_1_11, 1, "MW Range", UI_func_mw_range);
LCDML_add(15, LCDML_0_1_11, 2, "MW Assign", UI_function_not_implemented); 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(16, LCDML_0_1, 12, "Foot Ctrl", NULL);
LCDML_add(17, LCDML_0_1_12, 1, "FC Range", UI_function_not_implemented); 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); 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 #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.bank[instance_id]); get_voice_names_from_bank(configuration.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -582,8 +582,8 @@ void encoder_right_up(void)
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.bank[instance_id]); get_voice_names_from_bank(configuration.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -623,8 +623,8 @@ void encoder_right_down(void)
change_disp_sd(false); change_disp_sd(false);
#endif #endif
load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.bank[instance_id]); get_voice_names_from_bank(configuration.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -645,8 +645,8 @@ void encoder_right_down(void)
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
load_sysex(configuration.bank[instance_id], configuration.voice[instance_id]); load_sysex(configuration.bank[instance_id], configuration.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.bank[instance_id]); get_voice_names_from_bank(configuration.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -1409,13 +1409,13 @@ void UI_func_filter_cutoff(uint8_t param)
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
lcd_display_int(configuration.filter_cutoff[instance_id], 3, true, true, false); 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(" ");
Serial.print(MENU_ID_OF_INSTANCE_2,DEC); Serial.print(MENU_ID_OF_INSTANCE_2, DEC);
Serial.print(" INSTANCE: "); Serial.print(" INSTANCE: ");
Serial.print(instance_id,DEC); Serial.print(instance_id, DEC);
Serial.print(" value: "); Serial.print(" value: ");
Serial.println(configuration.filter_cutoff[instance_id] / 100.0,3); Serial.println(configuration.filter_cutoff[instance_id] / 100.0, 3);
MicroDexed[instance_id]->fx.Cutoff = configuration.filter_cutoff[instance_id] / 100.0; 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.setCursor(0, 1);
lcd_display_int(configuration.pb_range[instance_id], 2, false, true, false); 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 ********* if (LCDML.FUNC_close()) // ****** STABLE END *********
@ -1945,7 +1945,7 @@ void UI_func_pb_step(uint8_t param)
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
lcd_display_int(configuration.pb_step[instance_id], 2, false, true, false); 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 ********* 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) 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) 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) 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 #ifdef DEBUG
Serial.println(F("UI_func_voice_selection()")); Serial.println(F("UI_func_voice_selection()"));
#endif #endif
menu_state = MENU_VOICE; 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(); //LCDML.DISP_clear();
// display bank and voice number // display bank and voice number
lcd.show(0, 0, 2, configuration.bank[instance_id]); lcd.show(0, 0, 2, configuration.bank[selected_dexed_instance]);
lcd.show(1, 0, 2, configuration.voice[instance_id] + 1); lcd.show(1, 0, 2, configuration.voice[selected_dexed_instance] + 1);
// display names // display names
lcd.show(0, 4, 10, bank_name); lcd.show(0, 4, 10, bank_name[selected_dexed_instance]);
lcd.show(1, 4, 10, voice_names[configuration.voice[instance_id]]); lcd.show(1, 4, 10, voice_names[selected_dexed_instance][configuration.voice[selected_dexed_instance]]);
// display selected Dexed instance // display selected Dexed instance
if (selected_dexed_instance == 1) if (selected_dexed_instance == 1)

@ -358,7 +358,7 @@ enum { DEXED, REVERB, DELAY, CHORUS };
#define MW_RANGE_MAX 12 #define MW_RANGE_MAX 12
#define MW_RANGE_DEFAULT 12 #define MW_RANGE_DEFAULT 12
#define MW_ASIGN_MIN 0 #define MW_ASSIGN_MIN 0
#define MW_ASSIGN_MAX 7 #define MW_ASSIGN_MAX 7
#define MW_ASSIGN_DEFAULT 0 // Bitmapped: 0: Pitch, 1: Amp, 2: Bias #define MW_ASSIGN_DEFAULT 0 // Bitmapped: 0: Pitch, 1: Amp, 2: Bias

@ -172,8 +172,12 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer)
fx.process(sumbuf, n_samples); 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) for (i = 0; i < n_samples; ++i)
buffer[i] = static_cast<int16_t>(sumbuf[i] * 0x7fff); buffer[i] = static_cast<int16_t>(sumbuf[i] * 0x7fff);
#endif
} }
void Dexed::keydown(uint8_t pitch, uint8_t velo) { 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* p_data = data;
uint8_t op; uint8_t op;
uint8_t tmp; uint8_t tmp;
char dexed_voice_name[11];
notesOff(); notesOff();
@ -492,11 +497,11 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data)
doRefreshVoice(); doRefreshVoice();
//activate(); //activate();
strncpy(voice_name, (char *)&new_data[118], sizeof(voice_name) - 1); strncpy(dexed_voice_name, (char *)&new_data[118], sizeof(dexed_voice_name) - 1);
voice_name[10] = '\0'; dexed_voice_name[10] = '\0';
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Voice [")); Serial.print(F("Voice ["));
Serial.print(voice_name); Serial.print(dexed_voice_name);
Serial.println(F("] loaded.")); Serial.println(F("] loaded."));
#endif #endif
@ -505,6 +510,8 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data)
bool Dexed::loadVoiceParameters(uint8_t* new_data) bool Dexed::loadVoiceParameters(uint8_t* new_data)
{ {
char dexed_voice_name[11];
notesOff(); notesOff();
memcpy(&data, new_data, 155); memcpy(&data, new_data, 155);
@ -513,11 +520,11 @@ bool Dexed::loadVoiceParameters(uint8_t* new_data)
doRefreshVoice(); doRefreshVoice();
//activate(); //activate();
strncpy(voice_name, (char *)&new_data[145], sizeof(voice_name) - 1); strncpy(dexed_voice_name, (char *)&new_data[145], sizeof(dexed_voice_name) - 1);
voice_name[10] = '\0'; dexed_voice_name[10] = '\0';
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Voice [")); Serial.print(F("Voice ["));
Serial.print(voice_name); Serial.print(dexed_voice_name);
Serial.println(F("] loaded.")); Serial.println(F("] loaded."));
#endif #endif
@ -592,30 +599,116 @@ bool Dexed::initGlobalParameters(void)
return (true); 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_range %= PB_RANGE_MAX;
pb_step %= PB_STEP_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_range %= MW_RANGE_MAX;
mw_assign %= MW_ASSIGN_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; #ifdef DEBUG
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP] = controllers.values_[kControllerPitchStep] = pb_step; 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_RANGE] = mw_range;
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN] = mw_assign; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN] = mw_assign;
controllers.wheel.setTarget(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_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.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_RANGE] = bc_range;
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN] = bc_assign; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN] = bc_assign;
controllers.breath.setTarget(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_RANGE] = at_range;
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN] = at_assign; data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN] = at_assign;
controllers.at.setTarget(at_assign); controllers.at.setTarget(at_assign);

@ -44,7 +44,6 @@ extern AudioControlSGTL5000 sgtl5000_1;
extern float vol; extern float vol;
extern float vol_right; extern float vol_right;
extern float vol_left; extern float vol_left;
extern char voice_name[11];
struct ProcessorVoice { struct ProcessorVoice {
uint8_t midi_note; uint8_t midi_note;
@ -164,7 +163,11 @@ class Dexed
void setSustain(bool sustain); void setSustain(bool sustain);
bool getSustain(void); bool getSustain(void);
uint8_t getNumNotesPlaying(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]; ProcessorVoice voices[MAX_NOTES];
Controllers controllers; 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 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 00, // master tune
01, 01, 01, 01, 01, 01, // OP1-6 enable 01, 01, 01, 01, 01, 01, // OP1-6 enable
16 // number of voices MAX_NOTES // number of voices
}; // FM-Piano }; // FM-Piano
uint32_t overload = 0; uint32_t overload = 0;

@ -33,19 +33,19 @@
extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; 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 // init and set name for actual bank
memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN); memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN);
sysex_file_name[0] = '/'; sysex_file_name[0] = '/';
itoa(b, &sysex_file_name[1], 10); itoa(b, &sysex_file_name[1], 10);
strcat(sysex_file_name, "/"); strcat(sysex_file_name, "/");
strcat(sysex_file_name, bank_names[b]); strcat(sysex_file_name, bank_names[instance_id][b]);
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Created sysex_filename from bank ")); Serial.print(F("Created sysex_filename from bank "));
Serial.print(b, DEC); Serial.print(b, DEC);
Serial.print(F(" and name ")); Serial.print(F(" and name "));
Serial.print(bank_names[b]); Serial.print(bank_names[instance_id][b]);
Serial.print(F(": [")); Serial.print(F(": ["));
Serial.print(sysex_file_name); Serial.print(sysex_file_name);
Serial.println(F("]")); Serial.println(F("]"));
@ -65,7 +65,7 @@ void strip_extension(char* s, char* target)
strcpy(target, token); 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; File sysex;
uint8_t voice_counter = 0; uint8_t voice_counter = 0;
@ -75,14 +75,14 @@ bool get_voice_names_from_bank(uint8_t b)
b %= MAX_BANKS; b %= MAX_BANKS;
// erase all data for voice names // 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) if (sd_card_available)
{ {
char sysex_file_name[4 + VOICE_NAME_LEN]; char sysex_file_name[4 + VOICE_NAME_LEN];
// init and set name for actual bank // 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 #ifdef DEBUG
Serial.print(F("Reading voice names for bank [")); 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 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) if (n % 128 == 127)
voice_counter++; voice_counter++;
@ -174,13 +174,13 @@ bool get_voice_names_from_bank(uint8_t b)
return (false); return (false);
} }
uint8_t get_bank_names(void) uint8_t get_bank_names(uint8_t instance_id)
{ {
File root; File root;
uint8_t bank_counter = 0; uint8_t bank_counter = 0;
// erase all data for bank names // 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) if (sd_card_available)
{ {
@ -202,10 +202,10 @@ uint8_t get_bank_names(void)
File entry = root.openNextFile(); File entry = root.openNextFile();
if (!entry.isDirectory()) if (!entry.isDirectory())
{ {
strcpy(bank_names[bank_counter], entry.name()); strcpy(bank_names[instance_id][bank_counter], entry.name());
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Found bank [")); Serial.print(F("Found bank ["));
Serial.print(bank_names[bank_counter]); Serial.print(bank_names[instance_id][bank_counter]);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
bank_counter++; bank_counter++;
@ -218,7 +218,7 @@ uint8_t get_bank_names(void)
return (bank_counter); 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 #if DEBUG
bool found = false; bool found = false;
@ -232,7 +232,7 @@ bool load_sysex(uint8_t b, uint8_t v)
char sysex_file_name[4 + VOICE_NAME_LEN]; char sysex_file_name[4 + VOICE_NAME_LEN];
uint8_t data[128]; 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); sysex = SD.open(sysex_file_name);
if (!sysex) if (!sysex)
@ -251,10 +251,10 @@ bool load_sysex(uint8_t b, uint8_t v)
Serial.print(F("Loading sysex ")); Serial.print(F("Loading sysex "));
Serial.print(sysex_file_name); Serial.print(sysex_file_name);
Serial.print(F(" [")); Serial.print(F(" ["));
Serial.print(voice_names[v]); Serial.print(voice_names[instance_id][v]);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
return (MicroDexed[0]->loadPackedVoiceParameters(data)); return (MicroDexed[instance_id]->loadPackedVoiceParameters(data));
} }
#ifdef DEBUG #ifdef DEBUG
else else
@ -452,7 +452,7 @@ bool get_sysex_setup(File sysex, config_t configuration)
return (true); 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 #if DEBUG
bool found = false; 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(F("Loading sysex setup "));
Serial.print(sysex_setup_file_name); Serial.print(sysex_setup_file_name);
Serial.print(F(" [")); Serial.print(F(" ["));
Serial.print(voice_names[v]); Serial.print(voice_names[instance_id][v]);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
return (true); return (true);

@ -35,10 +35,10 @@ extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED];
//extern uint16_t render_time_max; //extern uint16_t render_time_max;
extern uint8_t bank; extern uint8_t bank;
extern uint8_t voice; extern uint8_t voice;
extern char bank_name[BANK_NAME_LEN]; extern char bank_name[NUM_DEXED][BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN]; extern char voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char bank_names[MAX_BANKS][BANK_NAME_LEN]; extern char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
extern char voice_names[MAX_VOICES][VOICE_NAME_LEN]; extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
extern uint8_t ui_state; extern uint8_t ui_state;
extern uint8_t ui_main_state; extern uint8_t ui_main_state;
extern config_t configuration; extern config_t configuration;
@ -46,12 +46,12 @@ extern config_t configuration;
void create_sysex_filename(uint8_t b, char* sysex_file_name); void create_sysex_filename(uint8_t b, char* sysex_file_name);
void strip_extension(char* s, char *target); void strip_extension(char* s, char *target);
bool get_voice_names_from_bank(uint8_t b); 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 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); 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); 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 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 #endif

Loading…
Cancel
Save