Merge branch 'dev-portamento' into dev

pull/17/head
Holger Wirtz 5 years ago
commit 86b1cebbb0
  1. 90
      MicroDexed.ino
  2. 189
      UI.hpp
  3. 11
      config.h
  4. 3
      controllers.h
  5. 29
      dexed.cpp
  6. 14
      dexed.h
  7. 37
      dx7note.cpp
  8. 45
      dx7note.h
  9. 35
      porta.cpp
  10. 28
      porta.h

@ -610,6 +610,10 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
MicroDexed[instance_id]->controllers.foot_cc = inValue;
MicroDexed[instance_id]->controllers.refresh();
break;
case 5: // Portamento time
configuration.dexed[instance_id].portamento_time = inValue;
MicroDexed[instance_id]->setPortamentoMode(configuration.dexed[instance_id].portamento_mode, configuration.dexed[instance_id].portamento_glissando, configuration.dexed[instance_id].portamento_time);
break;
case 7: // Volume
#ifdef DEBUG
Serial.println(F("VOLUME CC"));
@ -644,6 +648,9 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
}
}
break;
case 65:
MicroDexed[instance_id]->setPortamentoMode(configuration.dexed[instance_id].portamento_mode, configuration.dexed[instance_id].portamento_glissando, configuration.dexed[instance_id].portamento_time);
break;
case 103: // CC 103: filter resonance
configuration.dexed[instance_id].filter_resonance = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX);
MicroDexed[instance_id]->fx.Reso = mapfloat(configuration.dexed[instance_id].filter_resonance, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 1.0, 0.0);
@ -832,6 +839,7 @@ void handleSystemExclusive(byte * sysex, uint len)
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] / 10 * 0x4000 << 11) * (1.0 / 12);
MicroDexed[instance_id]->setPortamentoMode(MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_MODE], MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_GLISSANDO], MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_TIME]);
MicroDexed[instance_id]->controllers.refresh();
data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4];
}
@ -1182,20 +1190,23 @@ void check_configuration(void)
configuration.dexed[instance_id].filter_resonance = constrain(configuration.dexed[instance_id].filter_resonance, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX);
configuration.dexed[instance_id].loudness = constrain(configuration.dexed[instance_id].loudness, LOUDNESS_MIN, LOUDNESS_MAX);
configuration.dexed[instance_id].transpose = constrain(configuration.dexed[instance_id].transpose, TRANSPOSE_MIN, TRANSPOSE_MAX);
configuration.dexed[instance_id].tune = constrain(configuration.dexed[instance_id].tune, TUNE_MIN, TUNE_MAX);
configuration.dexed[instance_id].tune = constrain(configuration.dexed[instance_id].tune, TUNE_MIN, TUNE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] = configuration.dexed[instance_id].tune;
configuration.dexed[instance_id].polyphony = constrain(configuration.dexed[instance_id].polyphony, POLYPHONY_MIN, POLYPHONY_MAX);
configuration.dexed[instance_id].engine = constrain(configuration.dexed[instance_id].engine, ENGINE_MIN, ENGINE_MAX);
configuration.dexed[instance_id].monopoly = constrain(configuration.dexed[instance_id].monopoly, MONOPOLY_MIN, MONOPOLY_MAX);
configuration.dexed[instance_id].pb_range = constrain(configuration.dexed[instance_id].pb_range, PB_RANGE_MIN, PB_RANGE_MAX);
configuration.dexed[instance_id].pb_step = constrain(configuration.dexed[instance_id].pb_step, PB_STEP_MIN, PB_STEP_MAX);
configuration.dexed[instance_id].mw_range = constrain(configuration.dexed[instance_id].mw_range, MW_RANGE_MIN, MW_RANGE_MAX);
configuration.dexed[instance_id].mw_assign = constrain(configuration.dexed[instance_id].mw_assign, MW_ASSIGN_MIN, MW_ASSIGN_MAX);
configuration.dexed[instance_id].fc_range = constrain(configuration.dexed[instance_id].fc_range, FC_RANGE_MIN, FC_RANGE_MAX);
configuration.dexed[instance_id].fc_assign = constrain(configuration.dexed[instance_id].fc_assign, FC_ASSIGN_MIN, FC_ASSIGN_MAX);
configuration.dexed[instance_id].bc_range = constrain(configuration.dexed[instance_id].bc_range, BC_RANGE_MIN, BC_RANGE_MAX);
configuration.dexed[instance_id].bc_assign = constrain(configuration.dexed[instance_id].bc_assign, BC_ASSIGN_MIN, BC_ASSIGN_MAX);
configuration.dexed[instance_id].at_range = constrain(configuration.dexed[instance_id].at_range, AT_RANGE_MIN, AT_RANGE_MAX);
configuration.dexed[instance_id].at_assign = constrain(configuration.dexed[instance_id].at_assign, AT_ASSIGN_MIN, AT_ASSIGN_MAX);
configuration.dexed[instance_id].pb_range = constrain(configuration.dexed[instance_id].pb_range, PB_RANGE_MIN, PB_RANGE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE] = configuration.dexed[instance_id].pb_range;
configuration.dexed[instance_id].pb_step = constrain(configuration.dexed[instance_id].pb_step, PB_STEP_MIN, PB_STEP_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP] = configuration.dexed[instance_id].pb_step;
configuration.dexed[instance_id].mw_range = constrain(configuration.dexed[instance_id].mw_range, MW_RANGE_MIN, MW_RANGE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE] = configuration.dexed[instance_id].mw_range;
configuration.dexed[instance_id].mw_assign = constrain(configuration.dexed[instance_id].mw_assign, MW_ASSIGN_MIN, MW_ASSIGN_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN] = configuration.dexed[instance_id].mw_assign;
configuration.dexed[instance_id].fc_range = constrain(configuration.dexed[instance_id].fc_range, FC_RANGE_MIN, FC_RANGE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE] = configuration.dexed[instance_id].fc_range;
configuration.dexed[instance_id].fc_assign = constrain(configuration.dexed[instance_id].fc_assign, FC_ASSIGN_MIN, FC_ASSIGN_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN] = configuration.dexed[instance_id].fc_assign;
configuration.dexed[instance_id].bc_range = constrain(configuration.dexed[instance_id].bc_range, BC_RANGE_MIN, BC_RANGE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE] = configuration.dexed[instance_id].bc_range;
configuration.dexed[instance_id].bc_assign = constrain(configuration.dexed[instance_id].bc_assign, BC_ASSIGN_MIN, BC_ASSIGN_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN] = configuration.dexed[instance_id].bc_assign;
configuration.dexed[instance_id].at_range = constrain(configuration.dexed[instance_id].at_range, AT_RANGE_MIN, AT_RANGE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE] = configuration.dexed[instance_id].at_range;
configuration.dexed[instance_id].at_assign = constrain(configuration.dexed[instance_id].at_assign, AT_ASSIGN_MIN, AT_ASSIGN_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN] = configuration.dexed[instance_id].at_assign;
configuration.dexed[instance_id].portamento_mode = constrain(configuration.dexed[instance_id].portamento_mode, PORTAMENTO_MODE_MIN, PORTAMENTO_MODE_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_MODE] = configuration.dexed[instance_id].portamento_mode;
configuration.dexed[instance_id].portamento_glissando = constrain(configuration.dexed[instance_id].portamento_glissando, PORTAMENTO_GLISSANDO_MIN, PORTAMENTO_GLISSANDO_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_GLISSANDO] = configuration.dexed[instance_id].portamento_glissando;
configuration.dexed[instance_id].portamento_time = constrain(configuration.dexed[instance_id].portamento_time, PORTAMENTO_TIME_MIN, PORTAMENTO_TIME_MAX); MicroDexed[instance_id]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_TIME] = configuration.dexed[instance_id].portamento_time;
configuration.dexed[instance_id].op_enabled = constrain(configuration.dexed[instance_id].op_enabled, OP_ENABLED_MIN, OP_ENABLED_MAX);
}
}
@ -1246,6 +1257,9 @@ void init_configuration(void)
configuration.dexed[instance_id].bc_assign = BC_ASSIGN_DEFAULT;
configuration.dexed[instance_id].at_range = AT_RANGE_DEFAULT;
configuration.dexed[instance_id].at_assign = AT_ASSIGN_DEFAULT;
configuration.dexed[instance_id].portamento_mode = PORTAMENTO_MODE_DEFAULT;
configuration.dexed[instance_id].portamento_glissando = PORTAMENTO_GLISSANDO_DEFAULT;
configuration.dexed[instance_id].portamento_time = PORTAMENTO_TIME_DEFAULT;
configuration.dexed[instance_id].op_enabled = OP_ENABLED_DEFAULT;
}
eeprom_update();
@ -1359,31 +1373,33 @@ void show_configuration(void)
Serial.print(F("=== DEXED INSTANCE "));
Serial.print(instance_id, DEC);
Serial.println(" ===");
Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.dexed[instance_id].midi_channel, DEC);
Serial.print(F(" Bank ")); Serial.println(configuration.dexed[instance_id].bank, DEC);
Serial.print(F(" Voice ")); Serial.println(configuration.dexed[instance_id].voice, DEC);
Serial.print(F(" Reverb Send ")); Serial.println(configuration.dexed[instance_id].reverb_send, DEC);
Serial.print(F(" Chorus Send ")); Serial.println(configuration.dexed[instance_id].chorus_send, DEC);
Serial.print(F(" Delay Send ")); Serial.println(configuration.dexed[instance_id].delay_send, DEC);
Serial.print(F(" Filter Cutoff ")); Serial.println(configuration.dexed[instance_id].filter_cutoff, DEC);
Serial.print(F(" Filter Resonance ")); Serial.println(configuration.dexed[instance_id].filter_resonance, DEC);
Serial.print(F(" Loudness ")); Serial.println(configuration.dexed[instance_id].loudness, DEC);
Serial.print(F(" Transpose ")); Serial.println(configuration.dexed[instance_id].transpose, DEC);
Serial.print(F(" Tune ")); Serial.println(configuration.dexed[instance_id].tune, DEC);
Serial.print(F(" Polyphony ")); Serial.println(configuration.dexed[instance_id].polyphony, DEC);
Serial.print(F(" Engine ")); Serial.println(configuration.dexed[instance_id].engine, DEC);
Serial.print(F(" Mono/Poly ")); Serial.println(configuration.dexed[instance_id].monopoly, DEC);
Serial.print(F(" Pitchbend Range ")); Serial.println(configuration.dexed[instance_id].pb_range, DEC);
Serial.print(F(" Pitchbend Step ")); Serial.println(configuration.dexed[instance_id].pb_step, DEC);
Serial.print(F(" Modwheel Range ")); Serial.println(configuration.dexed[instance_id].mw_range, DEC);
Serial.print(F(" Modwheel Assign ")); Serial.println(configuration.dexed[instance_id].mw_assign, DEC);
Serial.print(F(" Footctrl Range ")); Serial.println(configuration.dexed[instance_id].fc_range, DEC);
Serial.print(F(" Footctrl Assign ")); Serial.println(configuration.dexed[instance_id].fc_assign, DEC);
Serial.print(F(" BreathCtrl Range ")); Serial.println(configuration.dexed[instance_id].bc_range, DEC);
Serial.print(F(" Breathctrl Assign ")); Serial.println(configuration.dexed[instance_id].bc_assign, DEC);
Serial.print(F(" Aftertouch Range ")); Serial.println(configuration.dexed[instance_id].at_range, DEC);
Serial.print(F(" Aftertouch Assign ")); Serial.println(configuration.dexed[instance_id].at_assign, DEC);
Serial.print(F(" OP Enabled ")); Serial.println(configuration.dexed[instance_id].op_enabled, DEC);
Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.dexed[instance_id].midi_channel, DEC);
Serial.print(F(" Bank ")); Serial.println(configuration.dexed[instance_id].bank, DEC);
Serial.print(F(" Voice ")); Serial.println(configuration.dexed[instance_id].voice, DEC);
Serial.print(F(" Reverb Send ")); Serial.println(configuration.dexed[instance_id].reverb_send, DEC);
Serial.print(F(" Chorus Send ")); Serial.println(configuration.dexed[instance_id].chorus_send, DEC);
Serial.print(F(" Delay Send ")); Serial.println(configuration.dexed[instance_id].delay_send, DEC);
Serial.print(F(" Filter Cutoff ")); Serial.println(configuration.dexed[instance_id].filter_cutoff, DEC);
Serial.print(F(" Filter Resonance ")); Serial.println(configuration.dexed[instance_id].filter_resonance, DEC);
Serial.print(F(" Loudness ")); Serial.println(configuration.dexed[instance_id].loudness, DEC);
Serial.print(F(" Transpose ")); Serial.println(configuration.dexed[instance_id].transpose, DEC);
Serial.print(F(" Tune ")); Serial.println(configuration.dexed[instance_id].tune, DEC);
Serial.print(F(" Polyphony ")); Serial.println(configuration.dexed[instance_id].polyphony, DEC);
Serial.print(F(" Engine ")); Serial.println(configuration.dexed[instance_id].engine, DEC);
Serial.print(F(" Mono/Poly ")); Serial.println(configuration.dexed[instance_id].monopoly, DEC);
Serial.print(F(" Pitchbend Range ")); Serial.println(configuration.dexed[instance_id].pb_range, DEC);
Serial.print(F(" Pitchbend Step ")); Serial.println(configuration.dexed[instance_id].pb_step, DEC);
Serial.print(F(" Modwheel Range ")); Serial.println(configuration.dexed[instance_id].mw_range, DEC);
Serial.print(F(" Modwheel Assign ")); Serial.println(configuration.dexed[instance_id].mw_assign, DEC);
Serial.print(F(" Footctrl Range ")); Serial.println(configuration.dexed[instance_id].fc_range, DEC);
Serial.print(F(" Footctrl Assign ")); Serial.println(configuration.dexed[instance_id].fc_assign, DEC);
Serial.print(F(" BreathCtrl Range ")); Serial.println(configuration.dexed[instance_id].bc_range, DEC);
Serial.print(F(" Breathctrl Assign ")); Serial.println(configuration.dexed[instance_id].bc_assign, DEC);
Serial.print(F(" Aftertouch Range ")); Serial.println(configuration.dexed[instance_id].at_range, DEC);
Serial.print(F(" Portamento Mode ")); Serial.println(configuration.dexed[instance_id].portamento_mode, DEC);
Serial.print(F(" Portamento Glissando ")); Serial.println(configuration.dexed[instance_id].portamento_glissando, DEC);
Serial.print(F(" Portamento Time ")); Serial.println(configuration.dexed[instance_id].portamento_time, DEC);
Serial.print(F(" OP Enabled ")); Serial.println(configuration.dexed[instance_id].op_enabled, DEC);
Serial.flush();
}
Serial.println();
@ -1484,7 +1500,7 @@ void show_patch(uint8_t instance_id)
Serial.print(voicename);
Serial.println(F("]"));
Serial.flush();
for (i = DEXED_GLOBAL_PARAMETER_OFFSET; i <= DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MAX_NOTES; i++)
for (i = DEXED_GLOBAL_PARAMETER_OFFSET; i <= DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_TIME; i++)
{
Serial.print(i, DEC);
Serial.print(F(": "));

189
UI.hpp

@ -158,6 +158,9 @@ void UI_func_bc_range(uint8_t param);
void UI_func_bc_assign(uint8_t param);
void UI_func_at_range(uint8_t param);
void UI_func_at_assign(uint8_t param);
void UI_func_portamento_mode(uint8_t param);
void UI_func_portamento_glissando(uint8_t param);
void UI_func_portamento_time(uint8_t param);
void UI_func_OP1(uint8_t param);
void UI_func_OP2(uint8_t param);
void UI_func_OP3(uint8_t param);
@ -211,9 +214,9 @@ LCDML_add(28, LCDML_0_1_1, 17, "Aftertouch 1", NULL);
LCDML_add(29, LCDML_0_1_1_17, 1, "AT Range 1", UI_func_at_range);
LCDML_add(30, LCDML_0_1_1_17, 2, "AT Assign 1", UI_func_at_assign);
LCDML_add(31, LCDML_0_1_1, 18, "Portamento 1", NULL);
LCDML_add(32, LCDML_0_1_1_18, 1, "Port. Mode 1", UI_function_not_enabled);
LCDML_add(33, LCDML_0_1_1_18, 2, "Port. Gliss 1", UI_function_not_enabled);
LCDML_add(34, LCDML_0_1_1_18, 3, "Port. Time 1", UI_function_not_enabled);
LCDML_add(32, LCDML_0_1_1_18, 1, "Port. Mode 1", UI_func_portamento_mode);
LCDML_add(33, LCDML_0_1_1_18, 2, "Port. Gliss 1", UI_func_portamento_glissando);
LCDML_add(34, LCDML_0_1_1_18, 3, "Port. Time 1", UI_func_portamento_time);
LCDML_add(35, LCDML_0_1_1, 19, "Operator 1", NULL);
LCDML_add(36, LCDML_0_1_1_19, 1, "OP1 1", UI_func_OP1);
LCDML_add(37, LCDML_0_1_1_19, 2, "OP2 1", UI_func_OP2);
@ -252,9 +255,9 @@ LCDML_add(69, LCDML_0_1_2, 17, "Aftertouch 2", NULL);
LCDML_add(70, LCDML_0_1_2_17, 1, "AT Range 2", UI_func_at_range);
LCDML_add(71, LCDML_0_1_2_17, 2, "AT Assign 2", UI_func_at_assign);
LCDML_add(72, LCDML_0_1_2, 18, "Portamento 2", NULL);
LCDML_add(73, LCDML_0_1_2_18, 1, "Port. Mode 2", UI_function_not_enabled);
LCDML_add(74, LCDML_0_1_2_18, 2, "Port. Gliss 2", UI_function_not_enabled);
LCDML_add(75, LCDML_0_1_2_18, 3, "Port. Time 2", UI_function_not_enabled);
LCDML_add(73, LCDML_0_1_2_18, 1, "Port. Mode 2", UI_func_portamento_mode);
LCDML_add(74, LCDML_0_1_2_18, 2, "Port. Gliss 2", UI_func_portamento_glissando);
LCDML_add(75, LCDML_0_1_2_18, 3, "Port. Time 2", UI_func_portamento_time);
LCDML_add(76, LCDML_0_1_2, 19, "Operator 2", NULL);
LCDML_add(77, LCDML_0_1_2_19, 1, "OP1 2", UI_func_OP1);
LCDML_add(78, LCDML_0_1_2_19, 2, "OP2 2", UI_func_OP2);
@ -311,9 +314,9 @@ LCDML_add(27, LCDML_0_1, 17, "Aftertouch", NULL);
LCDML_add(28, LCDML_0_1_17, 1, "AT Range", UI_func_at_range);
LCDML_add(29, LCDML_0_1_17, 2, "AT Assign", UI_func_at_assign);
LCDML_add(30, LCDML_0_1, 18, "Portamento", NULL);
LCDML_add(31, LCDML_0_1_18, 1, "Port. Mode", UI_function_not_implemented);
LCDML_add(32, LCDML_0_1_18, 2, "Port. Gliss", UI_function_not_implemented);
LCDML_add(33, LCDML_0_1_18, 3, "Port. Time", UI_function_not_implemented);
LCDML_add(31, LCDML_0_1_18, 1, "Port. Mode", UI_func_portamento_mode);
LCDML_add(32, LCDML_0_1_18, 2, "Port. Gliss", UI_func_portamento_glissando);
LCDML_add(33, LCDML_0_1_18, 3, "Port. Time", UI_func_portamento_time);
LCDML_add(34, LCDML_0_1, 19, "Operator", NULL);
LCDML_add(35, LCDML_0_1_19, 1, "OP1", UI_func_OP1);
LCDML_add(36, LCDML_0_1_19, 2, "OP2", UI_func_OP2);
@ -2663,7 +2666,175 @@ void UI_func_at_assign(uint8_t param)
lcd.print(F("[PTCH AMP EG-BS]"));
break;
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
// you can here reset some global vars or do nothing
eeprom_write();
}
}
void UI_func_portamento_mode(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("Portamento Mode"));
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkEnter())
{
LCDML.FUNC_goBackToMenu();
}
else if (LCDML.BT_checkDown() || LCDML.BT_checkUp())
{
if (LCDML.BT_checkDown())
{
if (configuration.dexed[instance_id].portamento_mode < PORTAMENTO_MODE_MAX)
{
configuration.dexed[instance_id].portamento_mode++;
}
}
else if (LCDML.BT_checkUp())
{
if (configuration.dexed[instance_id].portamento_mode > PORTAMENTO_MODE_MIN)
{
configuration.dexed[instance_id].portamento_mode--;
}
}
MicroDexed[instance_id]->setPortamentoMode(configuration.dexed[instance_id].portamento_mode, configuration.dexed[instance_id].portamento_glissando, configuration.dexed[instance_id].portamento_time);
}
lcd.setCursor(0, 1);
switch (configuration.dexed[instance_id].portamento_mode)
{
case 0:
lcd.print(F("[RETAIN ]"));
break;
case 1:
lcd.print(F("[FOLLOW ]"));
break;
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
// you can here reset some global vars or do nothing
eeprom_write();
}
}
void UI_func_portamento_glissando(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("Portam. Gliss."));
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkEnter())
{
LCDML.FUNC_goBackToMenu();
}
else if (LCDML.BT_checkDown() || LCDML.BT_checkUp())
{
if (LCDML.BT_checkDown())
{
if (configuration.dexed[instance_id].portamento_glissando < PORTAMENTO_GLISSANDO_MAX)
{
configuration.dexed[instance_id].portamento_glissando++;
}
}
else if (LCDML.BT_checkUp())
{
if (configuration.dexed[instance_id].portamento_glissando > PORTAMENTO_GLISSANDO_MIN)
{
configuration.dexed[instance_id].portamento_glissando--;
}
}
MicroDexed[instance_id]->setPortamentoMode(configuration.dexed[instance_id].portamento_mode, configuration.dexed[instance_id].portamento_glissando, configuration.dexed[instance_id].portamento_time);
}
lcd.setCursor(0, 1);
switch (configuration.dexed[instance_id].portamento_glissando)
{
case 0:
lcd.print(F("[OFF ]"));
break;
case 1:
lcd.print(F("[ON ]"));
break;
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
// you can here reset some global vars or do nothing
eeprom_write();
}
}
void UI_func_portamento_time(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("Portam. Time"));
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkEnter())
{
LCDML.FUNC_goBackToMenu();
}
else if (LCDML.BT_checkDown() || LCDML.BT_checkUp())
{
if (LCDML.BT_checkDown())
{
if (configuration.dexed[instance_id].portamento_time < PORTAMENTO_TIME_MAX)
{
configuration.dexed[instance_id].portamento_time++;
}
}
else if (LCDML.BT_checkUp())
{
if (configuration.dexed[instance_id].portamento_time > PORTAMENTO_TIME_MIN)
{
configuration.dexed[instance_id].portamento_time--;
}
}
MicroDexed[instance_id]->setPortamentoMode(configuration.dexed[instance_id].portamento_mode, configuration.dexed[instance_id].portamento_glissando, configuration.dexed[instance_id].portamento_time);
}
lcd.setCursor(0, 1);
lcd_display_int(configuration.dexed[instance_id].portamento_time, 2, false, true, false);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********

