summaryrefslogtreecommitdiff
path: root/project/Core/Src/Project/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'project/Core/Src/Project/parser.c')
-rw-r--r--project/Core/Src/Project/parser.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/project/Core/Src/Project/parser.c b/project/Core/Src/Project/parser.c
new file mode 100644
index 0000000..c34b3ba
--- /dev/null
+++ b/project/Core/Src/Project/parser.c
@@ -0,0 +1,141 @@
+/*
+ * player.c
+ *
+ * Created on: Nov 25, 2025
+ * Author: sowgro
+ */
+
+#include <parser.h>
+#include "endian_converters.h"
+#include <stdint.h>
+#include "endian_converters.h"
+#include "hw8.h"
+#include "activity4.h"
+#include "systick.h"
+#include "tone.h"
+
+static track_t tracks[4];
+static int nTracks;
+static int startTime;
+static song_info_t song_info;
+
+void parser_play_notes() {
+ int count = systick_get_count();
+ int curAbsTime = count - startTime;
+ for (int i = 0; i < nTracks; i++) {
+ note_event_t curEvent = tracks[i].events[tracks[i].curEventIndex];
+ if (curEvent.abs_time >= curAbsTime) {
+ switch (curEvent.ev_type) {
+ case NOTE_OFF_EVENT:
+ remove_tone(curEvent.key_number); break;
+ case NOTE_ON_EVENT:
+ add_tone(curEvent.key_number, curEvent.value); break;
+ }
+ }
+ tracks[i].curEventIndex++;
+ }
+ play_tones();
+}
+
+void parse_song(uint8_t *p_song) {
+ header_t header;
+ header = get_header(p_song);
+ p_song += sizeof(header_t) - 2; // move pointer past header
+
+ parse_song_info(p_song, &song_info);
+
+ nTracks = header.ntrcks;
+ for(int i = 0; i < nTracks; i++){
+ p_song = parse_track(p_song, &tracks[i]);
+ }
+}
+
+uint8_t *parse_track(uint8_t *p_song, track_t *track) {
+ printf("Parsing track \r\n");
+ p_song += 4; // skip MTrk
+ uint32_t MTrk_len = convert_to_uint32(p_song);
+ p_song += 4;
+
+ int curEvent = 0;
+ uint32_t prev_abs_time = 0;
+
+ for (uint8_t *p_end = p_song + MTrk_len; p_song != p_end; p_song++) {
+ note_event_t note;
+
+ parseDelay_result_t delay_result = parseDelay(p_song);
+ uint32_t abs_time = prev_abs_time + delay_result.value;
+ note.abs_time = abs_time;
+ prev_abs_time = abs_time;
+ p_song += delay_result.bytes_used;
+
+
+ if (*p_song >> 4 == 0b1000) {
+ note.ev_type = NOTE_OFF_EVENT;
+ } else if (*p_song >> 4 == 0b1001) {
+ note.ev_type = NOTE_ON_EVENT;
+ } else if (*p_song >> 4 == 0b1010) {
+ note.ev_type = KEY_PRESSURE;
+ } else {
+ continue;
+ }
+
+// size_t channelNumber = *p_song && 0b00001111;
+ p_song++;
+
+ note.key_number = *p_song;
+ p_song++;
+
+ note.value = *p_song;
+ p_song++;
+
+ track->events[curEvent++] = note;
+ }
+ track->nEvents = curEvent;
+ track->curEventIndex = 0;
+
+ printf("parsing track done\r\n");
+ return p_song;
+}
+
+uint8_t *parse_song_info(uint8_t *p_song, song_info_t *ret) {
+ ret->copyright = 0;
+ ret->tempo = 0;
+ ret->title = 0;
+
+ p_song += 4; // move past MTrk label
+ uint32_t MTrk_len = convert_to_uint32(p_song); // read in size of MTrk
+ p_song += sizeof(MTrk_len);
+
+ for (uint8_t *p_end = p_song + MTrk_len; p_song != p_end; p_song++) {
+ // FF 02 - copyright
+ if (convert_to_uint16(p_song) == 0xFF02) {
+ p_song += sizeof(uint16_t);
+ uint8_t ev_len = *(uint8_t *) p_song;
+ p_song += sizeof(ev_len);
+ ret->copyright = (char *) p_song;
+ ret->copyright[ev_len] = 0;
+ }
+
+ // FF 03 - title
+ if (convert_to_uint16(p_song) == 0xFF03) {
+ p_song += sizeof(uint16_t);
+ uint8_t ev_len = *(uint8_t *) p_song;
+ p_song += sizeof(ev_len);
+ ret->title = (char *) p_song;
+ ret->title[ev_len] = 0;
+ }
+
+ // FF 51 - tempo
+ if (convert_to_uint16(p_song) == 0xFF51) {
+ p_song += sizeof(uint16_t);
+ p_song += sizeof(uint8_t); // skip length, always 03
+ ret->tempo = convert_to_uint24(p_song);
+ }
+ }
+
+ return p_song;
+}
+
+song_info_t parser_get_song_info() {
+ return song_info;
+}