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.

818 lines
24KB

  1. // Copyright 2013 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Multi.
  28. #include "yarns/multi.h"
  29. #include <algorithm>
  30. #include "stmlib/algorithms/voice_allocator.h"
  31. #include "yarns/just_intonation_processor.h"
  32. #include "yarns/midi_handler.h"
  33. #include "yarns/settings.h"
  34. namespace yarns {
  35. using namespace std;
  36. using namespace stmlib;
  37. const uint8_t clock_divisions[] = {
  38. 96, 48, 32, 24, 16, 12, 8, 6, 4, 3, 2, 1
  39. };
  40. void Multi::Init() {
  41. just_intonation_processor.Init();
  42. fill(
  43. &settings_.custom_pitch_table[0],
  44. &settings_.custom_pitch_table[12],
  45. 0);
  46. for (uint8_t i = 0; i < kNumParts; ++i) {
  47. part_[i].Init();
  48. part_[i].set_custom_pitch_table(settings_.custom_pitch_table);
  49. }
  50. for (uint8_t i = 0; i < kNumVoices; ++i) {
  51. voice_[i].Init();
  52. }
  53. running_ = false;
  54. latched_ = false;
  55. recording_ = false;
  56. // Put the multi in a usable state. Even if these settings will later be
  57. // overriden with some data retrieved from Flash (presets).
  58. settings_.clock_tempo = 120;
  59. settings_.clock_swing = 0;
  60. settings_.clock_input_division = 1;
  61. settings_.clock_output_division = 7;
  62. settings_.clock_bar_duration = 4;
  63. settings_.clock_override = 0;
  64. MidiSettings* midi = part_[0].mutable_midi_settings();
  65. midi->channel = 0;
  66. midi->min_note = 0;
  67. midi->max_note = 127;
  68. midi->min_velocity = 0;
  69. midi->max_velocity = 127;
  70. midi->out_mode = MIDI_OUT_MODE_GENERATED_EVENTS;
  71. VoicingSettings* voicing = part_[0].mutable_voicing_settings();
  72. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  73. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  74. voicing->legato_mode = false;
  75. voicing->portamento = 0;
  76. voicing->pitch_bend_range = 2;
  77. voicing->vibrato_range = 1;
  78. voicing->modulation_rate = 50;
  79. voicing->trigger_duration = 2;
  80. voicing->aux_cv = 1;
  81. voicing->aux_cv_2 = 6;
  82. voicing->tuning_transpose = 0;
  83. voicing->tuning_fine = 0;
  84. voicing->tuning_root = 0;
  85. voicing->tuning_system = 0;
  86. voicing->audio_mode = 0;
  87. SequencerSettings* seq = part_[0].mutable_sequencer_settings();
  88. seq->clock_division = 7;
  89. seq->gate_length = 3;
  90. seq->arp_range = 0;
  91. seq->arp_direction = 0;
  92. seq->arp_pattern = 0;
  93. fill(
  94. &seq->step[0],
  95. &seq->step[kNumSteps],
  96. SequencerStep(SEQUENCER_STEP_REST, 0));
  97. seq->num_steps = 0;
  98. // A test sequence...
  99. // seq->num_steps = 4;
  100. // seq->step[0].data[0] = 48;
  101. // seq->step[0].data[1] = 0x7f;
  102. // seq->step[1].data[0] = 72;
  103. // seq->step[1].data[1] = 0x7f;
  104. // seq->step[2].data[0] = 60;
  105. // seq->step[2].data[1] = 0x7f;
  106. // seq->step[3].data[0] = 72;
  107. // seq->step[3].data[1] = 0x7f;
  108. // voicing->audio_mode = 1; // To hear it...
  109. num_active_parts_ = 1;
  110. part_[0].AllocateVoices(&voice_[0], 1, false);
  111. settings_.layout = LAYOUT_MONO;
  112. }
  113. void Multi::Clock() {
  114. if (!running_) {
  115. return;
  116. }
  117. uint16_t output_division = clock_divisions[settings_.clock_output_division];
  118. uint16_t input_division = settings_.clock_input_division;
  119. // Logic equation for computing a clock output with a 50% duty cycle.
  120. if (output_division > 1) {
  121. if (clock_output_prescaler_ == 0 && clock_input_prescaler_ == 0) {
  122. clock_pulse_counter_ = 0xffff;
  123. }
  124. if (clock_output_prescaler_ == (output_division >> 1) &&
  125. clock_input_prescaler_ == (input_division >> 1)) {
  126. clock_pulse_counter_ = 0;
  127. }
  128. } else {
  129. if (input_division > 1) {
  130. clock_pulse_counter_ = \
  131. clock_input_prescaler_ <= (input_division - 1) >> 1 ? 0xffff : 0;
  132. } else {
  133. // Because no division is used, neither on the output nor on the input,
  134. // we don't have a sufficient fast time base to derive a 50% duty cycle
  135. // output. Instead, we output 5ms pulses.
  136. clock_pulse_counter_ = 40;
  137. }
  138. }
  139. if (!clock_input_prescaler_) {
  140. midi_handler.OnClock();
  141. if (song_pointer_) {
  142. ClockSong();
  143. } else {
  144. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  145. part_[i].Clock();
  146. }
  147. }
  148. ++bar_position_;
  149. if (bar_position_ >= settings_.clock_bar_duration * 24) {
  150. bar_position_ = 0;
  151. }
  152. if (bar_position_ == 0) {
  153. reset_pulse_counter_ = 81;
  154. }
  155. if (settings_.clock_bar_duration > kMaxBarDuration) {
  156. bar_position_ = 1;
  157. }
  158. ++clock_output_prescaler_;
  159. if (clock_output_prescaler_ >= output_division) {
  160. clock_output_prescaler_ = 0;
  161. }
  162. }
  163. ++clock_input_prescaler_;
  164. if (clock_input_prescaler_ >= settings_.clock_input_division) {
  165. clock_input_prescaler_ = 0;
  166. }
  167. if (stop_count_down_) {
  168. --stop_count_down_;
  169. if (!stop_count_down_ && started_by_keyboard_ && internal_clock()) {
  170. Stop();
  171. }
  172. }
  173. }
  174. void Multi::Start(bool started_by_keyboard) {
  175. if (running_ || recording_) {
  176. return;
  177. }
  178. if (internal_clock()) {
  179. internal_clock_ticks_ = 0;
  180. internal_clock_.Start(settings_.clock_tempo, settings_.clock_swing);
  181. }
  182. midi_handler.OnStart();
  183. started_by_keyboard_ = started_by_keyboard;
  184. running_ = true;
  185. latched_ = false;
  186. clock_input_prescaler_ = 0;
  187. clock_output_prescaler_ = 0;
  188. stop_count_down_ = 0;
  189. bar_position_ = 0xffff;
  190. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  191. part_[i].Start(started_by_keyboard);
  192. }
  193. song_pointer_ = NULL;
  194. }
  195. void Multi::Stop() {
  196. if (!running()) {
  197. return;
  198. }
  199. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  200. part_[i].Stop();
  201. }
  202. midi_handler.OnStop();
  203. clock_pulse_counter_ = 0;
  204. reset_pulse_counter_ = 0;
  205. stop_count_down_ = 0;
  206. running_ = false;
  207. latched_ = false;
  208. started_by_keyboard_ = false;
  209. song_pointer_ = NULL;
  210. }
  211. void Multi::Refresh() {
  212. if (clock_pulse_counter_) {
  213. --clock_pulse_counter_;
  214. }
  215. if (reset_pulse_counter_) {
  216. --reset_pulse_counter_;
  217. }
  218. for (uint8_t i = 0; i < kNumVoices; ++i) {
  219. voice_[i].Refresh();
  220. }
  221. }
  222. void Multi::Set(uint8_t address, uint8_t value) {
  223. uint8_t* bytes;
  224. bytes = static_cast<uint8_t*>(static_cast<void*>(&settings_));
  225. uint8_t previous_value = bytes[address];
  226. bytes[address] = value;
  227. if (value != previous_value) {
  228. if (address == MULTI_LAYOUT) {
  229. ChangeLayout(
  230. static_cast<Layout>(previous_value),
  231. static_cast<Layout>(value));
  232. } else if (address == MULTI_CLOCK_TEMPO) {
  233. internal_clock_.set_tempo(settings_.clock_tempo);
  234. } else if (address == MULTI_CLOCK_SWING) {
  235. internal_clock_.set_swing(settings_.clock_swing);
  236. }
  237. }
  238. }
  239. void Multi::GetCvGate(uint16_t* cv, bool* gate) {
  240. switch (settings_.layout) {
  241. case LAYOUT_MONO:
  242. case LAYOUT_DUAL_POLYCHAINED:
  243. cv[0] = voice_[0].note_dac_code();
  244. cv[1] = voice_[0].velocity_dac_code();
  245. cv[2] = voice_[0].aux_cv_dac_code();
  246. cv[3] = voice_[0].aux_cv_dac_code_2();
  247. gate[0] = voice_[0].gate();
  248. gate[1] = voice_[0].trigger();
  249. gate[2] = clock();
  250. gate[3] = reset_or_playing_flag();
  251. break;
  252. case LAYOUT_DUAL_MONO:
  253. cv[0] = voice_[0].note_dac_code();
  254. cv[1] = voice_[1].note_dac_code();
  255. cv[2] = voice_[0].aux_cv_dac_code();
  256. cv[3] = voice_[1].aux_cv_dac_code();
  257. gate[0] = voice_[0].gate();
  258. gate[1] = voice_[1].gate();
  259. gate[2] = clock();
  260. gate[3] = reset_or_playing_flag();
  261. break;
  262. case LAYOUT_DUAL_POLY:
  263. case LAYOUT_QUAD_POLYCHAINED:
  264. cv[0] = voice_[0].note_dac_code();
  265. cv[1] = voice_[1].note_dac_code();
  266. cv[2] = voice_[0].aux_cv_dac_code();
  267. cv[3] = voice_[1].aux_cv_dac_code_2();
  268. gate[0] = voice_[0].gate();
  269. gate[1] = voice_[1].gate();
  270. gate[2] = clock();
  271. gate[3] = reset_or_playing_flag();
  272. break;
  273. case LAYOUT_QUAD_MONO:
  274. case LAYOUT_QUAD_POLY:
  275. case LAYOUT_OCTAL_POLYCHAINED:
  276. case LAYOUT_THREE_ONE:
  277. cv[0] = voice_[0].note_dac_code();
  278. cv[1] = voice_[1].note_dac_code();
  279. cv[2] = voice_[2].note_dac_code();
  280. cv[3] = voice_[3].note_dac_code();
  281. gate[0] = voice_[0].gate();
  282. gate[1] = voice_[1].gate();
  283. if (settings_.clock_override) {
  284. gate[2] = clock();
  285. gate[3] = reset_or_playing_flag();
  286. } else {
  287. gate[2] = voice_[2].gate();
  288. gate[3] = voice_[3].gate();
  289. }
  290. break;
  291. case LAYOUT_QUAD_TRIGGERS:
  292. cv[0] = voice_[0].trigger_dac_code();
  293. cv[1] = voice_[1].trigger_dac_code();
  294. cv[2] = voice_[2].trigger_dac_code();
  295. cv[3] = voice_[3].trigger_dac_code();
  296. gate[0] = voice_[0].trigger() && ~voice_[1].gate();
  297. gate[1] = voice_[0].trigger() && voice_[1].gate();
  298. gate[2] = clock();
  299. gate[3] = reset_or_playing_flag();
  300. break;
  301. case LAYOUT_QUAD_VOLTAGES:
  302. cv[0] = voice_[0].aux_cv_dac_code();
  303. cv[1] = voice_[1].aux_cv_dac_code();
  304. cv[2] = voice_[2].aux_cv_dac_code();
  305. cv[3] = voice_[3].aux_cv_dac_code();
  306. gate[0] = voice_[0].gate();
  307. gate[1] = voice_[1].gate();
  308. if (settings_.clock_override) {
  309. gate[2] = clock();
  310. gate[3] = reset_or_playing_flag();
  311. } else {
  312. gate[2] = voice_[2].gate();
  313. gate[3] = voice_[3].gate();
  314. }
  315. break;
  316. }
  317. }
  318. bool Multi::GetAudioSource(uint8_t* audio_source) {
  319. bool has_audio_source = false;
  320. switch (settings_.layout) {
  321. case LAYOUT_MONO:
  322. case LAYOUT_DUAL_POLYCHAINED:
  323. audio_source[0] = 0xff;
  324. audio_source[1] = 0xff;
  325. audio_source[2] = 0xff;
  326. audio_source[3] = voice_[0].audio_mode() ? 0 : 0xff;
  327. has_audio_source = voice_[0].audio_mode();
  328. break;
  329. case LAYOUT_DUAL_MONO:
  330. case LAYOUT_DUAL_POLY:
  331. case LAYOUT_QUAD_POLYCHAINED:
  332. audio_source[0] = 0xff;
  333. audio_source[1] = 0xff;
  334. audio_source[2] = voice_[0].audio_mode() ? 0 : 0xff;
  335. audio_source[3] = voice_[1].audio_mode() ? 1 : 0xff;
  336. has_audio_source = voice_[0].audio_mode() || voice_[1].audio_mode();
  337. break;
  338. case LAYOUT_QUAD_MONO:
  339. case LAYOUT_QUAD_POLY:
  340. case LAYOUT_OCTAL_POLYCHAINED:
  341. case LAYOUT_THREE_ONE:
  342. audio_source[0] = voice_[0].audio_mode() ? 0 : 0xff;
  343. audio_source[1] = voice_[1].audio_mode() ? 1 : 0xff;
  344. audio_source[2] = voice_[2].audio_mode() ? 2 : 0xff;
  345. audio_source[3] = voice_[3].audio_mode() ? 3 : 0xff;
  346. has_audio_source = voice_[0].audio_mode() || voice_[1].audio_mode() || \
  347. voice_[2].audio_mode() || voice_[3].audio_mode();
  348. break;
  349. case LAYOUT_QUAD_TRIGGERS:
  350. case LAYOUT_QUAD_VOLTAGES:
  351. audio_source[0] = 0xff;
  352. audio_source[1] = 0xff;
  353. audio_source[2] = 0xff;
  354. audio_source[3] = 0xff;
  355. has_audio_source = false;
  356. break;
  357. }
  358. return has_audio_source;
  359. }
  360. void Multi::GetLedsBrightness(uint8_t* brightness) {
  361. if (layout_configurator_.learning()) {
  362. fill(&brightness[0], &brightness[kNumVoices], 0);
  363. for (uint8_t i = 0; i < layout_configurator_.num_notes(); ++i) {
  364. brightness[i] = 255;
  365. }
  366. return;
  367. }
  368. switch (settings_.layout) {
  369. case LAYOUT_MONO:
  370. case LAYOUT_DUAL_POLYCHAINED:
  371. brightness[0] = voice_[0].gate() ? 255 : 0;
  372. brightness[1] = voice_[0].velocity() << 1;
  373. brightness[2] = voice_[0].aux_cv();
  374. brightness[3] = voice_[0].aux_cv_2();
  375. break;
  376. case LAYOUT_DUAL_MONO:
  377. brightness[0] = voice_[0].gate() ? 255 : 0;
  378. brightness[1] = voice_[1].gate() ? 255 : 0;
  379. brightness[2] = voice_[0].aux_cv();
  380. brightness[3] = voice_[1].aux_cv();
  381. break;
  382. case LAYOUT_DUAL_POLY:
  383. case LAYOUT_QUAD_POLYCHAINED:
  384. brightness[0] = voice_[0].gate() ? 255 : 0;
  385. brightness[1] = voice_[1].gate() ? 255 : 0;
  386. brightness[2] = voice_[0].aux_cv();
  387. brightness[3] = voice_[1].aux_cv_2();
  388. break;
  389. case LAYOUT_QUAD_MONO:
  390. case LAYOUT_QUAD_POLY:
  391. case LAYOUT_OCTAL_POLYCHAINED:
  392. case LAYOUT_QUAD_TRIGGERS:
  393. case LAYOUT_THREE_ONE:
  394. brightness[0] = voice_[0].gate() ? (voice_[0].velocity() << 1) : 0;
  395. brightness[1] = voice_[1].gate() ? (voice_[1].velocity() << 1) : 0;
  396. brightness[2] = voice_[2].gate() ? (voice_[2].velocity() << 1) : 0;
  397. brightness[3] = voice_[3].gate() ? (voice_[3].velocity() << 1) : 0;
  398. break;
  399. case LAYOUT_QUAD_VOLTAGES:
  400. brightness[0] = voice_[0].aux_cv();
  401. brightness[1] = voice_[1].aux_cv();
  402. brightness[2] = voice_[2].aux_cv();
  403. brightness[3] = voice_[3].aux_cv();
  404. break;
  405. }
  406. }
  407. void Multi::UpdateLayout() {
  408. // Reset and close all parts and voices.
  409. for (uint8_t i = 0; i < kNumParts; ++i) {
  410. part_[i].Reset();
  411. }
  412. for (uint8_t i = 0; i < kNumVoices; ++i) {
  413. voice_[i].NoteOff();
  414. }
  415. switch (settings_.layout) {
  416. case LAYOUT_MONO:
  417. case LAYOUT_DUAL_MONO:
  418. case LAYOUT_QUAD_MONO:
  419. {
  420. uint8_t num_parts = settings_.layout == LAYOUT_MONO ? 1 : \
  421. (settings_.layout == LAYOUT_DUAL_MONO ? 2 : 4);
  422. for (uint8_t i = 0; i < num_parts; ++i) {
  423. part_[i].AllocateVoices(&voice_[i], 1, false);
  424. }
  425. num_active_parts_ = num_parts;
  426. }
  427. break;
  428. case LAYOUT_DUAL_POLY:
  429. case LAYOUT_QUAD_POLY:
  430. case LAYOUT_DUAL_POLYCHAINED:
  431. case LAYOUT_QUAD_POLYCHAINED:
  432. case LAYOUT_OCTAL_POLYCHAINED:
  433. {
  434. uint8_t num_voices = settings_.layout == LAYOUT_DUAL_POLY || \
  435. settings_.layout == LAYOUT_QUAD_POLYCHAINED ? 2 : \
  436. (settings_.layout == LAYOUT_DUAL_POLYCHAINED ? 1 : 4);
  437. part_[0].AllocateVoices(
  438. &voice_[0],
  439. num_voices,
  440. settings_.layout >= LAYOUT_DUAL_POLYCHAINED);
  441. num_active_parts_ = 1;
  442. }
  443. break;
  444. case LAYOUT_QUAD_TRIGGERS:
  445. case LAYOUT_QUAD_VOLTAGES:
  446. {
  447. for (uint8_t i = 0; i < 4; ++i) {
  448. part_[i].AllocateVoices(&voice_[i], 1, false);
  449. }
  450. num_active_parts_ = 4;
  451. }
  452. break;
  453. case LAYOUT_THREE_ONE:
  454. {
  455. part_[0].AllocateVoices(&voice_[0], 3, false);
  456. part_[1].AllocateVoices(&voice_[3], 1, false);
  457. num_active_parts_ = 2;
  458. }
  459. break;
  460. default:
  461. break;
  462. }
  463. }
  464. void Multi::ChangeLayout(Layout old_layout, Layout new_layout) {
  465. // Reset and close all parts and voices.
  466. for (uint8_t i = 0; i < kNumParts; ++i) {
  467. part_[i].Reset();
  468. }
  469. for (uint8_t i = 0; i < kNumVoices; ++i) {
  470. voice_[i].NoteOff();
  471. }
  472. switch (new_layout) {
  473. case LAYOUT_MONO:
  474. case LAYOUT_DUAL_MONO:
  475. case LAYOUT_QUAD_MONO:
  476. {
  477. uint8_t num_parts = new_layout == LAYOUT_MONO ? 1 : \
  478. (new_layout == LAYOUT_DUAL_MONO ? 2 : 4);
  479. for (uint8_t i = 0; i < num_parts; ++i) {
  480. MidiSettings* midi = part_[i].mutable_midi_settings();
  481. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  482. midi->min_note = 0;
  483. midi->max_note = 127;
  484. }
  485. midi->min_velocity = 0;
  486. midi->max_velocity = 127;
  487. VoicingSettings* voicing = part_[i].mutable_voicing_settings();
  488. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  489. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  490. }
  491. // Duplicate uninitialized voices.
  492. for (uint8_t i = 1; i < num_parts; ++i) {
  493. uint8_t destination = i;
  494. uint8_t source = i % num_active_parts_;
  495. if (destination != source) {
  496. memcpy(
  497. part_[destination].mutable_midi_settings(),
  498. part_[source].mutable_midi_settings(),
  499. sizeof(MidiSettings));
  500. memcpy(
  501. part_[destination].mutable_voicing_settings(),
  502. part_[source].mutable_voicing_settings(),
  503. sizeof(VoicingSettings));
  504. memcpy(
  505. part_[destination].mutable_sequencer_settings(),
  506. part_[source].mutable_sequencer_settings(),
  507. sizeof(SequencerSettings));
  508. }
  509. }
  510. for (uint8_t i = 0; i < num_parts; ++i) {
  511. part_[i].AllocateVoices(&voice_[i], 1, false);
  512. }
  513. num_active_parts_ = num_parts;
  514. }
  515. break;
  516. case LAYOUT_DUAL_POLY:
  517. case LAYOUT_QUAD_POLY:
  518. case LAYOUT_DUAL_POLYCHAINED:
  519. case LAYOUT_QUAD_POLYCHAINED:
  520. case LAYOUT_OCTAL_POLYCHAINED:
  521. {
  522. uint8_t num_voices = settings_.layout == LAYOUT_DUAL_POLY || \
  523. settings_.layout == LAYOUT_QUAD_POLYCHAINED ? 2 : \
  524. (settings_.layout == LAYOUT_DUAL_POLYCHAINED ? 1 : 4);
  525. MidiSettings* midi = part_[0].mutable_midi_settings();
  526. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  527. midi->min_note = 0;
  528. midi->max_note = 127;
  529. }
  530. midi->min_velocity = 0;
  531. midi->max_velocity = 127;
  532. VoicingSettings* voicing = part_[0].mutable_voicing_settings();
  533. voicing->allocation_mode = VOICE_ALLOCATION_MODE_POLY;
  534. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  535. voicing->portamento = 0;
  536. voicing->legato_mode = 0;
  537. part_[0].AllocateVoices(
  538. &voice_[0],
  539. num_voices,
  540. new_layout >= LAYOUT_DUAL_POLYCHAINED);
  541. num_active_parts_ = 1;
  542. }
  543. break;
  544. case LAYOUT_QUAD_TRIGGERS:
  545. {
  546. for (uint8_t i = 0; i < 4; ++i) {
  547. MidiSettings* midi = part_[i].mutable_midi_settings();
  548. if (old_layout != LAYOUT_QUAD_TRIGGERS) {
  549. midi->min_note = 36 + i * 2;
  550. midi->max_note = 36 + i * 2;
  551. }
  552. midi->min_velocity = 0;
  553. midi->max_velocity = 127;
  554. midi->channel = part_[0].mutable_midi_settings()->channel;
  555. midi->out_mode = part_[0].mutable_midi_settings()->out_mode;
  556. VoicingSettings* voicing = part_[i].mutable_voicing_settings();
  557. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  558. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  559. voicing->portamento = 0;
  560. voicing->legato_mode = 0;
  561. }
  562. // Duplicate sequencer settings.
  563. for (uint8_t i = 1; i < 4; ++i) {
  564. uint8_t destination = i;
  565. uint8_t source = i % num_active_parts_;
  566. if (destination != source) {
  567. memcpy(
  568. part_[destination].mutable_sequencer_settings(),
  569. part_[source].mutable_sequencer_settings(),
  570. sizeof(SequencerSettings));
  571. }
  572. }
  573. for (uint8_t i = 0; i < 4; ++i) {
  574. part_[i].AllocateVoices(&voice_[i], 1, false);
  575. }
  576. num_active_parts_ = 4;
  577. }
  578. break;
  579. case LAYOUT_THREE_ONE:
  580. {
  581. MidiSettings* midi = part_[0].mutable_midi_settings();
  582. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  583. midi->min_note = 0;
  584. midi->max_note = 127;
  585. }
  586. midi->min_velocity = 0;
  587. midi->max_velocity = 127;
  588. VoicingSettings* voicing = part_[0].mutable_voicing_settings();
  589. voicing->allocation_mode = VOICE_ALLOCATION_MODE_POLY;
  590. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  591. voicing->portamento = 0;
  592. voicing->legato_mode = 0;
  593. part_[0].AllocateVoices(&voice_[0], 3, false);
  594. midi = part_[1].mutable_midi_settings();
  595. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  596. midi->min_note = 0;
  597. midi->max_note = 127;
  598. }
  599. midi->min_velocity = 0;
  600. midi->max_velocity = 127;
  601. voicing = part_[1].mutable_voicing_settings();
  602. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  603. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  604. voicing->portamento = 0;
  605. voicing->legato_mode = 0;
  606. part_[1].AllocateVoices(&voice_[3], 1, false);
  607. num_active_parts_ = 2;
  608. }
  609. break;
  610. case LAYOUT_QUAD_VOLTAGES:
  611. {
  612. uint8_t num_parts = 4;
  613. for (uint8_t i = 0; i < num_parts; ++i) {
  614. MidiSettings* midi = part_[i].mutable_midi_settings();
  615. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  616. midi->min_note = 0;
  617. midi->max_note = 127;
  618. }
  619. midi->min_velocity = 0;
  620. midi->max_velocity = 127;
  621. VoicingSettings* voicing = part_[i].mutable_voicing_settings();
  622. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  623. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  624. }
  625. // Duplicate uninitialized voices.
  626. for (uint8_t i = 1; i < num_parts; ++i) {
  627. uint8_t destination = i;
  628. uint8_t source = i % num_active_parts_;
  629. if (destination != source) {
  630. memcpy(
  631. part_[destination].mutable_midi_settings(),
  632. part_[source].mutable_midi_settings(),
  633. sizeof(MidiSettings));
  634. memcpy(
  635. part_[destination].mutable_voicing_settings(),
  636. part_[source].mutable_voicing_settings(),
  637. sizeof(VoicingSettings));
  638. memcpy(
  639. part_[destination].mutable_sequencer_settings(),
  640. part_[source].mutable_sequencer_settings(),
  641. sizeof(SequencerSettings));
  642. }
  643. }
  644. for (uint8_t i = 0; i < num_parts; ++i) {
  645. part_[i].AllocateVoices(&voice_[i], 1, false);
  646. }
  647. num_active_parts_ = num_parts;
  648. }
  649. break;
  650. default:
  651. break;
  652. }
  653. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  654. part_[i].set_siblings(num_active_parts_ > 1);
  655. }
  656. }
  657. void Multi::Touch() {
  658. Stop();
  659. internal_clock_.set_tempo(settings_.clock_tempo);
  660. UpdateLayout();
  661. for (uint8_t i = 0; i < kNumParts; ++i) {
  662. part_[i].Touch();
  663. }
  664. }
  665. const uint8_t song[] = {
  666. #include "song/song.h"
  667. 255,
  668. };
  669. void Multi::StartSong() {
  670. Set(MULTI_LAYOUT, LAYOUT_QUAD_MONO);
  671. part_[0].mutable_voicing_settings()->audio_mode = 0x83;
  672. part_[1].mutable_voicing_settings()->audio_mode = 0x83;
  673. part_[2].mutable_voicing_settings()->audio_mode = 0x84;
  674. part_[3].mutable_voicing_settings()->audio_mode = 0x86;
  675. UpdateLayout();
  676. settings_.clock_tempo = 140;
  677. Stop();
  678. Start(false);
  679. song_pointer_ = &song[0];
  680. song_clock_ = 0;
  681. song_delta_ = 0;
  682. }
  683. void Multi::ClockSong() {
  684. while (song_clock_ >= song_delta_) {
  685. if (*song_pointer_ == 255) {
  686. song_pointer_ = &song[0];
  687. }
  688. if (*song_pointer_ == 254) {
  689. song_delta_ += 6;
  690. } else {
  691. uint8_t part = *song_pointer_ >> 6;
  692. uint8_t note = *song_pointer_ & 0x3f;
  693. if (note == 0) {
  694. part_[part].AllNotesOff();
  695. } else {
  696. part_[part].NoteOn(0, note + 24, 100);
  697. }
  698. song_clock_ = 0;
  699. song_delta_ = 0;
  700. }
  701. ++song_pointer_;
  702. }
  703. ++song_clock_;
  704. }
  705. bool Multi::ControlChange(uint8_t channel, uint8_t controller, uint8_t value) {
  706. bool thru = true;
  707. if (channel + 1 == settings_.remote_control_channel) {
  708. yarns::settings.SetFromCC(0xff, controller, value);
  709. if (num_active_parts_ >= 4 && \
  710. (controller == 0x78 || controller == 0x79 || controller == 0x7b)) {
  711. // Do not continue to avoid treating these messages as "all sound off",
  712. // "reset all controllers" and "all notes off" CC.
  713. return true;
  714. }
  715. }
  716. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  717. if (part_[i].accepts(channel) && \
  718. channel + 1 != settings_.remote_control_channel) {
  719. thru = part_[i].ControlChange(channel, controller, value) && thru;
  720. yarns::settings.SetFromCC(i, controller, value);
  721. }
  722. }
  723. return thru;
  724. }
  725. /* extern */
  726. Multi multi;
  727. } // namespace yarns