//Add the passed midi to a recording in Denemo.project->movement static void record_midi (gchar * buf, gdouble time) { buf[0] |= 0xF; //here force the channel to 15 smf_event_t *event = smf_event_new_from_pointer (buf, 3); if (event && smf_event_is_valid (event)) { if (Denemo.project->movement->recorded_midi_track && ((smf_track_t *) Denemo.project->movement->recorded_midi_track)->smf) { smf_track_add_event_seconds (Denemo.project->movement->recorded_midi_track, event, time); if(Denemo.project->movement->recording && noteon_key(event)) { DenemoRecordedNote *note = g_malloc0(sizeof(DenemoRecordedNote)); note->timing = event->time_seconds * Denemo.project->movement->recording->samplerate; notenum2enharmonic (noteon_key(event), &(note->mid_c_offset), &(note->enshift), &(note->octave)); note->event = event; Denemo.project->movement->recording->notes = g_list_append (Denemo.project->movement->recording->notes, note); } } else { smf_event_delete (event); gdk_beep (); } } }
/** * Locates, basing on track->next_event_offset, the next event data in track->buffer, * interprets it, allocates smf_event_t and fills it properly. Returns smf_event_t * or NULL, if there was an error. Allocating event means adding it to the track; * see smf_event_new(). */ static smf_event_t * parse_next_event(smf_track_t *track) { uint32_t etime = 0; uint32_t len; size_t buffer_length; unsigned char *c, *start; smf_event_t *event = smf_event_new(); if (event == NULL) goto error; c = start = (unsigned char *)track->file_buffer + track->next_event_offset; assert(track->file_buffer != NULL); assert(track->file_buffer_length > 0); assert(track->next_event_offset > 0); buffer_length = track->file_buffer_length - track->next_event_offset; /* if there was no meta-EOT event, buffer_length can be zero. This is an error in the SMF file, but it shouldn't be treated as fatal. */ if (buffer_length == 0) { g_warning ("SMF warning: expected EOT at end of track, but none found"); goto error; } /* First, extract time offset from previous event. */ if (smf_extract_vlq(c, buffer_length, &etime, &len)) { goto error; } c += len; buffer_length -= len; if (buffer_length <= 0) goto error; /* Now, extract the actual event. */ if (extract_midi_event(c, buffer_length, event, &len, track->last_status)) { goto error; } c += len; buffer_length -= len; track->last_status = event->midi_buffer[0]; track->next_event_offset += c - start; smf_track_add_event_delta_pulses(track, event, etime); return (event); error: if (event != NULL) smf_event_delete(event); return (NULL); }
static int cmd_eventrm(char *number) { int num = parse_event_number(number); if (num < 0) return (-1); if (selected_event != NULL && num == selected_event->event_number) selected_event = NULL; smf_event_delete(smf_track_get_event_by_number(selected_track, num)); g_message("Event #%d removed.", num); return (0); }
/** * Detaches track from its smf and frees it. */ void smf_track_delete(smf_track_t *track) { assert(track); assert(track->events_array); /* Remove all the events, from last to first. */ while (track->events_array->len > 0) smf_event_delete(g_ptr_array_index(track->events_array, track->events_array->len - 1)); if (track->smf) smf_track_remove_from_smf(track); assert(track->events_array->len == 0); assert(track->number_of_events == 0); g_ptr_array_free(track->events_array, TRUE); memset(track, 0, sizeof(smf_track_t)); free(track); }
/** * Allocates an smf_event_t structure and fills it with "len" bytes copied * from "midi_data". * \param midi_data Pointer to MIDI data. It sill be copied to the newly allocated event->midi_buffer. * \param len Length of the buffer. It must be proper MIDI event length, e.g. 3 for Note On event. * \return Event containing MIDI data or NULL. */ smf_event_t * smf_event_new_from_pointer(void *midi_data, int len) { smf_event_t *event; event = smf_event_new(); if (event == NULL) return (NULL); event->midi_buffer_length = len; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); return (NULL); } memcpy(event->midi_buffer, midi_data, len); return (event); }
CAMLprim value ocaml_smf_event_delete(value event) { CAMLparam1(event); smf_event_delete(get_event(event)); CAMLreturn(Val_unit); }
static int cmd_eventadd(char *str) { int midi_buffer_length; double seconds; unsigned char *midi_buffer; char *time, *endtime; if (selected_track == NULL) { g_critical("Please select a track first, using 'track <number>' command."); return (-1); } if (str == NULL) { eventadd_usage(); return (-2); } /* Extract the time. Don't use strsep(3), it doesn't work on SunOS. */ time = str; str = strchr(str, ' '); if (str != NULL) { *str = '\0'; str++; } seconds = strtod(time, &endtime); if (endtime - time != strlen(time)) { g_critical("Time is supposed to be a number, without trailing characters."); return (-3); } /* Called with one parameter? */ if (str == NULL) { eventadd_usage(); return (-4); } if (decode_hex(str, &midi_buffer, &midi_buffer_length)) { eventadd_usage(); return (-5); } selected_event = smf_event_new(); if (selected_event == NULL) { g_critical("smf_event_new() failed, event not created."); return (-6); } selected_event->midi_buffer = midi_buffer; selected_event->midi_buffer_length = midi_buffer_length; if (smf_event_is_valid(selected_event) == 0) { g_critical("Event is invalid from the MIDI specification point of view, not created."); smf_event_delete(selected_event); selected_event = NULL; return (-7); } smf_track_add_event_seconds(selected_track, selected_event, seconds); g_message("Event created."); return (0); }
/** * Allocates an smf_event_t structure and fills it with at most three bytes of data. * For example, if you need to create Note On event, do something like this: * * smf_event_new_from_bytes(0x90, 0x3C, 0x7f); * * To create event for MIDI message that is shorter than three bytes, do something * like this: * * smf_event_new_from_bytes(0xC0, 0x42, -1); * * \param first_byte First byte of MIDI message. Must be valid status byte. * \param second_byte Second byte of MIDI message or -1, if message is one byte long. * \param third_byte Third byte of MIDI message or -1, if message is two bytes long. * \return Event containing MIDI data or NULL. */ smf_event_t * smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) { int len; smf_event_t *event; event = smf_event_new(); if (event == NULL) return (NULL); if (first_byte < 0) { g_critical("First byte of MIDI message cannot be < 0"); smf_event_delete(event); return (NULL); } if (first_byte > 255) { g_critical("smf_event_new_from_bytes: first byte is %d, which is larger than 255.", first_byte); return (NULL); } if (!is_status_byte(first_byte)) { g_critical("smf_event_new_from_bytes: first byte is not a valid status byte."); return (NULL); } if (second_byte < 0) len = 1; else if (third_byte < 0) len = 2; else len = 3; if (len > 1) { if (second_byte > 255) { g_critical("smf_event_new_from_bytes: second byte is %d, which is larger than 255.", second_byte); return (NULL); } if (is_status_byte(second_byte)) { g_critical("smf_event_new_from_bytes: second byte cannot be a status byte."); return (NULL); } } if (len > 2) { if (third_byte > 255) { g_critical("smf_event_new_from_bytes: third byte is %d, which is larger than 255.", third_byte); return (NULL); } if (is_status_byte(third_byte)) { g_critical("smf_event_new_from_bytes: third byte cannot be a status byte."); return (NULL); } } event->midi_buffer_length = len; event->midi_buffer = malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); return (NULL); } event->midi_buffer[0] = first_byte; if (len > 1) event->midi_buffer[1] = second_byte; if (len > 2) event->midi_buffer[2] = third_byte; return (event); }