From 395458bfd55147f5cce1ff4c66753c885af46ed9 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Fri, 2 Dec 2011 17:25:12 -0300 Subject: [PATCH] midigen/: MIDI traffic generator --- midigen/Makefile | 9 ++++ midigen/midigen.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 midigen/Makefile create mode 100644 midigen/midigen.c diff --git a/midigen/Makefile b/midigen/Makefile new file mode 100644 index 0000000..d2dbcc3 --- /dev/null +++ b/midigen/Makefile @@ -0,0 +1,9 @@ +CFLAGS = -Wall -g +LDLIBS = -lasound + +.PHONY: clean + +midigen: midigen.c + +clean: + rm -f midigen diff --git a/midigen/midigen.c b/midigen/midigen.c new file mode 100644 index 0000000..d511dcc --- /dev/null +++ b/midigen/midigen.c @@ -0,0 +1,110 @@ +/* + * midigen.c - MIDI traffic generator + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include +#include + + +#define NAME "midigen" + + +static void send_cc(snd_seq_t *midi, snd_seq_event_t *ev, int chan) +{ + static unsigned v = 0; + + snd_seq_ev_set_controller(ev, chan, (v >> 7) & 127, v & 127); + v++; + snd_seq_event_output(midi, ev); + snd_seq_drain_output(midi); +} + + +static void generate(snd_seq_t *midi, int port, int chan, int t_s, int t_us) +{ + snd_seq_event_t ev; + struct timeval next, now; + int dt_us; + + snd_seq_ev_clear(&ev); + snd_seq_ev_set_source(&ev, port); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_direct(&ev); + + gettimeofday(&next, NULL); + while (1) { + next.tv_sec += t_s; + next.tv_usec += t_us; + if (next.tv_usec > 999999) { + next.tv_sec++; + next.tv_usec -= 1000000; + } + gettimeofday(&now, NULL); + dt_us = (next.tv_sec-now.tv_sec)*1000000+ + next.tv_usec-now.tv_usec; + if (dt_us > 0) + usleep(dt_us); + send_cc(midi, &ev, chan); + } +} + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s [-c channel] rate_hz\n", name); + exit(1); +} + + +int main(int argc, char **argv) +{ + snd_seq_t *midi; + int c; + int chan = 0, t_us; + int port; + + while ((c = getopt(argc, argv, "c:")) != EOF) + switch (c) { + case 'c': + chan = atoi(optarg); + break; + default: + usage(*argv); + } + + switch (argc-optind) { + case 1: + t_us = 1000000/atof(argv[optind]); + break; + default: + usage(*argv); + } + + if (snd_seq_open(&midi, "hw", SND_SEQ_OPEN_OUTPUT,0) < 0) { + fprintf(stderr, "can't open ALSA sequencer\n"); + exit(1); + } + snd_seq_set_client_name(midi, NAME); + port = snd_seq_create_simple_port(midi, NAME, + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_APPLICATION); + if (port < 0) { + fprintf(stderr, "can't create sequencer port\n"); + exit(1); + } + + generate(midi, port, chan, t_us/1000000, t_us % 1000000); + + return 0; +}