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.

411 lines
11KB

  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. // Part.
  28. #ifndef YARNS_PART_H_
  29. #define YARNS_PART_H_
  30. #include <algorithm>
  31. #include "stmlib/stmlib.h"
  32. #include "stmlib/algorithms/voice_allocator.h"
  33. #include "stmlib/algorithms/note_stack.h"
  34. namespace yarns {
  35. class Voice;
  36. const uint8_t kNumSteps = 64;
  37. const uint8_t kMaxNumVoices = 4;
  38. enum ArpeggiatorDirection {
  39. ARPEGGIATOR_DIRECTION_UP,
  40. ARPEGGIATOR_DIRECTION_DOWN,
  41. ARPEGGIATOR_DIRECTION_UP_DOWN,
  42. ARPEGGIATOR_DIRECTION_RANDOM,
  43. ARPEGGIATOR_DIRECTION_AS_PLAYED,
  44. ARPEGGIATOR_DIRECTION_CHORD,
  45. ARPEGGIATOR_DIRECTION_LAST
  46. };
  47. enum VoiceAllocationMode {
  48. VOICE_ALLOCATION_MODE_MONO,
  49. VOICE_ALLOCATION_MODE_POLY,
  50. VOICE_ALLOCATION_MODE_POLY_CYCLIC,
  51. VOICE_ALLOCATION_MODE_POLY_RANDOM,
  52. VOICE_ALLOCATION_MODE_POLY_VELOCITY,
  53. VOICE_ALLOCATION_MODE_POLY_SORTED,
  54. VOICE_ALLOCATION_MODE_POLY_UNISON_1,
  55. VOICE_ALLOCATION_MODE_POLY_UNISON_2,
  56. VOICE_ALLOCATION_MODE_LAST
  57. };
  58. enum VoiceAllocationFlags {
  59. VOICE_ALLOCATION_NOT_FOUND = 0xff
  60. };
  61. enum MidiOutMode {
  62. MIDI_OUT_MODE_OFF,
  63. MIDI_OUT_MODE_THRU,
  64. MIDI_OUT_MODE_GENERATED_EVENTS
  65. };
  66. enum TuningSystem {
  67. TUNING_SYSTEM_EQUAL,
  68. TUNING_SYSTEM_JUST_INTONATION,
  69. TUNING_SYSTEM_PYTHAGOREAN,
  70. TUNING_SYSTEM_QUARTER_EB,
  71. TUNING_SYSTEM_QUARTER_E,
  72. TUNING_SYSTEM_QUARTER_EA,
  73. TUNING_SYSTEM_RAGA_1,
  74. TUNING_SYSTEM_RAGA_27 = TUNING_SYSTEM_RAGA_1 + 26,
  75. TUNING_SYSTEM_CUSTOM,
  76. TUNING_SYSTEM_LAST
  77. };
  78. struct MidiSettings {
  79. uint8_t channel;
  80. uint8_t min_note;
  81. uint8_t max_note;
  82. uint8_t min_velocity;
  83. uint8_t max_velocity;
  84. uint8_t out_mode;
  85. uint8_t padding[10];
  86. };
  87. struct VoicingSettings {
  88. uint8_t allocation_mode;
  89. uint8_t allocation_priority;
  90. uint8_t portamento;
  91. uint8_t legato_mode;
  92. uint8_t pitch_bend_range;
  93. uint8_t vibrato_range;
  94. uint8_t modulation_rate;
  95. int8_t tuning_transpose;
  96. int8_t tuning_fine;
  97. int8_t tuning_root;
  98. uint8_t tuning_system;
  99. uint8_t trigger_duration;
  100. uint8_t trigger_scale;
  101. uint8_t trigger_shape;
  102. uint8_t aux_cv;
  103. uint8_t audio_mode;
  104. uint8_t aux_cv_2;
  105. uint8_t padding[15];
  106. };
  107. enum PartSetting {
  108. PART_MIDI_CHANNEL,
  109. PART_MIDI_MIN_NOTE,
  110. PART_MIDI_MAX_NOTE,
  111. PART_MIDI_MIN_VELOCITY,
  112. PART_MIDI_MAX_VELOCITY,
  113. PART_MIDI_OUT_MODE,
  114. PART_MIDI_LAST = PART_MIDI_CHANNEL + sizeof(MidiSettings) - 1,
  115. PART_VOICING_ALLOCATION_MODE,
  116. PART_VOICING_ALLOCATION_PRIORITY,
  117. PART_VOICING_PORTAMENTO,
  118. PART_VOICING_LEGATO_MODE,
  119. PART_VOICING_PITCH_BEND_RANGE,
  120. PART_VOICING_VIBRATO_RANGE,
  121. PART_VOICING_MODULATION_RATE,
  122. PART_VOICING_TUNING_TRANSPOSE,
  123. PART_VOICING_TUNING_FINE,
  124. PART_VOICING_TUNING_ROOT,
  125. PART_VOICING_TUNING_SYSTEM,
  126. PART_VOICING_TRIGGER_DURATION,
  127. PART_VOICING_TRIGGER_SCALE,
  128. PART_VOICING_TRIGGER_SHAPE,
  129. PART_VOICING_AUX_CV,
  130. PART_VOICING_AUDIO_MODE,
  131. PART_VOICING_AUX_CV_2,
  132. PART_VOICING_LAST = PART_VOICING_ALLOCATION_MODE + sizeof(VoicingSettings) - 1,
  133. PART_SEQUENCER_CLOCK_DIVISION,
  134. PART_SEQUENCER_GATE_LENGTH,
  135. PART_SEQUENCER_ARP_RANGE,
  136. PART_SEQUENCER_ARP_DIRECTION,
  137. PART_SEQUENCER_ARP_PATTERN,
  138. PART_SEQUENCER_EUCLIDEAN_LENGTH,
  139. PART_SEQUENCER_EUCLIDEAN_FILL,
  140. PART_SEQUENCER_EUCLIDEAN_ROTATE
  141. };
  142. enum SequencerStepFlags {
  143. SEQUENCER_STEP_REST = 0x80,
  144. SEQUENCER_STEP_TIE = 0x81
  145. };
  146. struct SequencerStep {
  147. // BYTE 0:
  148. // 0x00 to 0x7f: note
  149. // 0x80: rest
  150. // 0x81: tie
  151. //
  152. // BYTE 1:
  153. // 7 bits of velocity + 1 bit for slide flag.
  154. SequencerStep() { }
  155. SequencerStep(uint8_t data_0, uint8_t data_1) {
  156. data[0] = data_0;
  157. data[1] = data_1;
  158. }
  159. uint8_t data[2];
  160. inline bool has_note() const { return !(data[0] & 0x80); }
  161. inline bool is_rest() const { return data[0] == SEQUENCER_STEP_REST; }
  162. inline bool is_tie() const { return data[0] == SEQUENCER_STEP_TIE; }
  163. inline uint8_t note() const { return data[0] & 0x7f; }
  164. inline bool is_slid() const { return data[1] & 0x80; }
  165. inline uint8_t velocity() const { return data[1] & 0x7f; }
  166. };
  167. struct SequencerSettings {
  168. uint8_t clock_division;
  169. uint8_t gate_length;
  170. uint8_t arp_range;
  171. uint8_t arp_direction;
  172. uint8_t arp_pattern;
  173. uint8_t euclidean_length;
  174. uint8_t euclidean_fill;
  175. uint8_t euclidean_rotate;
  176. uint8_t num_steps;
  177. SequencerStep step[kNumSteps];
  178. uint8_t padding[7];
  179. int16_t first_note() {
  180. for (uint8_t i = 0; i < num_steps; ++i) {
  181. if (step[i].has_note()) {
  182. return step[i].note();
  183. }
  184. }
  185. return 60;
  186. }
  187. };
  188. class Part {
  189. public:
  190. Part() { }
  191. ~Part() { }
  192. void Init();
  193. // The return value indicates whether the message can be forwarded to the
  194. // MIDI out (soft-thru). For example, when the arpeggiator is on, NoteOn
  195. // or NoteOff can return false to make sure that the chord that triggers
  196. // the arpeggiator does not find its way to the MIDI out. Instead it will
  197. // be sent note by note within InternalNoteOn and InternalNoteOff.
  198. //
  199. // Also, note that channel / keyrange / velocity range filtering is not
  200. // applied here. It is up to the caller to call accepts() first to check
  201. // whether the message should be sent to the part.
  202. bool NoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
  203. bool NoteOff(uint8_t channel, uint8_t note);
  204. bool ControlChange(uint8_t channel, uint8_t controller, uint8_t value);
  205. bool PitchBend(uint8_t channel, uint16_t pitch_bend);
  206. bool Aftertouch(uint8_t channel, uint8_t note, uint8_t velocity);
  207. bool Aftertouch(uint8_t channel, uint8_t velocity);
  208. void AllNotesOff();
  209. void Reset();
  210. void Clock();
  211. void Start(bool started_by_keyboard);
  212. void Stop();
  213. void StopRecording() {
  214. seq_recording_ = false;
  215. }
  216. void StartRecording();
  217. inline void RecordStep(const SequencerStep& step) {
  218. if (seq_recording_) {
  219. seq_.step[seq_rec_step_].data[0] = step.data[0];
  220. seq_.step[seq_rec_step_].data[1] |= step.data[1];
  221. ++seq_rec_step_;
  222. uint8_t last_step = seq_overdubbing_ ? seq_.num_steps : kNumSteps;
  223. // Extend sequence.
  224. if (!seq_overdubbing_ && seq_rec_step_ > seq_.num_steps) {
  225. seq_.num_steps = seq_rec_step_;
  226. }
  227. // Wrap to first step.
  228. if (seq_rec_step_ >= last_step) {
  229. seq_rec_step_ = 0;
  230. }
  231. }
  232. }
  233. inline void ModifyNoteAtCurrentStep(uint8_t note) {
  234. if (seq_recording_) {
  235. seq_.step[seq_rec_step_].data[0] = note;
  236. }
  237. }
  238. inline void RecordStep(SequencerStepFlags flag) {
  239. RecordStep(SequencerStep(flag, 0));
  240. }
  241. inline bool accepts(uint8_t channel) const {
  242. return midi_.channel == 0x10 || midi_.channel == channel;
  243. }
  244. inline bool accepts(uint8_t channel, uint8_t note) const {
  245. if (!accepts(channel)) {
  246. return false;
  247. }
  248. if (midi_.min_note <= midi_.max_note) {
  249. return note >= midi_.min_note && note <= midi_.max_note;
  250. } else {
  251. return note <= midi_.max_note || note >= midi_.min_note;
  252. }
  253. }
  254. inline bool accepts(uint8_t channel, uint8_t note, uint8_t velocity) const {
  255. return accepts(channel, note) && \
  256. velocity >= midi_.min_velocity && \
  257. velocity <= midi_.max_velocity;
  258. }
  259. void AllocateVoices(Voice* voice, uint8_t num_voices, bool polychain);
  260. inline void set_custom_pitch_table(int8_t* table) {
  261. custom_pitch_table_ = table;
  262. }
  263. inline uint8_t tx_channel() const {
  264. return midi_.channel == 0x10 ? 0 : midi_.channel;
  265. }
  266. inline bool direct_thru() const {
  267. return midi_.out_mode == MIDI_OUT_MODE_THRU && !polychained_;
  268. }
  269. inline uint8_t FindVoiceForNote(uint8_t note) const {
  270. for (uint8_t i = 0; i < num_voices_; ++i) {
  271. if (active_note_[i] == note) {
  272. return i;
  273. }
  274. }
  275. return VOICE_ALLOCATION_NOT_FOUND;
  276. }
  277. void Set(uint8_t address, uint8_t value);
  278. inline uint8_t Get(uint8_t address) const {
  279. const uint8_t* bytes;
  280. bytes = static_cast<const uint8_t*>(static_cast<const void*>(&midi_));
  281. return bytes[address];
  282. }
  283. inline const MidiSettings& midi_settings() const { return midi_; }
  284. inline const VoicingSettings& voicing_settings() const { return voicing_; }
  285. inline const SequencerSettings& sequencer_settings() const { return seq_; }
  286. inline MidiSettings* mutable_midi_settings() { return &midi_; }
  287. inline VoicingSettings* mutable_voicing_settings() { return &voicing_; }
  288. inline SequencerSettings* mutable_sequencer_settings() { return &seq_; }
  289. inline bool has_notes() const { return pressed_keys_.size() != 0; }
  290. inline bool recording() const { return seq_recording_; }
  291. inline bool overdubbing() const { return seq_overdubbing_; }
  292. inline uint8_t recording_step() const { return seq_rec_step_; }
  293. inline uint8_t num_steps() const { return seq_.num_steps; }
  294. inline void set_recording_step(uint8_t n) { seq_rec_step_ = n; }
  295. void Touch() {
  296. TouchVoices();
  297. TouchVoiceAllocation();
  298. }
  299. inline void Latch() {
  300. ignore_note_off_messages_ = true;
  301. release_latched_keys_on_next_note_on_ = true;
  302. }
  303. inline void Unlatch() {
  304. ignore_note_off_messages_ = false;
  305. release_latched_keys_on_next_note_on_ = true;
  306. }
  307. void set_siblings(bool has_siblings) {
  308. has_siblings_ = has_siblings;
  309. }
  310. private:
  311. int16_t Tune(int16_t note);
  312. void ResetAllControllers();
  313. void TouchVoiceAllocation();
  314. void TouchVoices();
  315. void InternalNoteOn(uint8_t note, uint8_t velocity);
  316. void InternalNoteOff(uint8_t note);
  317. void ReleaseLatchedNotes();
  318. void DispatchSortedNotes(bool unison);
  319. void KillAllInstancesOfNote(uint8_t note);
  320. void ClockSequencer();
  321. void ClockArpeggiator();
  322. void StopSequencerArpeggiatorNotes();
  323. MidiSettings midi_;
  324. VoicingSettings voicing_;
  325. SequencerSettings seq_;
  326. Voice* voice_[kMaxNumVoices];
  327. int8_t* custom_pitch_table_;
  328. uint8_t num_voices_;
  329. bool polychained_;
  330. bool ignore_note_off_messages_;
  331. bool release_latched_keys_on_next_note_on_;
  332. stmlib::NoteStack<12> pressed_keys_;
  333. stmlib::NoteStack<12> generated_notes_; // by sequencer or arpeggiator.
  334. stmlib::NoteStack<12> mono_allocator_;
  335. stmlib::VoiceAllocator<kMaxNumVoices * 2> poly_allocator_;
  336. uint8_t active_note_[kMaxNumVoices];
  337. uint8_t cyclic_allocation_note_counter_;
  338. uint8_t arp_seq_prescaler_;
  339. uint8_t arp_step_;
  340. int8_t arp_note_;
  341. int8_t arp_octave_;
  342. int8_t arp_direction_;
  343. bool seq_running_;
  344. bool seq_recording_;
  345. bool seq_overdubbing_;
  346. uint8_t seq_step_;
  347. uint8_t seq_rec_step_;
  348. uint16_t gate_length_counter_;
  349. uint16_t lfo_counter_;
  350. bool has_siblings_;
  351. DISALLOW_COPY_AND_ASSIGN(Part);
  352. };
  353. } // namespace yarns
  354. #endif // YARNS_PART_H_