45 #include <arpa/inet.h>
61 g_critical(
"Cannot allocate smf_t structure: %s", strerror(errno));
65 memset(smf, 0,
sizeof(
smf_t));
101 memset(smf, 0,
sizeof(
smf_t));
114 g_critical(
"Cannot allocate smf_track_t structure: %s", strerror(errno));
160 assert(track->
smf == NULL);
184 assert(track->
smf != NULL);
221 g_critical(
"Cannot allocate smf_event_t structure: %s", strerror(errno));
227 event->delta_time_pulses = -1;
228 event->time_pulses = -1;
229 event->time_seconds = -1.0;
230 event->track_number = -1;
251 event->midi_buffer_length = len;
254 g_critical(
"Cannot allocate MIDI buffer structure: %s", strerror(errno));
292 if (first_byte < 0) {
293 g_critical(
"First byte of MIDI message cannot be < 0");
299 if (first_byte > 255) {
300 g_critical(
"smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte);
305 g_critical(
"smf_event_new_from_bytes: first byte is not a valid status byte.");
312 else if (third_byte < 0)
318 if (second_byte > 255) {
319 g_critical(
"smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte);
324 g_critical(
"smf_event_new_from_bytes: second byte cannot be a status byte.");
330 if (third_byte > 255) {
331 g_critical(
"smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte);
336 g_critical(
"smf_event_new_from_bytes: third byte cannot be a status byte.");
341 event->midi_buffer_length = len;
344 g_critical(
"Cannot allocate MIDI buffer structure: %s", strerror(errno));
350 event->midi_buffer[0] = first_byte;
352 event->midi_buffer[1] = second_byte;
354 event->midi_buffer[2] = third_byte;
365 if (event->
track != NULL)
381 events_array_compare_function(gconstpointer aa, gconstpointer bb)
415 remove_eot_if_before_pulses(
smf_track_t *track,
int pulses)
443 int i, last_pulses = 0;
445 assert(track->
smf != NULL);
446 assert(event->
track == NULL);
451 remove_eot_if_before_pulses(track, event->
time_pulses);
453 event->track = track;
467 if (last_pulses <= event->time_pulses) {
468 event->delta_time_pulses =
event->time_pulses - last_pulses;
477 g_ptr_array_sort(track->
events_array, events_array_compare_function);
543 if (last_event != NULL) {
563 if (last_event != NULL) {
587 assert(event->
track != NULL);
590 track =
event->track;
607 for (i = event->
event_number; i <= track->number_of_events; i++) {
621 event->event_number = -1;
622 event->delta_time_pulses = -1;
623 event->time_pulses = -1;
624 event->time_seconds = -1.0;
654 assert(format == 0 || format == 1);
657 g_critical(
"There is more than one track, cannot set format to 0.");
705 assert(event != NULL);
752 assert(track_number >= 1);
773 assert(event_number >= 1);
778 event = g_ptr_array_index(track->
events_array, event_number - 1);
824 min_time_track = track;
828 return (min_time_track);
842 g_debug(
"End of the song.");
850 assert(event != NULL);
852 event->track->smf->last_seek_position = -1.0;
881 g_debug(
"End of the song.");
887 event = smf_peek_next_event_from_track(track);
889 assert(event != NULL);
912 assert(track != NULL);
916 event = smf_peek_next_event_from_track(track);
923 g_warning(
"Warning: empty track.");
970 assert(seconds >= 0.0);
974 g_debug(
"Avoiding seek to %f seconds.", seconds);
982 g_debug(
"Seeking to %f seconds.", seconds);
989 g_critical(
"Trying to seek past the end of song.");
1013 assert(pulses >= 0);
1018 g_debug(
"Seeking to %d pulses.", pulses);
1024 if (event == NULL) {
1025 g_critical(
"Trying to seek past the end of song.");
1061 pulses =
event->time_pulses;
1074 double seconds = 0.0;
1089 seconds =
event->time_seconds;
1114 return (SMF_VERSION);
void smf_rewind(smf_t *smf)
Rewinds the SMF.
smf_event_t * smf_track_get_event_by_number(const smf_track_t *track, int event_number)
double smf_get_length_seconds(const smf_t *smf)
int smf_event_is_tempo_change_or_time_signature(const smf_event_t *event)
void smf_track_add_event(smf_track_t *track, smf_event_t *event)
Adds the event to the track and computes ->delta_pulses.
int smf_set_ppqn(smf_t *smf, int ppqn)
Sets the PPQN ("Division") field of MThd header.
void smf_track_add_event_delta_pulses(smf_track_t *track, smf_event_t *event, int pulses)
Adds event to the track at the time "pulses" clocks from the previous event in this track...
GPtrArray * tempo_array
Private, used by smf_tempo.c.
unsigned char * midi_buffer
Pointer to the buffer containing MIDI message.
int smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
Add End Of Track metaevent.
Represents a "song", that is, collection of one or more tracks.
void smf_track_remove_from_smf(smf_track_t *track)
Detaches track from the smf.
int smf_seek_to_pulses(smf_t *smf, int pulses)
Seeks the SMF to the given position.
Represents a single track.
GPtrArray * tracks_array
Private, used by smf.c.
int smf_seek_to_event(smf_t *smf, const smf_event_t *target)
Seeks the SMF to the given event.
void smf_add_track(smf_t *smf, smf_track_t *track)
Appends smf_track_t to smf.
int ppqn
These fields are extracted from "division" field of MThd header.
int smf_track_add_eot_pulses(smf_track_t *track, int pulses)
int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT
void smf_init_tempo(smf_t *smf)
void smf_event_delete(smf_event_t *event)
Detaches event from its track and frees it.
void smf_create_tempo_map_and_compute_seconds(smf_t *smf)
int event_number
Number of this event in the track.
smf_event_t * smf_event_new_from_pointer(void *midi_data, int len)
Allocates an smf_event_t structure and fills it with "len" bytes copied from "midi_data".
int time_of_next_event
Absolute time of next event on events_queue.
void maybe_add_to_tempo_map(smf_event_t *event)
int smf_event_is_eot(const smf_event_t *event) WARN_UNUSED_RESULT
int time_pulses
Time, in pulses, since the start of the song.
smf_event_t * smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte)
Allocates an smf_event_t structure and fills it with at most three bytes of data. ...
void smf_delete(smf_t *smf)
Frees smf and all it's descendant structures.
const char * smf_get_version(void)
smf_track_t * smf_track_new(void)
Allocates new smf_track_t structure.
int midi_buffer_length
Length of the MIDI message in the buffer, in bytes.
smf_event_t * smf_event_new(void)
Allocates new smf_event_t structure.
void remove_last_tempo_with_pulses(smf_t *smf, int pulses)
void smf_track_add_event_pulses(smf_track_t *track, smf_event_t *event, int pulses)
Adds event to the track at the time "pulses" clocks from the start of song.
double last_seek_position
Public interface declaration for libsmf, Standard MIDI File format library.
int smf_get_length_pulses(const smf_t *smf)
int smf_seek_to_seconds(smf_t *smf, double seconds)
Seeks the SMF to the given position.
int smf_event_is_last(const smf_event_t *event)
int is_status_byte(const unsigned char status)
Returns 1 if the given byte is a valid status byte, 0 otherwise.
smf_event_t * smf_track_get_next_event(smf_track_t *track)
Returns next event from the track given and advances next event counter.
smf_track_t * smf_find_track_with_next_event(smf_t *smf)
Searches for track that contains next event, in time order.
smf_track_t * smf_get_track_by_number(const smf_t *smf, int track_number)
double time_seconds
Time, in seconds, since the start of the song.
Represents a single MIDI event or metaevent.
void smf_event_remove_from_track(smf_event_t *event)
Detaches event from its track.
smf_event_t * smf_track_get_last_event(const smf_track_t *track)
void smf_fini_tempo(smf_t *smf)
void smf_track_add_event_seconds(smf_track_t *track, smf_event_t *event, double seconds)
Adds event to the track at the time "seconds" seconds from the start of song.
void smf_track_delete(smf_track_t *track)
Detaches track from its smf and frees it.
int smf_track_add_eot_seconds(smf_track_t *track, double seconds)
int track_number
Tracks are numbered consecutively, starting from 1.
smf_event_t * smf_peek_next_event(smf_t *smf)
smf_t * smf_new(void)
Allocates new smf_t structure.
int delta_time_pulses
Note that the time fields are invalid, if event is not attached to a track.
int smf_set_format(smf_t *smf, int format)
Sets "Format" field of MThd header to the specified value.
smf_track_t * track
Pointer to the track, or NULL if event is not attached.
smf_event_t * smf_get_next_event(smf_t *smf)
void smf_skip_next_event(smf_t *smf)
Advance the "next event counter".