MicroDexed is a compatible 6-operator-FM-synth based on the Teensy(-3.6/-4.0) Microcontroller. https://www.parasitstudio.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

355 lines
8.1KB

  1. /*
  2. MicroDexed
  3. MicroDexed is a port of the Dexed sound engine
  4. (https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield.
  5. Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android
  6. (c)2018,2019 H. Wirtz <wirtz@parasitstudio.de>
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 3 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software Foundation,
  17. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include <Arduino.h>
  20. #include <Wire.h>
  21. #include <SPI.h>
  22. #include <SD.h>
  23. #include "dexed.h"
  24. #include "dexed_sysex.h"
  25. #include "config.h"
  26. #include "UI.h"
  27. void create_sysex_filename(uint8_t b, char* sysex_file_name)
  28. {
  29. // init and set name for actual bank
  30. memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN);
  31. sysex_file_name[0] = '/';
  32. itoa(b, &sysex_file_name[1], 10);
  33. strcat(sysex_file_name, "/");
  34. strcat(sysex_file_name, bank_names[b]);
  35. #ifdef DEBUG
  36. Serial.print(F("Created sysex_filename from bank "));
  37. Serial.print(b, DEC);
  38. Serial.print(F(" and name "));
  39. Serial.print(bank_names[b]);
  40. Serial.print(F(": ["));
  41. Serial.print(sysex_file_name);
  42. Serial.println(F("]"));
  43. #endif
  44. }
  45. void strip_extension(char* s, char* target)
  46. {
  47. char tmp[BANK_NAME_LEN];
  48. char* token;
  49. strcpy(tmp, s);
  50. token = strtok(tmp, ".");
  51. if (token == NULL)
  52. strcpy(target, "*ERROR*");
  53. else
  54. strcpy(target, token);
  55. }
  56. bool get_voice_names_from_bank(uint8_t b)
  57. {
  58. File sysex;
  59. uint8_t voice_counter = 0;
  60. int32_t bulk_checksum_calc = 0;
  61. int8_t bulk_checksum;
  62. b %= MAX_BANKS;
  63. // erase all data for voice names
  64. memset(voice_names, 0, MAX_VOICES * VOICE_NAME_LEN);
  65. if (sd_card_available)
  66. {
  67. char sysex_file_name[4 + VOICE_NAME_LEN];
  68. // init and set name for actual bank
  69. create_sysex_filename(b, sysex_file_name);
  70. #ifdef DEBUG
  71. Serial.print(F("Reading voice names for bank ["));
  72. Serial.print(sysex_file_name);
  73. Serial.println(F("]"));
  74. #endif
  75. // try to open bank directory
  76. sysex = SD.open(sysex_file_name);
  77. if (!sysex)
  78. return (false);
  79. if (sysex.size() != 4104) // check sysex size
  80. {
  81. #ifdef DEBUG
  82. Serial.println(F("E : SysEx file size wrong."));
  83. #endif
  84. return (false);
  85. }
  86. if (sysex.read() != 0xf0) // check sysex start-byte
  87. {
  88. #ifdef DEBUG
  89. Serial.println(F("E : SysEx start byte not found."));
  90. #endif
  91. return (false);
  92. }
  93. if (sysex.read() != 0x43) // check sysex vendor is Yamaha
  94. {
  95. #ifdef DEBUG
  96. Serial.println(F("E : SysEx vendor not Yamaha."));
  97. #endif
  98. return (false);
  99. }
  100. sysex.seek(4103);
  101. if (sysex.read() != 0xf7) // check sysex end-byte
  102. {
  103. #ifdef DEBUG
  104. Serial.println(F("E : SysEx end byte not found."));
  105. #endif
  106. return (false);
  107. }
  108. sysex.seek(3);
  109. if (sysex.read() != 0x09) // check for sysex type (0x09=32 voices)
  110. {
  111. #ifdef DEBUG
  112. Serial.println(F("E : SysEx type not 32 voices."));
  113. #endif
  114. return (false);
  115. }
  116. sysex.seek(4102); // Bulk checksum
  117. bulk_checksum = sysex.read();
  118. sysex.seek(6); // start of bulk data
  119. for (uint16_t n = 0; n < 4096; n++)
  120. {
  121. uint8_t d = sysex.read();
  122. if ((n % 128) >= 118 && (n % 128) < 128) // found the start of the voicename
  123. {
  124. voice_names[voice_counter][(n % 128) - 118] = d;
  125. }
  126. if (n % 128 == 127)
  127. voice_counter++;
  128. bulk_checksum_calc -= d;
  129. }
  130. bulk_checksum_calc &= 0x7f;
  131. #ifdef DEBUG
  132. Serial.print(F("Bulk checksum : 0x"));
  133. Serial.print(bulk_checksum_calc, HEX);
  134. Serial.print(F(" [0x"));
  135. Serial.print(bulk_checksum, HEX);
  136. Serial.println(F("]"));
  137. #endif
  138. if (bulk_checksum_calc != bulk_checksum)
  139. {
  140. #ifdef DEBUG
  141. Serial.print(F("E : Bulk checksum mismatch : 0x"));
  142. Serial.print(bulk_checksum_calc, HEX);
  143. Serial.print(F(" != 0x"));
  144. Serial.println(bulk_checksum, HEX);
  145. #endif
  146. return (false);
  147. }
  148. }
  149. return (false);
  150. }
  151. uint8_t get_bank_names(void)
  152. {
  153. File root;
  154. uint8_t bank_counter = 0;
  155. // erase all data for bank names
  156. memset(bank_names, 0, MAX_BANKS * BANK_NAME_LEN);
  157. if (sd_card_available)
  158. {
  159. char bankdir[4];
  160. do
  161. {
  162. // init and set name for actual bank directory
  163. memset(bankdir, 0, sizeof(bankdir));
  164. bankdir[0] = '/';
  165. itoa(bank_counter, &bankdir[1], 10);
  166. // try to open directory
  167. root = SD.open(bankdir);
  168. if (!root)
  169. break;
  170. // read filenames
  171. File entry = root.openNextFile();
  172. if (!entry.isDirectory())
  173. {
  174. strcpy(bank_names[bank_counter], entry.name());
  175. #ifdef DEBUG
  176. Serial.print(F("Found bank ["));
  177. Serial.print(bank_names[bank_counter]);
  178. Serial.println(F("]"));
  179. #endif
  180. bank_counter++;
  181. }
  182. } while (root);
  183. return (bank_counter);
  184. }
  185. else
  186. return (bank_counter);
  187. }
  188. bool load_sysex(uint8_t b, uint8_t v)
  189. {
  190. #if DEBUG
  191. bool found = false;
  192. #endif
  193. v %= MAX_VOICES;
  194. b %= MAX_BANKS;
  195. if (sd_card_available)
  196. {
  197. File sysex;
  198. char sysex_file_name[4 + VOICE_NAME_LEN];
  199. uint8_t data[128];
  200. create_sysex_filename(b, sysex_file_name);
  201. sysex = SD.open(sysex_file_name);
  202. if (!sysex)
  203. {
  204. #ifdef DEBUG
  205. Serial.print(F("E : Cannot open "));
  206. Serial.print(sysex_file_name);
  207. Serial.println(F("from SD."));
  208. #endif
  209. return (false);
  210. }
  211. if (get_sysex_voice(sysex, v, data))
  212. {
  213. #ifdef DEBUG
  214. char n[11];
  215. strncpy(n, (char*)&data[118], 10);
  216. Serial.print("Loading sysex ");
  217. Serial.print(sysex_file_name);
  218. Serial.print(F(" ["));
  219. Serial.print(voice_names[v]);
  220. Serial.println(F("]"));
  221. #endif
  222. return (dexed->loadSysexVoice(data));
  223. }
  224. #ifdef DEBUG
  225. else
  226. Serial.println(F("E : Cannot load voice data"));
  227. #endif
  228. }
  229. #ifdef DEBUG
  230. if (found == false)
  231. Serial.println(F("E : File not found."));
  232. #endif
  233. return (false);
  234. }
  235. bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data)
  236. {
  237. uint16_t n;
  238. int32_t bulk_checksum_calc = 0;
  239. int8_t bulk_checksum;
  240. if (sysex.size() != 4104) // check sysex size
  241. {
  242. #ifdef DEBUG
  243. Serial.println(F("E : SysEx file size wrong."));
  244. #endif
  245. return (false);
  246. }
  247. if (sysex.read() != 0xf0) // check sysex start-byte
  248. {
  249. #ifdef DEBUG
  250. Serial.println(F("E : SysEx start byte not found."));
  251. #endif
  252. return (false);
  253. }
  254. if (sysex.read() != 0x43) // check sysex vendor is Yamaha
  255. {
  256. #ifdef DEBUG
  257. Serial.println(F("E : SysEx vendor not Yamaha."));
  258. #endif
  259. return (false);
  260. }
  261. sysex.seek(4103);
  262. if (sysex.read() != 0xf7) // check sysex end-byte
  263. {
  264. #ifdef DEBUG
  265. Serial.println(F("E : SysEx end byte not found."));
  266. #endif
  267. return (false);
  268. }
  269. sysex.seek(3);
  270. if (sysex.read() != 0x09) // check for sysex type (0x09=32 voices)
  271. {
  272. #ifdef DEBUG
  273. Serial.println(F("E : SysEx type not 32 voices."));
  274. #endif
  275. return (false);
  276. }
  277. sysex.seek(4102); // Bulk checksum
  278. bulk_checksum = sysex.read();
  279. sysex.seek(6); // start of bulk data
  280. for (n = 0; n < 4096; n++)
  281. {
  282. uint8_t d = sysex.read();
  283. if (n >= voice_number * 128 && n < (voice_number + 1) * 128)
  284. {
  285. data[n - (voice_number * 128)] = d;
  286. }
  287. bulk_checksum_calc -= d;
  288. }
  289. bulk_checksum_calc &= 0x7f;
  290. #ifdef DEBUG
  291. Serial.print(F("Bulk checksum : 0x"));
  292. Serial.print(bulk_checksum_calc, HEX);
  293. Serial.print(F(" [0x"));
  294. Serial.print(bulk_checksum, HEX);
  295. Serial.println(F("]"));
  296. #endif
  297. if (bulk_checksum_calc != bulk_checksum)
  298. {
  299. #ifdef DEBUG
  300. Serial.print(F("E : Bulk checksum mismatch : 0x"));
  301. Serial.print(bulk_checksum_calc, HEX);
  302. Serial.print(F(" != 0x"));
  303. Serial.println(bulk_checksum, HEX);
  304. #endif
  305. return (false);
  306. }
  307. render_time_max = 0;
  308. return (true);
  309. }