tracker.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #include "tracker.h"
  2. #include <stdbool.h>
  3. #include "speaker_hal.h"
  4. // SongState song_state = {
  5. // .tick = 0,
  6. // .tick_limit = 2,
  7. // .row = 0,
  8. // };
  9. typedef struct {
  10. uint8_t speed;
  11. uint8_t depth;
  12. int8_t direction;
  13. int8_t value;
  14. } IntegerOscillator;
  15. typedef struct {
  16. float frequency;
  17. float frequency_target;
  18. float pwm;
  19. bool play;
  20. IntegerOscillator vibrato;
  21. } ChannelState;
  22. typedef struct {
  23. ChannelState* channels;
  24. uint8_t tick;
  25. uint8_t tick_limit;
  26. uint8_t pattern_index;
  27. uint8_t row_index;
  28. } SongState;
  29. typedef struct {
  30. uint8_t note;
  31. uint8_t effect;
  32. uint8_t data;
  33. } UnpackedRow;
  34. struct Tracker {
  35. Song* song;
  36. bool playing;
  37. TrackerMessageCallback callback;
  38. void* context;
  39. SongState song_state;
  40. };
  41. static void channels_state_init(ChannelState* channel) {
  42. channel->frequency = 0;
  43. channel->frequency_target = FREQUENCY_UNSET;
  44. channel->pwm = PWM_DEFAULT;
  45. channel->play = false;
  46. channel->vibrato.speed = 0;
  47. channel->vibrato.depth = 0;
  48. channel->vibrato.direction = 0;
  49. channel->vibrato.value = 0;
  50. }
  51. static void tracker_song_state_init(Tracker* tracker) {
  52. tracker->song_state.tick = 0;
  53. tracker->song_state.tick_limit = 2;
  54. tracker->song_state.pattern_index = 0;
  55. tracker->song_state.row_index = 0;
  56. if(tracker->song_state.channels != NULL) {
  57. free(tracker->song_state.channels);
  58. }
  59. tracker->song_state.channels = malloc(sizeof(ChannelState) * tracker->song->channels_count);
  60. for(uint8_t i = 0; i < tracker->song->channels_count; i++) {
  61. channels_state_init(&tracker->song_state.channels[i]);
  62. }
  63. }
  64. static uint8_t record_get_note(Row note) {
  65. return note & ROW_NOTE_MASK;
  66. }
  67. static uint8_t record_get_effect(Row note) {
  68. return (note >> 6) & ROW_EFFECT_MASK;
  69. }
  70. static uint8_t record_get_effect_data(Row note) {
  71. return (note >> 10) & ROW_EFFECT_DATA_MASK;
  72. }
  73. #define NOTES_PER_OCT 12
  74. const float notes_oct[NOTES_PER_OCT] = {
  75. 130.813f,
  76. 138.591f,
  77. 146.832f,
  78. 155.563f,
  79. 164.814f,
  80. 174.614f,
  81. 184.997f,
  82. 195.998f,
  83. 207.652f,
  84. 220.00f,
  85. 233.082f,
  86. 246.942f,
  87. };
  88. static float note_to_freq(uint8_t note) {
  89. if(note == NOTE_NONE) return 0.0f;
  90. note = note - NOTE_C2;
  91. uint8_t octave = note / NOTES_PER_OCT;
  92. uint8_t note_in_oct = note % NOTES_PER_OCT;
  93. return notes_oct[note_in_oct] * (1 << octave);
  94. }
  95. static float frequency_offset_semitones(float frequency, uint8_t semitones) {
  96. return frequency * (1.0f + ((1.0f / 12.0f) * semitones));
  97. }
  98. static float frequency_get_seventh_of_a_semitone(float frequency) {
  99. return frequency * ((1.0f / 12.0f) / 7.0f);
  100. }
  101. UnpackedRow get_current_row(Song* song, SongState* song_state, uint8_t channel) {
  102. Pattern* pattern = &song->patterns[song_state->pattern_index];
  103. Row row = pattern->channels[channel].rows[song_state->row_index];
  104. return (UnpackedRow){
  105. .note = record_get_note(row),
  106. .effect = record_get_effect(row),
  107. .data = record_get_effect_data(row),
  108. };
  109. }
  110. void tracker_interrupt_body(Tracker* tracker) {
  111. const uint8_t channel_index = 0;
  112. SongState* song_state = &tracker->song_state;
  113. ChannelState* channel_state = &song_state->channels[channel_index];
  114. Song* song = tracker->song;
  115. UnpackedRow row = get_current_row(song, song_state, channel_index);
  116. // load frequency from note at tick 0
  117. if(song_state->tick == 0) {
  118. // handle "on first tick" effects
  119. if(row.effect == EffectBreakPattern) {
  120. // TODO: advance to next pattern
  121. song_state->row_index = row.data;
  122. // reload note and effect
  123. row = get_current_row(song, song_state, channel_index);
  124. }
  125. if(row.effect == EffectJumpToPattern) {
  126. // TODO: advance to pattern[data]
  127. // reload note and effect
  128. row = get_current_row(song, song_state, channel_index);
  129. }
  130. // no "else", cos previous effects reloads the effect value
  131. if(row.effect == EffectSetSpeed) {
  132. song_state->tick_limit = row.data;
  133. }
  134. // handle note effects
  135. if(row.note == NOTE_OFF) {
  136. channel_state->play = false;
  137. } else if((row.note > NOTE_NONE) && (row.note < NOTE_OFF)) {
  138. channel_state->play = true;
  139. // reset vibrato
  140. channel_state->vibrato.speed = 0;
  141. channel_state->vibrato.depth = 0;
  142. channel_state->vibrato.value = 0;
  143. channel_state->vibrato.direction = 0;
  144. // reset pwm
  145. channel_state->pwm = PWM_DEFAULT;
  146. if(row.effect == EffectSlideToNote) {
  147. channel_state->frequency_target = note_to_freq(row.note);
  148. } else {
  149. channel_state->frequency = note_to_freq(row.note);
  150. channel_state->frequency_target = FREQUENCY_UNSET;
  151. }
  152. }
  153. }
  154. if(channel_state->play) {
  155. float frequency, pwm;
  156. if((row.effect == EffectSlideUp || row.effect == EffectSlideDown) &&
  157. row.data != EFFECT_DATA_NONE) {
  158. // apply slide effect
  159. channel_state->frequency += (row.effect == EffectSlideUp ? 1 : -1) * row.data;
  160. } else if(row.effect == EffectSlideToNote) {
  161. // apply slide to note effect, if target frequency is set
  162. if(channel_state->frequency_target > 0) {
  163. if(channel_state->frequency_target > channel_state->frequency) {
  164. channel_state->frequency += row.data;
  165. if(channel_state->frequency > channel_state->frequency_target) {
  166. channel_state->frequency = channel_state->frequency_target;
  167. channel_state->frequency_target = FREQUENCY_UNSET;
  168. }
  169. } else if(channel_state->frequency_target < channel_state->frequency) {
  170. channel_state->frequency -= row.data;
  171. if(channel_state->frequency < channel_state->frequency_target) {
  172. channel_state->frequency = channel_state->frequency_target;
  173. channel_state->frequency_target = FREQUENCY_UNSET;
  174. }
  175. }
  176. }
  177. }
  178. frequency = channel_state->frequency;
  179. pwm = channel_state->pwm;
  180. // apply arpeggio effect
  181. if(row.effect == EffectArpeggio) {
  182. if(row.data != EFFECT_DATA_NONE) {
  183. if((song_state->tick % 3) == 1) {
  184. uint8_t note_offset = EFFECT_DATA_GET_X(row.data);
  185. frequency = frequency_offset_semitones(frequency, note_offset);
  186. } else if((song_state->tick % 3) == 2) {
  187. uint8_t note_offset = EFFECT_DATA_GET_Y(row.data);
  188. frequency = frequency_offset_semitones(frequency, note_offset);
  189. }
  190. }
  191. } else if(row.effect == EffectVibrato) {
  192. // apply vibrato effect, data = speed, depth
  193. uint8_t vibrato_speed = EFFECT_DATA_GET_X(row.data);
  194. uint8_t vibrato_depth = EFFECT_DATA_GET_Y(row.data);
  195. // update vibrato parameters if speed or depth is non-zero
  196. if(vibrato_speed != 0) channel_state->vibrato.speed = vibrato_speed;
  197. if(vibrato_depth != 0) channel_state->vibrato.depth = vibrato_depth;
  198. // update vibrato value
  199. channel_state->vibrato.value +=
  200. channel_state->vibrato.direction * channel_state->vibrato.speed;
  201. // change direction if value is at the limit
  202. if(channel_state->vibrato.value > channel_state->vibrato.depth) {
  203. channel_state->vibrato.direction = -1;
  204. } else if(channel_state->vibrato.value < -channel_state->vibrato.depth) {
  205. channel_state->vibrato.direction = 1;
  206. } else if(channel_state->vibrato.direction == 0) {
  207. // set initial direction, if it is not set
  208. channel_state->vibrato.direction = 1;
  209. }
  210. frequency +=
  211. (frequency_get_seventh_of_a_semitone(frequency) * channel_state->vibrato.value);
  212. } else if(row.effect == EffectPWM) {
  213. pwm = (pwm - PWM_MIN) / EFFECT_DATA_1_MAX * row.data + PWM_MIN;
  214. }
  215. tracker_speaker_play(frequency, pwm);
  216. } else {
  217. tracker_speaker_stop();
  218. }
  219. song_state->tick++;
  220. if(song_state->tick >= song_state->tick_limit) {
  221. song_state->tick = 0;
  222. // next note
  223. song_state->row_index = (song_state->row_index + 1) % PATTERN_SIZE;
  224. //TODO: advance to next pattern
  225. }
  226. }
  227. void tracker_interrupt_cb(void* context) {
  228. Tracker* tracker = (Tracker*)context;
  229. tracker_debug_set(true);
  230. tracker_interrupt_body(tracker);
  231. tracker_debug_set(false);
  232. }
  233. /*********************************************************************
  234. * Tracker Interface
  235. *********************************************************************/
  236. Tracker* tracker_alloc() {
  237. Tracker* tracker = malloc(sizeof(Tracker));
  238. return tracker;
  239. }
  240. void tracker_free(Tracker* tracker) {
  241. free(tracker);
  242. }
  243. void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context) {
  244. furi_check(tracker->playing == false);
  245. tracker->callback = callback;
  246. tracker->context = context;
  247. }
  248. void tracker_set_song(Tracker* tracker, Song* song) {
  249. furi_check(tracker->playing == false);
  250. tracker->song = song;
  251. tracker_song_state_init(tracker);
  252. }
  253. void tracker_set_pattern(Tracker* tracker, uint8_t pattern) {
  254. furi_check(tracker->playing == false);
  255. furi_check(pattern < tracker->song->patterns_count);
  256. tracker->song_state.pattern_index = pattern;
  257. }
  258. void tracker_set_row(Tracker* tracker, uint8_t row) {
  259. furi_check(tracker->playing == false);
  260. furi_check(row < PATTERN_SIZE);
  261. tracker->song_state.row_index = row;
  262. }
  263. void tracker_start(Tracker* tracker) {
  264. furi_check(tracker->song != NULL);
  265. tracker->playing = true;
  266. tracker_debug_init();
  267. tracker_speaker_init();
  268. tracker_interrupt_init(tracker->song->ticks_per_second, tracker_interrupt_cb, tracker);
  269. }
  270. void tracker_stop(Tracker* tracker) {
  271. tracker_interrupt_deinit();
  272. tracker_speaker_deinit();
  273. tracker_debug_deinit();
  274. tracker->playing = false;
  275. }