sequencer.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /* Copyright 2020 Rodolphe Belouin
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "sequencer.h"
  17. #include "debug.h"
  18. #include "timer.h"
  19. #ifdef MIDI_ENABLE
  20. # include "process_midi.h"
  21. #endif
  22. #ifdef MIDI_MOCKED
  23. # include "tests/midi_mock.h"
  24. #endif
  25. sequencer_config_t sequencer_config = {
  26. false, // enabled
  27. {false}, // steps
  28. {0}, // track notes
  29. 60, // tempo
  30. SQ_RES_4, // resolution
  31. };
  32. sequencer_state_t sequencer_internal_state = {0, 0, 0, 0, SEQUENCER_PHASE_ATTACK};
  33. bool is_sequencer_on(void) {
  34. return sequencer_config.enabled;
  35. }
  36. void sequencer_on(void) {
  37. dprintln("sequencer on");
  38. sequencer_config.enabled = true;
  39. sequencer_internal_state.current_track = 0;
  40. sequencer_internal_state.current_step = 0;
  41. sequencer_internal_state.timer = timer_read();
  42. sequencer_internal_state.phase = SEQUENCER_PHASE_ATTACK;
  43. }
  44. void sequencer_off(void) {
  45. dprintln("sequencer off");
  46. sequencer_config.enabled = false;
  47. sequencer_internal_state.current_step = 0;
  48. }
  49. void sequencer_toggle(void) {
  50. if (is_sequencer_on()) {
  51. sequencer_off();
  52. } else {
  53. sequencer_on();
  54. }
  55. }
  56. void sequencer_set_track_notes(const uint16_t track_notes[SEQUENCER_TRACKS]) {
  57. for (uint8_t i = 0; i < SEQUENCER_TRACKS; i++) {
  58. sequencer_config.track_notes[i] = track_notes[i];
  59. }
  60. }
  61. bool is_sequencer_track_active(uint8_t track) {
  62. return (sequencer_internal_state.active_tracks >> track) & true;
  63. }
  64. void sequencer_set_track_activation(uint8_t track, bool value) {
  65. if (value) {
  66. sequencer_internal_state.active_tracks |= (1 << track);
  67. } else {
  68. sequencer_internal_state.active_tracks &= ~(1 << track);
  69. }
  70. dprintf("sequencer: track %d is %s\n", track, value ? "active" : "inactive");
  71. }
  72. void sequencer_toggle_track_activation(uint8_t track) {
  73. sequencer_set_track_activation(track, !is_sequencer_track_active(track));
  74. }
  75. void sequencer_toggle_single_active_track(uint8_t track) {
  76. if (is_sequencer_track_active(track)) {
  77. sequencer_internal_state.active_tracks = 0;
  78. } else {
  79. sequencer_internal_state.active_tracks = 1 << track;
  80. }
  81. }
  82. bool is_sequencer_step_on(uint8_t step) {
  83. return step < SEQUENCER_STEPS && (sequencer_config.steps[step] & sequencer_internal_state.active_tracks) > 0;
  84. }
  85. bool is_sequencer_step_on_for_track(uint8_t step, uint8_t track) {
  86. return step < SEQUENCER_STEPS && (sequencer_config.steps[step] >> track) & true;
  87. }
  88. void sequencer_set_step(uint8_t step, bool value) {
  89. if (step < SEQUENCER_STEPS) {
  90. if (value) {
  91. sequencer_config.steps[step] |= sequencer_internal_state.active_tracks;
  92. } else {
  93. sequencer_config.steps[step] &= ~sequencer_internal_state.active_tracks;
  94. }
  95. dprintf("sequencer: step %d is %s\n", step, value ? "on" : "off");
  96. } else {
  97. dprintf("sequencer: step %d is out of range\n", step);
  98. }
  99. }
  100. void sequencer_toggle_step(uint8_t step) {
  101. if (is_sequencer_step_on(step)) {
  102. sequencer_set_step_off(step);
  103. } else {
  104. sequencer_set_step_on(step);
  105. }
  106. }
  107. void sequencer_set_all_steps(bool value) {
  108. for (uint8_t step = 0; step < SEQUENCER_STEPS; step++) {
  109. if (value) {
  110. sequencer_config.steps[step] |= sequencer_internal_state.active_tracks;
  111. } else {
  112. sequencer_config.steps[step] &= ~sequencer_internal_state.active_tracks;
  113. }
  114. }
  115. dprintf("sequencer: all steps are %s\n", value ? "on" : "off");
  116. }
  117. uint8_t sequencer_get_tempo(void) {
  118. return sequencer_config.tempo;
  119. }
  120. void sequencer_set_tempo(uint8_t tempo) {
  121. if (tempo > 0) {
  122. sequencer_config.tempo = tempo;
  123. dprintf("sequencer: tempo set to %d bpm\n", tempo);
  124. } else {
  125. dprintln("sequencer: cannot set tempo to 0");
  126. }
  127. }
  128. void sequencer_increase_tempo(void) {
  129. // Handling potential uint8_t overflow
  130. if (sequencer_config.tempo < UINT8_MAX) {
  131. sequencer_set_tempo(sequencer_config.tempo + 1);
  132. } else {
  133. dprintf("sequencer: cannot set tempo above %d\n", UINT8_MAX);
  134. }
  135. }
  136. void sequencer_decrease_tempo(void) {
  137. sequencer_set_tempo(sequencer_config.tempo - 1);
  138. }
  139. sequencer_resolution_t sequencer_get_resolution(void) {
  140. return sequencer_config.resolution;
  141. }
  142. void sequencer_set_resolution(sequencer_resolution_t resolution) {
  143. if (resolution >= 0 && resolution < SEQUENCER_RESOLUTIONS) {
  144. sequencer_config.resolution = resolution;
  145. dprintf("sequencer: resolution set to %d\n", resolution);
  146. } else {
  147. dprintf("sequencer: resolution %d is out of range\n", resolution);
  148. }
  149. }
  150. void sequencer_increase_resolution(void) {
  151. sequencer_set_resolution(sequencer_config.resolution + 1);
  152. }
  153. void sequencer_decrease_resolution(void) {
  154. sequencer_set_resolution(sequencer_config.resolution - 1);
  155. }
  156. uint8_t sequencer_get_current_step(void) {
  157. return sequencer_internal_state.current_step;
  158. }
  159. void sequencer_phase_attack(void) {
  160. dprintf("sequencer: step %d\n", sequencer_internal_state.current_step);
  161. dprintf("sequencer: time %d\n", timer_read());
  162. if (sequencer_internal_state.current_track == 0) {
  163. sequencer_internal_state.timer = timer_read();
  164. }
  165. if (timer_elapsed(sequencer_internal_state.timer) < sequencer_internal_state.current_track * SEQUENCER_TRACK_THROTTLE) {
  166. return;
  167. }
  168. #if defined(MIDI_ENABLE) || defined(MIDI_MOCKED)
  169. if (is_sequencer_step_on_for_track(sequencer_internal_state.current_step, sequencer_internal_state.current_track)) {
  170. process_midi_basic_noteon(midi_compute_note(sequencer_config.track_notes[sequencer_internal_state.current_track]));
  171. }
  172. #endif
  173. if (sequencer_internal_state.current_track < SEQUENCER_TRACKS - 1) {
  174. sequencer_internal_state.current_track++;
  175. } else {
  176. sequencer_internal_state.phase = SEQUENCER_PHASE_RELEASE;
  177. }
  178. }
  179. void sequencer_phase_release(void) {
  180. if (timer_elapsed(sequencer_internal_state.timer) < SEQUENCER_PHASE_RELEASE_TIMEOUT + sequencer_internal_state.current_track * SEQUENCER_TRACK_THROTTLE) {
  181. return;
  182. }
  183. #if defined(MIDI_ENABLE) || defined(MIDI_MOCKED)
  184. if (is_sequencer_step_on_for_track(sequencer_internal_state.current_step, sequencer_internal_state.current_track)) {
  185. process_midi_basic_noteoff(midi_compute_note(sequencer_config.track_notes[sequencer_internal_state.current_track]));
  186. }
  187. #endif
  188. if (sequencer_internal_state.current_track > 0) {
  189. sequencer_internal_state.current_track--;
  190. } else {
  191. sequencer_internal_state.phase = SEQUENCER_PHASE_PAUSE;
  192. }
  193. }
  194. void sequencer_phase_pause(void) {
  195. if (timer_elapsed(sequencer_internal_state.timer) < sequencer_get_step_duration()) {
  196. return;
  197. }
  198. sequencer_internal_state.current_step = (sequencer_internal_state.current_step + 1) % SEQUENCER_STEPS;
  199. sequencer_internal_state.phase = SEQUENCER_PHASE_ATTACK;
  200. }
  201. void sequencer_task(void) {
  202. if (!sequencer_config.enabled) {
  203. return;
  204. }
  205. if (sequencer_internal_state.phase == SEQUENCER_PHASE_PAUSE) {
  206. sequencer_phase_pause();
  207. }
  208. if (sequencer_internal_state.phase == SEQUENCER_PHASE_RELEASE) {
  209. sequencer_phase_release();
  210. }
  211. if (sequencer_internal_state.phase == SEQUENCER_PHASE_ATTACK) {
  212. sequencer_phase_attack();
  213. }
  214. }
  215. uint16_t sequencer_get_beat_duration(void) {
  216. return get_beat_duration(sequencer_config.tempo);
  217. }
  218. uint16_t sequencer_get_step_duration(void) {
  219. return get_step_duration(sequencer_config.tempo, sequencer_config.resolution);
  220. }
  221. uint16_t get_beat_duration(uint8_t tempo) {
  222. // Don’t crash in the unlikely case where the given tempo is 0
  223. if (tempo == 0) {
  224. return get_beat_duration(60);
  225. }
  226. /**
  227. * Given
  228. * t = tempo and d = duration, both strictly greater than 0
  229. * When
  230. * t beats / minute = 1 beat / d ms
  231. * Then
  232. * t beats / 60000ms = 1 beat / d ms
  233. * d ms = 60000ms / t
  234. */
  235. return 60000 / tempo;
  236. }
  237. uint16_t get_step_duration(uint8_t tempo, sequencer_resolution_t resolution) {
  238. /**
  239. * Resolution cheatsheet:
  240. * 1/2 => 2 steps per 4 beats
  241. * 1/2T => 3 steps per 4 beats
  242. * 1/4 => 4 steps per 4 beats
  243. * 1/4T => 6 steps per 4 beats
  244. * 1/8 => 8 steps per 4 beats
  245. * 1/8T => 12 steps per 4 beats
  246. * 1/16 => 16 steps per 4 beats
  247. * 1/16T => 24 steps per 4 beats
  248. * 1/32 => 32 steps per 4 beats
  249. *
  250. * The number of steps for binary resolutions follows the powers of 2.
  251. * The ternary variants are simply 1.5x faster.
  252. */
  253. bool is_binary = resolution % 2 == 0;
  254. uint8_t binary_steps = 2 << (resolution / 2);
  255. uint16_t binary_step_duration = get_beat_duration(tempo) * 4 / binary_steps;
  256. return is_binary ? binary_step_duration : 2 * binary_step_duration / 3;
  257. }