Optimized bank and voice loading (not ready yet).

pull/4/head
Holger Wirtz 6 years ago
parent c10258cafd
commit d4fe310fff
  1. 63
      MicroDexed.ino
  2. 24
      UI.cpp
  3. 5
      UI.h
  4. 2
      config.h
  5. 385
      dexed_sysex.cpp
  6. 12
      dexed_sysex.h

@ -20,7 +20,6 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Audio.h>
@ -82,12 +81,15 @@ uint32_t overload = 0;
uint32_t peak = 0;
uint16_t render_time_max = 0;
uint8_t bank = 0;
uint8_t max_loaded_banks=0;
uint8_t voice = 0;
float vol = VOLUME;
float vol_right = 1.0;
float vol_left = 1.0;
char bank_name[11];
char voice_name[11];
char bank_name[BANK_NAME_LEN];
char voice_name[VOICE_NAME_LEN];
char bank_names[MAX_BANKS][BANK_NAME_LEN];
char voice_names[MAX_VOICES][VOICE_NAME_LEN];
#ifdef MASTER_KEY_MIDI
bool master_key_enabled = false;
#endif
@ -180,17 +182,41 @@ void setup()
Serial.println(F("SD card found."));
sd_card_available = true;
// read all bank names
max_loaded_banks=get_bank_names();
strip_extension(bank_names[bank],bank_name);
// read all voice name for actual bank
get_voice_names_from_bank(bank);
#ifdef DEBUG
Serial.print(F("Bank ["));
Serial.print(bank_names[bank]);
Serial.print(F("/"));
Serial.print(bank_name);
Serial.println(F("]"));
for (uint8_t n = 0; n < MAX_VOICES; n++)
{
if (n < 10)
Serial.print(F(" "));
Serial.print(F(" "));
Serial.print(n, DEC);
Serial.print(F("["));
Serial.print(voice_names[n]);
Serial.println(F("]"));
}
#endif
// load default SYSEX data
load_sysex(bank, voice);
}
#ifdef I2C_DISPLAY
enc[0].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read();
enc[1].write(voice);
enc_val[1] = enc[1].read();
but[0].update();
but[1].update();
enc[0].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read();
enc[1].write(voice);
enc_val[1] = enc[1].read();
but[0].update();
but[1].update();
#endif
}
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
// Initialize processor and memory measurements
@ -383,7 +409,7 @@ bool handle_master_key(uint8_t data)
#ifdef I2C_DISPLAY
lcd.show(1, 0, 2, voice + 1);
lcd.show(1, 2, 1, " ");
lcd.show(1, 3, 10, voice_name);
lcd.show(1, 3, 10, voice_names[voice]);
#endif
}
#ifdef DEBUG
@ -414,8 +440,9 @@ bool handle_master_key(uint8_t data)
Serial.println(bank, DEC);
#endif
#ifdef I2C_DISPLAY
if (get_bank_voice_name(bank, voice))
if (get_voice_names_from_bank(bank))
{
strip_extension(bank_names[bank],bank_name);
lcd.show(0, 0, 2, bank + 1);
lcd.show(0, 2, 1, " ");
lcd.show(0, 3, 10, bank_name);
@ -588,12 +615,12 @@ void set_volume(float v, float vr, float vl)
#endif
#ifdef TEENSY_AUDIO_BOARD
//sgtl5000_1.dacVolume(log(vol * vol_left)+1, log(vol * vol_right)+1);
sgtl5000_1.dacVolume(1 - pow((1 - vol * vol_left), 2.7), (1 - pow((1 - vol * vol_right), 2.7)));
//sgtl5000_1.dacVolume(vol * vol_left, vol * vol_right);
sgtl5000_1.dacVolume(pow(vol * vol_left, 0.2), pow(vol * vol_right, 0.2));
#else
volume_master.gain(1 - pow(1 - lvol, 2.7));
volume_r.gain(1 - pow(1 - vr, 2.7));
volume_l.gain(1 - pow(1 - vl, 2.7));
volume_master.gain(pow(lvol, 0.2));
volume_r.gain(pow(vr, 0.2));
volume_l.gain(pow(vl, 0.2));
#endif
}
@ -772,7 +799,7 @@ void show_cpu_and_mem_usage(void)
void show_patch(void)
{
uint8_t i;
char voicename[11];
char voicename[VOICE_NAME_LEN];
memset(voicename, 0, sizeof(voicename));
for (i = 0; i < 6; i++)

@ -109,33 +109,33 @@ void handle_ui(void)
case UI_MAIN_BANK:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= MAX_BANKS)
enc[i].write(MAX_BANKS);
else if (enc[i].read() > max_loaded_banks-1)
enc[i].write(max_loaded_banks-1);
bank = enc[i].read();
if (!get_bank_voice_name(bank, voice))
if (!get_voice_names_from_bank(bank))
{
bank--;
enc[i].write(bank);
get_bank_voice_name(bank, voice);
get_voice_names_from_bank(bank);
}
break;
case UI_MAIN_VOICE:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= MAX_VOICES)
enc[i].write(MAX_VOICES);
else if (enc[i].read() > MAX_VOICES-1)
enc[i].write(MAX_VOICES-1);
voice = enc[i].read();
break;
case UI_MAIN_VOICE_SELECTED:
ui_main_state = UI_MAIN_VOICE;
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= MAX_VOICES)
else if (enc[i].read() >= MAX_VOICES-1)
enc[i].write(MAX_VOICES);
voice = enc[i].read();
break;
}
get_bank_voice_name(bank, voice);
get_voice_names_from_bank(bank);
ui_show_main();
break;
}
@ -157,6 +157,8 @@ void ui_show_main(void)
lcd.clear();
lcd.show(0, 0, 2, bank + 1);
lcd.show(0, 2, 1, " ");
strip_extension(bank_names[bank], bank_name);
if (ui_main_state == UI_MAIN_BANK)
{
lcd.show(0, 2, 1, "[");
@ -171,17 +173,17 @@ void ui_show_main(void)
if (ui_main_state == UI_MAIN_VOICE)
{
lcd.show(1, 2, 1, "<");
lcd.show(1, 3, 10, voice_name);
lcd.show(1, 3, 10, voice_names[voice]);
lcd.show(1, 14, 1, ">");
}
else if (ui_main_state == UI_MAIN_VOICE_SELECTED)
{
lcd.show(1, 2, 1, "[");
lcd.show(1, 3, 10, voice_name);
lcd.show(1, 3, 10, voice_names[voice]);
lcd.show(1, 14, 1, "]");
}
else
lcd.show(1, 3, 10, voice_name);
lcd.show(1, 3, 10, voice_names[voice]);
}
void ui_show_volume(void)