@ -403,13 +403,13 @@ enum { DEXED, REVERB, DELAY, CHORUS };
#define PORTAMENTO_MODE_MAX 1
#define PORTAMENTO_MODE_DEFAULT 0 // 0: Retain, 1: Follow
#define PORTAMENTO_GLISS_MIN 0
#define PORTAMENTO_GLISS_MAX 1
#define PORTAMENTO_GLISS_DEFAULT 0
#define PORTAMENTO_GLISSANDO_MIN 0
#define PORTAMENTO_GLISSANDO_MAX 1
#define PORTAMENTO_GLISSANDO_DEFAULT 0
#define PORTAMENTO_TIME_MIN 0
#define PORTAMENTO_TIME_MAX 99
#define PORTAMENTO_TIME_DEFAULT 50
#define PORTAMENTO_TIME_DEFAULT 0
#define INSTANCES_MIN 1
#define INSTANCES_MAX NUM_DEXED
@ -449,6 +449,9 @@ typedef struct {
uint8_t bc_assign;
uint8_t at_range;
uint8_t at_assign;
uint8_t portamento_mode;
uint8_t portamento_glissando;
uint8_t portamento_time;
uint8_t op_enabled;
} dexed_t;

@ -21,6 +21,7 @@
#include "synth.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
// State of MIDI controllers
const int kControllerPitch = 0;
@ -79,6 +80,8 @@ class Controllers {
uint8_t breath_cc;
uint8_t foot_cc;
uint8_t modwheel_cc;
bool portamento_enable_cc;
int portamento_cc;
int masterTune;

@ -36,6 +36,7 @@
#include "PluginFx.h"
#include <unistd.h>
#include <limits.h>
#include "porta.h"
#ifdef USE_TEENSY_DSP
#include <Audio.h>
#endif
@ -52,6 +53,7 @@ Dexed::Dexed(int rate)
Lfo::init(rate);
PitchEnv::init(rate);
Env::init_sr(rate);
Porta::init_sr(rate);
fx.init(rate);
engineMkI = new EngineMkI;
@ -71,6 +73,7 @@ Dexed::Dexed(int rate)
controllers.masterTune = 0;
controllers.opSwitch = 0x3f; // enable all operators
//controllers.opSwitch=0x00;
lastKeyDown = -1;
lfo.reset(data + 137);
@ -188,6 +191,13 @@ void Dexed::keydown(uint8_t pitch, uint8_t velo) {
pitch += data[144] - TRANSPOSE_FIX;
int previousKeyDown = lastKeyDown;
lastKeyDown = pitch;
int porta = -1;
if ( controllers.portamento_enable_cc && previousKeyDown >= 0 )
porta = controllers.portamento_cc;
uint8_t note = currentNote;
uint8_t keydown_counter = 0;
@ -198,7 +208,7 @@ void Dexed::keydown(uint8_t pitch, uint8_t velo) {
voices[note].velocity = velo;
voices[note].sustained = sustain;
voices[note].keydown = true;
voices[note].dx7_note->init(data, (int)pitch, (int)velo);
voices[note].dx7_note->init(data, pitch, velo, previousKeyDown, porta);
if ( data[136] )
voices[note].dx7_note->oscSync();
break;
@ -355,6 +365,8 @@ void Dexed::resetControllers(void)
controllers.foot_cc = 0;
controllers.breath_cc = 0;
controllers.aftertouch_cc = 0;
controllers.portamento_enable_cc = false;
controllers.portamento_cc = 0;
controllers.refresh();
}
@ -718,3 +730,18 @@ void Dexed::setATController(uint8_t at_range, uint8_t at_assign)
controllers.refresh();
}
void Dexed::setPortamentoMode(uint8_t portamento_mode, uint8_t portamento_glissando, uint8_t portamento_time)
{
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_MODE] = portamento_mode;
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_GLISSANDO] = portamento_glissando;
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PORTAMENTO_TIME] = portamento_time;
controllers.portamento_cc = portamento_time;
if (portamento_time > 0)
controllers.portamento_enable_cc = true;
else
controllers.portamento_enable_cc = false;
controllers.refresh();
}

