Merge pull request 'added seq start/stop from left button, live pitched sample play, various fixes' (#110) from positionhigh/MicroDexed:dev into dev

Reviewed-on: https://codeberg.org/dcoredump/MicroDexed/pulls/110
pull/111/head
Holger Wirtz 3 years ago
commit 82d67515fa
  1. 198
      MicroDexed.ino
  2. 30
      UI.hpp
  3. 2
      drums.h
  4. 18
      drumset.h
  5. 30
      sequencer.cpp

@ -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

@ -110,10 +110,11 @@ extern int seq_oct_shift;
extern char arp_style_names[4][3]; extern char arp_style_names[4][3];
extern char seq_chord_names[7][4]; extern char seq_chord_names[7][4];
extern uint8_t seq_data_buffer[16]; extern uint8_t seq_data_buffer[16];
extern uint8_t seq_data[NUM_SEQ_PATTERN][16];
extern float drums_volume; extern float drums_volume;
extern uint8_t drum_midi_channel; extern uint8_t drum_midi_channel;
uint8_t seq_active_function = 99; uint8_t seq_active_function = 99;
uint8_t activesample; extern uint8_t seq_data[10][16]; uint8_t activesample;
#endif #endif
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
@ -646,6 +647,18 @@ void setup_debug_message(void)
} }
#endif #endif
void toggle_sequencer_play_status()
{
if (seq_running == false && seq_recording == false)
{
handleStart();
}
else if (seq_running == true && seq_recording == false)
{
handleStop();
}
}
/*********************************************************************** /***********************************************************************
MENU CONTROL MENU CONTROL
***********************************************************************/ ***********************************************************************/
@ -923,8 +936,12 @@ void lcdml_menu_control(void)
Serial.println(F("ENC-L long recognized")); Serial.println(F("ENC-L long recognized"));
#endif #endif
// when in Voice select Menu, long left-press sets/unsets favorite
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select)) if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select))
save_favorite(configuration.performance.bank[selected_instance_id], configuration.performance.voice[selected_instance_id], selected_instance_id); save_favorite(configuration.performance.bank[selected_instance_id], configuration.performance.voice[selected_instance_id], selected_instance_id);
// when not in Voice select Menu, long left-press starts/stops sequencer
else if (LCDML.FUNC_getID() != LCDML.OTHER_getIDFromFunction(UI_func_voice_select))
toggle_sequencer_play_status();
//for (uint8_t i = 0; i < NUM_DEXED; i++) //for (uint8_t i = 0; i < NUM_DEXED; i++)
// MicroDexed[i]->panic(); // MicroDexed[i]->panic();
@ -4837,7 +4854,7 @@ void seq_clear_active_pattern()
} }
void seq_clear_all_patterns() void seq_clear_all_patterns()
{ {
for (uint8_t i = 0; i < 10; i++) for (uint8_t i = 0; i < NUM_SEQ_PATTERN - 1; i++)
{ {
memset(seq_data[i], 0, sizeof(seq_data[i])); memset(seq_data[i], 0, sizeof(seq_data[i]));
memset(seq_vel[i], 0, sizeof(seq_vel[i])); memset(seq_vel[i], 0, sizeof(seq_vel[i]));
@ -4903,10 +4920,19 @@ void seq_print_current_note()
lcd.print( (seq_data[seq_active_track][seq_menu - 3] / 12) - 1); lcd.print( (seq_data[seq_active_track][seq_menu - 3] / 12) - 1);
lcd.print(" "); lcd.print(" ");
} }
void check_variable_samples_basespeed()
{
for (uint8_t i = 0; i < 6; i++)
{
if (drum_config[i].p_offset == 0)
drum_config[i].p_offset=1;
}
}
void UI_func_seq_pattern_editor(uint8_t param) void UI_func_seq_pattern_editor(uint8_t param)
{ {
if (LCDML.FUNC_setup()) // ****** SETUP ********* if (LCDML.FUNC_setup()) // ****** SETUP *********
{ {
check_variable_samples_basespeed();
lcd.createChar(0, (uint8_t*)special_chars[19]); //play symbol + record symbol switching lcd.createChar(0, (uint8_t*)special_chars[19]); //play symbol + record symbol switching
#ifdef TESTDISPLAY20x4 #ifdef TESTDISPLAY20x4
lcd.createChar(1, (uint8_t*)special_chars[9]); //bar graph lcd.createChar(1, (uint8_t*)special_chars[9]); //bar graph

@ -44,6 +44,6 @@ typedef struct drum_config_s {
float32_t reverb_send; // how much signal to send to the reverb (0.0 - 1.0) float32_t reverb_send; // how much signal to send to the reverb (0.0 - 1.0)
} drum_config_t; } drum_config_t;
enum {DRUM_NONE, DRUM_BASS, DRUM_SNARE, DRUM_HIHAT, DRUM_HANDCLAP, DRUM_RIDE, DRUM_CRASH, DRUM_LOWTOM, DRUM_MIDTOM, DRUM_HIGHTOM, DRUM_PERCUSSION}; enum {DRUM_NONE, DRUM_BASS, DRUM_SNARE, DRUM_HIHAT, DRUM_HANDCLAP, DRUM_RIDE, DRUM_CRASH, DRUM_LOWTOM, DRUM_MIDTOM, DRUM_HIGHTOM, DRUM_PERCUSSION,DRUM_POLY};
#endif #endif

@ -276210,7 +276210,7 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
{ {
#ifdef TEENSY4 #ifdef TEENSY4
{ {
DRUM_HIHAT, DRUM_POLY,
210, 210,
"SQBass", "SQBass",
DRUM_SQBass, DRUM_SQBass,
@ -276224,7 +276224,7 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
0.0 0.0
}, },
{ {
DRUM_MIDTOM, DRUM_POLY,
211, 211,
"CALLIOP", "CALLIOP",
DRUM_CALLIOP, DRUM_CALLIOP,
@ -276238,7 +276238,7 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
0.0 0.0
}, },
{ {
DRUM_CRASH, DRUM_POLY,
212, 212,
"ssaw", "ssaw",
DRUM_ssaw, DRUM_ssaw,
@ -276247,12 +276247,12 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.8, 0.7,
0.0, 0.0,
0.0 0.0
}, },
{ {
DRUM_RIDE, DRUM_POLY,
213, 213,
"ARR1", "ARR1",
DRUM_ARR1, DRUM_ARR1,
@ -276261,12 +276261,12 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.8, 0.7,
0.0, 0.0,
0.0 0.0
}, },
{ {
DRUM_BASS, DRUM_POLY,
214, 214,
"FVoice", "FVoice",
DRUM_FVoice, DRUM_FVoice,
@ -276275,12 +276275,12 @@ drum_config_t drum_config[NUM_DRUMSET_CONFIG] =
0.0, 0.0,
0.0, 0.0,
0.0, 0.0,
0.8, 0.7,
0.0, 0.0,
0.0 0.0
}, },
{ {
DRUM_BASS, DRUM_POLY,
215, 215,
"SlapB-M1", "SlapB-M1",
DRUM_SlapB_M1, DRUM_SlapB_M1,

@ -8,6 +8,8 @@ extern LCDMenuLib2 LCDML;
extern LiquidCrystal_I2C lcd; extern LiquidCrystal_I2C lcd;
extern config_t configuration; extern config_t configuration;
extern uint8_t drum_midi_channel; extern uint8_t drum_midi_channel;
extern uint8_t activesample;
extern uint8_t get_sample_note(uint8_t sample);
extern void handleNoteOn(byte , byte , byte ); extern void handleNoteOn(byte , byte , byte );
extern void handleNoteOff(byte , byte , byte ); extern void handleNoteOff(byte , byte , byte );
extern void UI_func_seq_pattern_editor(uint8_t); extern void UI_func_seq_pattern_editor(uint8_t);
@ -18,6 +20,24 @@ extern float get_sample_vol_max(uint8_t);
extern float get_sample_p_offset(uint8_t); extern float get_sample_p_offset(uint8_t);
boolean interrupt_swapper = false; boolean interrupt_swapper = false;
void seq_live_recording(void)
{
//record to sequencer if sequencer menu is active and recording is active
if (seq_note_in > 0 && seq_recording == true && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_seq_pattern_editor))
{
seq_data[seq_active_track][seq_step] = seq_note_in;
if ( get_sample_note(activesample) > 209 ) // pitched sample
{
seq_vel[seq_active_track][seq_step] = get_sample_note(activesample);
}
else
seq_vel[seq_active_track][seq_step] = seq_note_in_velocity;
seq_note_in = 0;
seq_note_in_velocity = 0;
}
}
void sequencer_part1(void) void sequencer_part1(void)
{ {
//if (seq_note_in > 0 && seq_note_in < 62 && seq_recording == false ) { //if (seq_note_in > 0 && seq_note_in < 62 && seq_recording == false ) {
@ -29,14 +49,7 @@ void sequencer_part1(void)
//seq_note_in = 0; //seq_note_in = 0;
//} //}
//record to sequencer if sequencer menu is active and recording is active seq_live_recording();
if (seq_note_in > 0 && seq_recording == true && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_seq_pattern_editor)) {
seq_data[seq_active_track][seq_step] = seq_note_in;
seq_vel[seq_active_track][seq_step] = seq_note_in_velocity;
seq_note_in = 0;
seq_note_in_velocity = 0;
}
for (uint8_t d = 0; d < NUM_SEQ_TRACKS; d++) for (uint8_t d = 0; d < NUM_SEQ_TRACKS; d++)
{ {
if (seq_patternchain[seq_chain_active_step][d] < NUM_SEQ_PATTERN ) // sequence not empty or muted if (seq_patternchain[seq_chain_active_step][d] < NUM_SEQ_PATTERN ) // sequence not empty or muted
@ -175,6 +188,7 @@ void sequencer_part1(void)
void sequencer_part2(void) void sequencer_part2(void)
{ {
seq_live_recording();
for (uint8_t d = 0; d < NUM_SEQ_TRACKS; d++) for (uint8_t d = 0; d < NUM_SEQ_TRACKS; d++)
{ {
if (seq_noteoffsent[d] == false) { if (seq_noteoffsent[d] == false) {

Loading…
Cancel
Save