tracker.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. uint8_t order_list_index;
  29. } SongState;
  30. typedef struct {
  31. uint8_t note;
  32. uint8_t effect;
  33. uint8_t data;
  34. } UnpackedRow;
  35. struct Tracker {
  36. Song* song;
  37. bool playing;
  38. TrackerMessageCallback callback;
  39. void* context;
  40. SongState song_state;
  41. };
  42. static void channels_state_init(ChannelState* channel) {
  43. channel->frequency = 0;
  44. channel->frequency_target = FREQUENCY_UNSET;
  45. channel->pwm = PWM_DEFAULT;
  46. channel->play = false;
  47. channel->vibrato.speed = 0;
  48. channel->vibrato.depth = 0;
  49. channel->vibrato.direction = 0;
  50. channel->vibrato.value = 0;
  51. }
  52. static void tracker_song_state_init(Tracker* tracker) {
  53. tracker->song_state.tick = 0;
  54. tracker->song_state.tick_limit = 2;
  55. tracker->song_state.row_index = 0;
  56. tracker->song_state.order_list_index = 0;
  57. tracker->song_state.pattern_index = tracker->song->order_list[0];
  58. if(tracker->song_state.channels != NULL) {
  59. free(tracker->song_state.channels);
  60. }
  61. tracker->song_state.channels = malloc(sizeof(ChannelState) * tracker->song->channels_count);
  62. for(uint8_t i = 0; i < tracker->song->channels_count; i++) {
  63. channels_state_init(&tracker->song_state.channels[i]);
  64. }
  65. }
  66. static uint8_t record_get_note(Row note) {
  67. return note & ROW_NOTE_MASK;
  68. }
  69. static uint8_t record_get_effect(Row note) {
  70. return (note >> 6) & ROW_EFFECT_MASK;
  71. }
  72. static uint8_t record_get_effect_data(Row note) {
  73. return (note >> 10) & ROW_EFFECT_DATA_MASK;
  74. }
  75. #define NOTES_PER_OCT 12
  76. const float notes_oct[NOTES_PER_OCT] = {
  77. 130.813f,
  78. 138.591f,
  79. 146.832f,
  80. 155.563f,
  81. 164.814f,
  82. 174.614f,
  83. 184.997f,
  84. 195.998f,
  85. 207.652f,
  86. 220.00f,
  87. 233.082f,
  88. 246.942f,
  89. };
  90. static float note_to_freq(uint8_t note) {
  91. if(note == NOTE_NONE) return 0.0f;
  92. note = note - NOTE_C2;
  93. uint8_t octave = note / NOTES_PER_OCT;
  94. uint8_t note_in_oct = note % NOTES_PER_OCT;
  95. return notes_oct[note_in_oct] * (1 << octave);
  96. }
  97. static float frequency_offset_semitones(float frequency, uint8_t semitones) {
  98. return frequency * (1.0f + ((1.0f / 12.0f) * semitones));
  99. }
  100. static float frequency_get_seventh_of_a_semitone(float frequency) {
  101. return frequency * ((1.0f / 12.0f) / 7.0f);
  102. }
  103. static UnpackedRow get_current_row(Song* song, SongState* song_state, uint8_t channel) {
  104. Pattern* pattern = &song->patterns[song_state->pattern_index];
  105. Row row = pattern->channels[channel].rows[song_state->row_index];
  106. return (UnpackedRow){
  107. .note = record_get_note(row),
  108. .effect = record_get_effect(row),
  109. .data = record_get_effect_data(row),
  110. };
  111. }
  112. static int16_t advance_order_and_get_next_pattern_index(Song* song, SongState* song_state) {
  113. song_state->order_list_index++;
  114. if(song_state->order_list_index >= song->order_list_size) {
  115. return -1;
  116. } else {
  117. return song->order_list[song_state->order_list_index];
  118. }
  119. }
  120. typedef struct {
  121. int16_t pattern;
  122. int16_t row;
  123. bool change_pattern;
  124. bool change_row;
  125. } Location;
  126. static void tracker_send_position_message(Tracker* tracker) {
  127. if(tracker->callback != NULL) {
  128. tracker->callback(
  129. (TrackerMessage){
  130. .type = TrackerPositionChanged,
  131. .data =
  132. {
  133. .position =
  134. {
  135. .order_list_index = tracker->song_state.order_list_index,
  136. .row = tracker->song_state.row_index,
  137. },
  138. },
  139. },
  140. tracker->context);
  141. }
  142. }
  143. static void tracker_send_end_message(Tracker* tracker) {
  144. if(tracker->callback != NULL) {
  145. tracker->callback((TrackerMessage){.type = TrackerEndOfSong}, tracker->context);
  146. }
  147. }
  148. static void advance_to_pattern(Tracker* tracker, Location advance) {
  149. if(advance.change_pattern) {
  150. if(advance.pattern < 0 || advance.pattern >= tracker->song->patterns_count) {
  151. tracker->playing = false;
  152. tracker_send_end_message(tracker);
  153. } else {
  154. tracker->song_state.pattern_index = advance.pattern;
  155. tracker->song_state.row_index = 0;
  156. }
  157. }
  158. if(advance.change_row) {
  159. if(advance.row < 0) advance.row = 0;
  160. if(advance.row >= PATTERN_SIZE) advance.row = PATTERN_SIZE - 1;
  161. tracker->song_state.row_index = advance.row;
  162. }
  163. tracker_send_position_message(tracker);
  164. }
  165. static void tracker_interrupt_body(Tracker* tracker) {
  166. if(!tracker->playing) {
  167. tracker_speaker_stop();
  168. return;
  169. }
  170. const uint8_t channel_index = 0;
  171. SongState* song_state = &tracker->song_state;
  172. ChannelState* channel_state = &song_state->channels[channel_index];
  173. Song* song = tracker->song;
  174. UnpackedRow row = get_current_row(song, song_state, channel_index);
  175. // load frequency from note at tick 0
  176. if(song_state->tick == 0) {
  177. bool invalidate_row = false;
  178. // handle "on first tick" effects
  179. if(row.effect == EffectBreakPattern) {
  180. int16_t next_row_index = row.data;
  181. int16_t next_pattern_index =
  182. advance_order_and_get_next_pattern_index(song, song_state);
  183. advance_to_pattern(
  184. tracker,
  185. (Location){
  186. .pattern = next_pattern_index,
  187. .row = next_row_index,
  188. .change_pattern = true,
  189. .change_row = true,
  190. });
  191. invalidate_row = true;
  192. }
  193. if(row.effect == EffectJumpToOrder) {
  194. song_state->order_list_index = row.data;
  195. int16_t next_pattern_index = song->order_list[song_state->order_list_index];
  196. advance_to_pattern(
  197. tracker,
  198. (Location){
  199. .pattern = next_pattern_index,
  200. .change_pattern = true,
  201. });
  202. invalidate_row = true;
  203. }
  204. // tracker state can be affected by effects
  205. if(!tracker->playing) {
  206. tracker_speaker_stop();
  207. return;
  208. }
  209. if(invalidate_row) {
  210. row = get_current_row(song, song_state, channel_index);
  211. if(row.effect == EffectSetSpeed) {
  212. song_state->tick_limit = row.data;
  213. }
  214. }
  215. // handle note effects
  216. if(row.note == NOTE_OFF) {
  217. channel_state->play = false;
  218. } else if((row.note > NOTE_NONE) && (row.note < NOTE_OFF)) {
  219. channel_state->play = true;
  220. // reset vibrato
  221. channel_state->vibrato.speed = 0;
  222. channel_state->vibrato.depth = 0;
  223. channel_state->vibrato.value = 0;
  224. channel_state->vibrato.direction = 0;
  225. // reset pwm
  226. channel_state->pwm = PWM_DEFAULT;
  227. if(row.effect == EffectSlideToNote) {
  228. channel_state->frequency_target = note_to_freq(row.note);
  229. } else {
  230. channel_state->frequency = note_to_freq(row.note);
  231. channel_state->frequency_target = FREQUENCY_UNSET;
  232. }
  233. }
  234. }
  235. if(channel_state->play) {
  236. float frequency, pwm;
  237. if((row.effect == EffectSlideUp || row.effect == EffectSlideDown) &&
  238. row.data != EFFECT_DATA_NONE) {
  239. // apply slide effect
  240. channel_state->frequency += (row.effect == EffectSlideUp ? 1 : -1) * row.data;
  241. } else if(row.effect == EffectSlideToNote) {
  242. // apply slide to note effect, if target frequency is set
  243. if(channel_state->frequency_target > 0) {
  244. if(channel_state->frequency_target > channel_state->frequency) {
  245. channel_state->frequency += row.data;
  246. if(channel_state->frequency > channel_state->frequency_target) {
  247. channel_state->frequency = channel_state->frequency_target;
  248. channel_state->frequency_target = FREQUENCY_UNSET;
  249. }
  250. } else if(channel_state->frequency_target < channel_state->frequency) {
  251. channel_state->frequency -= row.data;
  252. if(channel_state->frequency < channel_state->frequency_target) {
  253. channel_state->frequency = channel_state->frequency_target;
  254. channel_state->frequency_target = FREQUENCY_UNSET;
  255. }
  256. }
  257. }
  258. }
  259. frequency = channel_state->frequency;
  260. pwm = channel_state->pwm;
  261. // apply arpeggio effect
  262. if(row.effect == EffectArpeggio) {
  263. if(row.data != EFFECT_DATA_NONE) {
  264. if((song_state->tick % 3) == 1) {
  265. uint8_t note_offset = EFFECT_DATA_GET_X(row.data);
  266. frequency = frequency_offset_semitones(frequency, note_offset);
  267. } else if((song_state->tick % 3) == 2) {
  268. uint8_t note_offset = EFFECT_DATA_GET_Y(row.data);
  269. frequency = frequency_offset_semitones(frequency, note_offset);
  270. }
  271. }
  272. } else if(row.effect == EffectVibrato) {
  273. // apply vibrato effect, data = speed, depth
  274. uint8_t vibrato_speed = EFFECT_DATA_GET_X(row.data);
  275. uint8_t vibrato_depth = EFFECT_DATA_GET_Y(row.data);
  276. // update vibrato parameters if speed or depth is non-zero
  277. if(vibrato_speed != 0) channel_state->vibrato.speed = vibrato_speed;
  278. if(vibrato_depth != 0) channel_state->vibrato.depth = vibrato_depth;
  279. // update vibrato value
  280. channel_state->vibrato.value +=
  281. channel_state->vibrato.direction * channel_state->vibrato.speed;
  282. // change direction if value is at the limit
  283. if(channel_state->vibrato.value > channel_state->vibrato.depth) {
  284. channel_state->vibrato.direction = -1;
  285. } else if(channel_state->vibrato.value < -channel_state->vibrato.depth) {
  286. channel_state->vibrato.direction = 1;
  287. } else if(channel_state->vibrato.direction == 0) {
  288. // set initial direction, if it is not set
  289. channel_state->vibrato.direction = 1;
  290. }
  291. frequency +=
  292. (frequency_get_seventh_of_a_semitone(frequency) * channel_state->vibrato.value);
  293. } else if(row.effect == EffectPWM) {
  294. pwm = (pwm - PWM_MIN) / EFFECT_DATA_1_MAX * row.data + PWM_MIN;
  295. }
  296. tracker_speaker_play(frequency, pwm);
  297. } else {
  298. tracker_speaker_stop();
  299. }
  300. song_state->tick++;
  301. if(song_state->tick >= song_state->tick_limit) {
  302. song_state->tick = 0;
  303. // next note
  304. song_state->row_index = (song_state->row_index + 1);
  305. if(song_state->row_index >= PATTERN_SIZE) {
  306. int16_t next_pattern_index =
  307. advance_order_and_get_next_pattern_index(song, song_state);
  308. advance_to_pattern(
  309. tracker,
  310. (Location){
  311. .pattern = next_pattern_index,
  312. .change_pattern = true,
  313. });
  314. } else {
  315. tracker_send_position_message(tracker);
  316. }
  317. }
  318. }
  319. static void tracker_interrupt_cb(void* context) {
  320. Tracker* tracker = (Tracker*)context;
  321. tracker_debug_set(true);
  322. tracker_interrupt_body(tracker);
  323. tracker_debug_set(false);
  324. }
  325. /*********************************************************************
  326. * Tracker Interface
  327. *********************************************************************/
  328. Tracker* tracker_alloc() {
  329. Tracker* tracker = malloc(sizeof(Tracker));
  330. return tracker;
  331. }
  332. void tracker_free(Tracker* tracker) {
  333. free(tracker);
  334. }
  335. void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context) {
  336. furi_check(tracker->playing == false);
  337. tracker->callback = callback;
  338. tracker->context = context;
  339. }
  340. void tracker_set_song(Tracker* tracker, Song* song) {
  341. furi_check(tracker->playing == false);
  342. tracker->song = song;
  343. tracker_song_state_init(tracker);
  344. }
  345. void tracker_set_order_index(Tracker* tracker, uint8_t order_index) {
  346. furi_check(tracker->playing == false);
  347. furi_check(order_index < tracker->song->order_list_size);
  348. tracker->song_state.order_list_index = order_index;
  349. tracker->song_state.pattern_index = tracker->song->order_list[order_index];
  350. }
  351. void tracker_set_row(Tracker* tracker, uint8_t row) {
  352. furi_check(tracker->playing == false);
  353. furi_check(row < PATTERN_SIZE);
  354. tracker->song_state.row_index = row;
  355. }
  356. void tracker_start(Tracker* tracker) {
  357. furi_check(tracker->song != NULL);
  358. tracker->playing = true;
  359. tracker_send_position_message(tracker);
  360. tracker_debug_init();
  361. tracker_speaker_init();
  362. tracker_interrupt_init(tracker->song->ticks_per_second, tracker_interrupt_cb, tracker);
  363. }
  364. void tracker_stop(Tracker* tracker) {
  365. tracker_interrupt_deinit();
  366. tracker_speaker_deinit();
  367. tracker_debug_deinit();
  368. tracker->playing = false;
  369. }