Added sending of a single voice via MIDI sysex.

pull/32/head
Holger Wirtz 5 years ago
parent 1bbfed551e
commit 60f3ff7a7e
  1. 128
      UI.hpp
  2. 17
      UI_FX.h
  3. 17
      UI_NO_FX.h
  4. 15
      dexed.cpp
  5. 2
      dexed.h
  6. 2
      dexed_sd.cpp
  7. 27
      midi_devices.hpp

128
UI.hpp

@ -93,6 +93,8 @@ extern char sd_string[LCD_cols + 1];
extern char g_voice_name[NUM_DEXED][VOICE_NAME_LEN]; extern char g_voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char g_bank_name[NUM_DEXED][BANK_NAME_LEN]; extern char g_bank_name[NUM_DEXED][BANK_NAME_LEN];
extern void send_sysex_voice(uint8_t midi_channel, uint8_t* data);
/*********************************************************************** /***********************************************************************
GLOBAL GLOBAL
************************************************************************/ ************************************************************************/
@ -248,7 +250,6 @@ void UI_func_velocity_level(uint8_t param);
void UI_func_voice_select(uint8_t param); void UI_func_voice_select(uint8_t param);
void UI_func_sysex_send_voice(uint8_t param); void UI_func_sysex_send_voice(uint8_t param);
void UI_func_sysex_receive_voice(uint8_t param); void UI_func_sysex_receive_voice(uint8_t param);
void UI_func_save_voice(uint8_t param);
void UI_func_sysex_receive_bank(uint8_t param); void UI_func_sysex_receive_bank(uint8_t param);
void UI_func_sysex_send_bank(uint8_t param); void UI_func_sysex_send_bank(uint8_t param);
void UI_func_eq_bass(uint8_t param); void UI_func_eq_bass(uint8_t param);
@ -4935,7 +4936,7 @@ void UI_func_sysex_send_bank(uint8_t param)
{ {
encoderDir[ENC_R].reset(); encoderDir[ENC_R].reset();
if (bank_number != 0xff) if (bank_number < 0xff)
{ {
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
lcd.print(F("Canceled. ")); lcd.print(F("Canceled. "));
@ -4946,33 +4947,144 @@ void UI_func_sysex_send_bank(uint8_t param)
void UI_func_sysex_send_voice(uint8_t param) void UI_func_sysex_send_voice(uint8_t param)
{ {
static uint8_t mode;
static uint8_t bank_number;
static uint8_t voice_number;
if (LCDML.FUNC_setup()) // ****** SETUP ********* if (LCDML.FUNC_setup()) // ****** SETUP *********
{ {
encoderDir[ENC_R].reset(); encoderDir[ENC_R].reset();
mode = 0;
bank_number = configuration.performance.bank[selected_instance_id];
voice_number = configuration.performance.voice[selected_instance_id];
char bank_name[BANK_NAME_LEN];
if (!get_bank_name(bank_number, bank_name, sizeof(bank_name)))
strcpy(bank_name, "*ERROR*");
lcd.setCursor(0, 0); lcd.setCursor(0, 0);
lcd.print(F("MIDI Send Voice")); lcd.print(F("MIDI Send Voice"));
lcd.setCursor(0, 1); lcd.show(1, 0, 2, bank_number);
lcd.print(F("Not implemented.")); lcd.show(1, 4, 10, bank_name);
lcd.show(1, 2, 2, " [");
lcd.show(1, 14, 1, "]");
} }
if (LCDML.FUNC_loop()) // ****** LOOP ********* if (LCDML.FUNC_loop()) // ****** LOOP *********
{ {
char bank_name[BANK_NAME_LEN];
char voice_name[VOICE_NAME_LEN];
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()))
{ {
if (LCDML.BT_checkDown()) switch (mode)
{ {
; case 0: // Bank selection
if (LCDML.BT_checkDown())
bank_number = constrain(bank_number + ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1);
else if (LCDML.BT_checkUp() && bank_number > 0)
bank_number = constrain(bank_number - ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1);
if (!get_bank_name(bank_number, bank_name, sizeof(bank_name)))
strcpy(bank_name, "*ERROR*");
lcd.show(1, 0, 2, bank_number);
lcd.show(1, 4, 10, bank_name);
break;
case 1: // Voice selection
if (LCDML.BT_checkDown() && voice_number < MAX_VOICES - 1)
voice_number = constrain(voice_number + ENCODER[ENC_R].speed(), 0, MAX_VOICES - 1);
else if (LCDML.BT_checkUp() && voice_number > 0)
voice_number = constrain(voice_number - ENCODER[ENC_R].speed(), 0, MAX_VOICES - 1);
if (!get_bank_name(bank_number, bank_name, sizeof(bank_name)))
strncpy(bank_name, "*ERROR*", sizeof(bank_name));
if (!get_voice_by_bank_name(bank_number, bank_name, voice_number, voice_name, sizeof(voice_name)))
strncpy(voice_name, "*ERROR*", sizeof(voice_name));
lcd.show(1, 0, 2, voice_number + 1);
lcd.show(1, 4, 10, voice_name);
break;
} }
else if (LCDML.BT_checkUp()) }
else if (LCDML.BT_checkEnter())
{
if (encoderDir[ENC_R].ButtonShort())
mode++;
switch (mode)
{ {
; case 1:
if (!get_bank_name(bank_number, bank_name, sizeof(bank_name)))
strncpy(bank_name, "*ERROR*", sizeof(bank_name));
if (!get_voice_by_bank_name(bank_number, bank_name, voice_number, voice_name, sizeof(voice_name)))
strncpy(voice_name, "*ERROR*", sizeof(voice_name));
lcd.show(1, 0, 2, voice_number + 1);
lcd.show(1, 4, 10, voice_name);
break;
case 2:
File sysex;
char filename[FILENAME_LEN];
if (get_bank_name(bank_number, bank_name, sizeof(bank_name)))
{
sprintf(filename, "/%d/%s.syx", bank_number, bank_name);
#ifdef DEBUG
Serial.print(F("Send voice "));
Serial.print(voice_number);
Serial.print(F(" of "));
Serial.print(filename);
Serial.println(F(" from SD."));
#endif
sysex = SD.open(filename);
if (!sysex)
{
#ifdef DEBUG
Serial.println(F("Connot read from SD."));
#endif
lcd.show(1, 0, 16, "Read error.");
bank_number = 0xff;
}
else
{
uint8_t voice_data[155];
uint8_t encoded_voice_data[128];
sysex.seek(6 + (voice_number * 128));
sysex.read(encoded_voice_data, 128);
MicroDexed[selected_instance_id]->decodeVoice(encoded_voice_data, voice_data);
lcd.show(1, 0, 16, "Sending...");
send_sysex_voice(configuration.dexed[selected_instance_id].midi_channel, voice_data);
lcd.show(1, 0, 16, "Done.");
sysex.close();
bank_number = 0xff;
}
}
else
{
lcd.show(1, 0, 16, "No voice.");
bank_number = 0xff;
}
mode = 0xff;
delay(MESSAGE_WAIT_TIME);
LCDML.FUNC_goBackToMenu();
break;
} }
} }
} }
if (LCDML.FUNC_close()) // ****** STABLE END ********* if (LCDML.FUNC_close()) // ****** STABLE END *********
{ {
if (mode < 0xff)
{
lcd.show(1, 0, 16, "Canceled.");
delay(MESSAGE_WAIT_TIME);
}
encoderDir[ENC_R].reset(); encoderDir[ENC_R].reset();
} }
} }

@ -104,12 +104,13 @@ LCDML_add(75, LCDML_0_3_3, 1, "Load Effects", UI_func_load_fx);
LCDML_add(76, LCDML_0_3_3, 2, "Save Effects", UI_func_save_fx); LCDML_add(76, LCDML_0_3_3, 2, "Save Effects", UI_func_save_fx);
LCDML_add(77, LCDML_0_3, 5, "MIDI", NULL); LCDML_add(77, LCDML_0_3, 5, "MIDI", NULL);
LCDML_add(78, LCDML_0_3_5, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank); LCDML_add(78, LCDML_0_3_5, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank);
LCDML_add(79, LCDML_0_3_5, 2, "MIDI Send Bank", UI_func_sysex_send_bank); LCDML_add(79, LCDML_0_3_5, 2, "MIDI Snd Bank", UI_func_sysex_send_bank);
LCDML_add(80, LCDML_0, 4, "System", NULL); LCDML_add(80, LCDML_0_3_5, 3, "MIDI Snd Voice", UI_func_sysex_send_voice);
LCDML_add(81, LCDML_0_4, 1, "Volume", UI_func_volume); LCDML_add(81, LCDML_0, 4, "System", NULL);
LCDML_add(82, LCDML_0_4, 2, "Stereo/Mono", UI_func_stereo_mono); LCDML_add(82, LCDML_0_4, 1, "Volume", UI_func_volume);
LCDML_add(83, LCDML_0_4, 3, "MIDI Soft THRU", UI_func_midi_soft_thru); LCDML_add(83, LCDML_0_4, 2, "Stereo/Mono", UI_func_stereo_mono);
LCDML_add(84, LCDML_0_4, 4, "EEPROM Reset", UI_func_eeprom_reset); LCDML_add(84, LCDML_0_4, 3, "MIDI Soft THRU", UI_func_midi_soft_thru);
LCDML_add(85, LCDML_0, 6, "Info", UI_func_information); LCDML_add(85, LCDML_0_4, 4, "EEPROM Reset", UI_func_eeprom_reset);
#define _LCDML_DISP_cnt 85 LCDML_add(86, LCDML_0, 6, "Info", UI_func_information);
#define _LCDML_DISP_cnt 86
#endif #endif

@ -80,13 +80,14 @@ LCDML_add(51, LCDML_0_2_2, 1, "Load Voice Cfg", UI_func_load_voiceconfig);
LCDML_add(52, LCDML_0_2_2, 2, "Save Voice Cfg", UI_func_save_voiceconfig); LCDML_add(52, LCDML_0_2_2, 2, "Save Voice Cfg", UI_func_save_voiceconfig);
LCDML_add(53, LCDML_0_2, 4, "MIDI", NULL); LCDML_add(53, LCDML_0_2, 4, "MIDI", NULL);
LCDML_add(54, LCDML_0_2_4, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank); LCDML_add(54, LCDML_0_2_4, 1, "MIDI Recv Bank", UI_func_sysex_receive_bank);
LCDML_add(55, LCDML_0_2_4, 2, "MIDI Send Bank", UI_func_sysex_send_bank); LCDML_add(55, LCDML_0_2_4, 2, "MIDI Snd Bank", UI_func_sysex_send_bank);
LCDML_add(56, LCDML_0, 3, "System", NULL); LCDML_add(56, LCDML_0_2_4, 3, "MIDI Snd Voice", UI_func_sysex_send_voice);
LCDML_add(57, LCDML_0_3, 1, "Volume", UI_func_volume); LCDML_add(57, LCDML_0, 3, "System", NULL);
LCDML_add(58, LCDML_0_3, 2, "Stereo/Mono", UI_func_stereo_mono); LCDML_add(58, LCDML_0_3, 1, "Volume", UI_func_volume);
LCDML_add(59, LCDML_0_3, 3, "MIDI Soft THRU", UI_func_midi_soft_thru); LCDML_add(59, LCDML_0_3, 2, "Stereo/Mono", UI_func_stereo_mono);
LCDML_add(60, LCDML_0_3, 4, "EEPROM Reset", UI_func_eeprom_reset); LCDML_add(60, LCDML_0_3, 3, "MIDI Soft THRU", UI_func_midi_soft_thru);
LCDML_add(61, LCDML_0, 4, "Info", UI_func_information); LCDML_add(61, LCDML_0_3, 4, "EEPROM Reset", UI_func_eeprom_reset);
#define _LCDML_DISP_cnt 61 LCDML_add(62, LCDML_0, 4, "Info", UI_func_information);
#define _LCDML_DISP_cnt 62
#endif #endif

@ -510,9 +510,9 @@ uint8_t Dexed::getNumNotesPlaying(void)
return (count_playing_voices); return (count_playing_voices);
} }
bool Dexed::decodeVoice(uint8_t* encoded_data) bool Dexed::decodeVoice(uint8_t* encoded_data,uint8_t* new_data)
{ {
uint8_t* p_data = data; uint8_t* p_data = new_data;
uint8_t op; uint8_t op;
uint8_t tmp; uint8_t tmp;
char dexed_voice_name[11]; char dexed_voice_name[11];
@ -532,7 +532,7 @@ bool Dexed::decodeVoice(uint8_t* encoded_data)
// DEXED_OP_LEV_SCL_BRK_PT, // 8 // DEXED_OP_LEV_SCL_BRK_PT, // 8
// DEXED_OP_SCL_LEFT_DEPTH, // 9 // DEXED_OP_SCL_LEFT_DEPTH, // 9
// DEXED_OP_SCL_RGHT_DEPTH, // 10 // DEXED_OP_SCL_RGHT_DEPTH, // 10
memcpy(&data[op * 21], &encoded_data[op * 17], 11); memcpy(&new_data[op * 21], &encoded_data[op * 17], 11);
tmp = encoded_data[(op * 17) + 11]; tmp = encoded_data[(op * 17) + 11];
*(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) = (tmp & 0x03); *(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) = (tmp & 0x03);
*(p_data + DEXED_OP_SCL_RGHT_CURVE + (op * 21)) = (tmp & 0x0c) >> 2; *(p_data + DEXED_OP_SCL_RGHT_CURVE + (op * 21)) = (tmp & 0x0c) >> 2;
@ -556,7 +556,7 @@ bool Dexed::decodeVoice(uint8_t* encoded_data)
// DEXED_PITCH_EG_L2, // 5 // DEXED_PITCH_EG_L2, // 5
// DEXED_PITCH_EG_L3, // 6 // DEXED_PITCH_EG_L3, // 6
// DEXED_PITCH_EG_L4, // 7 // DEXED_PITCH_EG_L4, // 7
memcpy(&data[DEXED_VOICE_OFFSET], &encoded_data[102], 8); memcpy(&new_data[DEXED_VOICE_OFFSET], &encoded_data[102], 8);
tmp = encoded_data[110]; tmp = encoded_data[110];
*(p_data + DEXED_VOICE_OFFSET + DEXED_ALGORITHM) = (tmp & 0x1f); *(p_data + DEXED_VOICE_OFFSET + DEXED_ALGORITHM) = (tmp & 0x1f);
tmp = encoded_data[111]; tmp = encoded_data[111];
@ -566,23 +566,22 @@ bool Dexed::decodeVoice(uint8_t* encoded_data)
// DEXED_LFO_DELAY, // 12 // DEXED_LFO_DELAY, // 12
// DEXED_LFO_PITCH_MOD_DEP, // 13 // DEXED_LFO_PITCH_MOD_DEP, // 13
// DEXED_LFO_AMP_MOD_DEP, // 14 // DEXED_LFO_AMP_MOD_DEP, // 14
memcpy(&data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], &encoded_data[112], 4); memcpy(&new_data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], &encoded_data[112], 4);
tmp = encoded_data[116]; tmp = encoded_data[116];
*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS) = (tmp & 0x30) >> 4; *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS) = (tmp & 0x30) >> 4;
*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_WAVE) = (tmp & 0x0e) >> 1; *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_WAVE) = (tmp & 0x0e) >> 1;
*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_SYNC) = (tmp & 0x01); *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_SYNC) = (tmp & 0x01);
*(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = encoded_data[117]; *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = encoded_data[117];
memcpy(&data[DEXED_VOICE_OFFSET + DEXED_NAME], &encoded_data[118], 10); memcpy(&new_data[DEXED_VOICE_OFFSET + DEXED_NAME], &encoded_data[118], 10);
panic(); panic();
doRefreshVoice(); doRefreshVoice();
//activate();
strncpy(dexed_voice_name, (char *)&encoded_data[118], sizeof(dexed_voice_name) - 1); strncpy(dexed_voice_name, (char *)&encoded_data[118], sizeof(dexed_voice_name) - 1);
dexed_voice_name[10] = '\0'; dexed_voice_name[10] = '\0';
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Voice [")); Serial.print(F("Voice ["));
Serial.print(dexed_voice_name); Serial.print(dexed_voice_name);
Serial.println(F("] loaded.")); Serial.println(F("] decoded."));
#endif #endif
return (true); return (true);

@ -158,7 +158,7 @@ class Dexed
uint8_t getMaxNotes(void); uint8_t getMaxNotes(void);
void doRefreshVoice(void); void doRefreshVoice(void);
void setOPs(uint8_t ops); void setOPs(uint8_t ops);
bool decodeVoice(uint8_t* encoded_data); bool decodeVoice(uint8_t* encoded_data, uint8_t* data);
bool encodeVoice(uint8_t* encoded_data); bool encodeVoice(uint8_t* encoded_data);
bool getVoiceData(uint8_t* data_copy); bool getVoiceData(uint8_t* data_copy);
bool loadVoiceParameters(uint8_t* data); bool loadVoiceParameters(uint8_t* data);

@ -71,7 +71,7 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id)
Serial.print(voice_name); Serial.print(voice_name);
Serial.println(F("]")); Serial.println(F("]"));
#endif #endif
bool ret = MicroDexed[instance_id]->decodeVoice(data); bool ret = MicroDexed[instance_id]->decodeVoice(data,MicroDexed[instance_id]->data);
#ifdef DEBUG #ifdef DEBUG
show_patch(instance_id); show_patch(instance_id);
#endif #endif

@ -1674,27 +1674,26 @@ void check_midi_devices(void)
void send_sysex_voice(uint8_t midi_channel, uint8_t* data) void send_sysex_voice(uint8_t midi_channel, uint8_t* data)
{ {
uint8_t checksum = 0; uint8_t checksum = 0;
uint8_t voice_data[161]; uint8_t vd[161];
// Send SYSEX data also via MIDI // Send SYSEX data also via MIDI
//voice_data[0] = 0xF0; // SysEx start //vd[0] = 0xF0; // SysEx start
voice_data[0] = 0x43; // ID=Yamaha vd[0] = 0x43; // ID=Yamaha
voice_data[1] = midi_channel; // Sub-status and MIDI channel vd[1] = midi_channel; // Sub-status and MIDI channel
voice_data[2] = 0x00; // Format number (0=1 voice) vd[2] = 0x00; // Format number (0=1 voice)
voice_data[3] = 0x01; // Byte count MSB vd[3] = 0x01; // Byte count MSB
voice_data[4] = 0x1B; // Byte count LSB vd[4] = 0x1B; // Byte count LSB
for (uint8_t n = 0; n < 155; n++) for (uint8_t n = 0; n < 155; n++)
{ {
checksum -= data[n]; checksum -= data[n];
voice_data[5 + n] = data[n]; vd[5 + n] = data[n];
} }
checksum &= 0x7f; vd[160] = checksum & 0x7f; // Checksum
voice_data[160] = checksum; // Checksum //vd[162] = 0xF7; // SysEx end
//voice_data[162] = 0xF7; // SysEx end
midi_serial.sendSysEx(161, voice_data); // Send to DIN MIDI midi_serial.sendSysEx(161, vd); // Send to DIN MIDI
midi_usb.sendSysEx(161, voice_data); // Send to USB MIDI midi_usb.sendSysEx(161, vd); // Send to USB MIDI
usbMIDI.sendSysEx(161, voice_data); // Send to USB-HOST MIDI usbMIDI.sendSysEx(161, vd); // Send to USB-HOST MIDI
} }
void send_sysex_bank(uint8_t midi_channel, uint8_t* bank_data) void send_sysex_bank(uint8_t midi_channel, uint8_t* bank_data)

Loading…
Cancel
Save