/* * 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; }