util.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "util.h"
  2. void set_note(TrackerSongPatternStep *step, uint8_t note)
  3. {
  4. step->note &= 0x80;
  5. step->note |= (note & 0x7f);
  6. }
  7. void set_instrument(TrackerSongPatternStep *step, uint8_t inst)
  8. {
  9. step->note &= 0x7f;
  10. step->inst_vol &= 0x0f;
  11. step->note |= ((inst & 0x10) << 3);
  12. step->inst_vol |= ((inst & 0xf) << 4);
  13. }
  14. void set_volume(TrackerSongPatternStep *step, uint8_t vol)
  15. {
  16. step->command &= 0x7fff;
  17. step->inst_vol &= 0xf0;
  18. step->command |= ((vol & 0x10) << 11);
  19. step->inst_vol |= (vol & 0xf);
  20. }
  21. void set_command(TrackerSongPatternStep *step, uint16_t command)
  22. {
  23. step->command &= 0x8000;
  24. step->command |= command & (0x7fff);
  25. }
  26. void play_song(FlizzerTrackerApp *tracker, bool from_cursor)
  27. {
  28. tracker->tracker_engine.playing = true;
  29. tracker->was_editing = tracker->editing;
  30. tracker->editing = false;
  31. if (!(from_cursor))
  32. {
  33. tracker->tracker_engine.pattern_position = 0;
  34. }
  35. tracker_engine_set_rate(tracker->song.rate);
  36. tracker_engine_set_song(&tracker->tracker_engine, &tracker->song);
  37. play();
  38. }
  39. void stop_song(FlizzerTrackerApp *tracker)
  40. {
  41. tracker->tracker_engine.playing = false;
  42. tracker->editing = tracker->was_editing;
  43. stop();
  44. }
  45. bool is_pattern_empty(TrackerSong *song, uint8_t pattern)
  46. {
  47. TrackerSongPattern song_pattern = song->pattern[pattern];
  48. for (int i = 0; i < song->pattern_length; i++)
  49. {
  50. TrackerSongPatternStep *step = &song_pattern.step[i];
  51. if (tracker_engine_get_note(step) != MUS_NOTE_NONE ||
  52. tracker_engine_get_instrument(step) != MUS_NOTE_INSTRUMENT_NONE ||
  53. tracker_engine_get_volume(step) != MUS_NOTE_VOLUME_NONE ||
  54. tracker_engine_get_command(step) != 0)
  55. {
  56. return false;
  57. }
  58. }
  59. return true;
  60. }
  61. void set_empty_pattern(TrackerSongPattern *pattern, uint16_t pattern_length)
  62. {
  63. for (uint16_t i = 0; i < pattern_length; i++)
  64. {
  65. TrackerSongPatternStep *step = &pattern->step[i];
  66. set_note(step, MUS_NOTE_NONE);
  67. set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
  68. set_volume(step, MUS_NOTE_VOLUME_NONE);
  69. set_command(step, 0);
  70. }
  71. }
  72. bool check_and_allocate_pattern(TrackerSong *song, uint8_t pattern)
  73. {
  74. if (pattern < song->num_patterns) // we can set this pattern since it already exists
  75. {
  76. return true;
  77. }
  78. else
  79. {
  80. if (song->pattern[pattern - 1].step == NULL)
  81. return false; // if we hop through several patterns (e.g. editing upper digit)
  82. if (!(is_pattern_empty(song, pattern - 1))) // don't let the user flood the song with empty patterns
  83. {
  84. song->pattern[pattern].step = malloc(sizeof(TrackerSongPatternStep) * song->pattern_length);
  85. set_empty_pattern(&song->pattern[pattern], song->pattern_length);
  86. song->num_patterns++;
  87. return true;
  88. }
  89. else
  90. {
  91. return false;
  92. }
  93. }
  94. }
  95. void resize_pattern(TrackerSongPattern *pattern, uint16_t old_length, uint16_t new_length)
  96. {
  97. TrackerSongPattern temp;
  98. temp.step = malloc((new_length) * sizeof(TrackerSongPatternStep));
  99. set_empty_pattern(&temp, new_length);
  100. memcpy(temp.step, pattern->step, fmin(old_length, new_length) * sizeof(TrackerSongPatternStep));
  101. free(pattern->step);
  102. pattern->step = temp.step;
  103. }
  104. void change_pattern_length(TrackerSong *song, uint16_t new_length)
  105. {
  106. for (int i = 0; i < MAX_PATTERNS; i++)
  107. {
  108. if (song->pattern[i].step)
  109. {
  110. resize_pattern(&song->pattern[i], song->pattern_length, new_length);
  111. }
  112. }
  113. song->pattern_length = new_length;
  114. }