mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-02 11:49:33 +01:00
libsmf: speed up ridiculous design of smf_save()
This would realloc a buffer for every event, making it absurdly slow for large MIDI files (say, 10k events). Use the somewhat standard heuristic of doubling the requested allocation every time we need to increase the size. This results in a speedup of 40-100x when saving SMF to disk
This commit is contained in:
parent
662d1b9e46
commit
65332e603b
2 changed files with 27 additions and 15 deletions
|
|
@ -244,6 +244,7 @@ struct smf_struct {
|
|||
/** These are private fields using only by loading and saving routines. */
|
||||
FILE *stream;
|
||||
void *file_buffer;
|
||||
size_t file_buffer_capacity;
|
||||
size_t file_buffer_length;
|
||||
size_t next_chunk_offset;
|
||||
int expected_number_of_tracks;
|
||||
|
|
|
|||
|
|
@ -58,21 +58,32 @@ smf_extend(smf_t *smf, const int length)
|
|||
int i, previous_file_buffer_length = smf->file_buffer_length;
|
||||
char *previous_file_buffer = (char*)smf->file_buffer;
|
||||
|
||||
/* XXX: Not terribly efficient. */
|
||||
smf->file_buffer_length += length;
|
||||
smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_length);
|
||||
if (smf->file_buffer == NULL) {
|
||||
g_warning("realloc(3) failed: %s", strerror(errno));
|
||||
smf->file_buffer_length = 0;
|
||||
return (NULL);
|
||||
}
|
||||
if (smf->file_buffer_capacity >= smf->file_buffer_length + length) {
|
||||
smf->file_buffer_length += length;
|
||||
} else {
|
||||
|
||||
/* Fix up pointers. XXX: omgwtf. */
|
||||
for (i = 1; i <= smf->number_of_tracks; i++) {
|
||||
smf_track_t *track;
|
||||
track = smf_get_track_by_number(smf, i);
|
||||
if (track->file_buffer != NULL)
|
||||
track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
|
||||
if (smf->file_buffer_capacity == 0) {
|
||||
smf->file_buffer_capacity = length * 2;
|
||||
} else {
|
||||
smf->file_buffer_capacity *= 2;
|
||||
}
|
||||
smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_capacity);
|
||||
if (smf->file_buffer == NULL) {
|
||||
g_warning("realloc(3) failed: %s", strerror(errno));
|
||||
smf->file_buffer_length = 0;
|
||||
smf->file_buffer_capacity = 0;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
smf->file_buffer_length += length;
|
||||
|
||||
/* Fix up pointers. XXX: omgwtf. */
|
||||
for (i = 1; i <= smf->number_of_tracks; i++) {
|
||||
smf_track_t *track;
|
||||
track = smf_get_track_by_number(smf, i);
|
||||
if (track->file_buffer != NULL)
|
||||
track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return ((char *)smf->file_buffer + previous_file_buffer_length);
|
||||
|
|
@ -441,6 +452,7 @@ free_buffer(smf_t *smf)
|
|||
free(smf->file_buffer);
|
||||
smf->file_buffer = NULL;
|
||||
smf->file_buffer_length = 0;
|
||||
smf->file_buffer_capacity = 0;
|
||||
|
||||
for (i = 1; i <= smf->number_of_tracks; i++) {
|
||||
track = smf_get_track_by_number(smf, i);
|
||||
|
|
@ -681,4 +693,3 @@ smf_save(smf_t *smf, FILE* file)
|
|||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue