|
|
@ -541,13 +541,13 @@ void loop() |
|
|
|
} |
|
|
|
} |
|
|
|
#else |
|
|
|
#else |
|
|
|
static bool midi_playing[NUM_DEXED]; |
|
|
|
static bool midi_playing[NUM_DEXED]; |
|
|
|
if (midi_decay_timer > MIDI_DECAY_TIMER && midi_voices[instance_id] > 0 && midi_playing[instance_id] == false) |
|
|
|
if (midi_voices[instance_id] > 0 && midi_playing[instance_id] == false) |
|
|
|
{ |
|
|
|
{ |
|
|
|
midi_playing[instance_id] = true; |
|
|
|
midi_playing[instance_id] = true; |
|
|
|
lcd.setCursor(14 + instance_id, 1); |
|
|
|
lcd.setCursor(14 + instance_id, 1); |
|
|
|
lcd.write(6 + instance_id); |
|
|
|
lcd.write(6 + instance_id); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (midi_decay_timer > MIDI_DECAY_TIMER && midi_voices[instance_id] == 0) |
|
|
|
else if (midi_voices[instance_id] == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
midi_playing[instance_id] = false; |
|
|
|
midi_playing[instance_id] = false; |
|
|
|
lcd.setCursor(14 + instance_id, 1); |
|
|
|
lcd.setCursor(14 + instance_id, 1); |
|
|
@ -596,7 +596,7 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (MicroDexed[instance_id]->getMaxNotes() > 0) |
|
|
|
if (configuration.dexed[instance_id].polyphony > 0) |
|
|
|
MicroDexed[instance_id]->keydown(inNumber, uint8_t(float(configuration.dexed[instance_id].velocity_level / 127.0)*inVelocity + 0.5)); |
|
|
|
MicroDexed[instance_id]->keydown(inNumber, uint8_t(float(configuration.dexed[instance_id].velocity_level / 127.0)*inVelocity + 0.5)); |
|
|
|
|
|
|
|
|
|
|
|
midi_voices[instance_id]++; |
|
|
|
midi_voices[instance_id]++; |
|
|
@ -629,7 +629,7 @@ void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (MicroDexed[instance_id]->getMaxNotes() > 0) |
|
|
|
if (configuration.dexed[instance_id].polyphony > 0) |
|
|
|
MicroDexed[instance_id]->keyup(inNumber); |
|
|
|
MicroDexed[instance_id]->keyup(inNumber); |
|
|
|
|
|
|
|
|
|
|
|
midi_voices[instance_id]--; |
|
|
|
midi_voices[instance_id]--; |
|
|
@ -1513,7 +1513,7 @@ void check_configuration(void) |
|
|
|
configuration.dexed[instance_id].transpose = constrain(configuration.dexed[instance_id].transpose, TRANSPOSE_MIN, TRANSPOSE_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); |
|
|
|
#if NUM_DEXED > 1 |
|
|
|
#if NUM_DEXED > 1 |
|
|
|
configuration.dexed[instance_id].polyphony = constrain(configuration.dexed[instance_id].polyphony, POLYPHONY_MIN, POLYPHONY_MAX / 2); |
|
|
|
configuration.dexed[instance_id].polyphony = constrain(configuration.dexed[instance_id].polyphony + ((POLYPHONY_MAX % 2) - instance_id) , POLYPHONY_MIN, POLYPHONY_MAX / 2); |
|
|
|
#else |
|
|
|
#else |
|
|
|
configuration.dexed[instance_id].polyphony = constrain(configuration.dexed[instance_id].polyphony, POLYPHONY_MIN, POLYPHONY_MAX); |
|
|
|
configuration.dexed[instance_id].polyphony = constrain(configuration.dexed[instance_id].polyphony, POLYPHONY_MIN, POLYPHONY_MAX); |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -1584,6 +1584,11 @@ void init_configuration(void) |
|
|
|
configuration.dexed[instance_id].pan = PANORAMA_DEFAULT; |
|
|
|
configuration.dexed[instance_id].pan = PANORAMA_DEFAULT; |
|
|
|
configuration.dexed[instance_id].transpose = TRANSPOSE_DEFAULT; |
|
|
|
configuration.dexed[instance_id].transpose = TRANSPOSE_DEFAULT; |
|
|
|
configuration.dexed[instance_id].tune = TUNE_DEFAULT; |
|
|
|
configuration.dexed[instance_id].tune = TUNE_DEFAULT; |
|
|
|
|
|
|
|
#if NUM_DEXED > 1 |
|
|
|
|
|
|
|
configuration.dexed[instance_id].polyphony = (POLYPHONY_DEFAULT / 2) + (POLYPHONY_DEFAULT % 2) - instance_id; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
configuration.dexed[instance_id].polyphony = POLYPHONY_DEFAULT; |
|
|
|
|
|
|
|
#endif |
|
|
|
configuration.dexed[instance_id].velocity_level = VELOCITY_LEVEL_DEFAULT; |
|
|
|
configuration.dexed[instance_id].velocity_level = VELOCITY_LEVEL_DEFAULT; |
|
|
|
configuration.dexed[instance_id].engine = ENGINE_DEFAULT; |
|
|
|
configuration.dexed[instance_id].engine = ENGINE_DEFAULT; |
|
|
|
configuration.dexed[instance_id].monopoly = MONOPOLY_DEFAULT; |
|
|
|
configuration.dexed[instance_id].monopoly = MONOPOLY_DEFAULT; |
|
|
@ -1755,8 +1760,6 @@ void set_fx_params(void) |
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) |
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// CHORUS
|
|
|
|
// CHORUS
|
|
|
|
chorus_mixer[instance_id]->gain(0, 1.0 - mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); |
|
|
|
|
|
|
|
chorus_mixer[instance_id]->gain(1, mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); |
|
|
|
|
|
|
|
switch (configuration.fx.chorus_waveform[instance_id]) |
|
|
|
switch (configuration.fx.chorus_waveform[instance_id]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case 0: |
|
|
|
case 0: |
|
|
@ -1782,13 +1785,21 @@ void set_fx_params(void) |
|
|
|
modchorus_filter[instance_id]->setLowpass(2, MOD_FILTER_CUTOFF_HZ, 0.54); |
|
|
|
modchorus_filter[instance_id]->setLowpass(2, MOD_FILTER_CUTOFF_HZ, 0.54); |
|
|
|
modchorus_filter[instance_id]->setLowpass(3, MOD_FILTER_CUTOFF_HZ, 1.3); |
|
|
|
modchorus_filter[instance_id]->setLowpass(3, MOD_FILTER_CUTOFF_HZ, 1.3); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
//chorus_mixer[instance_id]->gain(0, 1.0 - pseudo_log_curve(mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)));
|
|
|
|
|
|
|
|
//chorus_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)));
|
|
|
|
|
|
|
|
//chorus_mixer[instance_id]->gain(0, 1.0 - mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5));
|
|
|
|
|
|
|
|
chorus_mixer[instance_id]->gain(0, 1.0); |
|
|
|
|
|
|
|
chorus_mixer[instance_id]->gain(1, mapfloat(configuration.fx.chorus_level[instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)); |
|
|
|
|
|
|
|
|
|
|
|
// DELAY
|
|
|
|
// DELAY
|
|
|
|
delay_mixer[instance_id]->gain(0, 1.0); |
|
|
|
delay_mixer[instance_id]->gain(0, 1.0); |
|
|
|
delay_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_level[instance_id], DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0))); |
|
|
|
delay_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_level[instance_id], DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0))); |
|
|
|
delay_fx[instance_id]->delay(0, constrain(configuration.fx.delay_time[instance_id], DELAY_TIME_MIN, DELAY_TIME_MAX) * 10); |
|
|
|
|
|
|
|
delay_fb_mixer[instance_id]->gain(0, 1.0); |
|
|
|
delay_fb_mixer[instance_id]->gain(0, 1.0); |
|
|
|
delay_fb_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_feedback[instance_id], DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); |
|
|
|
delay_fb_mixer[instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_feedback[instance_id], DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); |
|
|
|
|
|
|
|
if (configuration.fx.delay_level[selected_instance_id] <= DELAY_LEVEL_MIN) |
|
|
|
|
|
|
|
delay_fx[instance_id]->disable(0); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
delay_fx[instance_id]->delay(0, constrain(configuration.fx.delay_time[instance_id], DELAY_TIME_MIN, DELAY_TIME_MAX) * 10); |
|
|
|
|
|
|
|
|
|
|
|
// REVERB SEND
|
|
|
|
// REVERB SEND
|
|
|
|
reverb_mixer_r.gain(instance_id, pseudo_log_curve(configuration.fx.reverb_send[instance_id] / 100.0)); |
|
|
|
reverb_mixer_r.gain(instance_id, pseudo_log_curve(configuration.fx.reverb_send[instance_id] / 100.0)); |
|
|
@ -1807,8 +1818,8 @@ void set_fx_params(void) |
|
|
|
freeverb_r.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); |
|
|
|
freeverb_r.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); |
|
|
|
freeverb_l.roomsize(mapfloat(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0)); |
|
|
|
freeverb_l.roomsize(mapfloat(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0)); |
|
|
|
freeverb_l.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); |
|
|
|
freeverb_l.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); |
|
|
|
master_mixer_r.gain(3, pseudo_log_curve(configuration.fx.reverb_level / 100.0)); |
|
|
|
master_mixer_r.gain(3, pseudo_log_curve(mapfloat(configuration.fx.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0))); |
|
|
|
master_mixer_l.gain(3, pseudo_log_curve(configuration.fx.reverb_level / 100.0)); |
|
|
|
master_mixer_l.gain(3, pseudo_log_curve(mapfloat(configuration.fx.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0))); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1846,11 +1857,6 @@ void set_sys_params(void) |
|
|
|
HELPERS |
|
|
|
HELPERS |
|
|
|
******************************************************************************/ |
|
|
|
******************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
float mapfloat(float val, float in_min, float in_max, float out_min, float out_max) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://www.reddit.com/r/Teensy/comments/7r19uk/reset_and_reboot_teensy_lc_via_code/
|
|
|
|
// https://www.reddit.com/r/Teensy/comments/7r19uk/reset_and_reboot_teensy_lc_via_code/
|
|
|
|
#define SCB_AIRCR (*(volatile uint32_t *)0xE000ED0C) // Application Interrupt and Reset Control location
|
|
|
|
#define SCB_AIRCR (*(volatile uint32_t *)0xE000ED0C) // Application Interrupt and Reset Control location
|
|
|
|
void _softRestart(void) |
|
|
|
void _softRestart(void) |
|
|
@ -1863,12 +1869,14 @@ float pseudo_log_curve(float value) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const float _pseudo_log = 1048575 / (float)(1 << 20); |
|
|
|
const float _pseudo_log = 1048575 / (float)(1 << 20); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
/*
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
Serial.print(F("value in: ")); |
|
|
|
Serial.print(F("value in: ")); |
|
|
|
Serial.print(value, 3); |
|
|
|
Serial.print(value, 3); |
|
|
|
Serial.print(F(" value out: ")); |
|
|
|
Serial.print(F(" value out: ")); |
|
|
|
Serial.println(mapfloat(_pseudo_log * arm_sin_f32(value), 0.0, _pseudo_log * arm_sin_f32(1.0), 0.0, 1.0), 3); |
|
|
|
Serial.println(mapfloat(_pseudo_log * arm_sin_f32(value), 0.0, _pseudo_log * arm_sin_f32(1.0), 0.0, 1.0), 3); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
return (mapfloat(_pseudo_log * arm_sin_f32(value), 0.0, _pseudo_log * arm_sin_f32(1.0), 0.0, 1.0)); |
|
|
|
return (mapfloat(_pseudo_log * arm_sin_f32(value), 0.0, _pseudo_log * arm_sin_f32(1.0), 0.0, 1.0)); |
|
|
|
} |
|
|
|
} |
|
|
|