1
0
mirror of git://projects.qi-hardware.com/wernermisc.git synced 2024-12-25 07:52:24 +02:00
wernermisc/midigen/midigen.c

111 lines
2.2 KiB
C
Raw Normal View History

2011-12-02 22:25:12 +02:00
/*
* 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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <alsa/asoundlib.h>
#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;
}