Added direct voice/bankname reading from SD instead of caching.

Fixes.
pull/32/head
Holger Wirtz 4 years ago
parent 161f77c3e2
commit 11b2afb949
  1. 56
      MicroDexed.ino
  2. 79
      UI.hpp
  3. 2
      config.h
  4. 225
      dexed_sd.cpp
  5. 12
      dexed_sd.h

@ -194,12 +194,6 @@ void create_audio_connections(AudioSourceMicroDexed &dexed, AudioEffectMonoStere
uint8_t sd_card = 0;
Sd2Card card;
SdVolume volume;
uint8_t max_loaded_banks = 0;
char bank_name[NUM_DEXED][BANK_NAME_LEN];
char voice_name[NUM_DEXED][VOICE_NAME_LEN];
char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
uint8_t dexed_setup_number = 1;
uint8_t midi_timing_counter = 0; // 24 per qarter
elapsedMillis midi_timing_timestep;
uint16_t midi_timing_quarter = 0;
@ -375,11 +369,6 @@ void setup()
#ifdef DEBUG
Serial.println(F("SD card not accessable."));
#endif
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
strcpy(bank_name[instance_id], "Default");
strcpy(voice_name[instance_id], "Default");
}
}
else
{
@ -387,30 +376,6 @@ void setup()
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
// read all bank names
max_loaded_banks = get_bank_names(instance_id);
strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]);
// read all voice name for actual bank
get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id);
#ifdef DEBUG
Serial.print(F("Bank ["));
Serial.print(bank_names[instance_id][configuration.performance.bank[instance_id]]);
Serial.print(F("/"));
Serial.print(bank_name[instance_id]);
Serial.println(F("]"));
for (uint8_t n = 0; n < MAX_VOICES - 1; n++)
{
if (n < 10)
Serial.print(F(" "));
Serial.print(F(" "));
Serial.print(n, DEC);
Serial.print(F("["));
Serial.print(voice_names[instance_id][n]);
Serial.println(F("]"));
}
#endif
// load default SYSEX data
load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id);
}
@ -986,13 +951,13 @@ void handleSystemExclusive(byte * sysex, uint len)
// load sysex-data into voice memory
MicroDexed[instance_id]->loadVoiceParameters(&sysex[6]);
//MicroDexed[instance_id]->initGlobalParameters();
// manipulate UI names and numbers
strncpy(voice_name[instance_id], (char *)&sysex[151], sizeof(voice_name[instance_id]) - 1);
Serial.print(F("Got voice ["));
Serial.print(voice_name[instance_id]);
Serial.println(F("]."));
/*
// manipulate UI names and numbers
strncpy(voice_name[instance_id], (char *)&sysex[151], sizeof(voice_name[instance_id]) - 1);
Serial.print(F("Got voice ["));
Serial.print(voice_name[instance_id]);
Serial.println(F("]."));*/
}
#ifdef DEBUG
else
@ -1245,7 +1210,7 @@ void check_configuration(void)
configuration.sys.mono = constrain(configuration.sys.mono, MONO_MIN, MONO_MAX);
configuration.sys.soft_midi_thru = constrain(configuration.sys.soft_midi_thru, SOFT_MIDI_THRU_MIN, SOFT_MIDI_THRU_MAX);
configuration.sys.performance_number = constrain(configuration.sys.performance_number, PERFORMANCE_NUM_MIN, PERFORMANCE_NUM_MAX);
configuration.performance.fx_number = constrain(configuration.performance.fx_number, FX_NUM_MIN, FX_NUM_MAX);
configuration.fx.reverb_roomsize = constrain(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX);
@ -1337,10 +1302,9 @@ void init_configuration(void)
configuration.fx.delay_feedback = DELAY_FEEDBACK_DEFAULT;
configuration.fx.delay_level = DELAY_LEVEL_DEFAULT;
//configuration.performance.checksum = 0xffff;
configuration.performance.fx_number = FX_NUM_DEFAULT;
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
for (uint8_t instance_id = 0; instance_id < MAX_DEXED; instance_id++)
{
configuration.performance.bank[instance_id] = SYSEXBANK_DEFAULT;
configuration.performance.voice[instance_id] = SYSEXSOUND_DEFAULT;
@ -1828,8 +1792,8 @@ void check_and_create_directories(void)
}
}
#ifdef DEBUG
#else
Serial.println(F("No SD card for directory check available."));
else
Serial.println(F("No SD card for directory check available."));
#endif
}

