|
|
@ -776,104 +776,126 @@ void loop() |
|
|
|
******************************************************************************/ |
|
|
|
******************************************************************************/ |
|
|
|
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) |
|
|
|
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) |
|
|
|
{ |
|
|
|
{ |
|
|
|
//Ignore the note when playing & recording the same note into the sequencer
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
if (seq_recording == false || (seq_recording && inNumber != seq_note_in )) |
|
|
|
if (activesample < 6 && seq_running == false && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_seq_pattern_editor) ) // live play pitched sample
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// Check for MicroDexed
|
|
|
|
if (drum_counter >= NUM_DRUMS) |
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) |
|
|
|
drum_counter = 0; |
|
|
|
|
|
|
|
uint8_t slot = drum_get_slot(drum_config[activesample].drum_class); |
|
|
|
|
|
|
|
float pan = mapfloat(drum_config[activesample].pan, -1.0, 1.0, 0.0, 1.0); |
|
|
|
|
|
|
|
drum_mixer_r.gain(slot, (1.0 - pan) * drum_config[activesample].vol_max); |
|
|
|
|
|
|
|
drum_mixer_l.gain(slot, pan * drum_config[activesample].vol_max); |
|
|
|
|
|
|
|
#ifdef USE_FX |
|
|
|
|
|
|
|
drum_reverb_send_mixer_r.gain(slot, (1.0 - pan) * volume_transform(drum_config[activesample].reverb_send)); |
|
|
|
|
|
|
|
drum_reverb_send_mixer_l.gain(slot, pan * volume_transform(drum_config[activesample].reverb_send)); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
if (drum_config[activesample].drum_data != NULL && drum_config[activesample].len > 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (checkMidiChannel(inChannel, instance_id)) |
|
|
|
Drum[slot]->enableInterpolation(true); |
|
|
|
|
|
|
|
Drum[slot]->setPlaybackRate( (float)pow (2, (inNumber - 72) / 12.00) * drum_config[activesample].p_offset ); |
|
|
|
|
|
|
|
Drum[slot]->playRaw((int16_t*)drum_config[activesample].drum_data, drum_config[activesample].len, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
//Ignore the note when playing & recording the same note into the sequencer
|
|
|
|
|
|
|
|
if (seq_recording == false || (seq_recording && inNumber != seq_note_in )) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Check for MicroDexed
|
|
|
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
if (checkMidiChannel(inChannel, instance_id)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (configuration.dexed[instance_id].polyphony > 0) |
|
|
|
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note) |
|
|
|
MicroDexed[instance_id]->keydown(inNumber, uint8_t(float(configuration.dexed[instance_id].velocity_level / 127.0)*inVelocity + 0.5)); |
|
|
|
{ |
|
|
|
|
|
|
|
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)); |
|
|
|
|
|
|
|
|
|
|
|
midi_voices[instance_id]++; |
|
|
|
midi_voices[instance_id]++; |
|
|
|
#ifdef TEENSY4 |
|
|
|
#ifdef TEENSY4 |
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select)) |
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
midi_decay_timer = 0; |
|
|
|
midi_decay_timer = 0; |
|
|
|
midi_decay[instance_id] = min(inVelocity / 5, 7); |
|
|
|
midi_decay[instance_id] = min(inVelocity / 5, 7); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
char note_name[4]; |
|
|
|
char note_name[4]; |
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
Serial.print(F("Keydown ")); |
|
|
|
Serial.print(F("Keydown ")); |
|
|
|
Serial.print(note_name); |
|
|
|
Serial.print(note_name); |
|
|
|
Serial.print(F(" instance ")); |
|
|
|
Serial.print(F(" instance ")); |
|
|
|
Serial.print(instance_id, DEC); |
|
|
|
Serial.print(instance_id, DEC); |
|
|
|
Serial.print(F(" MIDI-channel ")); |
|
|
|
Serial.print(F(" MIDI-channel ")); |
|
|
|
Serial.print(inChannel, DEC); |
|
|
|
Serial.print(inChannel, DEC); |
|
|
|
Serial.println(); |
|
|
|
Serial.println(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
// Check for Drum
|
|
|
|
// Check for Drum
|
|
|
|
if (inChannel == drum_midi_channel) |
|
|
|
if (inChannel == drum_midi_channel) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (drum_counter >= NUM_DRUMS) |
|
|
|
if (drum_counter >= NUM_DRUMS) |
|
|
|
drum_counter = 0; |
|
|
|
drum_counter = 0; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
char note_name[4]; |
|
|
|
char note_name[4]; |
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
getNoteName(note_name, inNumber); |
|
|
|
Serial.print(F("=> Drum[")); |
|
|
|
Serial.print(F("=> Drum[")); |
|
|
|
Serial.print(drum_counter, DEC); |
|
|
|
Serial.print(drum_counter, DEC); |
|
|
|
Serial.print(F("]: ")); |
|
|
|
Serial.print(F("]: ")); |
|
|
|
Serial.println(note_name); |
|
|
|
Serial.println(note_name); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG; d++) |
|
|
|
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG; d++) |
|
|
|
{ |
|
|
|
|
|
|
|
if (inNumber == drum_config[d].midinote) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
uint8_t slot = drum_get_slot(drum_config[d].drum_class); |
|
|
|
if (inNumber == drum_config[d].midinote) |
|
|
|
float pan = mapfloat(drum_config[d].pan, -1.0, 1.0, 0.0, 1.0); |
|
|
|
{ |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
drum_mixer_r.gain(slot, (1.0 - pan) * volume_transform(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max))); |
|
|
|
drum_mixer_r.gain(slot, (1.0 - pan) * volume_transform(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max))); |
|
|
|
drum_mixer_l.gain(slot, pan * volume_transform(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max))); |
|
|
|
drum_mixer_l.gain(slot, pan * volume_transform(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max))); |
|
|
|
#ifdef USE_FX |
|
|
|
#ifdef USE_FX |
|
|
|
drum_reverb_send_mixer_r.gain(slot, (1.0 - pan) * volume_transform(drum_config[d].reverb_send)); |
|
|
|
drum_reverb_send_mixer_r.gain(slot, (1.0 - pan) * volume_transform(drum_config[d].reverb_send)); |
|
|
|
drum_reverb_send_mixer_l.gain(slot, pan * volume_transform(drum_config[d].reverb_send)); |
|
|
|
drum_reverb_send_mixer_l.gain(slot, pan * volume_transform(drum_config[d].reverb_send)); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
if (drum_config[d].drum_data != NULL && drum_config[d].len > 0) |
|
|
|
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]->play(drum_config[d].drum_data);
|
|
|
|
Drum[slot]->setPlaybackRate(drum_config[d].pitch); |
|
|
|
if (drum_config[d].pitch != 0.0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Drum[slot]->enableInterpolation(true); |
|
|
|
|
|
|
|
Drum[slot]->setPlaybackRate(drum_config[d].pitch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Drum[slot]->playRaw((int16_t*)drum_config[d].drum_data, drum_config[d].len, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
Drum[slot]->playRaw((int16_t*)drum_config[d].drum_data, drum_config[d].len, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
Serial.print(F("Drum ")); |
|
|
|
Serial.print(F("Drum ")); |
|
|
|
Serial.print(drum_config[d].shortname); |
|
|
|
Serial.print(drum_config[d].shortname); |
|
|
|
Serial.print(F(" [")); |
|
|
|
Serial.print(F(" [")); |
|
|
|
Serial.print(drum_config[d].name); |
|
|
|
Serial.print(drum_config[d].name); |
|
|
|
Serial.print(F("], Slot ")); |
|
|
|
Serial.print(F("], Slot ")); |
|
|
|
Serial.print(slot); |
|
|
|
Serial.print(slot); |
|
|
|
Serial.print(F(": V")); |
|
|
|
Serial.print(F(": V")); |
|
|
|
Serial.print(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max), 2); |
|
|
|
Serial.print(mapfloat(inVelocity, 0, 127, drum_config[d].vol_min, drum_config[d].vol_max), 2); |
|
|
|
Serial.print(F(" P")); |
|
|
|
Serial.print(F(" P")); |
|
|
|
Serial.print(drum_config[d].pan, 2); |
|
|
|
Serial.print(drum_config[d].pan, 2); |
|
|
|
Serial.print(F(" PAN")); |
|
|
|
Serial.print(F(" PAN")); |
|
|
|
Serial.print(pan, 2); |
|
|
|
Serial.print(pan, 2); |
|
|
|
Serial.print(F(" RS")); |
|
|
|
Serial.print(F(" RS")); |
|
|
|
Serial.println(drum_config[d].reverb_send, 2); |
|
|
|
Serial.println(drum_config[d].reverb_send, 2); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if NUM_DRUMS > 0 |
|
|
|
#if NUM_DRUMS > 0 |
|
|
@ -887,29 +909,29 @@ uint8_t drum_get_slot(uint8_t dt) |
|
|
|
Drum[i]->enableInterpolation(false); |
|
|
|
Drum[i]->enableInterpolation(false); |
|
|
|
Drum[i]->setPlaybackRate(1.0); |
|
|
|
Drum[i]->setPlaybackRate(1.0); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
// else
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
if (drum_type[i] == dt) |
|
|
|
// if (drum_type[i] == dt)
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
#ifdef DEBUG |
|
|
|
//#ifdef DEBUG
|
|
|
|
Serial.print(F("Stopping Drum ")); |
|
|
|
// Serial.print(F("Stopping Drum "));
|
|
|
|
Serial.print(i); |
|
|
|
// Serial.print(i);
|
|
|
|
Serial.print(F(" type ")); |
|
|
|
// Serial.print(F(" type "));
|
|
|
|
Serial.println(dt); |
|
|
|
// Serial.println(dt);
|
|
|
|
#endif |
|
|
|
//#endif
|
|
|
|
Drum[i]->stop(); |
|
|
|
// Drum[i]->stop();
|
|
|
|
|
|
|
|
//
|
|
|
|
return (i); |
|
|
|
// return (i);
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
} |
|
|
|
#ifdef DEBUG |
|
|
|
#ifdef DEBUG |
|
|
|
Serial.print(F("Using next free Drum slot ")); |
|
|
|
Serial.print(F("Using next free Drum slot ")); |
|
|
|
Serial.println(drum_counter % 4); |
|
|
|
Serial.println(drum_counter % NUM_DRUMS); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
drum_type[drum_counter % 4] = dt; |
|
|
|
drum_type[drum_counter % NUM_DRUMS] = dt; |
|
|
|
drum_counter++; |
|
|
|
drum_counter++; |
|
|
|
return (drum_counter - 1 % 4); |
|
|
|
return (drum_counter - 1 % NUM_DRUMS); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|