@ -56,8 +56,8 @@ struct ProcessorVoice {
enum DexedEngineResolution {
DEXED_ENGINE_MODERN, // 0
DEXED_ENGINE_MARKI, // 1
DEXED_ENGINE_OPL // 2
DEXED_ENGINE_MARKI, // 1
DEXED_ENGINE_OPL // 2
};
enum DexedVoiceOPParameters {
@ -128,7 +128,9 @@ enum DexedGlobalParameters {
DEXED_OP5_ENABLE, // 15
DEXED_OP6_ENABLE, // 16
DEXED_MAX_NOTES, // 17
DEXED_VOICE_VOLUME // 18
DEXED_PORTAMENTO_MODE, // 18
DEXED_PORTAMENTO_GLISSANDO, // 19
DEXED_PORTAMENTO_TIME, // 20
};
// GLOBALS
@ -168,12 +170,13 @@ class Dexed
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);
void setPortamentoMode(uint8_t portamento_mode, uint8_t portamento_glissando, uint8_t portamento_time);
ProcessorVoice voices[MAX_NOTES];
Controllers controllers;
PluginFx fx;
uint8_t data[173] = {
uint8_t data[176] = {
95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune
95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00, // OP5
95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07, // OP4
@ -188,10 +191,13 @@ 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
00, 00, 00, // portamento_mode, portamento_glissando, portamento_time
MAX_NOTES // number of voices
}; // FM-Piano
uint32_t overload = 0;
int lastKeyDown;
protected:
static const uint8_t MAX_ACTIVE_NOTES = MAX_NOTES;
uint8_t max_notes = MAX_ACTIVE_NOTES;

@ -19,6 +19,7 @@
#include <stdlib.h>
#include "synth.h"
#include "freqlut.h"
#include "porta.h"
#include "exp2.h"
#include "controllers.h"
#include "dx7note.h"
@ -147,7 +148,7 @@ Dx7Note::Dx7Note() {
}
//void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) {
void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity) {
void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity, int srcnote, int porta) {
int rates[4];
int levels[4];
for (int op = 0; op < 6; op++) {
@ -176,6 +177,9 @@ void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity) {
opMode[op] = mode;
basepitch_[op] = freq;
ampmodsens_[op] = ampmodsenstab[patch[off + 14] & 3];
if (porta >= 0)
porta_curpitch_[op] = osc_freq(srcnote, mode, coarse, fine, detune);
}
for (int i = 0; i < 4; i++) {
rates[i] = patch[126 + i];
@ -188,6 +192,7 @@ void Dx7Note::init(const uint8_t patch[173], int midinote, int velocity) {
pitchmoddepth_ = (patch[139] * 165) >> 6;
pitchmodsens_ = pitchmodsenstab[patch[143] & 7];
ampmoddepth_ = (patch[140] * 165) >> 6;
porta_rateindex_ = (porta < 128) ? porta : 127;
}
void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Controllers *ctrls) {
@ -236,10 +241,15 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
} else {
//int32_t gain = pow(2, 10 + level * (1.0 / (1 << 24)));
int32_t basepitch = basepitch_[op];
if ( opMode[op] )
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_base);
else
params_[op].freq = Freqlut::lookup(basepitch_[op] + pitch_mod);
params_[op].freq = Freqlut::lookup(basepitch + pitch_base);
else {
if ( porta_rateindex_ >= 0 )
basepitch = porta_curpitch_[op];
params_[op].freq = Freqlut::lookup(basepitch + pitch_mod);
}
int32_t level = env_[op].getsample();
if (ampmodsens_[op] != 0) {
@ -254,6 +264,25 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay, const Co
params_[op].level_in = level;
}
}
// ==== PORTAMENTO ====
int porta = porta_rateindex_;
if ( porta >= 0 ) {
int32_t rate = Porta::rates[porta];
for (int op = 0; op < 6; op++) {
int32_t cur = porta_curpitch_[op];
int32_t dst = basepitch_[op];
bool going_up = cur < dst;
int32_t newpitch = cur + (going_up ? +rate : -rate);
if ( going_up ? (cur > dst) : (cur < dst) )
newpitch = dst;
porta_curpitch_[op] = newpitch;
}
}
ctrls->core->render(buf, params_, algorithm_, fb_buf_, fb_shift_);
}

