From f5bae5286f039f35b2eca2e1f8bffb70eaac6315 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Fri, 18 May 2018 15:04:52 +0200 Subject: [PATCH] Started SysEX reading from SD. --- MicroDexed.ino | 180 +++++++++++++++++++++++++++++++++++++++++-------- dexed.h | 40 +++++------ 2 files changed, 171 insertions(+), 49 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index 472245e..76040ac 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -12,18 +12,23 @@ #include #include "dexed.h" -#define AUDIO_MEM 2 +#define VOLUME 0.5 #define SAMPLE_RATE 44100 -#define INIT_AUDIO_QUEUE 1 +//#define INIT_AUDIO_QUEUE 1 //#define SHOW_DEXED_TIMING 1 #define SHOW_XRUN 1 #define SHOW_CPU_LOAD_MSEC 5000 #define MAX_NOTES 10 -#define TEST_MIDI 1 +//#define TEST_MIDI 1 #define TEST_NOTE 40 #define TEST_VEL_MIN 60 #define TEST_VEL_MAX 110 //#define ADD_EFFECT_CHORUS 1 +#ifdef ADD_EFFECT_CHORUS +#define AUDIO_MEM 6 +#else +#define AUDIO_MEM 2 +#endif // Use these with the Teensy Audio Shield #define SDCARD_CS_PIN 10 @@ -53,8 +58,7 @@ AudioControlSGTL5000 sgtl5000_1; //xy=507,403 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); Dexed* dexed = new Dexed(SAMPLE_RATE); IntervalTimer sched; -Sd2Card card; -SdVolume volume; +bool sd_card_available = false; #ifdef ADD_EFFECT_CHORUS // Number of samples in each delay line @@ -65,38 +69,24 @@ short delayline[CHORUS_DELAY_LENGTH]; void setup() { - //while (!Serial) ; // wait for Arduino Serial Monitor Serial.begin(115200); + delay(50); Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed")); Serial.println(F("(c)2018 H. Wirtz")); Serial.println(F("setup start")); SPI.setMOSI(SDCARD_MOSI_PIN); SPI.setSCK(SDCARD_SCK_PIN); - if (card.init(SPI_FULL_SPEED, SDCARD_CS_PIN)) { - Serial.println(F("SD card found.")); - } - else + if (!SD.begin(SDCARD_CS_PIN)) { - Serial.println(F("No SD card found.")); + Serial.println(F("SD card not accessable")); } - - switch (card.type()) + else { - case SD_CARD_TYPE_SD1: - case SD_CARD_TYPE_SD2: - Serial.println(F("Card type is SD")); - break; - case SD_CARD_TYPE_SDHC: - Serial.println(F("Card type is SDHC")); - break; - default: - Serial.println(F("Card is an unknown type (maybe SDXC?)")); - } - if (!volume.init(card)) { - Serial.println(F("Unable to access the filesystem")); + sd_card_available = true; } + //load_sysex_file("ROM1A.SYX"); MIDI.begin(MIDI_CHANNEL_OMNI); @@ -105,7 +95,7 @@ void setup() AudioMemory(AUDIO_MEM); sgtl5000_1.enable(); - sgtl5000_1.volume(0.2); + sgtl5000_1.volume(VOLUME); // Initialize processor and memory measurements #ifdef SHOW_CPU_LOAD_MSEC @@ -225,8 +215,140 @@ void cpu_and_mem_usage(void) } #endif -void spaces(int num) { - for (int i = 0; i < num; i++) { - Serial.print(" "); +void load_sysex_file(char *name) +{ + File root; + + if (sd_card_available) + { + root = SD.open("/"); + while (42 == 42) + { + File entry = root.openNextFile(); + if (!entry) + break; + else + { + if (!entry.isDirectory()) + { + if (strcmp(name, entry.name()) == 0) + { + Serial.println(entry.name()); + check_sysex(entry); + load_sysex(entry, 2); + entry.close(); + break; + } + entry.close(); + } + } + } + } +} + +bool load_sysex(File sysex, uint8_t voice_number) +{ + File file; + char voice_name[11]; + + if (file = SD.open(sysex.name())) + { + uint8_t* p_data = dexed->data; + uint8_t i; + uint8_t tmp; + + file.seek(6 + (voice_number * 128)); + for (i = 0; i < 6; i++) + { + file.read(p_data + (i * 17), 11); // R1, R2, R3, R4, L1, L2, L3, L4, LEV SCL BRK PT, SCL LEFT DEPTH, SCL RGHT DEPTH + tmp = file.read(); + *(p_data + 11 + (i * 21)) = (tmp & 0x0c) >> 2; + *(p_data + 12 + (i * 21)) = (tmp & 0x3); + tmp = file.read(); + *(p_data + 13 + (i * 21)) = (tmp & 0x78) >> 3; + *(p_data + 14 + (i * 21)) = (tmp & 0x07); + tmp = file.read(); + *(p_data + 15 + (i * 21)) = (tmp & 0x1c) >> 2; + *(p_data + 16 + (i * 21)) = (tmp & 0x03); + *(p_data + 17 + (i * 21)) = file.read(); + tmp = file.read(); + *(p_data + 18 + (i * 21)) = (tmp & 0x3e) >> 1; + *(p_data + 19 + (i * 21)) = (tmp & 0x01); + file.read(p_data + (i * 21), 1); // FREQ FINE + } + file.read(p_data + 125, 8); // PR1, PR2, PR3, PR4, PL1, PL2, PL3, PL4 + tmp = file.read(); + *(p_data + 133) = (tmp & 0x1f); + tmp = file.read(); + *(p_data + 134) = (tmp & 0x08) >> 3; + *(p_data + 135) = (tmp & 0x07); + file.read(p_data + 136, 4); // LFS, LFD, LPMD, LAMD + tmp = file.read(); + *(p_data + 140) = (tmp & 0x60) >> 5; + *(p_data + 141) = (tmp & 0x1e) >> 1; + *(p_data + 142) = (tmp & 0x01); + file.read(p_data + 143, 1); // TRNSP + file.read(p_data + 144, 10); + strncpy(voice_name, (char*)(p_data + 144), 10); + voice_name[10] = '\0'; + + *(p_data + 166) = 1; + *(p_data + 167) = 1; + *(p_data + 168) = 1; + *(p_data + 169) = 1; + *(p_data + 170) = 1; + *(p_data + 171) = 1; + *(p_data + 172) = 16; } + + Serial.println(voice_name); + return (true); } + +bool check_sysex(File sysex) +{ + File file; + uint16_t i; + uint32_t calc_checksum = 0; + + if (sysex.size() != 4104) // check sysex size + return (false); + if (file = SD.open(sysex.name())) + { + if (file.read() != 0xf0) // check sysex start-byte + { + Serial.println(F("E: SysEx start byte not found.")); + return (false); + } + if (file.read() != 0x43) // check sysex vendor is Yamaha + { + Serial.println(F("E: SysEx vendor not Yamaha.")); + return (false); + } + file.seek(4103); + if (file.read() != 0xf7) // check sysex end-byte + { + Serial.println(F("E: SysEx end byte not found.")); + return (false); + } + file.seek(3); + if (file.read() != 0x09) // check for sysex type (0x09=32 voices) + { + Serial.println(F("E: SysEx type not 32 voices.")); + return (false); + } + file.seek(6); // start of 32*128 (=4096) bytes data + for (i = 0; i < 4096; i++) + calc_checksum += (file.read() & 0x7F); // calculate checksum + calc_checksum = uint8_t(~calc_checksum + 1); + if (calc_checksum != uint8_t(file.read())) + { + Serial.println(F("E: checksum mismatch.")); + return (false); + } + } + file.close(); + return (true); +} + + diff --git a/dexed.h b/dexed.h index a9c3f07..4832280 100644 --- a/dexed.h +++ b/dexed.h @@ -72,12 +72,29 @@ class Dexed Controllers controllers; VoiceStatus voiceStatus; + uint8_t data[173] = { + 95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune + 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00, // OP5 + 95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07, // OP4 + 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 07, // OP3 + 95, 50, 35, 78, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 07, 58, 00, 14, 00, 07, // OP2 + 96, 25, 25, 67, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 10, // OP1 + 94, 67, 95, 60, 50, 50, 50, 50, // 4 * pitch EG rates, 4 *pitch EG level + 04, 06, 00, // algorithm, feedback, osc sync + 34, 33, 00, 00, 00, 04, // lfo speed, lfo delay, lfo pitch_mod_depth, lfo_amp_mod_depth, lfo_sync, lfo_waveform + 03, 24, // pitch_mod_sensitivity, transpose + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // 10 * char for name + 01, 00, 99, 00, 99, 00, 99, 00, 99, 00, // pitch_bend_range, pitch_bend_step, mod_wheel_range, mod_wheel_assign, foot_ctrl_range, foot_ctrl_assign, breath_ctrl_range, breath_ctrl_assign, aftertouch_range, aftertouch_assign + 00, // master tune + 01, 01, 01, 01, 01, 01, // OP1-6 enable + 16 // number of voices + }; // FM-Piano + protected: //void onParam(uint8_t param_num,float param_val); void keyup(uint8_t pitch); void keydown(uint8_t pitch, uint8_t velo); - static const uint8_t MAX_ACTIVE_NOTES = 16; uint8_t max_notes = MAX_ACTIVE_NOTES; ProcessorVoice voices[MAX_ACTIVE_NOTES]; @@ -91,28 +108,11 @@ class Dexed EngineMkI* engineMkI; EngineOpl* engineOpl; + + private: uint8_t _k_rate_counter; uint8_t _param_change_counter; - - uint8_t data[173] = { - 95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune - 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00, // OP5 - 95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07, // OP4 - 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 07, // OP3 - 95, 50, 35, 78, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 07, 58, 00, 14, 00, 07, // OP2 - 96, 25, 25, 67, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 10, // OP1 - 94, 67, 95, 60, 50, 50, 50, 50, // 4 * pitch EG rates, 4 *pitch EG level - 04, 06, 00, // algorithm, feedback, osc sync - 34, 33, 00, 00, 00, 04, // lfo speed, lfo delay, lfo pitch_mod_depth, lfo_amp_mod_depth, lfo_sync, lfo_waveform - 03, 24, // pitch_mod_sensitivity, transpose - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // 10 * char for name - 01, 00, 99, 00, 99, 00, 99, 00, 99, 00, // pitch_bend_range, pitch_bend_step, mod_wheel_range, mod_wheel_assign, foot_ctrl_range, foot_ctrl_assign, breath_ctrl_range, breath_ctrl_assign, aftertouch_range, aftertouch_assign - 00, // master tune - 01, 01, 01, 01, 01, 01, // OP1-6 enable - 16 // number of voices - }; // INIT - }; #endif // PLUGINPROCESSOR_H_INCLUDED