• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <sys/time.h>
5 #include "../include/asoundlib.h"
6 #include <string.h>
7 #include <signal.h>
8 
usage(void)9 static void usage(void)
10 {
11 	fprintf(stderr, "Usage: midiloop [options]\n");
12 	fprintf(stderr, "  options:\n");
13 	fprintf(stderr, "    -v: verbose mode\n");
14 	fprintf(stderr, "    -i <rawmidi device> : test input device\n");
15 	fprintf(stderr, "    -o <rawmidi device> : test output device\n");
16 }
17 
18 int stop = 0;
19 
sighandler(int dummy ATTRIBUTE_UNUSED)20 void sighandler(int dummy ATTRIBUTE_UNUSED)
21 {
22 	stop=1;
23 }
24 
timediff(struct timeval t1,struct timeval t2)25 long long timediff(struct timeval t1, struct timeval t2)
26 {
27 	signed long l;
28 
29 	t1.tv_sec -= t2.tv_sec;
30 	l = (signed long) t1.tv_usec - (signed long) t2.tv_usec;
31 	if (l < 0) {
32 		t1.tv_sec--;
33 		l = -l;
34 		l %= 1000000;
35 	}
36 	return ((long long)t1.tv_sec * (long long)1000000) + (long long)l;
37 }
38 
writepattern(snd_rawmidi_t * handle_out,unsigned char * obuf)39 int writepattern(snd_rawmidi_t *handle_out, unsigned char *obuf)
40 {
41 	int patsize, i;
42 
43 	patsize = 0;
44 	for (i = 0; i < 15; i++) {
45 		obuf[patsize++] = 0x90 + i;
46 		obuf[patsize++] = 0x40;
47 		obuf[patsize++] = 0x3f;
48 		obuf[patsize++] = 0xb0 + i;
49 		obuf[patsize++] = 0x2e;
50 		obuf[patsize++] = 0x7a;
51 		obuf[patsize++] = 0x80 + i;
52 		obuf[patsize++] = 0x23;
53 		obuf[patsize++] = 0x24;
54 		obuf[patsize++] = 0xf0;
55 		obuf[patsize++] = i;
56 		obuf[patsize++] = 0xf7;
57 	}
58 	i = snd_rawmidi_write(handle_out, obuf, patsize);
59 	if (i != patsize) {
60 		printf("Written only %i bytes from %i bytes\n", i, patsize);
61 		exit(EXIT_FAILURE);
62 	}
63 	return patsize;
64 }
65 
main(int argc,char ** argv)66 int main(int argc, char** argv)
67 {
68 	int i, j, k, opos, ipos, patsize;
69 	int err;
70 	int verbose = 0;
71 	snd_rawmidi_t *handle_in = NULL, *handle_out = NULL;
72 	unsigned char ibuf[512], obuf[512];
73 	char *iname = "hw:0,0", *oname = "hw:0,0";
74 	struct timeval start, end;
75 	long long diff;
76 	snd_rawmidi_status_t *istat, *ostat;
77 
78 	for (i = 1 ; i<argc ; i++) {
79 		if (argv[i][0]=='-') {
80 			if (!strcmp(argv[i], "--help")) {
81 				usage();
82 				return 0;
83 			}
84 			switch (argv[i][1]) {
85 				case 'h':
86 					usage();
87 					return 0;
88 				case 'v':
89 					verbose = 1;
90 					break;
91 				case 'i':
92 					if (i + 1 < argc)
93 						iname = argv[++i];
94 					break;
95 				case 'o':
96 					if (i + 1 < argc)
97 						oname = argv[++i];
98 					break;
99 			}
100 		}
101 	}
102 
103 	if (iname == NULL)
104 		iname = oname;
105 	if (oname == NULL)
106 		oname = iname;
107 
108 	if (verbose) {
109 		fprintf(stderr, "Using: \n");
110 		fprintf(stderr, "  Input: %s  Output: %s\n", iname, oname);
111 	}
112 
113 	err = snd_rawmidi_open(&handle_in, NULL, iname, SND_RAWMIDI_NONBLOCK);
114 	if (err) {
115 		fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",iname,err);
116 		exit(EXIT_FAILURE);
117 	}
118 
119 	err = snd_rawmidi_open(NULL, &handle_out, oname, 0);
120 	if (err) {
121 		fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",oname,err);
122 		exit(EXIT_FAILURE);
123 	}
124 
125 	signal(SIGINT, sighandler);
126 
127 	i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf));
128 	if (i > 0) {
129 		printf("Read ahead: %i\n", i);
130 		for (j = 0; j < i; j++)
131 			printf("%02x:", ibuf[j]);
132 		printf("\n");
133 		exit(EXIT_FAILURE);
134 	}
135 
136 	snd_rawmidi_nonblock(handle_in, 0);
137 
138 	patsize = writepattern(handle_out, obuf);
139 	gettimeofday(&start, NULL);
140 	patsize = writepattern(handle_out, obuf);
141 
142 	k = ipos = opos = err = 0;
143 	while (!stop) {
144 		i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf));
145 		for (j = 0; j < i; j++, ipos++)
146 			if (obuf[k] != ibuf[j]) {
147 				printf("ipos = %i, i[0x%x] != o[0x%x]\n", ipos, ibuf[j], obuf[k]);
148 				if (opos > 0)
149 					stop = 1;
150 			} else {
151 				printf("match success: ipos = %i, opos = %i [%i:0x%x]\n", ipos, opos, k, obuf[k]);
152 				k++; opos++;
153 				if (k >= patsize) {
154 					patsize = writepattern(handle_out, obuf);
155 					k = 0;
156 				}
157 			}
158 	}
159 
160 	gettimeofday(&end, NULL);
161 
162 	printf("End...\n");
163 
164 	snd_rawmidi_status_alloca(&istat);
165 	snd_rawmidi_status_alloca(&ostat);
166 	err = snd_rawmidi_status(handle_in, istat);
167 	if (err < 0)
168 		fprintf(stderr, "input stream status error: %d\n", err);
169 	err = snd_rawmidi_status(handle_out, ostat);
170 	if (err < 0)
171 		fprintf(stderr, "output stream status error: %d\n", err);
172 	printf("input.status.avail = %zi\n", snd_rawmidi_status_get_avail(istat));
173 	printf("input.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(istat));
174 	printf("output.status.avail = %zi\n", snd_rawmidi_status_get_avail(ostat));
175 	printf("output.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(ostat));
176 
177 	diff = timediff(end, start);
178 	printf("Time diff: %lliusec (%lli bytes/sec)\n", diff, ((long long)opos * 1000000) / diff);
179 
180 	if (verbose) {
181 		fprintf(stderr,"Closing\n");
182 	}
183 
184 	snd_rawmidi_drain(handle_in);
185 	snd_rawmidi_close(handle_in);
186 	snd_rawmidi_drain(handle_out);
187 	snd_rawmidi_close(handle_out);
188 
189 	return 0;
190 }
191