@ -1,19 +1,19 @@
/*
* Copyright 2016-2017 Pascal Gauthier.
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Copyright 2016-2017 Pascal Gauthier.
Copyright 2012 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SYNTH_DX7NOTE_H_
#define SYNTH_DX7NOTE_H_
@ -30,15 +30,15 @@
#include "fm_core.h"
struct VoiceStatus {
uint32_t amp[6];
char ampStep[6];
char pitchStep;
uint32_t amp[6];
char ampStep[6];
char pitchStep;
};
class Dx7Note {
public:
public:
Dx7Note();
void init(const uint8_t patch[156], int midinote, int velocity);
void init(const uint8_t patch[156], int midinote, int velocity, int srcnote, int porta);
// Note: this _adds_ to the buffer. Interesting question whether it's
// worth it...
@ -59,7 +59,7 @@ public:
void transferSignal(Dx7Note &src);
void oscSync();
private:
private:
Env env_[6];
FmOpParams params_[6];
PitchEnv pitchenv_;
@ -73,6 +73,9 @@ private:
int algorithm_;
int pitchmoddepth_;
int pitchmodsens_;
int porta_rateindex_;
int32_t porta_curpitch_[6];
};
#endif // SYNTH_DX7NOTE_H_

@ -0,0 +1,35 @@
/*
Copyright 2019 Jean Pierre Cimalando.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <math.h>
#include "porta.h"
#include "synth.h"
void Porta::init_sr(double sampleRate)
{
// compute portamento for CC 7-bit range
for (unsigned int i = 0; i < 128; ++i) {
// number of semitones travelled
double sps = 350.0 * pow(2.0, -0.062 * i); // per second
double spf = sps / sampleRate; // per frame
double spp = spf * _N_; // per period
const int step = (1 << 24) / 12;
rates[i] = (int32_t)(0.5f + step * spp); // to pitch units
}
}
int32_t Porta::rates[128];

@ -0,0 +1,28 @@
/*
Copyright 2019 Jean Pierre Cimalando.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SYNTH_PORTA_H_
#define SYNTH_PORTA_H_
#include <stdint.h>
struct Porta {
public:
static void init_sr(double sampleRate);
static int32_t rates[128];
};
#endif // SYNTH_PORTA_H_
Loading…
Cancel
Save