Date:2011-12-02 21:25:12 (7 years 7 months ago)
Author:Werner Almesberger
Commit:395458bfd55147f5cce1ff4c66753c885af46ed9
Message:midigen/: MIDI traffic generator

Files: midigen/Makefile (1 diff)
midigen/midigen.c (1 diff)

Change Details

midigen/Makefile
1CFLAGS = -Wall -g
2LDLIBS = -lasound
3
4.PHONY: clean
5
6midigen: midigen.c
7
8clean:
9        rm -f midigen
midigen/midigen.c
1/*
2 * midigen.c - MIDI traffic generator
3 *
4 * Written 2011 by Werner Almesberger
5 * Copyright 2011 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdlib.h>
15#include <stdio.h>
16#include <unistd.h>
17#include <sys/time.h>
18#include <alsa/asoundlib.h>
19
20
21#define NAME "midigen"
22
23
24static void send_cc(snd_seq_t *midi, snd_seq_event_t *ev, int chan)
25{
26    static unsigned v = 0;
27
28    snd_seq_ev_set_controller(ev, chan, (v >> 7) & 127, v & 127);
29    v++;
30    snd_seq_event_output(midi, ev);
31    snd_seq_drain_output(midi);
32}
33
34
35static void generate(snd_seq_t *midi, int port, int chan, int t_s, int t_us)
36{
37    snd_seq_event_t ev;
38    struct timeval next, now;
39    int dt_us;
40
41    snd_seq_ev_clear(&ev);
42    snd_seq_ev_set_source(&ev, port);
43    snd_seq_ev_set_subs(&ev);
44    snd_seq_ev_set_direct(&ev);
45
46    gettimeofday(&next, NULL);
47    while (1) {
48        next.tv_sec += t_s;
49        next.tv_usec += t_us;
50        if (next.tv_usec > 999999) {
51            next.tv_sec++;
52            next.tv_usec -= 1000000;
53        }
54        gettimeofday(&now, NULL);
55        dt_us = (next.tv_sec-now.tv_sec)*1000000+
56            next.tv_usec-now.tv_usec;
57        if (dt_us > 0)
58            usleep(dt_us);
59        send_cc(midi, &ev, chan);
60    }
61}
62
63static void usage(const char *name)
64{
65    fprintf(stderr, "usage: %s [-c channel] rate_hz\n", name);
66    exit(1);
67}
68
69
70int main(int argc, char **argv)
71{
72    snd_seq_t *midi;
73    int c;
74    int chan = 0, t_us;
75    int port;
76
77    while ((c = getopt(argc, argv, "c:")) != EOF)
78        switch (c) {
79        case 'c':
80            chan = atoi(optarg);
81            break;
82        default:
83            usage(*argv);
84        }
85
86    switch (argc-optind) {
87    case 1:
88        t_us = 1000000/atof(argv[optind]);
89        break;
90    default:
91        usage(*argv);
92    }
93
94    if (snd_seq_open(&midi, "hw", SND_SEQ_OPEN_OUTPUT,0) < 0) {
95        fprintf(stderr, "can't open ALSA sequencer\n");
96        exit(1);
97    }
98    snd_seq_set_client_name(midi, NAME);
99    port = snd_seq_create_simple_port(midi, NAME,
100              SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
101              SND_SEQ_PORT_TYPE_APPLICATION);
102    if (port < 0) {
103        fprintf(stderr, "can't create sequencer port\n");
104        exit(1);
105    }
106
107    generate(midi, port, chan, t_us/1000000, t_us % 1000000);
108
109    return 0;
110}

Archive Download the corresponding diff file

Branches:
master



interactive