midi: simplify some things

This commit is contained in:
Wim Taymans 2020-02-19 10:48:16 +01:00
parent 7df66cd6ad
commit cc1ed84f9f
2 changed files with 62 additions and 70 deletions

View file

@ -38,25 +38,34 @@ static inline uint32_t parse_be32(const uint8_t *in)
return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3]; return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
} }
static inline int avail(struct midi_file *mf) static inline int mf_avail(struct midi_file *mf)
{ {
if (mf->p < mf->data + mf->size) if (mf->p < mf->data + mf->size)
return mf->size + mf->data - mf->p; return mf->size + mf->data - mf->p;
return 0; return 0;
} }
static inline int tr_avail(struct midi_track *tr)
{
if (tr->eof)
return 0;
if (tr->p < tr->data + tr->size)
return tr->size + tr->data - tr->p;
tr->eof = true;
return 0;
}
static int read_mthd(struct midi_file *mf) static int read_mthd(struct midi_file *mf)
{ {
if (avail(mf) < 14) if (mf_avail(mf) < 14 ||
return -EIO; memcmp(mf->p, "MThd", 4) != 0)
if (memcmp(mf->p, "MThd", 4))
return -EIO; return -EIO;
mf->length = parse_be32(mf->p + 4); mf->length = parse_be32(mf->p + 4);
mf->format = parse_be16(mf->p + 8); mf->format = parse_be16(mf->p + 8);
mf->ntracks = parse_be16(mf->p + 10); mf->ntracks = parse_be16(mf->p + 10);
mf->division = parse_be16(mf->p + 12); mf->division = parse_be16(mf->p + 12);
mf->p += 14; mf->p += 14;
return 0; return 0;
} }
@ -67,9 +76,8 @@ int midi_file_init(struct midi_file *mf, const char *mode,
int res; int res;
spa_zero(*mf); spa_zero(*mf);
mf->data = data; mf->data = mf->p = data;
mf->size = size; mf->size = size;
mf->p = data;
if ((res = read_mthd(mf)) < 0) if ((res = read_mthd(mf)) < 0)
return res; return res;
@ -84,30 +92,23 @@ int midi_file_init(struct midi_file *mf, const char *mode,
static int read_mtrk(struct midi_file *mf, struct midi_track *track) static int read_mtrk(struct midi_file *mf, struct midi_track *track)
{ {
if (avail(mf) < 8) if (mf_avail(mf) < 8 ||
memcmp(mf->p, "MTrk", 4) != 0)
return -EIO; return -EIO;
if (memcmp(mf->p, "MTrk", 4)) track->data = track->p = mf->p + 8;
return -EIO;
track->p = track->data = mf->p + 8;
track->size = parse_be32(mf->p + 4); track->size = parse_be32(mf->p + 4);
mf->p += track->size + 8;
mf->p = track->data + track->size;
return 0; return 0;
} }
static int parse_varlen(struct midi_file *mf, struct midi_track *tr, uint32_t *result) static int parse_varlen(struct midi_file *mf, struct midi_track *tr, uint32_t *result)
{ {
uint32_t i, value = 0; uint32_t value = 0;
uint8_t b;
value = 0; while (tr_avail(tr) > 0) {
for (i = 0; i < 4; i++) { uint8_t b = *tr->p++;
if (tr->p >= tr->data + tr->size) {
tr->eof = true;
break;
}
b = *tr->p++;
value = (value << 7) | (b & 0x7f); value = (value << 7) | (b & 0x7f);
if ((b & 0x80) == 0) if ((b & 0x80) == 0)
break; break;
@ -119,10 +120,10 @@ static int parse_varlen(struct midi_file *mf, struct midi_track *tr, uint32_t *r
static int peek_event(struct midi_file *mf, struct midi_track *tr, struct midi_event *event) static int peek_event(struct midi_file *mf, struct midi_track *tr, struct midi_event *event)
{ {
uint8_t *save, status; uint8_t *save, status;
uint32_t size = 0; uint32_t size;
int res; int res;
if (tr->eof || tr->p >= tr->data + tr->size) if (tr_avail(tr) == 0)
return -EIO; return -EIO;
save = tr->p; save = tr->p;
@ -133,51 +134,54 @@ static int peek_event(struct midi_file *mf, struct midi_track *tr, struct midi_e
if ((status & 0x80) == 0) { if ((status & 0x80) == 0) {
status = tr->running_status; status = tr->running_status;
event->data = tr->p;
} else { } else {
tr->running_status = status; tr->running_status = status;
event->data = ++tr->p; tr->p++;
} }
event->status = status; event->status = status;
if (status < 0xf0) { switch (status) {
size++; case 0xc0 ... 0xdf:
if (status < 0xc0 || status >= 0xe0) size = 1;
size++; break;
} else {
if (status == 0xff) {
event->meta = *tr->p++;
if ((res = parse_varlen(mf, tr, &size)) < 0) case 0x00 ... 0xbf:
return res; case 0xe0 ... 0xef:
size = 2;
break;
event->data = tr->p; case 0xff:
event->meta = *tr->p++;
switch (event->meta) { if ((res = parse_varlen(mf, tr, &size)) < 0)
case 0x2f: return res;
tr->eof = true;
break;
case 0x51:
if (size < 3)
break;
mf->tick_sec = event->sec;
mf->tick_start = tr->tick;
mf->tempo = (tr->p[0]<<16) | (tr->p[1]<<8) | tr->p[2];
break;
}
} else if (status == 0xf0 || status == 0xf7) { switch (event->meta) {
if ((res = parse_varlen(mf, tr, &size)) < 0) case 0x2f:
return res; tr->eof = true;
event->data = tr->p; break;
} else { case 0x51:
return -EIO; if (size < 3)
return -EIO;
mf->tick_sec = event->sec;
mf->tick_start = tr->tick;
mf->tempo = (tr->p[0]<<16) | (tr->p[1]<<8) | tr->p[2];
break;
} }
break;
case 0xf0:
case 0xf7:
if ((res = parse_varlen(mf, tr, &size)) < 0)
return res;
break;
default:
return -EIO;
} }
event->data = tr->p;
tr->p = save; tr->p = save;
event->size = size; event->size = size;
return 0; return 0;
} }
@ -193,7 +197,6 @@ int midi_file_add_track(struct midi_file *mf, struct midi_track *track)
return res; return res;
track->tick = delta_time; track->tick = delta_time;
spa_list_init(&track->events);
spa_list_append(&mf->tracks, &track->link); spa_list_append(&mf->tracks, &track->link);
return 0; return 0;
@ -204,7 +207,7 @@ int midi_file_peek_event(struct midi_file *mf, struct midi_event *event)
struct midi_track *tr, *found = NULL; struct midi_track *tr, *found = NULL;
spa_list_for_each(tr, &mf->tracks, link) { spa_list_for_each(tr, &mf->tracks, link) {
if (tr->eof) if (tr_avail(tr) == 0)
continue; continue;
if (found == NULL || tr->tick < found->tick) if (found == NULL || tr->tick < found->tick)
found = tr; found = tr;
@ -222,15 +225,10 @@ int midi_file_consume_event(struct midi_file *mf, struct midi_event *event)
int res; int res;
tr->p = event->data + event->size; tr->p = event->data + event->size;
if ((res = parse_varlen(mf, tr, &delta_time)) < 0) if ((res = parse_varlen(mf, tr, &delta_time)) < 0)
return res; return res;
tr->tick += delta_time; tr->tick += delta_time;
return 0; return 0;
} }
int midi_file_add_event(struct midi_file *mf, struct midi_track *track, struct midi_event *event)
{
spa_list_append(&track->events, &event->link);
return 0;
}

View file

@ -50,8 +50,6 @@ struct midi_track {
int64_t tick; int64_t tick;
uint8_t running_status; uint8_t running_status;
unsigned int eof:1; unsigned int eof:1;
struct spa_list events;
}; };
struct midi_file { struct midi_file {
@ -79,7 +77,3 @@ int midi_file_add_track(struct midi_file *mf, struct midi_track *track);
int midi_file_peek_event(struct midi_file *mf, struct midi_event *event); int midi_file_peek_event(struct midi_file *mf, struct midi_event *event);
int midi_file_consume_event(struct midi_file *mf, struct midi_event *event); int midi_file_consume_event(struct midi_file *mf, struct midi_event *event);
int midi_file_add_event(struct midi_file *mf, struct midi_track *track, struct midi_event *event);