@ -40,9 +40,10 @@ extern float vol_left;
extern float vol_right;
extern LiquidCrystalPlus_I2C lcd;
extern uint8_t bank;
extern uint8_t max_loaded_banks;
extern uint8_t voice;
extern char bank_name[11];
extern char voice_name[11];
extern char bank_name[BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN];
extern uint8_t ui_state;
extern uint8_t ui_main_state;
extern void update_eeprom_checksum(void);

@ -49,6 +49,8 @@
#define SAMPLE_RATE 44100
#define MAX_BANKS 99
#define MAX_VOICES 32 // voices per bank
#define BANK_NAME_LEN 13 // FAT12 filenames (plus '\0')
#define VOICE_NAME_LEN 11 // 10 (plus '\0')
#if !defined(__MK66FX1M0__) // check for Teensy-3.6
#define MAX_NOTES 11 // No?

@ -32,64 +32,193 @@
#include "config.h"
#include "UI.h"
bool get_bank_voice_name(uint8_t b, uint8_t v)
void create_sysex_filename(uint8_t b, char* sysex_file_name)
{
File root;
// init and set name for actual bank
memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN);
sysex_file_name[0] = '/';
itoa(b, &sysex_file_name[1], 10);
strcat(sysex_file_name, "/");
strcat(sysex_file_name, bank_names[b]);
#ifdef DEBUG
Serial.print(F("Created sysex_filename from bank "));
Serial.print(b, DEC);
Serial.print(F(" and name "));
Serial.print(bank_names[b]);
Serial.print(F(": ["));
Serial.print(sysex_file_name);
Serial.println(F("]"));
#endif
}
void strip_extension(char* s, char* target)
{
char tmp[BANK_NAME_LEN];
char* token;
strcpy(tmp,s);
token = strtok(tmp, ".");
if (token == NULL)
strcpy(target, "*ERROR*");
else
strcpy(target, token);
}
bool get_voice_names_from_bank(uint8_t b)
{
File sysex;
uint8_t voice_counter = 0;
int32_t bulk_checksum_calc = 0;
int8_t bulk_checksum;
b %= MAX_BANKS;
// erase all data for voice names
memset(voice_names, 0, MAX_VOICES * VOICE_NAME_LEN);
if (sd_card_available)
{
char bankdir[4];
char sysex_file_name[4 + VOICE_NAME_LEN];
// init and set name for actual bank
create_sysex_filename(b, sysex_file_name);
memset(bankdir, 0, sizeof(bankdir));
bankdir[0] = '/';
itoa(b, &bankdir[1], 10);
#ifdef DEBUG
Serial.print(F("Reading voice names for bank ["));
Serial.print(sysex_file_name);
Serial.println(F("]"));
#endif
root = SD.open(bankdir);
if (!root)
// try to open bank directory
sysex = SD.open(sysex_file_name);
if (!sysex)
return (false);
if (sysex.size() != 4104) // check sysex size
{
#ifdef DEBUG
Serial.println(F("E: Cannot open main dir from SD."));
Serial.println(F("E : SysEx file size wrong."));
#endif
return (false);
}
while (42 == 42)
if (sysex.read() != 0xf0) // check sysex start-byte
{
File entry = root.openNextFile();
if (!entry)
#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
{
#ifdef DEBUG
Serial.println(F("E : SysEx end byte not found."));
#endif
return (false);
}
sysex.seek(3);
if (sysex.read() != 0x09) // check for sysex type (0x09=32 voices)
{
#ifdef DEBUG
Serial.println(F("E : SysEx type not 32 voices."));
#endif
return (false);
}
sysex.seek(4102); // Bulk checksum
bulk_checksum = sysex.read();
sysex.seek(6); // start of bulk data
for (uint16_t n = 0; n < 4096; n++)
{
uint8_t d = sysex.read();
if ((n % 128) >= 118 && (n % 128) < 128) // found the start of the voicename
{
// No more files
break;
voice_names[voice_counter][(n % 128) - 118] = d;
}
else
if (n % 128 == 127)
voice_counter++;
bulk_checksum_calc -= d;
}
bulk_checksum_calc &= 0x7f;
#ifdef DEBUG
Serial.print(F("Bulk checksum : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" [0x"));
Serial.print(bulk_checksum, HEX);
Serial.println(F("]"));
#endif
if (bulk_checksum_calc != bulk_checksum)
{
#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);
#endif
return (false);
}
}
else
return (false);
}
uint8_t get_bank_names(void)
{
File root;
uint8_t bank_counter = 0;
// erase all data for bank names
memset(bank_names, 0, MAX_BANKS * BANK_NAME_LEN);
if (sd_card_available)
{
char bankdir[4];
do
{
// init and set name for actual bank directory
memset(bankdir, 0, sizeof(bankdir));
bankdir[0] = '/';
itoa(bank_counter, &bankdir[1], 10);
// try to open directory
root = SD.open(bankdir);
if (!root)
break;
// read filenames
File entry = root.openNextFile();
if (!entry.isDirectory())
{
if (!entry.isDirectory())
{
char *token;
uint8_t data[128];
if (get_sysex_voice(bankdir, entry, v, data))
strncpy(voice_name, (char*)&data[118], 10);
else
strcpy(voice_name, "*ERROR*");
token = strtok(entry.name(), ".");
if (token == NULL)
strcpy(bank_name, "*ERROR*");
else
strcpy(bank_name, token);
return (true);
}
strcpy(bank_names[bank_counter], entry.name());
#ifdef DEBUG
Serial.print(F("Found bank ["));
Serial.print(bank_names[bank_counter]);
Serial.println(F("]"));
#endif
bank_counter++;
}
}
} while (root);
return (bank_counter);
}
return (false);
else
return (bank_counter);
}
bool load_sysex(uint8_t b, uint8_t v)
{
File root;
bool found = false;
v %= MAX_VOICES;
@ -97,170 +226,126 @@ bool load_sysex(uint8_t b, uint8_t v)
if (sd_card_available)
{
char bankdir[4];
File sysex;
char sysex_file_name[4 + VOICE_NAME_LEN];
uint8_t data[128];
memset(bankdir, 0, sizeof(bankdir));
bankdir[0] = '/';
itoa(b, &bankdir[1], 10);
create_sysex_filename(b, sysex_file_name);
root = SD.open(bankdir);
if (!root)
sysex = SD.open(sysex_file_name);
if (!sysex)
{
#ifdef DEBUG
Serial.println(F("E: Cannot open main dir from SD."));
Serial.print(F("E : Cannot open "));
Serial.print(sysex_file_name);
Serial.println(F("from SD."));
#endif
return (false);
}
while (42 == 42)
if (get_sysex_voice(sysex, v, data))
{
File entry = root.openNextFile();
if (!entry)
{
// No more files
break;
}
else
{
if (!entry.isDirectory())
{
uint8_t data[128];
found = true;
if (get_sysex_voice(bankdir, entry, v, data))
{
#ifdef DEBUG
char n[11];
strncpy(n, (char*)&data[118], 10);
Serial.print("Loading sysex ");
Serial.print(bankdir);
Serial.print("/");
Serial.print(entry.name());
Serial.print(F(" ["));
Serial.print(n);
Serial.println(F("]"));
char n[11];
strncpy(n, (char*)&data[118], 10);
Serial.print("Loading sysex ");
Serial.print(sysex_file_name);
Serial.print(F(" ["));
Serial.print(voice_names[v]);
Serial.println(F(" ["));
#endif
char *token;
token = strtok(entry.name(), ".");
if (token != NULL)
strcpy(bank_name, token);
else
strcpy(bank_name, "*ERROR*");
return (dexed->loadSysexVoice(data));
}
else
return (dexed->loadSysexVoice(data));
}
else
#ifdef DEBUG
Serial.println(F("E: Cannot load voice data"));
Serial.println(F("E : Cannot load voice data"));
#endif
entry.close();
break;
}
}
}
}
#ifdef DEBUG
if (found == false)
Serial.println(F("E: File not found."));
Serial.println(F("E : File not found."));
#endif
return (false);
}
bool get_sysex_voice(char* dir, File sysex, uint8_t voice_number, uint8_t* data)
bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data)
{
File file;
uint16_t n;
int32_t bulk_checksum_calc = 0;
int8_t bulk_checksum;
char sysex_file[20];
strcpy(sysex_file, dir);
strcat(sysex_file, "/");
strcat(sysex_file, sysex.name());
if (sysex.size() != 4104) // check sysex size
{
#ifdef DEBUG
Serial.println(F("E: SysEx file size wrong."));
Serial.println(F("E : SysEx file size wrong."));
#endif
return (false);
}
if (file = SD.open(sysex_file))
if (sysex.read() != 0xf0) // check sysex start-byte
{
if (file.read() != 0xf0) // check sysex start-byte
{
#ifdef DEBUG
Serial.println(F("E: SysEx start byte not found."));
Serial.println(F("E : SysEx start byte not found."));
#endif
return (false);
}
if (file.read() != 0x43) // check sysex vendor is Yamaha
{
return (false);
}
if (sysex.read() != 0x43) // check sysex vendor is Yamaha
{
#ifdef DEBUG
Serial.println(F("E: SysEx vendor not Yamaha."));
Serial.println(F("E : SysEx vendor not Yamaha."));
#endif
return (false);
}
file.seek(4103);
if (file.read() != 0xf7) // check sysex end-byte
{
return (false);
}
sysex.seek(4103);
if (sysex.read() != 0xf7) // check sysex end-byte
{
#ifdef DEBUG
Serial.println(F("E: SysEx end byte not found."));
Serial.println(F("E : SysEx end byte not found."));
#endif
return (false);
}
file.seek(3);
if (file.read() != 0x09) // check for sysex type (0x09=32 voices)
{
return (false);
}
sysex.seek(3);
if (sysex.read() != 0x09) // check for sysex type (0x09=32 voices)
{
#ifdef DEBUG
Serial.println(F("E: SysEx type not 32 voices."));
Serial.println(F("E : SysEx type not 32 voices."));
#endif
return (false);
}
file.seek(4102); // Bulk checksum
bulk_checksum = file.read();
return (false);
}
sysex.seek(4102); // Bulk checksum
bulk_checksum = sysex.read();
file.seek(6); // start of bulk data
for (n = 0; n < 4096; n++)
sysex.seek(6); // start of bulk data
for (n = 0; n < 4096; n++)
{
uint8_t d = sysex.read();
if (n >= voice_number * 128 && n < (voice_number + 1) * 128)
{
uint8_t d = file.read();
if (n >= voice_number * 128 && n < (voice_number + 1) * 128)
{
data[n - (voice_number * 128)] = d;
}
bulk_checksum_calc -= d;
data[n - (voice_number * 128)] = d;
}
bulk_checksum_calc &= 0x7f;
bulk_checksum_calc -= d;
}
bulk_checksum_calc &= 0x7f;
#ifdef DEBUG
Serial.print(F("Bulk checksum: 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" [0x"));
Serial.print(bulk_checksum, HEX);
Serial.println(F("]"));
Serial.print(F("Bulk checksum : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" [0x"));
Serial.print(bulk_checksum, HEX);
Serial.println(F("]"));
#endif
if (bulk_checksum_calc != bulk_checksum)
{
if (bulk_checksum_calc != bulk_checksum)
{
#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("E : Bulk checksum mismatch : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" != 0x"));
Serial.println(bulk_checksum, HEX);
#endif
return (false);
}
}
#ifdef DEBUG
else
{
Serial.print(F("Cannot open "));
Serial.println(sysex.name());
return (false);
}
#endif
render_time_max = 0;

@ -33,13 +33,19 @@ extern Dexed* dexed;
extern uint16_t render_time_max;
extern uint8_t bank;
extern uint8_t voice;
extern char bank_name[11];
extern char voice_name[11];
extern char bank_name[BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN];
extern char bank_names[MAX_BANKS][BANK_NAME_LEN];
extern char voice_names[MAX_VOICES][VOICE_NAME_LEN];
extern uint8_t ui_state;
extern uint8_t ui_main_state;
void create_sysex_filename(uint8_t b, char* sysex_file_name);
void strip_extension(char* s, char *target);
bool get_voice_names_from_bank(uint8_t b);
uint8_t get_bank_names(void);
bool get_bank_voice_name(uint8_t b, uint8_t v);
bool load_sysex(uint8_t b, uint8_t v);
bool get_sysex_voice(char* dir, File sysex, uint8_t voice_number, uint8_t* data);
bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data);
#endif

Loading…
Cancel
Save