| #include <stdlib.h> |
| #include <stdio.h> |
| #include <ctype.h> |
| #include <sys/time.h> |
| #include "../include/asoundlib.h" |
| #include <string.h> |
| #include <signal.h> |
| |
| static void usage(void) |
| { |
| fprintf(stderr, "Usage: midiloop [options]\n"); |
| fprintf(stderr, " options:\n"); |
| fprintf(stderr, " -v: verbose mode\n"); |
| fprintf(stderr, " -i <rawmidi device> : test input device\n"); |
| fprintf(stderr, " -o <rawmidi device> : test output device\n"); |
| } |
| |
| int stop = 0; |
| |
| void sighandler(int dummy ATTRIBUTE_UNUSED) |
| { |
| stop=1; |
| } |
| |
| long long timediff(struct timeval t1, struct timeval t2) |
| { |
| signed long l; |
| |
| t1.tv_sec -= t2.tv_sec; |
| l = (signed long) t1.tv_usec - (signed long) t2.tv_usec; |
| if (l < 0) { |
| t1.tv_sec--; |
| l = -l; |
| l %= 1000000; |
| } |
| return ((long long)t1.tv_sec * (long long)1000000) + (long long)l; |
| } |
| |
| int writepattern(snd_rawmidi_t *handle_out, unsigned char *obuf) |
| { |
| int patsize, i; |
| |
| patsize = 0; |
| for (i = 0; i < 15; i++) { |
| obuf[patsize++] = 0x90 + i; |
| obuf[patsize++] = 0x40; |
| obuf[patsize++] = 0x3f; |
| obuf[patsize++] = 0xb0 + i; |
| obuf[patsize++] = 0x2e; |
| obuf[patsize++] = 0x7a; |
| obuf[patsize++] = 0x80 + i; |
| obuf[patsize++] = 0x23; |
| obuf[patsize++] = 0x24; |
| obuf[patsize++] = 0xf0; |
| obuf[patsize++] = i; |
| obuf[patsize++] = 0xf7; |
| } |
| i = snd_rawmidi_write(handle_out, obuf, patsize); |
| if (i != patsize) { |
| printf("Written only %i bytes from %i bytes\n", i, patsize); |
| exit(EXIT_FAILURE); |
| } |
| return patsize; |
| } |
| |
| int main(int argc, char** argv) |
| { |
| int i, j, k, opos, ipos, patsize; |
| int err; |
| int verbose = 0; |
| snd_rawmidi_t *handle_in = NULL, *handle_out = NULL; |
| unsigned char ibuf[512], obuf[512]; |
| char *iname = "hw:0,0", *oname = "hw:0,0"; |
| struct timeval start, end; |
| long long diff; |
| snd_rawmidi_status_t *istat, *ostat; |
| |
| for (i = 1 ; i<argc ; i++) { |
| if (argv[i][0]=='-') { |
| if (!strcmp(argv[i], "--help")) { |
| usage(); |
| return 0; |
| } |
| switch (argv[i][1]) { |
| case 'h': |
| usage(); |
| return 0; |
| case 'v': |
| verbose = 1; |
| break; |
| case 'i': |
| if (i + 1 < argc) |
| iname = argv[++i]; |
| break; |
| case 'o': |
| if (i + 1 < argc) |
| oname = argv[++i]; |
| break; |
| } |
| } |
| } |
| |
| if (iname == NULL) |
| iname = oname; |
| if (oname == NULL) |
| oname = iname; |
| |
| if (verbose) { |
| fprintf(stderr, "Using: \n"); |
| fprintf(stderr, " Input: %s Output: %s\n", iname, oname); |
| } |
| |
| err = snd_rawmidi_open(&handle_in, NULL, iname, SND_RAWMIDI_NONBLOCK); |
| if (err) { |
| fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",iname,err); |
| exit(EXIT_FAILURE); |
| } |
| |
| err = snd_rawmidi_open(NULL, &handle_out, oname, 0); |
| if (err) { |
| fprintf(stderr,"snd_rawmidi_open %s failed: %d\n",oname,err); |
| exit(EXIT_FAILURE); |
| } |
| |
| signal(SIGINT, sighandler); |
| |
| i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf)); |
| if (i > 0) { |
| printf("Read ahead: %i\n", i); |
| for (j = 0; j < i; j++) |
| printf("%02x:", ibuf[j]); |
| printf("\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| snd_rawmidi_nonblock(handle_in, 0); |
| |
| patsize = writepattern(handle_out, obuf); |
| gettimeofday(&start, NULL); |
| patsize = writepattern(handle_out, obuf); |
| |
| k = ipos = opos = err = 0; |
| while (!stop) { |
| i = snd_rawmidi_read(handle_in, ibuf, sizeof(ibuf)); |
| for (j = 0; j < i; j++, ipos++) |
| if (obuf[k] != ibuf[j]) { |
| printf("ipos = %i, i[0x%x] != o[0x%x]\n", ipos, ibuf[j], obuf[k]); |
| if (opos > 0) |
| stop = 1; |
| } else { |
| printf("match success: ipos = %i, opos = %i [%i:0x%x]\n", ipos, opos, k, obuf[k]); |
| k++; opos++; |
| if (k >= patsize) { |
| patsize = writepattern(handle_out, obuf); |
| k = 0; |
| } |
| } |
| } |
| |
| gettimeofday(&end, NULL); |
| |
| printf("End...\n"); |
| |
| snd_rawmidi_status_alloca(&istat); |
| snd_rawmidi_status_alloca(&ostat); |
| err = snd_rawmidi_status(handle_in, istat); |
| if (err < 0) |
| fprintf(stderr, "input stream status error: %d\n", err); |
| err = snd_rawmidi_status(handle_out, ostat); |
| if (err < 0) |
| fprintf(stderr, "output stream status error: %d\n", err); |
| printf("input.status.avail = %zi\n", snd_rawmidi_status_get_avail(istat)); |
| printf("input.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(istat)); |
| printf("output.status.avail = %zi\n", snd_rawmidi_status_get_avail(ostat)); |
| printf("output.status.xruns = %zi\n", snd_rawmidi_status_get_xruns(ostat)); |
| |
| diff = timediff(end, start); |
| printf("Time diff: %lliusec (%lli bytes/sec)\n", diff, ((long long)opos * 1000000) / diff); |
| |
| if (verbose) { |
| fprintf(stderr,"Closing\n"); |
| } |
| |
| snd_rawmidi_drain(handle_in); |
| snd_rawmidi_close(handle_in); |
| snd_rawmidi_drain(handle_out); |
| snd_rawmidi_close(handle_out); |
| |
| return 0; |
| } |