@ -47,15 +47,7 @@
#define _LCDML_DISP_cfg_scrollbar 1 // enable a scrollbar
extern config_t configuration;
extern uint8_t dexed_setup_number;
extern void set_volume(uint8_t v, uint8_t m);
extern char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
extern char bank_name[NUM_DEXED][BANK_NAME_LEN];
extern char voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
extern void strip_extension(char* s, char *target);
//extern void eeprom_write(void);
extern bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id);
extern bool load_sysex(uint8_t b, uint8_t v);
extern void generate_version_string(char* buffer, uint8_t len);
extern void initial_values_from_eeprom(bool init);
@ -3197,7 +3189,7 @@ void UI_func_eeprom_reset(uint8_t param)
void UI_func_voice_select(uint8_t param)
{
uint8_t instance_id = 0;
static uint8_t menu_voice_select = MENU_VOICE_SOUND;
static uint8_t menu_voice_select = MENU_VOICE_SOUND;
if (LCDML.FUNC_getID() > MENU_ID_OF_INSTANCE_2)
instance_id = 1;
@ -3206,12 +3198,18 @@ void UI_func_voice_select(uint8_t param)
{
encoderDir[ENC_R].reset();
strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]);
char bank_name[BANK_NAME_LEN];
char voice_name[VOICE_NAME_LEN];
if (!get_bank_name(configuration.performance.bank[instance_id], bank_name, sizeof(bank_name)))
strncpy(bank_name, "*ERROR*", sizeof(bank_name));
if (!get_voice_by_bank_name(configuration.performance.bank[instance_id], bank_name, configuration.performance.voice[instance_id], voice_name, sizeof(voice_name)))
strncpy(voice_name, "*ERROR*", sizeof(voice_name));
lcd.show(0, 0, 2, configuration.performance.bank[instance_id]);
lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1);
lcd.show(0, 4, 10, bank_name[instance_id]);
lcd.show(1, 4, 10, voice_names[instance_id][configuration.performance.voice[instance_id]]);
lcd.show(0, 4, 10, bank_name);
lcd.show(1, 4, 10, voice_name);
switch (menu_voice_select)
{
@ -3232,12 +3230,16 @@ void UI_func_voice_select(uint8_t param)
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()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
uint8_t bank_tmp;
int8_t voice_tmp;
if (LCDML.BT_checkUp())
{
switch (menu_voice_select)
{
case MENU_VOICE_BANK:
@ -3247,7 +3249,6 @@ void UI_func_voice_select(uint8_t param)
change_disp_sd(false);
#endif
load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(true);
#endif
@ -3265,18 +3266,18 @@ void UI_func_voice_select(uint8_t param)
}
if (voice_tmp < 0)
voice_tmp = MAX_VOICES + voice_tmp;
configuration.performance.voice[instance_id] = voice_tmp;
configuration.performance.voice[instance_id] = constrain(voice_tmp, 0, MAX_VOICES - 1);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(false);
#endif
load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(true);
#endif
break;
}
}
else if (LCDML.BT_checkDown())
{
switch (menu_voice_select)
@ -3288,7 +3289,6 @@ void UI_func_voice_select(uint8_t param)
change_disp_sd(false);
#endif
load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(true);
#endif
@ -3305,18 +3305,16 @@ void UI_func_voice_select(uint8_t param)
{
voice_tmp = MAX_VOICES - 1;
}
configuration.performance.voice[instance_id] = voice_tmp;
configuration.performance.voice[instance_id] = constrain(voice_tmp, 0, MAX_VOICES - 1);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(false);
#endif
load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id);
get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id);
#ifdef DISPLAY_LCD_SPI
change_disp_sd(true);
#endif
break;
}
}
else if (LCDML.BT_checkEnter())
@ -3326,29 +3324,32 @@ void UI_func_voice_select(uint8_t param)
else
menu_voice_select = MENU_VOICE_BANK;
}
}
strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]);
if (!get_bank_name(configuration.performance.bank[instance_id], bank_name, sizeof(bank_name)))
strncpy(bank_name, "*ERROR*", sizeof(bank_name));
if (!get_voice_by_bank_name(configuration.performance.bank[instance_id], bank_name, configuration.performance.voice[instance_id], voice_name, sizeof(voice_name)))
strncpy(voice_name, "*ERROR*", sizeof(voice_name));
lcd.show(0, 0, 2, configuration.performance.bank[instance_id]);
lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1);
lcd.show(0, 4, 10, bank_name[instance_id]);
lcd.show(1, 4, 10, voice_names[instance_id][configuration.performance.voice[instance_id]]);
lcd.show(0, 0, 2, configuration.performance.bank[instance_id]);
lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1);
lcd.show(0, 4, 10, bank_name);
lcd.show(1, 4, 10, voice_name);
switch (menu_voice_select)
{
case MENU_VOICE_BANK:
lcd.show(0, 2, 2, " [");
lcd.show(0, 14, 1, "]");
lcd.show(1, 2, 2, " ");
lcd.show(1, 14, 1, " ");
break;
case MENU_VOICE_SOUND:
lcd.show(0, 2, 2, " ");
lcd.show(0, 14, 1, " ");
lcd.show(1, 2, 2, " [");
lcd.show(1, 14, 1, "]");
break;
}
switch (menu_voice_select)
{
case MENU_VOICE_BANK:
lcd.show(0, 2, 2, " [");
lcd.show(0, 14, 1, "]");
lcd.show(1, 2, 2, " ");
lcd.show(1, 14, 1, " ");
break;
case MENU_VOICE_SOUND:
lcd.show(0, 2, 2, " ");
lcd.show(0, 14, 1, " ");
lcd.show(1, 2, 2, " [");
lcd.show(1, 14, 1, "]");
break;
}
}

