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.

552 lines
15KB

  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 "synth.h"
  20. #include "dexed.h"
  21. #include "config.h"
  22. #include "EngineMkI.h"
  23. #include "EngineOpl.h"
  24. #include "fm_core.h"
  25. #include "exp2.h"
  26. #include "sin.h"
  27. #include "freqlut.h"
  28. #include "controllers.h"
  29. #include "PluginFx.h"
  30. #include <unistd.h>
  31. #include <limits.h>
  32. #ifdef USE_TEENSY_DSP
  33. #include <Audio.h>
  34. #endif
  35. Dexed::Dexed(int rate)
  36. {
  37. uint8_t i;
  38. Exp2::init();
  39. Tanh::init();
  40. Sin::init();
  41. Freqlut::init(rate);
  42. Lfo::init(rate);
  43. PitchEnv::init(rate);
  44. Env::init_sr(rate);
  45. fx.init(rate);
  46. engineMkI = new EngineMkI;
  47. engineOpl = new EngineOpl;
  48. engineMsfa = new FmCore;
  49. for (i = 0; i < MAX_ACTIVE_NOTES; i++) {
  50. voices[i].dx7_note = new Dx7Note;
  51. voices[i].keydown = false;
  52. voices[i].sustained = false;
  53. voices[i].live = false;
  54. }
  55. max_notes = MAX_NOTES;
  56. currentNote = 0;
  57. resetControllers();
  58. controllers.masterTune = 0;
  59. controllers.opSwitch = 0x3f; // enable all operators
  60. //controllers.opSwitch=0x00;
  61. lfo.reset(data + 137);
  62. setMonoMode(false);
  63. sustain = false;
  64. setEngineType(DEXED_ENGINE);
  65. }
  66. Dexed::~Dexed()
  67. {
  68. currentNote = -1;
  69. for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; note++)
  70. delete voices[note].dx7_note;
  71. delete(engineMsfa);
  72. delete(engineOpl);
  73. delete(engineMkI);
  74. }
  75. void Dexed::activate(void)
  76. {
  77. panic();
  78. controllers.values_[kControllerPitchRange] = data[155];
  79. controllers.values_[kControllerPitchStep] = data[156];
  80. controllers.refresh();
  81. }
  82. void Dexed::deactivate(void)
  83. {
  84. panic();
  85. }
  86. void Dexed::getSamples(uint16_t n_samples, int16_t* buffer)
  87. {
  88. uint16_t i;
  89. float sumbuf[n_samples];
  90. if (refreshVoice)
  91. {
  92. for (i = 0; i < max_notes; i++)
  93. {
  94. if ( voices[i].live )
  95. voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity);
  96. }
  97. lfo.reset(data + 137);
  98. refreshVoice = false;
  99. }
  100. for (i = 0; i < n_samples; i += _N_)
  101. {
  102. AlignedBuf<int32_t, _N_> audiobuf;
  103. for (uint8_t j = 0; j < _N_; ++j)
  104. {
  105. audiobuf.get()[j] = 0;
  106. sumbuf[i + j] = 0.0;
  107. }
  108. int32_t lfovalue = lfo.getsample();
  109. int32_t lfodelay = lfo.getdelay();
  110. for (uint8_t note = 0; note < max_notes; ++note)
  111. {
  112. if (voices[note].live)
  113. {
  114. voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers);
  115. for (uint8_t j = 0; j < _N_; ++j)
  116. {
  117. int32_t val = audiobuf.get()[j];
  118. val = val >> 4;
  119. #ifdef USE_TEENSY_DSP
  120. int32_t clip_val = signed_saturate_rshift(val, 24, 9);
  121. #else
  122. int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9;
  123. #endif
  124. float f = static_cast<float>(clip_val >> REDUCE_LOUDNESS) / 0x7fff;
  125. if (f > 1.0)
  126. {
  127. f = 1.0;
  128. overload++;
  129. }
  130. else if (f < -1.0)
  131. {
  132. f = -1.0;
  133. overload++;
  134. }
  135. sumbuf[i + j] += f;
  136. audiobuf.get()[j] = 0;
  137. }
  138. }
  139. }
  140. }
  141. fx.process(sumbuf, n_samples);
  142. for (i = 0; i < n_samples; ++i)
  143. buffer[i] = static_cast<int16_t>(sumbuf[i] * 0x7fff);
  144. }
  145. void Dexed::keydown(uint8_t pitch, uint8_t velo) {
  146. if ( velo == 0 ) {
  147. keyup(pitch);
  148. return;
  149. }
  150. pitch += data[144] - 24;
  151. #if defined(NORMALIZE_DX_VELOCITY)
  152. velo = ((float)velo) * 0.7874015; // 100/127
  153. #endif
  154. uint8_t note = currentNote;
  155. uint8_t keydown_counter = 0;
  156. for (uint8_t i = 0; i < max_notes; i++) {
  157. if (!voices[note].keydown) {
  158. currentNote = (note + 1) % max_notes;
  159. voices[note].midi_note = pitch;
  160. voices[note].velocity = velo;
  161. voices[note].sustained = sustain;
  162. voices[note].keydown = true;
  163. voices[note].dx7_note->init(data, (int)pitch, (int)velo);
  164. if ( data[136] )
  165. voices[note].dx7_note->oscSync();
  166. break;
  167. }
  168. else
  169. keydown_counter++;
  170. note = (note + 1) % max_notes;
  171. }
  172. if (keydown_counter == 0)
  173. lfo.keydown();
  174. if ( monoMode ) {
  175. for (uint8_t i = 0; i < max_notes; i++) {
  176. if ( voices[i].live ) {
  177. // all keys are up, only transfer signal
  178. if ( ! voices[i].keydown ) {
  179. voices[i].live = false;
  180. voices[note].dx7_note->transferSignal(*voices[i].dx7_note);
  181. break;
  182. }
  183. if ( voices[i].midi_note < pitch ) {
  184. voices[i].live = false;
  185. voices[note].dx7_note->transferState(*voices[i].dx7_note);
  186. break;
  187. }
  188. return;
  189. }
  190. }
  191. }
  192. voices[note].live = true;
  193. }
  194. void Dexed::keyup(uint8_t pitch) {
  195. pitch += data[144] - TRANSPOSE_FIX;
  196. uint8_t note;
  197. for (note = 0; note < max_notes; ++note) {
  198. if ( voices[note].midi_note == pitch && voices[note].keydown ) {
  199. voices[note].keydown = false;
  200. break;
  201. }
  202. }
  203. // note not found ?
  204. if ( note >= max_notes ) {
  205. return;
  206. }
  207. if ( monoMode ) {
  208. int8_t highNote = -1;
  209. int8_t target = 0;
  210. for (int8_t i = 0; i < max_notes; i++) {
  211. if ( voices[i].keydown && voices[i].midi_note > highNote ) {
  212. target = i;
  213. highNote = voices[i].midi_note;
  214. }
  215. }
  216. if ( highNote != -1 && voices[note].live ) {
  217. voices[note].live = false;
  218. voices[target].live = true;
  219. voices[target].dx7_note->transferState(*voices[note].dx7_note);
  220. }
  221. }
  222. if ( sustain ) {
  223. voices[note].sustained = true;
  224. } else {
  225. voices[note].dx7_note->keyup();
  226. }
  227. }
  228. void Dexed::doRefreshVoice(void)
  229. {
  230. refreshVoice = true;
  231. }
  232. void Dexed::setOPs(uint8_t ops)
  233. {
  234. controllers.opSwitch = ops;
  235. }
  236. uint8_t Dexed::getEngineType() {
  237. return engineType;
  238. }
  239. void Dexed::setEngineType(uint8_t tp) {
  240. if (engineType == tp)
  241. return;
  242. switch (tp) {
  243. case DEXED_ENGINE_MARKI:
  244. controllers.core = engineMkI;
  245. break;
  246. case DEXED_ENGINE_OPL:
  247. controllers.core = engineOpl;
  248. break;
  249. default:
  250. controllers.core = engineMsfa;
  251. tp = DEXED_ENGINE_MODERN;
  252. break;
  253. }
  254. engineType = tp;
  255. panic();
  256. controllers.refresh();
  257. }
  258. bool Dexed::isMonoMode(void) {
  259. return monoMode;
  260. }
  261. void Dexed::setMonoMode(bool mode) {
  262. if (monoMode == mode)
  263. return;
  264. monoMode = mode;
  265. }
  266. void Dexed::setSustain(bool s)
  267. {
  268. if (sustain == s)
  269. return;
  270. sustain = s;
  271. }
  272. bool Dexed::getSustain(void)
  273. {
  274. return sustain;
  275. }
  276. void Dexed::panic(void) {
  277. for (uint8_t i = 0; i < MAX_ACTIVE_NOTES; i++)
  278. {
  279. if (voices[i].live == true) {
  280. voices[i].keydown = false;
  281. voices[i].live = false;
  282. voices[i].sustained = false;
  283. if ( voices[i].dx7_note != NULL ) {
  284. voices[i].dx7_note->oscSync();
  285. }
  286. }
  287. }
  288. }
  289. void Dexed::resetControllers(void)
  290. {
  291. controllers.values_[kControllerPitch] = 0x2000;
  292. controllers.values_[kControllerPitchRange] = 0;
  293. controllers.values_[kControllerPitchStep] = 0;
  294. controllers.modwheel_cc = 0;
  295. controllers.foot_cc = 0;
  296. controllers.breath_cc = 0;
  297. controllers.aftertouch_cc = 0;
  298. controllers.refresh();
  299. }
  300. void Dexed::notesOff(void) {
  301. for (uint8_t i = 0; i < MAX_ACTIVE_NOTES; i++) {
  302. if (voices[i].live == true && voices[i].keydown == true) {
  303. voices[i].keydown = false;
  304. }
  305. }
  306. }
  307. void Dexed::setMaxNotes(uint8_t n) {
  308. if (n <= MAX_ACTIVE_NOTES)
  309. {
  310. notesOff();
  311. max_notes = n;
  312. panic();
  313. controllers.refresh();
  314. }
  315. }
  316. uint8_t Dexed::getMaxNotes(void)
  317. {
  318. return max_notes;
  319. }
  320. uint8_t Dexed::getNumNotesPlaying(void)
  321. {
  322. uint8_t op_carrier = controllers.core->get_carrier_operators(data[134]); // look for carriers
  323. uint8_t i;
  324. uint8_t count_playing_voices = 0;
  325. for (i = 0; i < max_notes; i++)
  326. {
  327. if (voices[i].live == true)
  328. {
  329. uint8_t op_amp = 0;
  330. uint8_t op_carrier_num = 0;
  331. memset(&voiceStatus, 0, sizeof(VoiceStatus));
  332. voices[i].dx7_note->peekVoiceStatus(voiceStatus);
  333. for (uint8_t op = 0; op < 6; op++)
  334. {
  335. if ((op_carrier & (1 << op)))
  336. {
  337. // this voice is a carrier!
  338. op_carrier_num++;
  339. if (voiceStatus.amp[op] <= 1069 && voiceStatus.ampStep[op] == 4)
  340. {
  341. // this voice produces no audio output
  342. op_amp++;
  343. }
  344. }
  345. }
  346. if (op_amp == op_carrier_num)
  347. {
  348. // all carrier-operators are silent -> disable the voice
  349. voices[i].live = false;
  350. voices[i].sustained = false;
  351. voices[i].keydown = false;
  352. #ifdef DEBUG
  353. Serial.print(F("Shutdown voice: "));
  354. Serial.println(i, DEC);
  355. #endif
  356. }
  357. else
  358. count_playing_voices++;
  359. }
  360. }
  361. return (count_playing_voices);
  362. }
  363. bool Dexed::loadSysexVoice(uint8_t* new_data)
  364. {
  365. uint8_t* p_data = data;
  366. uint8_t op;
  367. uint8_t tmp;
  368. //notesOff();
  369. for (op = 0; op < 6; op++)
  370. {
  371. // DEXED_OP_EG_R1, // 0
  372. // DEXED_OP_EG_R2, // 1
  373. // DEXED_OP_EG_R3, // 2
  374. // DEXED_OP_EG_R4, // 3
  375. // DEXED_OP_EG_L1, // 4
  376. // DEXED_OP_EG_L2, // 5
  377. // DEXED_OP_EG_L3, // 6
  378. // DEXED_OP_EG_L4, // 7
  379. // DEXED_OP_LEV_SCL_BRK_PT, // 8
  380. // DEXED_OP_SCL_LEFT_DEPTH, // 9
  381. // DEXED_OP_SCL_RGHT_DEPTH, // 10
  382. memcpy(&data[op * 21], &new_data[op * 17], 11);
  383. tmp = new_data[(op * 17) + 11];
  384. *(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) = (tmp & 0x3);
  385. *(p_data + DEXED_OP_SCL_RGHT_CURVE + (op * 21)) = (tmp & 0x0c) >> 2;
  386. tmp = new_data[(op * 17) + 12];
  387. *(p_data + DEXED_OP_OSC_DETUNE + (op * 21)) = (tmp & 0x78) >> 3;
  388. *(p_data + DEXED_OP_OSC_RATE_SCALE + (op * 21)) = (tmp & 0x07);
  389. tmp = new_data[(op * 17) + 13];
  390. *(p_data + DEXED_OP_KEY_VEL_SENS + (op * 21)) = (tmp & 0x1c) >> 2;
  391. *(p_data + DEXED_OP_AMP_MOD_SENS + (op * 21)) = (tmp & 0x03);
  392. *(p_data + DEXED_OP_OUTPUT_LEV + (op * 21)) = new_data[(op * 17) + 14];
  393. tmp = new_data[(op * 17) + 15];
  394. *(p_data + DEXED_OP_FREQ_COARSE + (op * 21)) = (tmp & 0x3e) >> 1;
  395. *(p_data + DEXED_OP_OSC_MODE + (op * 21)) = (tmp & 0x01);
  396. *(p_data + DEXED_OP_FREQ_FINE + (op * 21)) = new_data[(op * 17) + 16];
  397. }
  398. // DEXED_PITCH_EG_R1, // 0
  399. // DEXED_PITCH_EG_R2, // 1
  400. // DEXED_PITCH_EG_R3, // 2
  401. // DEXED_PITCH_EG_R4, // 3
  402. // DEXED_PITCH_EG_L1, // 4
  403. // DEXED_PITCH_EG_L2, // 5
  404. // DEXED_PITCH_EG_L3, // 6
  405. // DEXED_PITCH_EG_L4, // 7
  406. memcpy(&data[DEXED_VOICE_OFFSET], &new_data[102], 8);
  407. tmp = new_data[110];
  408. *(p_data + DEXED_VOICE_OFFSET + DEXED_ALGORITHM) = (tmp & 0x1f);
  409. tmp = new_data[111];
  410. *(p_data + DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC) = (tmp & 0x08) >> 3;
  411. *(p_data + DEXED_VOICE_OFFSET + DEXED_FEEDBACK) = (tmp & 0x07);
  412. // DEXED_LFO_SPEED, // 11
  413. // DEXED_LFO_DELAY, // 12
  414. // DEXED_LFO_PITCH_MOD_DEP, // 13
  415. // DEXED_LFO_AMP_MOD_DEP, // 14
  416. memcpy(&data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], &new_data[112], 4);
  417. tmp = new_data[116];
  418. *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS) = (tmp & 0x30) >> 4;
  419. *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_WAVE) = (tmp & 0x0e) >> 1;
  420. *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_SYNC) = (tmp & 0x01);
  421. *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = new_data[117];
  422. memcpy(&data[DEXED_VOICE_OFFSET + DEXED_NAME], &new_data[118], 10);
  423. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE) = 1;
  424. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP) = 1;
  425. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE) = 99;
  426. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN) = 7;
  427. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE) = 99;
  428. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN) = 7;
  429. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE) = 99;
  430. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN) = 7;
  431. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE) = 99;
  432. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN) = 7;
  433. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE) = 0;
  434. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP1_ENABLE) = 1;
  435. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP2_ENABLE) = 1;
  436. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP3_ENABLE) = 1;
  437. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP4_ENABLE) = 1;
  438. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP5_ENABLE) = 1;
  439. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP6_ENABLE) = 1;
  440. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MAX_NOTES) = MAX_NOTES;
  441. controllers.values_[kControllerPitchRange] = data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE];
  442. controllers.values_[kControllerPitchStep] = data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP];
  443. controllers.wheel.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]);
  444. controllers.wheel.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]);
  445. controllers.foot.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]);
  446. controllers.foot.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]);
  447. controllers.breath.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]);
  448. controllers.breath.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]);
  449. controllers.at.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]);
  450. controllers.at.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]);
  451. controllers.masterTune = (data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12);
  452. controllers.refresh();
  453. setOPs((*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP1_ENABLE) << 5) |
  454. (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP2_ENABLE) << 4) |
  455. (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP3_ENABLE) << 3) |
  456. (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP4_ENABLE) << 2) |
  457. (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP5_ENABLE) << 1) |
  458. *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP6_ENABLE ));
  459. setMaxNotes(*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MAX_NOTES));
  460. //panic();
  461. doRefreshVoice();
  462. //activate();
  463. strncpy(voice_name, (char *)&data[145], sizeof(voice_name) - 1);
  464. #ifdef DEBUG
  465. //char voicename[11];
  466. //memset(voicename, 0, sizeof(voicename));
  467. //strncpy(voicename, (char *)&data[145], sizeof(voicename) - 1);
  468. Serial.print(F("Voice ["));
  469. //Serial.print(voicename);
  470. Serial.print(voice_name);
  471. Serial.println(F("] loaded."));
  472. #endif
  473. return (true);
  474. }