Significantly speed up loading SMF tempo-maps
Files that have many tracks, each with tempo information were near impossible to load (30+ mins on modern 4.2Ghz CPU!), because tempo is parsed incrementally: ``` For each new track: for each new tempo-event: rewind() for each loaded track so far: for each event on this track so far ``` This reduces the complexity from O(tracks^2 * tempos^2) to O(tracks * tempos). "Come Thou Fount Tempo Map.mid" has 238 Tracks and 56168 total Tempo Changes (236 per track). This now requires only 56168 iterations in smf_create_tempo_map_and_compute_seconds, rather than 1.64e+9 iterations
This commit is contained in:
parent
3da54244ea
commit
cd53301d06
@ -525,7 +525,7 @@ smf_track_add_event(smf_track_t *track, smf_event_t *event)
|
|||||||
if (smf_event_is_last(event))
|
if (smf_event_is_last(event))
|
||||||
maybe_add_to_tempo_map(event);
|
maybe_add_to_tempo_map(event);
|
||||||
else
|
else
|
||||||
smf_create_tempo_map_and_compute_seconds(event->track->smf);
|
event->track->smf->need_tempo_map_compute = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,6 +709,7 @@ smf_track_get_next_event(smf_track_t *track)
|
|||||||
if (track->next_event_number < track->number_of_events) {
|
if (track->next_event_number < track->number_of_events) {
|
||||||
next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
|
next_event = smf_track_get_event_by_number(track, track->next_event_number + 1);
|
||||||
assert(next_event);
|
assert(next_event);
|
||||||
|
assert(next_event->time_pulses >= event->time_pulses);
|
||||||
|
|
||||||
track->time_of_next_event = next_event->time_pulses;
|
track->time_of_next_event = next_event->time_pulses;
|
||||||
track->next_event_number++;
|
track->next_event_number++;
|
||||||
|
@ -251,6 +251,7 @@ struct smf_struct {
|
|||||||
/** Private, used by smf.c. */
|
/** Private, used by smf.c. */
|
||||||
GPtrArray *tracks_array;
|
GPtrArray *tracks_array;
|
||||||
double last_seek_position;
|
double last_seek_position;
|
||||||
|
int need_tempo_map_compute;
|
||||||
|
|
||||||
/** Private, used by smf_tempo.c. */
|
/** Private, used by smf_tempo.c. */
|
||||||
/** Array of pointers to smf_tempo_struct. */
|
/** Array of pointers to smf_tempo_struct. */
|
||||||
|
@ -972,6 +972,11 @@ smf_load_from_memory(void *buffer, const size_t buffer_length)
|
|||||||
smf->expected_number_of_tracks = smf->number_of_tracks;
|
smf->expected_number_of_tracks = smf->number_of_tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* process tempo-map */
|
||||||
|
if (smf->need_tempo_map_compute) {
|
||||||
|
smf_create_tempo_map_and_compute_seconds(smf);
|
||||||
|
}
|
||||||
|
|
||||||
smf->file_buffer = NULL;
|
smf->file_buffer = NULL;
|
||||||
smf->file_buffer_length = 0;
|
smf->file_buffer_length = 0;
|
||||||
smf->next_chunk_offset = 0;
|
smf->next_chunk_offset = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user