@ -224,7 +224,7 @@
#define MAX_FX 99
#define MAX_PERFORMANCE 99
#define MAX_VOICECONFIG 99
#define BANK_NAME_LEN 13 // FAT12 filenames (plus '\0')
#define BANK_NAME_LEN 11 // 10 (plus '\0')
#define VOICE_NAME_LEN 11 // 10 (plus '\0')
#define FILENAME_LEN BANK_NAME_LEN + VOICE_NAME_LEN

@ -46,9 +46,11 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id)
{
File sysex;
char filename[FILENAME_LEN];
char bank_name[BANK_NAME_LEN];
uint8_t data[128];
sprintf(filename, "/%d/%s", b, bank_names[instance_id][b]);
get_bank_name(b, bank_name, sizeof(bank_name));
sprintf(filename, "/%d/%s.syx", b, bank_name);
sysex = SD.open(filename);
if (!sysex)
@ -64,10 +66,12 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id)
if (get_sd_voice(sysex, v, data))
{
#ifdef DEBUG
char voice_name[VOICE_NAME_LEN];
get_voice_name(b, v, voice_name, sizeof(voice_name));
Serial.print(F("Loading voice from "));
Serial.print(filename);
Serial.print(F(" ["));
Serial.print(voice_names[instance_id][v]);
Serial.print(voice_name);
Serial.println(F("]"));
#endif
bool ret = MicroDexed[instance_id]->decodeVoice(data);
@ -83,6 +87,7 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id)
else
Serial.println(F("E : Cannot load voice data"));
#endif
sysex.close();
}
#ifdef DEBUG
if (found == false)
@ -615,25 +620,9 @@ uint8_t calc_checksum(uint8_t* data, uint16_t len)
return (bulk_checksum_calc & 0x7f);
}
void create_sd_voiceconfig_filename(char* filename, uint8_t b, uint8_t instance_id)
{
// init and set name for actual bank
memset(filename, 0, FILENAME_LEN);
sprintf(filename, "/%d/%s", b, bank_names[instance_id][b]);
#ifdef DEBUG
Serial.print(F("Created filename from bank "));
Serial.print(b, DEC);
Serial.print(F(" and name "));
Serial.print(bank_names[instance_id][b]);
Serial.print(F(": ["));
Serial.print(filename);
Serial.println(F("]"));
#endif
}
void strip_extension(char* s, char* target)
{
char tmp[BANK_NAME_LEN];
char tmp[FILENAME_LEN];
char* token;
strcpy(tmp, s);
@ -644,152 +633,136 @@ void strip_extension(char* s, char* target)
strcpy(target, token);
}
bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id)
bool get_bank_name(uint8_t b, char* name, uint8_t len)
{
File sysex;
uint8_t voice_counter = 0;
int32_t bulk_checksum_calc = 0;
int8_t bulk_checksum;
b = constrain(b, 0, MAX_BANKS - 1);
// erase all data for voice names
memset(voice_names[instance_id], 0, MAX_VOICES * VOICE_NAME_LEN);
if (sd_card > 0)
{
char filename[FILENAME_LEN];
char bankdir[4];
File entry;
sprintf(filename, "/%d/%s", b, bank_names[instance_id][b]);
memset(name, 0, len);
#ifdef DEBUG
Serial.print(F("Reading voice names for bank ["));
Serial.print(filename);
Serial.println(F("]"));
#endif
sprintf(bankdir, "/%d", b);
// try to open bank directory
sysex = SD.open(filename);
// try to open directory
sysex = SD.open(bankdir);
if (!sysex)
return (false);
if (sysex.size() != 4104) // check sysex size
{
#ifdef DEBUG
Serial.println(F("E : SysEx file size wrong."));
#endif
return (false);
}
if (sysex.read() != 0xf0) // check sysex start-byte
{
#ifdef DEBUG
Serial.println(F("E : SysEx start byte not found."));
#endif
return (false);
}
if (sysex.read() != 0x43) // check sysex vendor is Yamaha
{
#ifdef DEBUG
Serial.println(F("E : SysEx vendor not Yamaha."));
#endif
return (false);
}
sysex.seek(4103);
if (sysex.read() != 0xf7) // check sysex end-byte
do
{
#ifdef DEBUG
Serial.println(F("E : SysEx end byte not found."));
#endif
entry = sysex.openNextFile();
} while (entry.isDirectory());
if (entry.isDirectory())
return (false);
}
sysex.seek(3);
if (sysex.read() != 0x09) // check for sysex type (0x09=32 voices)
{
strip_extension(entry.name(), name);
#ifdef DEBUG
Serial.println(F("E : SysEx type not 32 voices."));
Serial.print(F("Found bank-name ["));
Serial.print(name);
Serial.print(F("] for bank ["));
Serial.print(b);
Serial.println(F("]"));
#endif
return (false);
}
sysex.seek(4102); // Bulk checksum
bulk_checksum = sysex.read();
sysex.seek(6); // start of bulk data
sysex.close();
for (uint16_t n = 0; n < 4096; n++)
{
uint8_t d = sysex.read();
return (true);
}
if ((n % 128) >= 118 && (n % 128) < 128) // found the start of the voicename
{
voice_names[instance_id][voice_counter][(n % 128) - 118] = d;
}
if (n % 128 == 127)
voice_counter++;
bulk_checksum_calc -= d;
}
bulk_checksum_calc &= 0x7f;
return (false);
}
bool get_voice_name(uint8_t b, uint8_t v, char* name, uint8_t len)
{
File sysex;
if (sd_card > 0)
{
char bank_name[BANK_NAME_LEN];
char filename[FILENAME_LEN];
b = constrain(b, 0, MAX_BANKS - 1);
v = constrain(v, 0, MAX_VOICES - 1);
get_bank_name(b, bank_name, sizeof(bank_name));
sprintf(filename, "/%d/%s.syx", b, bank_name);
#ifdef DEBUG
Serial.print(F("Bulk checksum : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" [0x"));
Serial.print(bulk_checksum, HEX);
Serial.print(F("Reading voice-name from ["));
Serial.print(filename);
Serial.println(F("]"));
#endif
if (bulk_checksum_calc != bulk_checksum)
{
// try to open directory
sysex = SD.open(filename);
if (!sysex)
return (false);
memset(name, 0, len);
sysex.seek(124 + (v * 128));
sysex.read(name, min(len, 10));
#ifdef DEBUG
Serial.print(F("E : Bulk checksum mismatch : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" != 0x"));
Serial.println(bulk_checksum, HEX);
Serial.print(F("Found voice-name ["));
Serial.print(name);
Serial.print(F("] for bank ["));
Serial.print(b);
Serial.print(F("] and voice ["));
Serial.print(v);
Serial.println(F("]"));
#endif
return (false);
}
sysex.close();
return (true);
}
return (false);
}
uint8_t get_bank_names(uint8_t instance_id)
bool get_voice_by_bank_name(uint8_t b, const char* bank_name, uint8_t v, char* voice_name, uint8_t len)
{
File root;
uint8_t bank_counter = 0;
// erase all data for bank names
memset(bank_names[instance_id], 0, MAX_BANKS * BANK_NAME_LEN);
File sysex;
if (sd_card > 0)
{
char bankdir[4];
char filename[FILENAME_LEN];
do
{
// init and set name for actual bank directory
sprintf(bankdir, "/%d", bank_counter);
sprintf(filename, "/%d/%s.syx", b, bank_name);
#ifdef DEBUG
Serial.print(F("Reading voice-name from ["));
Serial.print(filename);
Serial.println(F("]"));
#endif
// try to open directory
root = SD.open(bankdir);
if (!root)
break;
// try to open directory
sysex = SD.open(filename);
if (!sysex)
return (false);
memset(voice_name, 0, len);
sysex.seek(124 + (v * 128));
sysex.read(voice_name, min(len, 10));
// read filenames
File entry = root.openNextFile();
if (!entry.isDirectory())
{
strcpy(bank_names[instance_id][bank_counter], entry.name());
#ifdef DEBUG
Serial.print(F("Found bank ["));
Serial.print(bank_names[instance_id][bank_counter]);
Serial.println(F("]"));
Serial.print(F("Found voice-name ["));
Serial.print(voice_name);
Serial.print(F("] for bank ["));
Serial.print(b);
Serial.print(F("|"));
Serial.print(bank_name);
Serial.print(F("] and voice ["));
Serial.print(v);
Serial.println(F("]"));
#endif
bank_counter++;
}
} while (root);
return (bank_counter);
sysex.close();
return (true);
}
else
return (0);
return (false);
}

@ -36,10 +36,6 @@ extern void show_patch(uint8_t instance_id);
extern uint8_t bank;
extern uint8_t voice;
extern char bank_name[NUM_DEXED][BANK_NAME_LEN];
extern char voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char bank_names[NUM_DEXED][MAX_BANKS][BANK_NAME_LEN];
extern char voice_names[NUM_DEXED][MAX_VOICES][VOICE_NAME_LEN];
extern uint8_t ui_state;
extern uint8_t ui_main_state;
extern config_t configuration;
@ -66,7 +62,9 @@ bool save_sd_performance(uint8_t p);
bool get_sd_data(File sysex, uint8_t format, uint8_t* conf);
bool write_sd_data(File sysex, uint8_t format, uint8_t* data, uint16_t len);
uint8_t calc_checksum(uint8_t* data, uint16_t len);
void strip_extension(char* s, char *target);
bool get_voice_names_from_bank(uint8_t b, uint8_t i);
uint8_t get_bank_names(uint8_t instance_id);
void strip_extension(char* s, char* target);
bool get_bank_name(uint8_t b, char* name, uint8_t len);
bool get_voice_name(uint8_t b, uint8_t v, char* name, uint8_t len);
bool get_voice_by_bank_name(uint8_t b, const char* bank_name, uint8_t v, char* voice_name, uint8_t len);
#endif

Loading…
Cancel
Save