pattern.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #include "pattern.h"
  2. uint8_t get_field(uint8_t patternx) {
  3. uint8_t field = 0;
  4. if(patternx <= 1) field = 0;
  5. if(patternx == 2) field = 1;
  6. if(patternx == 3) field = 2;
  7. if(patternx > 3) field = 3;
  8. return field;
  9. }
  10. void edit_note(
  11. FlizzerTrackerApp* tracker,
  12. TrackerSongPatternStep* step,
  13. int8_t delta) // here we need data about last note if we place a new note
  14. {
  15. int16_t note = tracker_engine_get_note(step);
  16. if(note == MUS_NOTE_RELEASE) {
  17. if(delta < 0) {
  18. set_note(step, MUS_NOTE_CUT);
  19. }
  20. return;
  21. }
  22. if(note == MUS_NOTE_CUT) {
  23. if(delta > 0) {
  24. set_note(step, MUS_NOTE_RELEASE);
  25. }
  26. return;
  27. }
  28. if(note == MUS_NOTE_NONE) {
  29. note =
  30. tracker->current_note; // remember which note we entered earlier and use it as reference
  31. }
  32. clamp(note, delta, 0, MAX_NOTE);
  33. set_note(step, (uint8_t)note);
  34. set_instrument(step, tracker->current_instrument);
  35. tracker->current_note = (uint8_t)note;
  36. }
  37. void edit_instrument(FlizzerTrackerApp* tracker, TrackerSongPatternStep* step, int8_t delta) {
  38. int16_t inst = tracker_engine_get_instrument(step);
  39. if(inst == MUS_NOTE_INSTRUMENT_NONE) {
  40. if(delta > 0) {
  41. inst = tracker->current_instrument;
  42. }
  43. else {
  44. inst = MUS_NOTE_INSTRUMENT_NONE - 1;
  45. }
  46. }
  47. clamp(inst, delta, 0, tracker->song.num_instruments - 1);
  48. tracker->current_instrument = inst; // remember last instrument
  49. set_instrument(step, (uint8_t)inst);
  50. }
  51. void edit_volume(FlizzerTrackerApp* tracker, TrackerSongPatternStep* step, int8_t delta) {
  52. int16_t vol = tracker_engine_get_volume(step);
  53. vol = tracker->current_volume;
  54. if(vol + delta < 0) {
  55. vol = MUS_NOTE_VOLUME_NONE - 1 - delta;
  56. }
  57. if(vol + delta >= MUS_NOTE_VOLUME_NONE) {
  58. vol = 0 - delta;
  59. }
  60. clamp(vol, delta, 0, MUS_NOTE_VOLUME_NONE - 1);
  61. set_volume(step, (uint8_t)vol);
  62. tracker->current_volume = vol;
  63. }
  64. void edit_command(TrackerSongPatternStep* step, uint8_t digit, int8_t delta) {
  65. int32_t command = tracker_engine_get_command(step);
  66. switch(digit) {
  67. case 0: // upper 7 bits
  68. {
  69. int16_t fx_name = ((command & 0x7f00) >> 8);
  70. if(fx_name + delta > 35) // loop
  71. { // 0-9 and then A-Z
  72. fx_name = 0;
  73. }
  74. else if(fx_name + delta < 0) {
  75. fx_name = 35;
  76. }
  77. else {
  78. fx_name += delta;
  79. }
  80. command &= 0x00ff;
  81. command |= (fx_name << 8);
  82. set_command(step, (uint16_t)command);
  83. break;
  84. }
  85. case 1: // upper digit of command param
  86. {
  87. int8_t upper_digit = ((command & 0x00f0) >> 4);
  88. if(upper_digit + delta > 0xf) // loop
  89. {
  90. upper_digit = 0;
  91. }
  92. else if(upper_digit + delta < 0) {
  93. upper_digit = 0xf;
  94. }
  95. else {
  96. upper_digit += delta;
  97. }
  98. command &= 0xff0f;
  99. command |= (upper_digit << 4);
  100. set_command(step, (uint16_t)command);
  101. break;
  102. }
  103. case 2: // lower digit of command param
  104. {
  105. int8_t lower_digit = (command & 0x000f);
  106. if(lower_digit + delta > 0xf) // loop
  107. {
  108. lower_digit = 0;
  109. }
  110. else if(lower_digit + delta < 0) {
  111. lower_digit = 0xf;
  112. }
  113. else {
  114. lower_digit += delta;
  115. }
  116. command &= 0xfff0;
  117. command |= lower_digit;
  118. set_command(step, (uint16_t)command);
  119. break;
  120. }
  121. default:
  122. break;
  123. }
  124. }
  125. void delete_field(TrackerSongPatternStep* step, uint8_t field) {
  126. switch(field) {
  127. case 0: // note
  128. {
  129. set_note(step, MUS_NOTE_NONE);
  130. set_instrument(step, MUS_NOTE_INSTRUMENT_NONE); // also delete instrument
  131. break;
  132. }
  133. case 1: // instrument
  134. {
  135. set_instrument(step, MUS_NOTE_INSTRUMENT_NONE);
  136. break;
  137. }
  138. case 2: // volume
  139. {
  140. set_volume(step, MUS_NOTE_VOLUME_NONE);
  141. break;
  142. }
  143. case 3: // command
  144. {
  145. set_command(step, 0);
  146. break;
  147. }
  148. default:
  149. break;
  150. }
  151. }
  152. void edit_pattern_step(FlizzerTrackerApp* tracker, TrackerSongPatternStep* step, int8_t delta) {
  153. switch(get_field(tracker->patternx)) {
  154. case 0: // note
  155. {
  156. if(tracker->patternx) // editing octave
  157. {
  158. edit_note(tracker, step, 12 * delta);
  159. }
  160. else // editing note
  161. {
  162. edit_note(tracker, step, delta);
  163. }
  164. break;
  165. }
  166. case 1: // instrument
  167. {
  168. edit_instrument(tracker, step, delta);
  169. break;
  170. }
  171. case 2: // volume
  172. {
  173. edit_volume(tracker, step, delta);
  174. break;
  175. }
  176. case 3: // command
  177. {
  178. uint8_t digit = 0;
  179. if(tracker->patternx == 4) digit = 0;
  180. if(tracker->patternx == 5) digit = 1;
  181. if(tracker->patternx == 6) digit = 2;
  182. edit_command(step, digit, delta);
  183. break;
  184. }
  185. default:
  186. break;
  187. }
  188. }
  189. void pattern_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event) {
  190. if(event->input.key == InputKeyLeft && event->input.type == InputTypeLong &&
  191. !(tracker->editing)) {
  192. flipbit(
  193. tracker->tracker_engine.channel[tracker->current_channel].channel_flags, TEC_DISABLED);
  194. return;
  195. }
  196. if(event->input.key == InputKeyDown && event->input.type == InputTypeLong &&
  197. !(tracker->editing)) {
  198. tracker->tracker_engine.pattern_position =
  199. tracker->tracker_engine.song->pattern_length - 1; // go to pattern last row
  200. return;
  201. }
  202. if(event->input.key == InputKeyUp && event->input.type == InputTypeLong &&
  203. !(tracker->editing)) {
  204. tracker->tracker_engine.pattern_position = 0; // return to pattern 1st row
  205. return;
  206. }
  207. uint8_t sequence_position = tracker->tracker_engine.sequence_position;
  208. uint8_t current_pattern =
  209. tracker->tracker_engine.song->sequence.sequence_step[sequence_position]
  210. .pattern_indices[tracker->current_channel];
  211. uint16_t pattern_step = tracker->tracker_engine.pattern_position;
  212. uint16_t pattern_length = tracker->tracker_engine.song->pattern_length;
  213. TrackerSongPattern* pattern = &tracker->tracker_engine.song->pattern[current_pattern];
  214. TrackerSongPatternStep* step = NULL;
  215. if(pattern_step < pattern_length) {
  216. step = &pattern->step[pattern_step];
  217. }
  218. if(!(step)) return;
  219. if(event->input.key == InputKeyOk && event->input.type == InputTypeShort &&
  220. !tracker->tracker_engine.playing) {
  221. tracker->editing = !tracker->editing;
  222. if(tracker->editing) {
  223. // stop_song(tracker);
  224. }
  225. }
  226. if(event->input.key == InputKeyOk && event->input.type == InputTypeLong) {
  227. if(!(tracker->editing)) {
  228. if(tracker->tracker_engine.playing) {
  229. stop_song(tracker);
  230. }
  231. else {
  232. if(tracker->tracker_engine.pattern_position == tracker->song.pattern_length - 1 &&
  233. tracker->tracker_engine.sequence_position ==
  234. tracker->song.num_sequence_steps -
  235. 1) // if we are at the very end of the song
  236. {
  237. stop_song(tracker);
  238. }
  239. else {
  240. play_song(tracker, true);
  241. }
  242. }
  243. }
  244. else {
  245. if(get_field(tracker->patternx) == 0) {
  246. set_note(step, MUS_NOTE_RELEASE);
  247. }
  248. }
  249. }
  250. if(event->input.key == InputKeyRight && event->input.type == InputTypeShort) {
  251. tracker->patternx++;
  252. if(tracker->patternx > MAX_PATTERNX - 1) {
  253. tracker->current_channel++;
  254. tracker->patternx = 0;
  255. if(tracker->current_channel > SONG_MAX_CHANNELS - 1) {
  256. tracker->current_channel = 0;
  257. }
  258. }
  259. }
  260. if(event->input.key == InputKeyLeft && event->input.type == InputTypeShort) {
  261. tracker->patternx--;
  262. if(tracker->patternx > MAX_PATTERNX - 1) // unsigned int overflow
  263. {
  264. tracker->current_channel--;
  265. tracker->patternx = MAX_PATTERNX - 1;
  266. if(tracker->current_channel > SONG_MAX_CHANNELS - 1) // unsigned int overflow
  267. {
  268. tracker->current_channel = SONG_MAX_CHANNELS - 1;
  269. }
  270. }
  271. }
  272. if(event->input.key == InputKeyDown && event->input.type == InputTypeShort) {
  273. if(!(tracker->editing)) {
  274. tracker->tracker_engine.pattern_position++;
  275. if(tracker->tracker_engine.pattern_position >
  276. tracker->tracker_engine.song->pattern_length - 1 &&
  277. tracker->tracker_engine.sequence_position <
  278. tracker->tracker_engine.song->num_sequence_steps - 1) {
  279. tracker->tracker_engine.pattern_position = 0;
  280. tracker->tracker_engine.sequence_position++;
  281. }
  282. else if(
  283. tracker->tracker_engine.pattern_position >
  284. tracker->tracker_engine.song->pattern_length - 1) {
  285. tracker->tracker_engine.pattern_position =
  286. tracker->tracker_engine.song->pattern_length - 1;
  287. }
  288. }
  289. if(tracker->editing) {
  290. edit_pattern_step(tracker, step, -1);
  291. }
  292. }
  293. if(event->input.key == InputKeyUp && event->input.type == InputTypeShort) {
  294. if(!(tracker->editing)) {
  295. int16_t temp_pattern_position = tracker->tracker_engine.pattern_position - 1;
  296. if(temp_pattern_position < 0) {
  297. if(tracker->tracker_engine.sequence_position > 0) {
  298. tracker->tracker_engine.sequence_position--;
  299. tracker->tracker_engine.pattern_position =
  300. tracker->tracker_engine.song->pattern_length - 1;
  301. }
  302. }
  303. else {
  304. tracker->tracker_engine.pattern_position--;
  305. }
  306. }
  307. if(tracker->editing) {
  308. edit_pattern_step(tracker, step, 1);
  309. }
  310. }
  311. if(event->input.key == InputKeyBack && event->input.type == InputTypeShort &&
  312. tracker->editing) {
  313. uint8_t field = get_field(tracker->patternx);
  314. delete_field(step, field);
  315. }
  316. }