Example #1
0
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;
}
Example #2
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;
}
Example #3
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;
}
Example #4
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;
}
Example #5
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;
}
Example #6
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;
}