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)
{
//Ignore the note when playing & recording the same note into the sequencer
if (seq_recording == false || (seq_recording && inNumber != seq_note_in ))
#if NUM_DRUMS > 0
if (activesample < 6 && seq_running == false && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_seq_pattern_editor) ) // live play pitched sample
{
// Check for MicroDexed
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
if (drum_counter >= NUM_DRUMS)
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)
MicroDexed[instance_id]->keydown(inNumber, uint8_t(float(configuration.dexed[instance_id].velocity_level / 127.0)*inVelocity + 0.5));
if (inNumber >= configuration.dexed[instance_id].lowest_note && inNumber <= configuration.dexed[instance_id].highest_note)
{
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
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select))
{
midi_decay_timer = 0;
midi_decay[instance_id] = min(inVelocity / 5, 7);
}
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select))
{
midi_decay_timer = 0;
midi_decay[instance_id] = min(inVelocity / 5, 7);
}
#endif
#ifdef DEBUG
char note_name[4];
getNoteName(note_name, inNumber);
Serial.print(F("Keydown "));
Serial.print(note_name);
Serial.print(F(" instance "));
Serial.print(instance_id, DEC);
Serial.print(F(" MIDI-channel "));
Serial.print(inChannel, DEC);
Serial.println();
char note_name[4];
getNoteName(note_name, inNumber);
Serial.print(F("Keydown "));
Serial.print(note_name);
Serial.print(F(" instance "));
Serial.print(instance_id, DEC);
Serial.print(F(" MIDI-channel "));
Serial.print(inChannel, DEC);
Serial.println();
#endif
return;
return;
}
}
}
}
#if NUM_DRUMS > 0
// Check for Drum
if (inChannel == drum_midi_channel)
{
if (drum_counter >= NUM_DRUMS)
drum_counter = 0;
// Check for Drum
if (inChannel == drum_midi_channel)
{
if (drum_counter >= NUM_DRUMS)
drum_counter = 0;
#ifdef DEBUG
char note_name[4];
getNoteName(note_name, inNumber);
Serial.print(F("=> Drum["));
Serial.print(drum_counter, DEC);
Serial.print(F("]: "));
Serial.println(note_name);
char note_name[4];
getNoteName(note_name, inNumber);
Serial.print(F("=> Drum["));
Serial.print(drum_counter, DEC);
Serial.print(F("]: "));
Serial.println(note_name);
#endif
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG; d++)
{
if (inNumber == drum_config[d].midinote)
for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG; d++)
{
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);
if (inNumber == 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);
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_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)));
#ifdef USE_FX
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_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));
#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)
if (drum_config[d].drum_data != NULL && drum_config[d].len > 0)
{
Drum[slot]->enableInterpolation(true);
Drum[slot]->setPlaybackRate(drum_config[d].pitch);
//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);
}
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
Serial.print(F("Drum "));
Serial.print(drum_config[d].shortname);
Serial.print(F(" ["));
Serial.print(drum_config[d].name);
Serial.print(F("], Slot "));
Serial.print(slot);
Serial.print(F(": V"));
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(pan, 2);
Serial.print(F(" RS"));
Serial.println(drum_config[d].reverb_send, 2);
Serial.print(F("Drum "));
Serial.print(drum_config[d].shortname);
Serial.print(F(" ["));
Serial.print(drum_config[d].name);
Serial.print(F("], Slot "));
Serial.print(slot);
Serial.print(F(": V"));
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(pan, 2);
Serial.print(F(" RS"));
Serial.println(drum_config[d].reverb_send, 2);
#endif
break;
break;
}
}
}
}
#endif
}
}
}
#if NUM_DRUMS > 0
@ -887,29 +909,29 @@ uint8_t drum_get_slot(uint8_t dt)
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);
}
}
// 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 % 4);
Serial.println(drum_counter % NUM_DRUMS);
#endif
drum_type[drum_counter % 4] = dt;
drum_type[drum_counter % NUM_DRUMS] = dt;
drum_counter++;
return (drum_counter - 1 % 4);
return (drum_counter - 1 % NUM_DRUMS);
}
#endif

@ -110,10 +110,11 @@ extern int seq_oct_shift;
extern char arp_style_names[4][3];
extern char seq_chord_names[7][4];
extern uint8_t seq_data_buffer[16];
extern uint8_t seq_data[NUM_SEQ_PATTERN][16];
extern float drums_volume;
extern uint8_t drum_midi_channel;
uint8_t seq_active_function = 99;
uint8_t activesample; extern uint8_t seq_data[10][16];
uint8_t activesample;
#endif
#ifdef DISPLAY_LCD_SPI
@ -646,6 +647,18 @@ void setup_debug_message(void)
}
#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
***********************************************************************/
@ -923,8 +936,12 @@ void lcdml_menu_control(void)
Serial.println(F("ENC-L long recognized"));
#endif
// when in Voice select Menu, long left-press sets/unsets favorite
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);
// 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++)
// MicroDexed[i]->panic();
@ -4837,7 +4854,7 @@ void seq_clear_active_pattern()
}
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_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(" ");
}
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)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
check_variable_samples_basespeed();
lcd.createChar(0, (uint8_t*)special_chars[19]); //play symbol + record symbol switching
#ifdef TESTDISPLAY20x4
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)
} 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

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

@ -8,6 +8,8 @@ extern LCDMenuLib2 LCDML;
extern LiquidCrystal_I2C lcd;
extern config_t configuration;
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 handleNoteOff(byte , byte , byte );
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);
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)
{
//if (seq_note_in > 0 && seq_note_in < 62 && seq_recording == false ) {
@ -29,14 +49,7 @@ void sequencer_part1(void)
//seq_note_in = 0;
//}
//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;
seq_vel[seq_active_track][seq_step] = seq_note_in_velocity;
seq_note_in = 0;
seq_note_in_velocity = 0;
}
seq_live_recording();
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
@ -175,6 +188,7 @@ void sequencer_part1(void)
void sequencer_part2(void)
{
seq_live_recording();
for (uint8_t d = 0; d < NUM_SEQ_TRACKS; d++)
{
if (seq_noteoffsent[d] == false) {

Loading…
Cancel
Save