61 assert(
smf->file_buffer != NULL);
62 assert(
smf->file_buffer_length > 0);
63 assert(
smf->next_chunk_offset >= 0);
66 g_critical(
"SMF warning: no more chunks left.");
70 next_chunk_ptr = (
unsigned char *)
smf->file_buffer +
smf->next_chunk_offset;
74 if (!isalpha(chunk->
id[0]) || !isalpha(chunk->
id[1]) || !isalpha(chunk->
id[2]) || !isalpha(chunk->
id[3])) {
75 g_critical(
"SMF error: chunk signature contains at least one non-alphanumeric byte.");
85 if (
smf->next_chunk_offset >
smf->file_buffer_length) {
86 g_critical(
"SMF warning: malformed chunk; truncated file?");
87 smf->next_chunk_offset = smf->file_buffer_length;
99 if (!memcmp(chunk->
id, signature, 4))
121 if (
smf->file_buffer_length < 6) {
122 g_critical(
"SMF error: file is too short, it cannot be a MIDI file.");
127 tmp_mthd =
smf->file_buffer;
129 if (!chunk_signature_matches(tmp_mthd,
"MThd")) {
130 g_critical(
"SMF error: MThd signature not found, is that a MIDI file?");
136 mthd = next_chunk(
smf);
140 assert(mthd == tmp_mthd);
142 len = ntohl(mthd->
length);
144 g_critical(
"SMF error: MThd chunk length %d, must be 6.", len);
158 signed char first_byte_of_division, second_byte_of_division;
164 if (parse_mthd_header(
smf))
170 if (
smf->format < 0 ||
smf->format > 2) {
171 g_critical(
"SMF error: bad MThd format field value: %d, valid values are 0-2, inclusive.",
smf->format);
175 if (
smf->format == 2) {
176 g_critical(
"SMF file uses format #2, no support for that yet.");
181 if (
smf->expected_number_of_tracks <= 0) {
182 g_critical(
"SMF error: bad number of tracks: %d, must be greater than zero.",
smf->expected_number_of_tracks);
187 first_byte_of_division = *((
signed char *)&(mthd->
division));
188 second_byte_of_division = *((
signed char *)&(mthd->
division) + 1);
190 if (first_byte_of_division >= 0) {
192 smf->frames_per_second = 0;
196 smf->frames_per_second = - first_byte_of_division;
197 smf->resolution = second_byte_of_division;
200 if (
smf->ppqn == 0) {
201 g_critical(
"SMF file uses FPS timing instead of PPQN, no support for that yet.");
215extract_vlq(
const unsigned char *buf,
const int buffer_length,
int *value,
int *len)
218 const unsigned char *c = buf;
220 assert(buffer_length > 0);
223 if (c >= buf + buffer_length) {
224 g_critical(
"End of buffer in extract_vlq().");
228 val = (val << 7) + (*c & 0x7F);
240 g_critical(
"SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
253 return (status & 0x80);
257is_sysex_byte(
const unsigned char status)
266is_escape_byte(
const unsigned char status)
282expected_sysex_length(
const unsigned char status,
const unsigned char *second_byte,
const int buffer_length,
int *consumed_bytes)
284 int sysex_length, len;
286 assert(status == 0xF0 || status == 0xF7);
288 if (buffer_length < 3) {
289 g_critical(
"SMF error: end of buffer in expected_sysex_length().");
293 if (extract_vlq(second_byte, buffer_length, &sysex_length, &len))
296 if (consumed_bytes != NULL)
297 *consumed_bytes = len;
300 return (sysex_length + 1);
304expected_escaped_length(
const unsigned char status,
const unsigned char *second_byte,
const int buffer_length,
int *consumed_bytes)
307 return (expected_sysex_length(status, second_byte, buffer_length, consumed_bytes) - 1);
316expected_message_length(
unsigned char status,
const unsigned char *second_byte,
const int buffer_length)
322 assert(!is_sysex_byte(status));
325 assert(!is_escape_byte(status));
328 assert(buffer_length >= 0);
331 if (status == 0xFF) {
332 if (buffer_length < 2) {
333 g_critical(
"SMF error: end of buffer in expected_message_length().");
341 return (*(second_byte + 1) + 3);
344 if ((status & 0xF0) == 0xF0) {
363 g_critical(
"SMF error: unknown 0xFx-type status byte '0x%x'.", status);
384 g_critical(
"SMF error: unknown status byte '0x%x'.", status);
390extract_sysex_event(
const unsigned char *buf,
const int buffer_length,
smf_event_t *event,
int *len,
int last_status)
392 int status, message_length, vlq_length;
393 const unsigned char *c = buf;
397 assert(is_sysex_byte(status));
401 message_length = expected_sysex_length(status, c, buffer_length - 1, &vlq_length);
403 if (message_length < 0)
408 if (vlq_length + message_length >= buffer_length) {
409 g_critical(
"End of buffer in extract_sysex_event().");
413 event->midi_buffer_length = message_length;
416 g_critical(
"Cannot allocate memory in extract_sysex_event(): %s", strerror(errno));
420 event->midi_buffer[0] = status;
421 memcpy(event->
midi_buffer + 1, c, message_length - 1);
423 *len = vlq_length + message_length;
429extract_escaped_event(
const unsigned char *buf,
const int buffer_length,
smf_event_t *event,
int *len,
int last_status)
431 int status, message_length, vlq_length;
432 const unsigned char *c = buf;
436 assert(is_escape_byte(status));
440 message_length = expected_escaped_length(status, c, buffer_length - 1, &vlq_length);
442 if (message_length <= 0)
447 if (vlq_length + message_length >= buffer_length) {
448 g_critical(
"End of buffer in extract_escaped_event().");
452 event->midi_buffer_length = message_length;
455 g_critical(
"Cannot allocate memory in extract_escaped_event(): %s", strerror(errno));
462 g_critical(
"Escaped event is invalid.");
467 g_warning(
"Escaped event is not System Realtime nor System Common.");
470 *len = vlq_length + message_length;
482extract_midi_event(
const unsigned char *buf,
const int buffer_length,
smf_event_t *event,
int *len,
int last_status)
484 int status, message_length;
485 const unsigned char *c = buf;
487 assert(buffer_length > 0);
496 status = last_status;
500 g_critical(
"SMF error: bad status byte (MSB is zero).");
504 if (is_sysex_byte(status)) {
506 g_critical(
"SMF error: running status is not applicable to System Exclusive events.");
509 return (extract_sysex_event(buf, buffer_length, event, len, last_status));
512 if (is_escape_byte(status)) {
514 g_critical(
"SMF error: running status is not applicable to Escape events.");
517 return (extract_escaped_event(buf, buffer_length, event, len, last_status));
521 message_length = expected_message_length(status, c, buffer_length - (c - buf));
523 if (message_length < 0)
526 if (message_length - 1 > buffer_length - (c - buf)) {
527 g_critical(
"End of buffer in extract_midi_event().");
531 event->midi_buffer_length = message_length;
534 g_critical(
"Cannot allocate memory in extract_midi_event(): %s", strerror(errno));
538 event->midi_buffer[0] = status;
539 memcpy(event->
midi_buffer + 1, c, message_length - 1);
541 *len = c + message_length - 1 - buf;
555 int time = 0, len, buffer_length;
556 unsigned char *c, *start;
569 assert(buffer_length > 0);
572 if (extract_vlq(c, buffer_length, &time, &len))
576 buffer_length -= len;
578 if (buffer_length <= 0)
582 if (extract_midi_event(c, buffer_length, event, &len, track->
last_status))
586 buffer_length -= len;
606make_string(
const unsigned char *buf,
const int buffer_length,
int len)
610 assert(buffer_length > 0);
613 if (len > buffer_length) {
614 g_critical(
"End of buffer in make_string().");
619 str = malloc(len + 1);
621 g_critical(
"Cannot allocate memory in make_string().");
625 memcpy(str, buf, len);
659 int string_length = -1, length_length = -1;
665 g_critical(
"smf_event_extract_text: truncated MIDI message.");
671 if (string_length <= 0) {
672 g_critical(
"smf_event_extract_text: truncated MIDI message.");
690 assert(track->
smf != NULL);
692 mtrk = next_chunk(track->
smf);
697 if (!chunk_signature_matches(mtrk,
"MTrk")) {
698 g_warning(
"SMF warning: Expected MTrk signature, got %c%c%c%c instead; ignoring this chunk.",
699 mtrk->
id[0], mtrk->
id[1], mtrk->
id[2], mtrk->
id[3]);
762 g_critical(
"First byte of MIDI message is not a valid status byte.");
782 if (parse_mtrk_header(track))
792 g_warning(
"SMF warning: The track did not finish with the End of Track event.");
796 event = parse_next_event(track);
800 g_critical(
"Unable to parse MIDI event; truncating track.");
802 g_critical(
"smf_track_add_eot_delta_pulses failed.");
810 if (event_is_end_of_track(event))
825load_file_into_buffer(
void **file_buffer,
int *file_buffer_length,
const char *file_name)
827 FILE *stream = fopen(file_name,
"rb");
829 if (stream == NULL) {
830 g_critical(
"Cannot open input file: %s", strerror(errno));
835 if (fseek(stream, 0, SEEK_END)) {
836 g_critical(
"fseek(3) failed: %s", strerror(errno));
841 *file_buffer_length = ftell(stream);
842 if (*file_buffer_length == -1) {
843 g_critical(
"ftell(3) failed: %s", strerror(errno));
848 if (fseek(stream, 0, SEEK_SET)) {
849 g_critical(
"fseek(3) failed: %s", strerror(errno));
854 *file_buffer = malloc(*file_buffer_length);
855 if (*file_buffer == NULL) {
856 g_critical(
"malloc(3) failed: %s", strerror(errno));
861 if (fread(*file_buffer, 1, *file_buffer_length, stream) != *file_buffer_length) {
862 g_critical(
"fread(3) failed: %s", strerror(errno));
867 if (fclose(stream)) {
868 g_critical(
"fclose(3) failed: %s", strerror(errno));
887 smf->file_buffer = (
void *)buffer;
888 smf->file_buffer_length = buffer_length;
889 smf->next_chunk_offset = 0;
891 if (parse_mthd_chunk(
smf)) {
896 for (i = 1; i <=
smf->expected_number_of_tracks; i++) {
906 if (parse_mtrk_chunk(track)) {
907 g_warning(
"SMF warning: Cannot load track.");
917 if (
smf->expected_number_of_tracks !=
smf->number_of_tracks) {
918 g_warning(
"SMF warning: MThd header declared %d tracks, but only %d found; continuing anyway.",
919 smf->expected_number_of_tracks,
smf->number_of_tracks);
921 smf->expected_number_of_tracks =
smf->number_of_tracks;
924 smf->file_buffer = NULL;
925 smf->file_buffer_length = 0;
926 smf->next_chunk_offset = -1;
940 int file_buffer_length;
944 if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
949 memset(file_buffer, 0, file_buffer_length);
smf_event_t * smf_event_new(void)
Allocates new smf_event_t structure.
void smf_delete(smf_t *smf)
Frees smf and all it's descendant structures.
int smf_track_add_eot_delta_pulses(smf_track_t *track, int delta)
Add End Of Track metaevent.
smf_track_t * smf_track_new(void)
Allocates new smf_track_t structure.
void smf_add_track(smf_t *smf, smf_track_t *track)
Appends smf_track_t to smf.
void smf_track_delete(smf_track_t *track)
Detaches track from its smf and frees it.
smf_t * smf_new(void)
Allocates new smf_t structure.
void smf_rewind(smf_t *smf)
Rewinds the SMF.
void smf_event_delete(smf_event_t *event)
Detaches event from its track and frees it.
Public interface declaration for libsmf, Standard MIDI File format library.
int smf_event_is_system_common(const smf_event_t *event) WARN_UNUSED_RESULT
int smf_event_is_metadata(const smf_event_t *event) WARN_UNUSED_RESULT
int smf_event_is_sysex(const smf_event_t *event) WARN_UNUSED_RESULT
struct smf_event_struct smf_event_t
struct smf_track_struct smf_track_t
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.
int smf_event_is_system_realtime(const smf_event_t *event) WARN_UNUSED_RESULT
int smf_event_is_textual(const smf_event_t *event)
smf_t * smf_load_from_memory(const void *buffer, const int buffer_length)
Creates new SMF and fills it with data loaded from the given buffer.
char * smf_event_extract_text(const smf_event_t *event)
Extracts text from "textual metaevents", such as Text or Lyric.
int smf_event_is_valid(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.
int smf_event_length_is_valid(const smf_event_t *event)
smf_t * smf_load(const char *file_name)
Loads SMF file.
SMF chunk, used only by smf_load.c and smf_save.c.
uint16_t number_of_tracks
unsigned char * midi_buffer
Pointer to the buffer containing MIDI message.
int midi_buffer_length
Length of the MIDI message in the buffer, in bytes.
int next_event_offset
Private, used by smf.c.
void * file_buffer
These are private fields using only by loading and saving routines.