int test_sky_data_file_add_small_event_to_new_ending_path_causing_block_split() { sky_data_file *data_file; INIT_DATA_FILE("tests/fixtures/data_files/2/e", 0); ADD_EVENT(15LL, 12LL, 20); ASSERT_DATA_FILE("tests/fixtures/data_files/2/i"); sky_data_file_free(data_file); return 0; }
int test_sky_data_file_add_event_to_new_starting_path_causing_block_split() { sky_data_file *data_file; INIT_DATA_FILE("tests/fixtures/data_files/2/a", 0); ADD_EVENT(2LL, 12LL, 20); ASSERT_DATA_FILE("tests/fixtures/data_files/2/d"); sky_data_file_free(data_file); return 0; }
int test_sky_data_file_add_event_with_prepending_path() { sky_data_file *data_file; INIT_DATA_FILE("tests/fixtures/data_files/1/b", 0); ADD_EVENT(2LL, 11LL, 22); ASSERT_DATA_FILE("tests/fixtures/data_files/1/e"); sky_data_file_free(data_file); return 0; }
int test_sky_data_file_append_event_to_existing_path() { sky_data_file *data_file; INIT_DATA_FILE("tests/fixtures/data_files/1/b", 0); ADD_EVENT(3LL, 11LL, 22); ASSERT_DATA_FILE("tests/fixtures/data_files/1/c"); sky_data_file_free(data_file); return 0; }
int test_sky_data_file_add_event_to_new_block() { sky_data_file *data_file; INIT_DATA_FILE("", 64); ADD_EVENT(3LL, 10LL, 20); ASSERT_DATA_FILE("tests/fixtures/data_files/1/a"); sky_data_file_free(data_file); return 0; }
int txtmidi_parse(const char * filename, struct smf_header * header, struct smf_track ** track) { char * eventspace = NULL; int lineno = 0; FILE * file = fopen(filename, "r"); if (file == NULL) { ERRORNO("Unable to open file"); goto fail; } char buffer[4096]; if (fgets(buffer, sizeof buffer, file) == NULL) { ERRORNO("Unable to fgets header"); goto fail; } unsigned int evcount, evlen, division; if (sscanf(buffer, "%u @ %u / %u", &evcount, &evlen, &division) != 3) { ERROR("Unable to parse header. Should be in form \"16 @ 1 / 4\". Had \"%s\"", buffer); goto fail; } header->header_ntracks = 1; header->header_division = division; #define MAX_EVENTS 1024 eventspace = calloc(MAX_EVENTS + 2, sizeof(struct smf_event) + 8); *track = (struct smf_track *) eventspace; char * evdata = eventspace + (MAX_EVENTS + 2) * sizeof(struct smf_event); struct smf_event * events = (*track)->track_events; size_t count = 0; while (fgets(buffer, sizeof buffer, file) != NULL) { int note = 0; char * notestr = strtok(buffer, ":"); //XXX if (notestr == NULL) { ERROR("Parse error"); goto fail; } note = atoi(notestr); if (note < 0 || note >= 128) { ERROR("Invalid note number; expected 0-127, got %d", note); goto fail; } char * evstr = strtok(NULL, ""); if (evstr == NULL) { ERROR("Parse error"); goto fail; } unsigned int time = 0; bool on = false; #define ADD_EVENT(status) ({ \ *events++ = (struct smf_event) { \ .event_deltatime = time * evlen, \ .event_length = 3, \ .event_data = evdata \ }; \ (*track)->track_nevents++; \ *evdata++ = (status); /* Note on/off */ \ *evdata++ = note; /* note */ \ *evdata++ = 127; /* velocity */ \ }) while (*evstr) { switch(*evstr) { case '#': // Note if (on) { ADD_EVENT(0x80); on = false; } ADD_EVENT(0x90); on = true; time++; break; case '>': // Sustain if (!on) { ERROR("'>' not preceeded by '#' or '>'"); goto fail; } time++; break; case '.': // Rest if (on) { ADD_EVENT(0x80); on = false; } time++; break; default: break; } evstr++; } if (on) { ADD_EVENT(0x80); on = false; } if (time != evcount) { ERROR("Invalid number of ticks; expected %d got %d", evcount, time); goto fail; } if ((*track)->track_nevents >= MAX_EVENTS) { ERROR("Too many events; MAX_EVENTS is %d", MAX_EVENTS); goto fail; } } qsort((*track)->track_events, (*track)->track_nevents, sizeof(struct smf_event), ev_compare); // Now convert all the event times into delta times for (size_t i = (*track)->track_nevents - 1; i >= 1; i--) { (*track)->track_events[i].event_deltatime -= (*track)->track_events[i-1].event_deltatime; } return 0; fail: fclose(file); free(eventspace); return -1; }