diff options
| -rw-r--r-- | MIDIPlayer.cpp | 6 | ||||
| -rw-r--r-- | aplaymidi-mp.c | 74 | 
2 files changed, 63 insertions, 17 deletions
| diff --git a/MIDIPlayer.cpp b/MIDIPlayer.cpp index 8202850..061b8f6 100644 --- a/MIDIPlayer.cpp +++ b/MIDIPlayer.cpp @@ -11,6 +11,7 @@  #include <string>  #include <thread>  #include <unordered_set> +#include <stdexcept>  namespace bp = boost::process;  namespace fs = std::filesystem; @@ -43,7 +44,10 @@ void MIDIPlayer::start()    if (m_child.valid() && m_child.running()) {      stop();    } else { -    m_child = bp::child(fmt::format("aplaymidi -p{} \"{}\"", m_client, m_file).c_str());//, bp::std_out > bp::null); +    m_child = bp::child(fmt::format("/home/ernie/code/midiplay/aplaymidi-mp -c -p{} \"{}\"", m_client, m_file).c_str());//, bp::std_out > bp::null); +    if (!m_child.valid() || !m_child.running()) { +      throw std::runtime_error("aplaymidi not started"); +    }    }  } diff --git a/aplaymidi-mp.c b/aplaymidi-mp.c index 8ad9630..0599f2a 100644 --- a/aplaymidi-mp.c +++ b/aplaymidi-mp.c @@ -77,7 +77,8 @@ static int num_tracks;  static struct track *tracks;  static int smpte_timing;  static int ump_mode; -static int add_clock; +static int clock_mode; +static int time_division;  /* prints an error message to stderr */  static void errormsg(const char *msg, ...) @@ -298,6 +299,20 @@ static void skip(int bytes)  		read_byte(), --bytes;  } +static void add_clock(struct track *track, int tick_step, int track_end) +{ +	int tick = 0; +	struct event *event; + +	while (tick <= track_end) { +		event = new_event(track, 0); +		event->type = SND_SEQ_EVENT_CLOCK; +		event->port = 0; +		event->tick = tick; +		tick += tick_step; +	} +} +  /* reads one complete track from the file */  static int read_track(struct track *track, int track_end)  { @@ -454,10 +469,10 @@ _error:  /* reads an entire MIDI file */  static int read_smf(void)  { -	int header_len, type, time_division, i, err; +	int header_len, type, i, err;  	snd_seq_queue_tempo_t *queue_tempo; -	/* the curren position is immediately after the "MThd" id */ +	/* the current position is immediately after the "MThd" id */  	header_len = read_int(4);  	if (header_len < 6) {  invalid_format: @@ -504,19 +519,23 @@ invalid_format:  		switch (i) {  		case 24:  			snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); -			snd_seq_queue_tempo_set_ppq(queue_tempo, 12 * time_division); +			time_division *= 12; +			snd_seq_queue_tempo_set_ppq(queue_tempo, time_division);  			break;  		case 25:  			snd_seq_queue_tempo_set_tempo(queue_tempo, 400000); -			snd_seq_queue_tempo_set_ppq(queue_tempo, 10 * time_division); +			time_division *= 10; +			snd_seq_queue_tempo_set_ppq(queue_tempo, time_division);  			break;  		case 29: /* 30 drop-frame */  			snd_seq_queue_tempo_set_tempo(queue_tempo, 100000000); -			snd_seq_queue_tempo_set_ppq(queue_tempo, 2997 * time_division); +			time_division *= 2997; +			snd_seq_queue_tempo_set_ppq(queue_tempo, time_division);  			break;  		case 30:  			snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); -			snd_seq_queue_tempo_set_ppq(queue_tempo, 15 * time_division); +			time_division *= 15; +			snd_seq_queue_tempo_set_ppq(queue_tempo, time_division);  			break;  		default:  			errormsg("%s: invalid number of SMPTE frames per second (%d)", @@ -676,6 +695,11 @@ static int fill_legacy_event(struct event* event, snd_seq_event_t *ev)  		snd_seq_ev_set_variable(ev, event->data.length, event->sysex);  		handle_big_sysex(ev);  		break; +	case SND_SEQ_EVENT_CLOCK: +		snd_seq_ev_set_fixed(ev); +		ev->data.control.channel = event->data.d[0]; +		ev->data.control.value = event->data.d[1]; +		break;  	default:  		fatal("Invalid event type %d!", ev->type);  	} @@ -759,19 +783,26 @@ static int fill_ump_event(struct event* event, snd_seq_ump_event_t *ump_ev,  	return 0;  } -static void play_midi(void) +static int get_max_tick(void)  { -	snd_seq_ump_event_t ump_ev; -	snd_seq_event_t ev; -	int i, max_tick, err; -  	/* calculate length of the entire file */ -	max_tick = -1; +	int i, max_tick = -1;  	for (i = 0; i < num_tracks; ++i) {  		if (tracks[i].end_tick > max_tick)  			max_tick = tracks[i].end_tick;  	} +	return max_tick; +} + +static void play_midi(void) +{ +	snd_seq_ump_event_t ump_ev; +	snd_seq_event_t ev; +	int i, max_tick, err; + +	max_tick = get_max_tick(); +  	/* initialize current position in each track */  	for (i = 0; i < num_tracks; ++i)  		tracks[i].current_event = tracks[i].first_event; @@ -900,8 +931,19 @@ static void play_file(void)  	if (file != stdin)  		fclose(file); -	if (ok) +	if (ok) { +		if (clock_mode) { +			num_tracks += 1; +			tracks = realloc(tracks, num_tracks * sizeof(struct track)); +			if (!tracks) { +				errormsg("out of memory"); +				return; +			} +			memset(&tracks[num_tracks - 1], 0, sizeof(struct track)); +			add_clock(&tracks[num_tracks - 1], time_division / 24, get_max_tick()); +		}  		play_midi(); +	}  	cleanup_file_data();  } @@ -960,7 +1002,7 @@ static void version(void)  	puts("aplaymidi version " SND_UTIL_VERSION_STR);  } -#define OPTIONS	"hVlp:d:u:" +#define OPTIONS	"hVlcp:d:u:"  int main(int argc, char *argv[])  { @@ -1004,7 +1046,7 @@ int main(int argc, char *argv[])  				fatal("Only MIDI 1.0 is supported");  			break;  		case 'c': -                        add_clock = 1; +                        clock_mode = 1;  			break;  		default:  			usage(argv[0]); | 
