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.

409 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 padding[16];
  105. };
  106. enum PartSetting {
  107. PART_MIDI_CHANNEL,
  108. PART_MIDI_MIN_NOTE,
  109. PART_MIDI_MAX_NOTE,
  110. PART_MIDI_MIN_VELOCITY,
  111. PART_MIDI_MAX_VELOCITY,
  112. PART_MIDI_OUT_MODE,
  113. PART_MIDI_LAST = PART_MIDI_CHANNEL + sizeof(MidiSettings) - 1,
  114. PART_VOICING_ALLOCATION_MODE,
  115. PART_VOICING_ALLOCATION_PRIORITY,
  116. PART_VOICING_PORTAMENTO,
  117. PART_VOICING_LEGATO_MODE,
  118. PART_VOICING_PITCH_BEND_RANGE,
  119. PART_VOICING_VIBRATO_RANGE,
  120. PART_VOICING_MODULATION_RATE,
  121. PART_VOICING_TUNING_TRANSPOSE,
  122. PART_VOICING_TUNING_FINE,
  123. PART_VOICING_TUNING_ROOT,
  124. PART_VOICING_TUNING_SYSTEM,
  125. PART_VOICING_TRIGGER_DURATION,
  126. PART_VOICING_TRIGGER_SCALE,
  127. PART_VOICING_TRIGGER_SHAPE,
  128. PART_VOICING_AUX_CV,
  129. PART_VOICING_AUDIO_MODE,
  130. PART_VOICING_LAST = PART_VOICING_ALLOCATION_MODE + sizeof(VoicingSettings) - 1,
  131. PART_SEQUENCER_CLOCK_DIVISION,
  132. PART_SEQUENCER_GATE_LENGTH,
  133. PART_SEQUENCER_ARP_RANGE,
  134. PART_SEQUENCER_ARP_DIRECTION,
  135. PART_SEQUENCER_ARP_PATTERN,
  136. PART_SEQUENCER_EUCLIDEAN_LENGTH,
  137. PART_SEQUENCER_EUCLIDEAN_FILL,
  138. PART_SEQUENCER_EUCLIDEAN_ROTATE
  139. };
  140. enum SequencerStepFlags {
  141. SEQUENCER_STEP_REST = 0x80,
  142. SEQUENCER_STEP_TIE = 0x81
  143. };
  144. struct SequencerStep {
  145. // BYTE 0:
  146. // 0x00 to 0x7f: note
  147. // 0x80: rest
  148. // 0x81: tie
  149. //
  150. // BYTE 1:
  151. // 7 bits of velocity + 1 bit for slide flag.
  152. SequencerStep() { }
  153. SequencerStep(uint8_t data_0, uint8_t data_1) {
  154. data[0] = data_0;
  155. data[1] = data_1;
  156. }
  157. uint8_t data[2];
  158. inline bool has_note() const { return !(data[0] & 0x80); }
  159. inline bool is_rest() const { return data[0] == SEQUENCER_STEP_REST; }
  160. inline bool is_tie() const { return data[0] == SEQUENCER_STEP_TIE; }
  161. inline uint8_t note() const { return data[0] & 0x7f; }
  162. inline bool is_slid() const { return data[1] & 0x80; }
  163. inline uint8_t velocity() const { return data[1] & 0x7f; }
  164. };
  165. struct SequencerSettings {
  166. uint8_t clock_division;
  167. uint8_t gate_length;
  168. uint8_t arp_range;
  169. uint8_t arp_direction;
  170. uint8_t arp_pattern;
  171. uint8_t euclidean_length;
  172. uint8_t euclidean_fill;
  173. uint8_t euclidean_rotate;
  174. uint8_t num_steps;
  175. SequencerStep step[kNumSteps];
  176. uint8_t padding[7];
  177. int16_t first_note() {
  178. for (uint8_t i = 0; i < num_steps; ++i) {
  179. if (step[i].has_note()) {
  180. return step[i].note();
  181. }
  182. }
  183. return 60;
  184. }
  185. };
  186. class Part {
  187. public:
  188. Part() { }
  189. ~Part() { }
  190. void Init();
  191. // The return value indicates whether the message can be forwarded to the
  192. // MIDI out (soft-thru). For example, when the arpeggiator is on, NoteOn
  193. // or NoteOff can return false to make sure that the chord that triggers
  194. // the arpeggiator does not find its way to the MIDI out. Instead it will
  195. // be sent note by note within InternalNoteOn and InternalNoteOff.
  196. //
  197. // Also, note that channel / keyrange / velocity range filtering is not
  198. // applied here. It is up to the caller to call accepts() first to check
  199. // whether the message should be sent to the part.
  200. bool NoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
  201. bool NoteOff(uint8_t channel, uint8_t note);
  202. bool ControlChange(uint8_t channel, uint8_t controller, uint8_t value);
  203. bool PitchBend(uint8_t channel, uint16_t pitch_bend);
  204. bool Aftertouch(uint8_t channel, uint8_t note, uint8_t velocity);
  205. bool Aftertouch(uint8_t channel, uint8_t velocity);
  206. void AllNotesOff();
  207. void Reset();
  208. void Clock();
  209. void Start(bool started_by_keyboard);
  210. void Stop();
  211. void StopRecording() {
  212. seq_recording_ = false;
  213. }
  214. void StartRecording();
  215. inline void RecordStep(const SequencerStep& step) {
  216. if (seq_recording_) {
  217. seq_.step[seq_rec_step_].data[0] = step.data[0];
  218. seq_.step[seq_rec_step_].data[1] |= step.data[1];
  219. ++seq_rec_step_;
  220. uint8_t last_step = seq_overdubbing_ ? seq_.num_steps : kNumSteps;
  221. // Extend sequence.
  222. if (!seq_overdubbing_ && seq_rec_step_ > seq_.num_steps) {
  223. seq_.num_steps = seq_rec_step_;
  224. }
  225. // Wrap to first step.
  226. if (seq_rec_step_ >= last_step) {
  227. seq_rec_step_ = 0;
  228. }
  229. }
  230. }
  231. inline void ModifyNoteAtCurrentStep(uint8_t note) {
  232. if (seq_recording_) {
  233. seq_.step[seq_rec_step_].data[0] = note;
  234. }
  235. }
  236. inline void RecordStep(SequencerStepFlags flag) {
  237. RecordStep(SequencerStep(flag, 0));
  238. }
  239. inline bool accepts(uint8_t channel) const {
  240. return midi_.channel == 0x10 || midi_.channel == channel;
  241. }
  242. inline bool accepts(uint8_t channel, uint8_t note) const {
  243. if (!accepts(channel)) {
  244. return false;
  245. }
  246. if (midi_.min_note <= midi_.max_note) {
  247. return note >= midi_.min_note && note <= midi_.max_note;
  248. } else {
  249. return note <= midi_.max_note || note >= midi_.min_note;
  250. }
  251. }
  252. inline bool accepts(uint8_t channel, uint8_t note, uint8_t velocity) const {
  253. return accepts(channel, note) && \
  254. velocity >= midi_.min_velocity && \
  255. velocity <= midi_.max_velocity;
  256. }
  257. void AllocateVoices(Voice* voice, uint8_t num_voices, bool polychain);
  258. inline void set_custom_pitch_table(int8_t* table) {
  259. custom_pitch_table_ = table;
  260. }
  261. inline uint8_t tx_channel() const {
  262. return midi_.channel == 0x10 ? 0 : midi_.channel;
  263. }
  264. inline bool direct_thru() const {
  265. return midi_.out_mode == MIDI_OUT_MODE_THRU && !polychained_;
  266. }
  267. inline uint8_t FindVoiceForNote(uint8_t note) const {
  268. for (uint8_t i = 0; i < num_voices_; ++i) {
  269. if (active_note_[i] == note) {
  270. return i;
  271. }
  272. }
  273. return VOICE_ALLOCATION_NOT_FOUND;
  274. }
  275. void Set(uint8_t address, uint8_t value);
  276. inline uint8_t Get(uint8_t address) const {
  277. const uint8_t* bytes;
  278. bytes = static_cast<const uint8_t*>(static_cast<const void*>(&midi_));
  279. return bytes[address];
  280. }
  281. inline const MidiSettings& midi_settings() const { return midi_; }
  282. inline const VoicingSettings& voicing_settings() const { return voicing_; }
  283. inline const SequencerSettings& sequencer_settings() const { return seq_; }
  284. inline MidiSettings* mutable_midi_settings() { return &midi_; }
  285. inline VoicingSettings* mutable_voicing_settings() { return &voicing_; }
  286. inline SequencerSettings* mutable_sequencer_settings() { return &seq_; }
  287. inline bool has_notes() const { return pressed_keys_.size() != 0; }
  288. inline bool recording() const { return seq_recording_; }
  289. inline bool overdubbing() const { return seq_overdubbing_; }
  290. inline uint8_t recording_step() const { return seq_rec_step_; }
  291. inline uint8_t num_steps() const { return seq_.num_steps; }
  292. inline void set_recording_step(uint8_t n) { seq_rec_step_ = n; }
  293. void Touch() {
  294. TouchVoices();
  295. TouchVoiceAllocation();
  296. }
  297. inline void Latch() {
  298. ignore_note_off_messages_ = true;
  299. release_latched_keys_on_next_note_on_ = true;
  300. }
  301. inline void Unlatch() {
  302. ignore_note_off_messages_ = false;
  303. release_latched_keys_on_next_note_on_ = true;
  304. }
  305. void set_siblings(bool has_siblings) {
  306. has_siblings_ = has_siblings;
  307. }
  308. private:
  309. int16_t Tune(int16_t note);
  310. void ResetAllControllers();
  311. void TouchVoiceAllocation();
  312. void TouchVoices();
  313. void InternalNoteOn(uint8_t note, uint8_t velocity);
  314. void InternalNoteOff(uint8_t note);
  315. void ReleaseLatchedNotes();
  316. void DispatchSortedNotes(bool unison);
  317. void KillAllInstancesOfNote(uint8_t note);
  318. void ClockSequencer();
  319. void ClockArpeggiator();
  320. void StopSequencerArpeggiatorNotes();
  321. MidiSettings midi_;
  322. VoicingSettings voicing_;
  323. SequencerSettings seq_;
  324. Voice* voice_[kMaxNumVoices];
  325. int8_t* custom_pitch_table_;
  326. uint8_t num_voices_;
  327. bool polychained_;
  328. bool ignore_note_off_messages_;
  329. bool release_latched_keys_on_next_note_on_;
  330. stmlib::NoteStack<12> pressed_keys_;
  331. stmlib::NoteStack<12> generated_notes_; // by sequencer or arpeggiator.
  332. stmlib::NoteStack<12> mono_allocator_;
  333. stmlib::VoiceAllocator<kMaxNumVoices * 2> poly_allocator_;
  334. uint8_t active_note_[kMaxNumVoices];
  335. uint8_t cyclic_allocation_note_counter_;
  336. uint8_t arp_seq_prescaler_;
  337. uint8_t arp_step_;
  338. int8_t arp_note_;
  339. int8_t arp_octave_;
  340. int8_t arp_direction_;
  341. bool seq_running_;
  342. bool seq_recording_;
  343. bool seq_overdubbing_;
  344. uint8_t seq_step_;
  345. uint8_t seq_rec_step_;
  346. uint16_t gate_length_counter_;
  347. uint16_t lfo_counter_;
  348. bool has_siblings_;
  349. DISALLOW_COPY_AND_ASSIGN(Part);
  350. };
  351. } // namespace yarns
  352. #endif // YARNS_PART_H_