/** * Detaches event from its track. */ void smf_event_remove_from_track(smf_event_t *event) { size_t i; int was_last; smf_event_t *tmp; smf_track_t *track; assert(event->track != NULL); assert(event->track->smf != NULL); track = event->track; was_last = smf_event_is_last(event); /* Adjust ->delta_time_pulses of the next event. */ if (event->event_number < track->number_of_events) { tmp = smf_track_get_event_by_number(track, event->event_number + 1); assert(tmp); tmp->delta_time_pulses += event->delta_time_pulses; } track->number_of_events--; g_ptr_array_remove(track->events_array, event); if (track->number_of_events == 0) track->next_event_number = 0; /* Renumber the rest of the events, so they are consecutively numbered. */ for (i = event->event_number; i <= track->number_of_events; i++) { tmp = smf_track_get_event_by_number(track, i); tmp->event_number = i; } if (smf_event_is_tempo_change_or_time_signature(event)) { /* XXX: This will cause problems, when there is more than one Tempo Change event at a given time. */ if (was_last) remove_last_tempo_with_pulses(event->track->smf, event->time_pulses); else smf_create_tempo_map_and_compute_seconds(track->smf); } event->track = NULL; event->event_number = 0; event->delta_time_pulses = -1; event->time_pulses = 0; event->time_seconds = -1.0; }
/** * Adds the event to the track and computes ->delta_pulses. Note that it is faster * to append events to the end of the track than to insert them in the middle. * Usually you want to use smf_track_add_event_seconds or smf_track_add_event_pulses * instead of this one. Event needs to have ->time_pulses and ->time_seconds already set. * If you try to add event after an EOT, EOT event will be automatically deleted. */ void smf_track_add_event(smf_track_t *track, smf_event_t *event) { int i, last_pulses = 0; assert(track->smf != NULL); assert(event->track == NULL); assert(event->delta_time_pulses == -1); assert(event->time_pulses >= 0); assert(event->time_seconds >= 0.0); remove_eot_if_before_pulses(track, event->time_pulses); event->track = track; event->track_number = track->track_number; if (track->number_of_events == 0) { assert(track->next_event_number == -1); track->next_event_number = 1; } if (track->number_of_events > 0) last_pulses = smf_track_get_last_event(track)->time_pulses; track->number_of_events++; /* Are we just appending element at the end of the track? */ if (last_pulses <= event->time_pulses) { event->delta_time_pulses = event->time_pulses - last_pulses; assert(event->delta_time_pulses >= 0); g_ptr_array_add(track->events_array, event); event->event_number = track->number_of_events; /* We need to insert in the middle of the track. XXX: This is slow. */ } else { /* Append, then sort according to ->time_pulses. */ g_ptr_array_add(track->events_array, event); g_ptr_array_sort(track->events_array, events_array_compare_function); /* Renumber entries and fix their ->delta_pulses. */ for (i = 1; i <= track->number_of_events; i++) { smf_event_t *tmp = smf_track_get_event_by_number(track, i); tmp->event_number = i; if (tmp->delta_time_pulses != -1) continue; if (i == 1) { tmp->delta_time_pulses = tmp->time_pulses; } else { tmp->delta_time_pulses = tmp->time_pulses - smf_track_get_event_by_number(track, i - 1)->time_pulses; assert(tmp->delta_time_pulses >= 0); } } /* Adjust ->delta_time_pulses of the next event. */ if (event->event_number < track->number_of_events) { smf_event_t *next_event = smf_track_get_event_by_number(track, event->event_number + 1); assert(next_event); assert(next_event->time_pulses >= event->time_pulses); next_event->delta_time_pulses -= event->delta_time_pulses; assert(next_event->delta_time_pulses >= 0); } } if (smf_event_is_tempo_change_or_time_signature(event)) { if (smf_event_is_last(event)) maybe_add_to_tempo_map(event); else smf_create_tempo_map_and_compute_seconds(event->track->smf); } }