|
|
|
@ -407,6 +407,7 @@ int16_t* ep_delayline_l; |
|
|
|
|
extern drum_config_t drum_config[NUM_DRUMSET_CONFIG]; |
|
|
|
|
uint8_t drum_counter; |
|
|
|
|
uint8_t drum_type[NUM_DRUMS]; |
|
|
|
|
int8_t drum_map[NUM_DRUMSET_CONFIG]; |
|
|
|
|
uint8_t drum_midi_channel = DRUM_MIDI_CHANNEL; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
@ -416,7 +417,6 @@ extern LCDMenuLib2 LCDML; |
|
|
|
|
|
|
|
|
|
extern void getNoteName(char* noteName, uint8_t noteNumber); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
|
SETUP |
|
|
|
|
***********************************************************************/ |
|
|
|
@ -568,6 +568,7 @@ void setup() { |
|
|
|
|
configuration.drums.drum_reverb_send[i] = mapfloat(drum_config[i].reverb_send, 0.0, 1.0, DRUMS_REVERB_SEND_MIN, DRUMS_REVERB_SEND_MAX); |
|
|
|
|
configuration.drums.drum_pitch[i] = mapfloat(drum_config[i].pitch, -1.0, 1.0, DRUMS_PITCH_MIN, DRUMS_PITCH_MAX); |
|
|
|
|
configuration.drums.drum_midi_note[i] = constrain(drum_config[i].midinote, DRUMS_MIDI_NOTE_MIN, DRUMS_MIDI_NOTE_MAX); |
|
|
|
|
drum_map[i] = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
@ -918,7 +919,7 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
// Play Notes
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// Check for MicroDexed
|
|
|
|
|
// MicroDexed
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
|
if (checkMidiChannel(inChannel, instance_id)) { |
|
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) { |
|
|
|
@ -947,8 +948,27 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// E-Piano
|
|
|
|
|
#if defined(USE_EPIANO) |
|
|
|
|
if (configuration.epiano.midi_channel == MIDI_CHANNEL_OMNI || configuration.epiano.midi_channel == inChannel) { |
|
|
|
|
if (inNumber >= configuration.epiano.lowest_note && inNumber <= configuration.epiano.highest_note) { |
|
|
|
|
ep.noteOn(inNumber + configuration.epiano.transpose - 24, inVelocity); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
char note_name[4]; |
|
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
|
Serial.print(F("KeyDown ")); |
|
|
|
|
Serial.print(note_name); |
|
|
|
|
Serial.print(F(" EPIANO ")); |
|
|
|
|
Serial.print(F(" MIDI-channel ")); |
|
|
|
|
Serial.print(inChannel, DEC); |
|
|
|
|
Serial.println(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Drums
|
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
|
// Check for Drum
|
|
|
|
|
if (inChannel == drum_midi_channel || drum_midi_channel == MIDI_CHANNEL_OMNI) { |
|
|
|
|
if (drum_counter >= NUM_DRUMS) |
|
|
|
|
drum_counter = 0; |
|
|
|
@ -956,14 +976,25 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
char note_name[4]; |
|
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
|
Serial.print(F("=> Drum[")); |
|
|
|
|
Serial.print(F("Triggring Drum[")); |
|
|
|
|
Serial.print(drum_counter, DEC); |
|
|
|
|
Serial.print(F("]: ")); |
|
|
|
|
Serial.print(F("]: with note ")); |
|
|
|
|
Serial.println(note_name); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
int8_t mapped_note = -1; |
|
|
|
|
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG; d++) { |
|
|
|
|
if (inNumber == drum_config[d].midinote) { |
|
|
|
|
if (drum_map[inNumber] != -1) { |
|
|
|
|
mapped_note = drum_map[inNumber]; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI drum-note mapping ["); |
|
|
|
|
Serial.print(inNumber); |
|
|
|
|
Serial.print("] -> ["); |
|
|
|
|
Serial.print(mapped_note); |
|
|
|
|
Serial.println("]"); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
if (mapped_note == drum_config[d].midinote) { |
|
|
|
|
uint8_t slot = drum_get_slot(drum_config[d].drum_class); |
|
|
|
|
float pan = mapfloat(drum_config[d].pan, -1.0, 1.0, 0.0, 1.0); |
|
|
|
|
|
|
|
|
@ -974,8 +1005,6 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
drum_reverb_send_mixer_l.gain(slot, pan * volume_transform(drum_config[d].reverb_send)); |
|
|
|
|
#endif |
|
|
|
|
if (drum_config[d].drum_data != NULL && drum_config[d].len > 0) { |
|
|
|
|
//Drum[slot]->play(drum_config[d].drum_data);
|
|
|
|
|
|
|
|
|
|
if (drum_config[d].pitch != 0.0) { |
|
|
|
|
Drum[slot]->enableInterpolation(true); |
|
|
|
|
Drum[slot]->setPlaybackRate(drum_config[d].pitch); |
|
|
|
@ -988,15 +1017,13 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
Serial.print(drum_config[d].shortname); |
|
|
|
|
Serial.print(F(" [")); |
|
|
|
|
Serial.print(drum_config[d].name); |
|
|
|
|
Serial.print(F("], Slot ")); |
|
|
|
|
Serial.print(F("], Slot [")); |
|
|
|
|
Serial.print(slot); |
|
|
|
|
Serial.print(F(": V")); |
|
|
|
|
Serial.print(F("]: Velocity=")); |
|
|
|
|
Serial.print(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max), 2); |
|
|
|
|
Serial.print(F(" P")); |
|
|
|
|
Serial.print(drum_config[d].pan, 2); |
|
|
|
|
Serial.print(F(" PAN")); |
|
|
|
|
Serial.print(F(" Pan=")); |
|
|
|
|
Serial.print(pan, 2); |
|
|
|
|
Serial.print(F(" RS")); |
|
|
|
|
Serial.print(F(" ReverbSend=")); |
|
|
|
|
Serial.println(drum_config[d].reverb_send, 2); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
@ -1004,135 +1031,6 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined(USE_EPIANO) |
|
|
|
|
//
|
|
|
|
|
// E-Piano
|
|
|
|
|
//
|
|
|
|
|
if (configuration.epiano.midi_channel == MIDI_CHANNEL_OMNI || configuration.epiano.midi_channel == inChannel) { |
|
|
|
|
if (inNumber >= configuration.epiano.lowest_note && inNumber <= configuration.epiano.highest_note) { |
|
|
|
|
ep.noteOn(inNumber + configuration.epiano.transpose - 24, inVelocity); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
char note_name[4]; |
|
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
|
Serial.print(F("KeyDown ")); |
|
|
|
|
Serial.print(note_name); |
|
|
|
|
Serial.print(F(" EPIANO ")); |
|
|
|
|
Serial.print(F(" MIDI-channel ")); |
|
|
|
|
Serial.print(inChannel, DEC); |
|
|
|
|
Serial.println(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
|
uint8_t drum_get_slot(uint8_t dt) { |
|
|
|
|
for (uint8_t i = 0; i < NUM_DRUMS; i++) { |
|
|
|
|
if (!Drum[i]->isPlaying()) { |
|
|
|
|
drum_type[i] = DRUM_NONE; |
|
|
|
|
Drum[i]->enableInterpolation(false); |
|
|
|
|
Drum[i]->setPlaybackRate(1.0); |
|
|
|
|
} |
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// if (drum_type[i] == dt)
|
|
|
|
|
// {
|
|
|
|
|
//#ifdef DEBUG
|
|
|
|
|
// Serial.print(F("Stopping Drum "));
|
|
|
|
|
// Serial.print(i);
|
|
|
|
|
// Serial.print(F(" type "));
|
|
|
|
|
// Serial.println(dt);
|
|
|
|
|
//#endif
|
|
|
|
|
// Drum[i]->stop();
|
|
|
|
|
//
|
|
|
|
|
// return (i);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
} |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("Using next free Drum slot ")); |
|
|
|
|
Serial.println(drum_counter % NUM_DRUMS); |
|
|
|
|
#endif |
|
|
|
|
drum_type[drum_counter % NUM_DRUMS] = dt; |
|
|
|
|
drum_counter++; |
|
|
|
|
return (drum_counter - 1 % NUM_DRUMS); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
int8_t handle_midi_learn(int8_t note) { |
|
|
|
|
int8_t ret_channel = -1; |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learning for "); |
|
|
|
|
Serial.println(note); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_drum_midi_note)) { |
|
|
|
|
ret_channel = configuration.drums.drum_midi_channel; |
|
|
|
|
//LCDML.OTHER_jumpToFunc(UI_func_drum_midi_note);
|
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_epiano_lowest_note)) { |
|
|
|
|
if (note > configuration.epiano.highest_note) |
|
|
|
|
configuration.epiano.lowest_note = configuration.epiano.highest_note; |
|
|
|
|
else |
|
|
|
|
configuration.epiano.lowest_note = note; |
|
|
|
|
ret_channel = configuration.epiano.midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned lowest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for EPiano, ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_epiano_highest_note)) { |
|
|
|
|
if (note < configuration.epiano.lowest_note) |
|
|
|
|
configuration.epiano.highest_note = configuration.epiano.lowest_note; |
|
|
|
|
else |
|
|
|
|
configuration.epiano.highest_note = note; |
|
|
|
|
ret_channel = configuration.epiano.midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned highest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for EPiano, ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check for Dexed
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_lowest_note)) { |
|
|
|
|
if (note > configuration.dexed[selected_instance_id].highest_note) |
|
|
|
|
configuration.dexed[selected_instance_id].lowest_note = configuration.dexed[selected_instance_id].highest_note; |
|
|
|
|
else |
|
|
|
|
configuration.dexed[selected_instance_id].lowest_note = note; |
|
|
|
|
ret_channel = configuration.dexed[selected_instance_id].midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned lowest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for instance: "); |
|
|
|
|
Serial.print(selected_instance_id); |
|
|
|
|
Serial.print(", ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_highest_note)) { |
|
|
|
|
if (note < configuration.dexed[selected_instance_id].lowest_note) |
|
|
|
|
configuration.dexed[selected_instance_id].highest_note = configuration.dexed[selected_instance_id].lowest_note; |
|
|
|
|
else |
|
|
|
|
configuration.dexed[selected_instance_id].highest_note = note; |
|
|
|
|
ret_channel = configuration.dexed[selected_instance_id].midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned highest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for instance: "); |
|
|
|
|
Serial.print(selected_instance_id); |
|
|
|
|
Serial.print(", ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
LCDML.OTHER_updateFunc(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (ret_channel); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
@ -1145,6 +1043,7 @@ void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
inChannel = tmp_channel; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Dexed
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
|
if (checkMidiChannel(inChannel, instance_id)) { |
|
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) { |
|
|
|
@ -1167,6 +1066,7 @@ void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// EPiano
|
|
|
|
|
#if defined(USE_EPIANO) |
|
|
|
|
if (configuration.epiano.midi_channel == MIDI_CHANNEL_OMNI || configuration.epiano.midi_channel == inChannel) { |
|
|
|
|
if (inNumber >= configuration.epiano.lowest_note && inNumber <= configuration.epiano.highest_note) { |
|
|
|
@ -1190,6 +1090,13 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) { |
|
|
|
|
inCtrl = constrain(inCtrl, 0, 127); |
|
|
|
|
inValue = constrain(inValue, 0, 127); |
|
|
|
|
|
|
|
|
|
// EPiano
|
|
|
|
|
#if defined(USE_EPIANO) |
|
|
|
|
if (configuration.epiano.midi_channel == MIDI_CHANNEL_OMNI || configuration.epiano.midi_channel == inChannel) |
|
|
|
|
ep.processMidiController(inCtrl, inValue); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Dexed
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
|
if (checkMidiChannel(inChannel, instance_id)) { |
|
|
|
|
#ifdef DEBUG |
|
|
|
@ -1389,11 +1296,6 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if defined(USE_EPIANO) |
|
|
|
|
if (configuration.epiano.midi_channel == MIDI_CHANNEL_OMNI || configuration.epiano.midi_channel == inChannel) |
|
|
|
|
ep.processMidiController(inCtrl, inValue); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void handleAfterTouch(byte inChannel, byte inPressure) { |
|
|
|
@ -1856,6 +1758,7 @@ void set_drums_volume(float vol) { |
|
|
|
|
master_mixer_r.gain(MASTER_MIX_CH_DRUMS, vol); |
|
|
|
|
master_mixer_l.gain(MASTER_MIX_CH_DRUMS, vol); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_volume(uint8_t v, uint8_t m) { |
|
|
|
|
float tmp_v; |
|
|
|
|
|
|
|
|
@ -2073,6 +1976,26 @@ void check_configuration_epiano(void) { |
|
|
|
|
configuration.epiano.midi_channel = constrain(configuration.epiano.midi_channel, EP_MIDI_CHANNEL_MIN, EP_MIDI_CHANNEL_MAX); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void check_configuration_drum_config(void) { |
|
|
|
|
configuration.drums.drum_main_vol = constrain(configuration.drums.drum_main_vol, DRUMS_MAIN_VOL_MIN, DRUMS_MAIN_VOL_MAX); |
|
|
|
|
for (uint8_t i = 0; i < NUM_DRUMSET_CONFIG - 1; i++) { |
|
|
|
|
drum_config[i].midinote = constrain(drum_config[i].midinote, DRUMS_MIDI_NOTE_MIN, DRUMS_MIDI_NOTE_MAX); |
|
|
|
|
drum_config[i].pitch = constrain(drum_config[i].pitch, DRUMS_PITCH_MIN, DRUMS_PITCH_MAX); |
|
|
|
|
drum_config[i].pan = constrain(drum_config[i].pan, DRUMS_PANORAMA_MIN, DRUMS_PANORAMA_MAX); |
|
|
|
|
drum_config[i].vol_max = constrain(drum_config[i].vol_max, DRUMS_VOL_MIN, DRUMS_VOL_MAX); |
|
|
|
|
drum_config[i].vol_min = constrain(drum_config[i].vol_min, DRUMS_VOL_MIN, DRUMS_VOL_MAX); |
|
|
|
|
drum_config[i].reverb_send = constrain(drum_config[i].reverb_send, DRUMS_REVERB_SEND_MIN, DRUMS_REVERB_SEND_MAX); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void check_configuration_drum_map(void) { |
|
|
|
|
for (uint8_t i = 0; i < NUM_DRUMSET_CONFIG - 1; i++) { |
|
|
|
|
drum_map[i] = constrain(drum_map[i], -1, DRUMS_MIDI_NOTE_MAX); |
|
|
|
|
if (drum_map[i] >= 0 && drum_map[i] < DRUMS_MIDI_NOTE_MIN) |
|
|
|
|
drum_map[i] = -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void init_configuration(void) { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("INITIALIZING CONFIGURATION")); |
|
|
|
@ -2183,69 +2106,6 @@ void eeprom_update(void) { |
|
|
|
|
EEPROM.update(EEPROM_START_ADDRESS + 2, configuration.sys.vol); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
PARAMETER-HELPERS |
|
|
|
|
******************************************************************************/ |
|
|
|
|
|
|
|
|
|
void set_sample_note(uint8_t sample, uint8_t note) { |
|
|
|
|
drum_config[sample].midinote = note; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_sample_pitch(uint8_t sample, float playbackspeed) { |
|
|
|
|
drum_config[sample].pitch = playbackspeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_sample_pan(uint8_t sample, float s_pan) { |
|
|
|
|
drum_config[sample].pan = s_pan; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_sample_vol_max(uint8_t sample, float s_max) { |
|
|
|
|
drum_config[sample].vol_max = s_max; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_sample_vol_min(uint8_t sample, float s_min) { |
|
|
|
|
drum_config[sample].vol_min = s_min; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_sample_reverb_send(uint8_t sample, float s_reverb) { |
|
|
|
|
drum_config[sample].reverb_send = s_reverb; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t get_sample_note(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].midinote); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float get_sample_pitch(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].pitch); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float get_sample_pan(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].pan); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float get_sample_vol_max(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].vol_max); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float get_sample_vol_min(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].vol_min); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float get_sample_reverb_send(uint8_t sample) { |
|
|
|
|
return (drum_config[sample].reverb_send); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t find_drum_number_from_note(uint8_t note) { |
|
|
|
|
uint8_t number = 0; |
|
|
|
|
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG - 1; d++) { |
|
|
|
|
if (note == drum_config[d].midinote) { |
|
|
|
|
number = d; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void set_fx_params(void) { |
|
|
|
|
#if defined(USE_FX) |
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
@ -2442,7 +2302,7 @@ void set_sys_params(void) { |
|
|
|
|
// 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
|
|
|
|
|
void _softRestart(void) { |
|
|
|
|
Serial.end(); //clears the serial monitor if used
|
|
|
|
|
Serial.end(); //clears the serial monitor if used
|
|
|
|
|
SCB_AIRCR = 0x05FA0004; //write value for restart
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2454,6 +2314,114 @@ void _softRestart(void) { |
|
|
|
|
return (pow(value, 2.2)); |
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
|
uint8_t drum_get_slot(uint8_t dt) { |
|
|
|
|
for (uint8_t i = 0; i < NUM_DRUMS; i++) { |
|
|
|
|
if (!Drum[i]->isPlaying()) { |
|
|
|
|
drum_type[i] = DRUM_NONE; |
|
|
|
|
Drum[i]->enableInterpolation(false); |
|
|
|
|
Drum[i]->setPlaybackRate(1.0); |
|
|
|
|
} |
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// if (drum_type[i] == dt)
|
|
|
|
|
// {
|
|
|
|
|
//#ifdef DEBUG
|
|
|
|
|
// Serial.print(F("Stopping Drum "));
|
|
|
|
|
// Serial.print(i);
|
|
|
|
|
// Serial.print(F(" type "));
|
|
|
|
|
// Serial.println(dt);
|
|
|
|
|
//#endif
|
|
|
|
|
// Drum[i]->stop();
|
|
|
|
|
//
|
|
|
|
|
// return (i);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
} |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("Using next free Drum slot ")); |
|
|
|
|
Serial.println(drum_counter % NUM_DRUMS); |
|
|
|
|
#endif |
|
|
|
|
drum_type[drum_counter % NUM_DRUMS] = dt; |
|
|
|
|
drum_counter++; |
|
|
|
|
return (drum_counter - 1 % NUM_DRUMS); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
int8_t handle_midi_learn(int8_t note) { |
|
|
|
|
int8_t ret_channel = -1; |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learning for "); |
|
|
|
|
Serial.println(note); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_drum_midi_note)) { |
|
|
|
|
ret_channel = configuration.drums.drum_midi_channel; |
|
|
|
|
//LCDML.OTHER_jumpToFunc(UI_func_drum_midi_note);
|
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_epiano_lowest_note)) { |
|
|
|
|
if (note > configuration.epiano.highest_note) |
|
|
|
|
configuration.epiano.lowest_note = configuration.epiano.highest_note; |
|
|
|
|
else |
|
|
|
|
configuration.epiano.lowest_note = note; |
|
|
|
|
ret_channel = configuration.epiano.midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned lowest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for EPiano, ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_epiano_highest_note)) { |
|
|
|
|
if (note < configuration.epiano.lowest_note) |
|
|
|
|
configuration.epiano.highest_note = configuration.epiano.lowest_note; |
|
|
|
|
else |
|
|
|
|
configuration.epiano.highest_note = note; |
|
|
|
|
ret_channel = configuration.epiano.midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned highest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for EPiano, ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check for Dexed
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { |
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_lowest_note)) { |
|
|
|
|
if (note > configuration.dexed[selected_instance_id].highest_note) |
|
|
|
|
configuration.dexed[selected_instance_id].lowest_note = configuration.dexed[selected_instance_id].highest_note; |
|
|
|
|
else |
|
|
|
|
configuration.dexed[selected_instance_id].lowest_note = note; |
|
|
|
|
ret_channel = configuration.dexed[selected_instance_id].midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned lowest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for instance: "); |
|
|
|
|
Serial.print(selected_instance_id); |
|
|
|
|
Serial.print(", ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_highest_note)) { |
|
|
|
|
if (note < configuration.dexed[selected_instance_id].lowest_note) |
|
|
|
|
configuration.dexed[selected_instance_id].highest_note = configuration.dexed[selected_instance_id].lowest_note; |
|
|
|
|
else |
|
|
|
|
configuration.dexed[selected_instance_id].highest_note = note; |
|
|
|
|
ret_channel = configuration.dexed[selected_instance_id].midi_channel; |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print("MIDI learned highest note: "); |
|
|
|
|
Serial.print(note); |
|
|
|
|
Serial.print(" for instance: "); |
|
|
|
|
Serial.print(selected_instance_id); |
|
|
|
|
Serial.print(", ghosting MIDI channel "); |
|
|
|
|
Serial.println(ret_channel); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
LCDML.OTHER_updateFunc(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (ret_channel); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float midi_volume_transform(uint8_t midi_amp) { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("midi_amp=")); |
|
|
|
|