|
|
|
@ -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); |
|
|
|
|
} |
|
|
|
|