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.

778 lines
22KB

  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 = 0;
  81. voicing->tuning_transpose = 0;
  82. voicing->tuning_fine = 0;
  83. voicing->tuning_root = 0;
  84. voicing->tuning_system = 0;
  85. voicing->audio_mode = 0;
  86. SequencerSettings* seq = part_[0].mutable_sequencer_settings();
  87. seq->clock_division = 7;
  88. seq->gate_length = 3;
  89. seq->arp_range = 0;
  90. seq->arp_direction = 0;
  91. seq->arp_pattern = 0;
  92. fill(
  93. &seq->step[0],
  94. &seq->step[kNumSteps],
  95. SequencerStep(SEQUENCER_STEP_REST, 0));
  96. seq->num_steps = 0;
  97. // A test sequence...
  98. // seq->num_steps = 4;
  99. // seq->step[0].data[0] = 48;
  100. // seq->step[0].data[1] = 0x7f;
  101. // seq->step[1].data[0] = 72;
  102. // seq->step[1].data[1] = 0x7f;
  103. // seq->step[2].data[0] = 60;
  104. // seq->step[2].data[1] = 0x7f;
  105. // seq->step[3].data[0] = 72;
  106. // seq->step[3].data[1] = 0x7f;
  107. // voicing->audio_mode = 1; // To hear it...
  108. num_active_parts_ = 1;
  109. part_[0].AllocateVoices(&voice_[0], 1, false);
  110. settings_.layout = LAYOUT_MONO;
  111. }
  112. void Multi::Clock() {
  113. if (!running_) {
  114. return;
  115. }
  116. uint16_t output_division = clock_divisions[settings_.clock_output_division];
  117. uint16_t input_division = settings_.clock_input_division;
  118. // Logic equation for computing a clock output with a 50% duty cycle.
  119. if (output_division > 1) {
  120. if (clock_output_prescaler_ == 0 && clock_input_prescaler_ == 0) {
  121. clock_pulse_counter_ = 0xffff;
  122. }
  123. if (clock_output_prescaler_ == (output_division >> 1) &&
  124. clock_input_prescaler_ == (input_division >> 1)) {
  125. clock_pulse_counter_ = 0;
  126. }
  127. } else {
  128. if (input_division > 1) {
  129. clock_pulse_counter_ = \
  130. clock_input_prescaler_ <= (input_division - 1) >> 1 ? 0xffff : 0;
  131. } else {
  132. // Because no division is used, neither on the output nor on the input,
  133. // we don't have a sufficient fast time base to derive a 50% duty cycle
  134. // output. Instead, we output 5ms pulses.
  135. clock_pulse_counter_ = 40;
  136. }
  137. }
  138. if (!clock_input_prescaler_) {
  139. midi_handler.OnClock();
  140. if (song_pointer_) {
  141. ClockSong();
  142. } else {
  143. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  144. part_[i].Clock();
  145. }
  146. }
  147. ++bar_position_;
  148. if (bar_position_ >= settings_.clock_bar_duration * 24) {
  149. bar_position_ = 0;
  150. }
  151. if (bar_position_ == 0) {
  152. reset_pulse_counter_ = 81;
  153. }
  154. if (settings_.clock_bar_duration > kMaxBarDuration) {
  155. bar_position_ = 1;
  156. }
  157. ++clock_output_prescaler_;
  158. if (clock_output_prescaler_ >= output_division) {
  159. clock_output_prescaler_ = 0;
  160. }
  161. }
  162. ++clock_input_prescaler_;
  163. if (clock_input_prescaler_ >= settings_.clock_input_division) {
  164. clock_input_prescaler_ = 0;
  165. }
  166. if (stop_count_down_) {
  167. --stop_count_down_;
  168. if (!stop_count_down_ && started_by_keyboard_ && internal_clock()) {
  169. Stop();
  170. }
  171. }
  172. }
  173. void Multi::Start(bool started_by_keyboard) {
  174. if (running_ || recording_) {
  175. return;
  176. }
  177. if (internal_clock()) {
  178. internal_clock_ticks_ = 0;
  179. internal_clock_.Start(settings_.clock_tempo, settings_.clock_swing);
  180. }
  181. midi_handler.OnStart();
  182. started_by_keyboard_ = started_by_keyboard;
  183. running_ = true;
  184. latched_ = false;
  185. clock_input_prescaler_ = 0;
  186. clock_output_prescaler_ = 0;
  187. stop_count_down_ = 0;
  188. bar_position_ = 0xffff;
  189. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  190. part_[i].Start(started_by_keyboard);
  191. }
  192. song_pointer_ = NULL;
  193. }
  194. void Multi::Stop() {
  195. if (!running()) {
  196. return;
  197. }
  198. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  199. part_[i].Stop();
  200. }
  201. midi_handler.OnStop();
  202. clock_pulse_counter_ = 0;
  203. reset_pulse_counter_ = 0;
  204. stop_count_down_ = 0;
  205. running_ = false;
  206. latched_ = false;
  207. started_by_keyboard_ = false;
  208. song_pointer_ = NULL;
  209. }
  210. void Multi::Refresh() {
  211. if (clock_pulse_counter_) {
  212. --clock_pulse_counter_;
  213. }
  214. if (reset_pulse_counter_) {
  215. --reset_pulse_counter_;
  216. }
  217. for (uint8_t i = 0; i < kNumVoices; ++i) {
  218. voice_[i].Refresh();
  219. }
  220. }
  221. void Multi::Set(uint8_t address, uint8_t value) {
  222. uint8_t* bytes;
  223. bytes = static_cast<uint8_t*>(static_cast<void*>(&settings_));
  224. uint8_t previous_value = bytes[address];
  225. bytes[address] = value;
  226. if (value != previous_value) {
  227. if (address == MULTI_LAYOUT) {
  228. ChangeLayout(
  229. static_cast<Layout>(previous_value),
  230. static_cast<Layout>(value));
  231. } else if (address == MULTI_CLOCK_TEMPO) {
  232. internal_clock_.set_tempo(settings_.clock_tempo);
  233. } else if (address == MULTI_CLOCK_SWING) {
  234. internal_clock_.set_swing(settings_.clock_swing);
  235. }
  236. }
  237. }
  238. void Multi::GetCvGate(uint16_t* cv, bool* gate) {
  239. switch (settings_.layout) {
  240. case LAYOUT_MONO:
  241. case LAYOUT_DUAL_POLYCHAINED:
  242. {
  243. cv[0] = voice_[0].note_dac_code();
  244. cv[1] = voice_[0].velocity_dac_code();
  245. cv[2] = voice_[0].modulation_dac_code();
  246. cv[3] = voice_[0].aux_cv_dac_code();
  247. gate[0] = voice_[0].gate();
  248. gate[1] = voice_[0].trigger();
  249. gate[2] = clock();
  250. gate[3] = reset_or_playing_flag();
  251. }
  252. break;
  253. case LAYOUT_DUAL_MONO:
  254. // {
  255. // cv[0] = voice_[0].note_dac_code();
  256. // cv[1] = voice_[1].note_dac_code();
  257. // cv[2] = voice_[0].modulation_dac_code();
  258. // cv[3] = voice_[1].modulation_dac_code();
  259. // gate[0] = voice_[0].gate();
  260. // gate[1] = voice_[1].gate();
  261. // gate[2] = clock();
  262. // gate[3] = reset_or_playing_flag();
  263. // }
  264. // break;
  265. case LAYOUT_DUAL_POLY:
  266. case LAYOUT_QUAD_POLYCHAINED:
  267. {
  268. cv[0] = voice_[0].note_dac_code();
  269. cv[1] = voice_[1].note_dac_code();
  270. cv[2] = (voice_[0].modulation_dac_code() >> 1) + \
  271. (voice_[1].modulation_dac_code() >> 1);
  272. cv[3] = (voice_[0].aux_cv_dac_code() >> 1) +
  273. (voice_[1].aux_cv_dac_code() >> 1);
  274. gate[0] = voice_[0].gate();
  275. gate[1] = voice_[1].gate();
  276. gate[2] = clock();
  277. gate[3] = reset_or_playing_flag();
  278. }
  279. break;
  280. case LAYOUT_QUAD_MONO:
  281. case LAYOUT_QUAD_POLY:
  282. case LAYOUT_OCTAL_POLYCHAINED:
  283. case LAYOUT_THREE_ONE:
  284. {
  285. cv[0] = voice_[0].note_dac_code();
  286. cv[1] = voice_[1].note_dac_code();
  287. cv[2] = voice_[2].note_dac_code();
  288. cv[3] = voice_[3].note_dac_code();
  289. gate[0] = voice_[0].gate();
  290. gate[1] = voice_[1].gate();
  291. if (settings_.clock_override) {
  292. gate[2] = clock();
  293. gate[3] = reset_or_playing_flag();
  294. } else {
  295. gate[2] = voice_[2].gate();
  296. gate[3] = voice_[3].gate();
  297. }
  298. }
  299. break;
  300. case LAYOUT_QUAD_TRIGGERS:
  301. {
  302. cv[0] = voice_[0].trigger_dac_code();
  303. cv[1] = voice_[1].trigger_dac_code();
  304. cv[2] = voice_[2].trigger_dac_code();
  305. cv[3] = voice_[3].trigger_dac_code();
  306. gate[0] = voice_[0].trigger() && ~voice_[1].gate();
  307. gate[1] = voice_[0].trigger() && voice_[1].gate();
  308. gate[2] = clock();
  309. gate[3] = reset_or_playing_flag();
  310. }
  311. break;
  312. }
  313. }
  314. bool Multi::GetAudioSource(uint8_t* audio_source) {
  315. bool has_audio_source = false;
  316. switch (settings_.layout) {
  317. case LAYOUT_MONO:
  318. case LAYOUT_DUAL_POLYCHAINED:
  319. {
  320. audio_source[0] = 0xff;
  321. audio_source[1] = 0xff;
  322. audio_source[2] = 0xff;
  323. audio_source[3] = voice_[0].audio_mode() ? 0 : 0xff;
  324. has_audio_source = voice_[0].audio_mode();
  325. }
  326. break;
  327. case LAYOUT_DUAL_MONO:
  328. case LAYOUT_DUAL_POLY:
  329. case LAYOUT_QUAD_POLYCHAINED:
  330. {
  331. audio_source[0] = 0xff;
  332. audio_source[1] = 0xff;
  333. audio_source[2] = voice_[0].audio_mode() ? 0 : 0xff;
  334. audio_source[3] = voice_[1].audio_mode() ? 1 : 0xff;
  335. has_audio_source = voice_[0].audio_mode() || voice_[1].audio_mode();
  336. }
  337. break;
  338. case LAYOUT_QUAD_MONO:
  339. case LAYOUT_QUAD_POLY:
  340. case LAYOUT_OCTAL_POLYCHAINED:
  341. case LAYOUT_THREE_ONE:
  342. {
  343. audio_source[0] = voice_[0].audio_mode() ? 0 : 0xff;
  344. audio_source[1] = voice_[1].audio_mode() ? 1 : 0xff;
  345. audio_source[2] = voice_[2].audio_mode() ? 2 : 0xff;
  346. audio_source[3] = voice_[3].audio_mode() ? 3 : 0xff;
  347. has_audio_source = voice_[0].audio_mode() || voice_[1].audio_mode() || \
  348. voice_[2].audio_mode() || voice_[3].audio_mode();
  349. }
  350. break;
  351. case LAYOUT_QUAD_TRIGGERS:
  352. {
  353. audio_source[0] = 0xff;
  354. audio_source[1] = 0xff;
  355. audio_source[2] = 0xff;
  356. audio_source[3] = 0xff;
  357. has_audio_source = false;
  358. }
  359. break;
  360. }
  361. return has_audio_source;
  362. }
  363. void Multi::GetLedsBrightness(uint8_t* brightness) {
  364. if (layout_configurator_.learning()) {
  365. fill(&brightness[0], &brightness[kNumVoices], 0);
  366. for (uint8_t i = 0; i < layout_configurator_.num_notes(); ++i) {
  367. brightness[i] = 255;
  368. }
  369. return;
  370. }
  371. switch (settings_.layout) {
  372. case LAYOUT_MONO:
  373. case LAYOUT_DUAL_POLYCHAINED:
  374. {
  375. brightness[0] = voice_[0].gate() ? 255 : 0;
  376. brightness[1] = voice_[0].velocity() << 1;
  377. brightness[2] = voice_[0].modulation() << 1;
  378. brightness[3] = voice_[0].aux_cv();
  379. }
  380. break;
  381. case LAYOUT_DUAL_MONO:
  382. // {
  383. // brightness[0] = voice_[0].gate() ? 255 : 0;
  384. // brightness[1] = voice_[1].gate() ? 255 : 0;
  385. // brightness[2] = voice_[0].modulation();
  386. // brightness[3] = voice_[1].modulation();
  387. // }
  388. // break;
  389. //
  390. case LAYOUT_DUAL_POLY:
  391. case LAYOUT_QUAD_POLYCHAINED:
  392. {
  393. brightness[0] = voice_[0].gate() ? 255 : 0;
  394. brightness[1] = voice_[1].gate() ? 255 : 0;
  395. brightness[2] = voice_[0].modulation() + voice_[1].modulation();
  396. brightness[3] = (voice_[0].aux_cv() >> 1) + (voice_[1].aux_cv() >> 1);
  397. }
  398. break;
  399. case LAYOUT_QUAD_MONO:
  400. case LAYOUT_QUAD_POLY:
  401. case LAYOUT_OCTAL_POLYCHAINED:
  402. case LAYOUT_QUAD_TRIGGERS:
  403. case LAYOUT_THREE_ONE:
  404. {
  405. brightness[0] = voice_[0].gate() ? (voice_[0].velocity() << 1) : 0;
  406. brightness[1] = voice_[1].gate() ? (voice_[1].velocity() << 1) : 0;
  407. brightness[2] = voice_[2].gate() ? (voice_[2].velocity() << 1) : 0;
  408. brightness[3] = voice_[3].gate() ? (voice_[3].velocity() << 1) : 0;
  409. }
  410. break;
  411. }
  412. }
  413. void Multi::UpdateLayout() {
  414. // Reset and close all parts and voices.
  415. for (uint8_t i = 0; i < kNumParts; ++i) {
  416. part_[i].Reset();
  417. }
  418. for (uint8_t i = 0; i < kNumVoices; ++i) {
  419. voice_[i].NoteOff();
  420. }
  421. switch (settings_.layout) {
  422. case LAYOUT_MONO:
  423. case LAYOUT_DUAL_MONO:
  424. case LAYOUT_QUAD_MONO:
  425. {
  426. uint8_t num_parts = settings_.layout == LAYOUT_MONO ? 1 : \
  427. (settings_.layout == LAYOUT_DUAL_MONO ? 2 : 4);
  428. for (uint8_t i = 0; i < num_parts; ++i) {
  429. part_[i].AllocateVoices(&voice_[i], 1, false);
  430. }
  431. num_active_parts_ = num_parts;
  432. }
  433. break;
  434. case LAYOUT_DUAL_POLY:
  435. case LAYOUT_QUAD_POLY:
  436. case LAYOUT_DUAL_POLYCHAINED:
  437. case LAYOUT_QUAD_POLYCHAINED:
  438. case LAYOUT_OCTAL_POLYCHAINED:
  439. {
  440. uint8_t num_voices = settings_.layout == LAYOUT_DUAL_POLY || \
  441. settings_.layout == LAYOUT_QUAD_POLYCHAINED ? 2 : \
  442. (settings_.layout == LAYOUT_DUAL_POLYCHAINED ? 1 : 4);
  443. part_[0].AllocateVoices(
  444. &voice_[0],
  445. num_voices,
  446. settings_.layout >= LAYOUT_DUAL_POLYCHAINED);
  447. num_active_parts_ = 1;
  448. }
  449. break;
  450. case LAYOUT_QUAD_TRIGGERS:
  451. {
  452. for (uint8_t i = 0; i < 4; ++i) {
  453. part_[i].AllocateVoices(&voice_[i], 1, false);
  454. }
  455. num_active_parts_ = 4;
  456. }
  457. break;
  458. case LAYOUT_THREE_ONE:
  459. {
  460. part_[0].AllocateVoices(&voice_[0], 3, false);
  461. part_[1].AllocateVoices(&voice_[3], 1, false);
  462. num_active_parts_ = 2;
  463. }
  464. break;
  465. default:
  466. break;
  467. }
  468. }
  469. void Multi::ChangeLayout(Layout old_layout, Layout new_layout) {
  470. // Reset and close all parts and voices.
  471. for (uint8_t i = 0; i < kNumParts; ++i) {
  472. part_[i].Reset();
  473. }
  474. for (uint8_t i = 0; i < kNumVoices; ++i) {
  475. voice_[i].NoteOff();
  476. }
  477. switch (new_layout) {
  478. case LAYOUT_MONO:
  479. case LAYOUT_DUAL_MONO:
  480. case LAYOUT_QUAD_MONO:
  481. {
  482. uint8_t num_parts = new_layout == LAYOUT_MONO ? 1 : \
  483. (new_layout == LAYOUT_DUAL_MONO ? 2 : 4);
  484. for (uint8_t i = 0; i < num_parts; ++i) {
  485. MidiSettings* midi = part_[i].mutable_midi_settings();
  486. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  487. midi->min_note = 0;
  488. midi->max_note = 127;
  489. }
  490. midi->min_velocity = 0;
  491. midi->max_velocity = 127;
  492. VoicingSettings* voicing = part_[i].mutable_voicing_settings();
  493. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  494. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  495. }
  496. // Duplicate uninitialized voices.
  497. for (uint8_t i = 1; i < num_parts; ++i) {
  498. uint8_t destination = i;
  499. uint8_t source = i % num_active_parts_;
  500. if (destination != source) {
  501. memcpy(
  502. part_[destination].mutable_midi_settings(),
  503. part_[source].mutable_midi_settings(),
  504. sizeof(MidiSettings));
  505. memcpy(
  506. part_[destination].mutable_voicing_settings(),
  507. part_[source].mutable_voicing_settings(),
  508. sizeof(VoicingSettings));
  509. memcpy(
  510. part_[destination].mutable_sequencer_settings(),
  511. part_[source].mutable_sequencer_settings(),
  512. sizeof(SequencerSettings));
  513. }
  514. }
  515. for (uint8_t i = 0; i < num_parts; ++i) {
  516. part_[i].AllocateVoices(&voice_[i], 1, false);
  517. }
  518. num_active_parts_ = num_parts;
  519. }
  520. break;
  521. case LAYOUT_DUAL_POLY:
  522. case LAYOUT_QUAD_POLY:
  523. case LAYOUT_DUAL_POLYCHAINED:
  524. case LAYOUT_QUAD_POLYCHAINED:
  525. case LAYOUT_OCTAL_POLYCHAINED:
  526. {
  527. uint8_t num_voices = settings_.layout == LAYOUT_DUAL_POLY || \
  528. settings_.layout == LAYOUT_QUAD_POLYCHAINED ? 2 : \
  529. (settings_.layout == LAYOUT_DUAL_POLYCHAINED ? 1 : 4);
  530. MidiSettings* midi = part_[0].mutable_midi_settings();
  531. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  532. midi->min_note = 0;
  533. midi->max_note = 127;
  534. }
  535. midi->min_velocity = 0;
  536. midi->max_velocity = 127;
  537. VoicingSettings* voicing = part_[0].mutable_voicing_settings();
  538. voicing->allocation_mode = VOICE_ALLOCATION_MODE_POLY;
  539. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  540. voicing->portamento = 0;
  541. voicing->legato_mode = 0;
  542. part_[0].AllocateVoices(
  543. &voice_[0],
  544. num_voices,
  545. new_layout >= LAYOUT_DUAL_POLYCHAINED);
  546. num_active_parts_ = 1;
  547. }
  548. break;
  549. case LAYOUT_QUAD_TRIGGERS:
  550. {
  551. for (uint8_t i = 0; i < 4; ++i) {
  552. MidiSettings* midi = part_[i].mutable_midi_settings();
  553. if (old_layout != LAYOUT_QUAD_TRIGGERS) {
  554. midi->min_note = 36 + i * 2;
  555. midi->max_note = 36 + i * 2;
  556. }
  557. midi->min_velocity = 0;
  558. midi->max_velocity = 127;
  559. midi->channel = part_[0].mutable_midi_settings()->channel;
  560. midi->out_mode = part_[0].mutable_midi_settings()->out_mode;
  561. VoicingSettings* voicing = part_[i].mutable_voicing_settings();
  562. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  563. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  564. voicing->portamento = 0;
  565. voicing->legato_mode = 0;
  566. }
  567. // Duplicate sequencer settings.
  568. for (uint8_t i = 1; i < 4; ++i) {
  569. uint8_t destination = i;
  570. uint8_t source = i % num_active_parts_;
  571. if (destination != source) {
  572. memcpy(
  573. part_[destination].mutable_sequencer_settings(),
  574. part_[source].mutable_sequencer_settings(),
  575. sizeof(SequencerSettings));
  576. }
  577. }
  578. for (uint8_t i = 0; i < 4; ++i) {
  579. part_[i].AllocateVoices(&voice_[i], 1, false);
  580. }
  581. num_active_parts_ = 4;
  582. }
  583. break;
  584. case LAYOUT_THREE_ONE:
  585. {
  586. MidiSettings* midi = part_[0].mutable_midi_settings();
  587. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  588. midi->min_note = 0;
  589. midi->max_note = 127;
  590. }
  591. midi->min_velocity = 0;
  592. midi->max_velocity = 127;
  593. VoicingSettings* voicing = part_[0].mutable_voicing_settings();
  594. voicing->allocation_mode = VOICE_ALLOCATION_MODE_POLY;
  595. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  596. voicing->portamento = 0;
  597. voicing->legato_mode = 0;
  598. part_[0].AllocateVoices(&voice_[0], 3, false);
  599. midi = part_[1].mutable_midi_settings();
  600. if (old_layout == LAYOUT_QUAD_TRIGGERS) {
  601. midi->min_note = 0;
  602. midi->max_note = 127;
  603. }
  604. midi->min_velocity = 0;
  605. midi->max_velocity = 127;
  606. voicing = part_[1].mutable_voicing_settings();
  607. voicing->allocation_mode = VOICE_ALLOCATION_MODE_MONO;
  608. voicing->allocation_priority = NOTE_STACK_PRIORITY_LAST;
  609. voicing->portamento = 0;
  610. voicing->legato_mode = 0;
  611. part_[1].AllocateVoices(&voice_[3], 1, false);
  612. num_active_parts_ = 2;
  613. }
  614. break;
  615. default:
  616. break;
  617. }
  618. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  619. part_[i].set_siblings(num_active_parts_ > 1);
  620. }
  621. }
  622. void Multi::Touch() {
  623. Stop();
  624. internal_clock_.set_tempo(settings_.clock_tempo);
  625. UpdateLayout();
  626. for (uint8_t i = 0; i < kNumParts; ++i) {
  627. part_[i].Touch();
  628. }
  629. }
  630. const uint8_t song[] = {
  631. #include "song/song.h"
  632. 255,
  633. };
  634. void Multi::StartSong() {
  635. Set(MULTI_LAYOUT, LAYOUT_QUAD_MONO);
  636. part_[0].mutable_voicing_settings()->audio_mode = 0x83;
  637. part_[1].mutable_voicing_settings()->audio_mode = 0x83;
  638. part_[2].mutable_voicing_settings()->audio_mode = 0x84;
  639. part_[3].mutable_voicing_settings()->audio_mode = 0x86;
  640. UpdateLayout();
  641. settings_.clock_tempo = 140;
  642. Stop();
  643. Start(false);
  644. song_pointer_ = &song[0];
  645. song_clock_ = 0;
  646. song_delta_ = 0;
  647. }
  648. void Multi::ClockSong() {
  649. while (song_clock_ >= song_delta_) {
  650. if (*song_pointer_ == 255) {
  651. song_pointer_ = &song[0];
  652. }
  653. if (*song_pointer_ == 254) {
  654. song_delta_ += 6;
  655. } else {
  656. uint8_t part = *song_pointer_ >> 6;
  657. uint8_t note = *song_pointer_ & 0x3f;
  658. if (note == 0) {
  659. part_[part].AllNotesOff();
  660. } else {
  661. part_[part].NoteOn(0, note + 24, 100);
  662. }
  663. song_clock_ = 0;
  664. song_delta_ = 0;
  665. }
  666. ++song_pointer_;
  667. }
  668. ++song_clock_;
  669. }
  670. bool Multi::ControlChange(uint8_t channel, uint8_t controller, uint8_t value) {
  671. bool thru = true;
  672. if (channel + 1 == settings_.remote_control_channel) {
  673. yarns::settings.SetFromCC(0xff, controller, value);
  674. if (num_active_parts_ >= 4 && \
  675. (controller == 0x78 || controller == 0x79 || controller == 0x7b)) {
  676. // Do not continue to avoid treating these messages as "all sound off",
  677. // "reset all controllers" and "all notes off" CC.
  678. return true;
  679. }
  680. }
  681. for (uint8_t i = 0; i < num_active_parts_; ++i) {
  682. if (part_[i].accepts(channel) && \
  683. channel + 1 != settings_.remote_control_channel) {
  684. thru = part_[i].ControlChange(channel, controller, value) && thru;
  685. yarns::settings.SetFromCC(i, controller, value);
  686. }
  687. }
  688. return thru;
  689. }
  690. /* extern */
  691. Multi multi;
  692. } // namespace yarns