From b6a6d1f0bbf9ca85fee33d04f7984b6dbf5f8e64 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 18 Feb 2020 16:13:35 +0100 Subject: [PATCH] pw-cat: fix tempo changes Use time in seconds as event timestamp. Apply tempo from the new events, keep track of elapsed time and time since tempo change to get the right time. Skip metadata midi in pw-cat. --- src/tools/midifile.c | 4 +++- src/tools/midifile.h | 4 +++- src/tools/pw-cat.c | 11 ++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/tools/midifile.c b/src/tools/midifile.c index 30457c515..feff133c7 100644 --- a/src/tools/midifile.c +++ b/src/tools/midifile.c @@ -140,7 +140,7 @@ static int peek_event(struct midi_file *mf, struct midi_track *tr, struct midi_e return res < 0 ? res : -EIO; event->track = tr; - event->tick = tr->tick; + event->sec = mf->tick_sec + ((tr->tick - mf->tick_start) * (double)mf->tempo) / (1000000.0 * mf->division); start = event->offset = tr->offset; status = buffer[0]; @@ -183,6 +183,8 @@ static int peek_event(struct midi_file *mf, struct midi_track *tr, struct midi_e if ((res = mf->events->read(mf->data, tr->start + tr->offset, buffer, 3)) != 3) return res < 0 ? res : -EIO; + mf->tick_sec = event->sec; + mf->tick_start = tr->tick; mf->tempo = (buffer[0]<<16) | (buffer[1]<<8) | buffer[2]; break; } diff --git a/src/tools/midifile.h b/src/tools/midifile.h index 8c600383e..782332507 100644 --- a/src/tools/midifile.h +++ b/src/tools/midifile.h @@ -32,7 +32,7 @@ struct midi_event { struct midi_track *track; - int64_t tick; + double sec; uint8_t status; uint8_t meta; uint32_t offset; @@ -69,6 +69,8 @@ struct midi_file { uint32_t offset; int64_t tick; + double tick_sec; + double tick_start; const struct midi_events *events; void *data; diff --git a/src/tools/pw-cat.c b/src/tools/pw-cat.c index ae361bdf5..46107d887 100644 --- a/src/tools/pw-cat.c +++ b/src/tools/pw-cat.c @@ -989,8 +989,10 @@ static int midi_play(struct data *d, void *src, unsigned int n_frames) if (res < 0) return res; - frame = ev.tick * ((double)d->position->clock.rate.denom * d->md.file.tempo) / - (1000000.0 * d->md.file.division); + if (ev.status == 0xff) + goto next; + + frame = ev.sec * d->position->clock.rate.denom; if (frame < first_frame) frame = 0; @@ -1001,11 +1003,10 @@ static int midi_play(struct data *d, void *src, unsigned int n_frames) spa_pod_builder_control(&b, frame, SPA_CONTROL_Midi); buf[0] = ev.status; - if (ev.status == 0xff) - buf[1] = ev.meta; - midi_read(d, ev.offset, ev.status == 0xff ? &buf[2] : &buf[1], ev.size); + midi_read(d, ev.offset, &buf[1], ev.size); spa_pod_builder_bytes(&b, buf, ev.size + 1); +next: midi_file_consume_event(&d->md.file, &ev); } spa_pod_builder_pop(&b, &f);