Beispiel #1
0
/**
 * 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);
}
Beispiel #2
0
/**
 * 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);
}
Beispiel #3
0
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);
}
Beispiel #4
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);
}