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 9static 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 18int stop = 0; 19 20void sighandler(int dummy ATTRIBUTE_UNUSED) 21{ 22 stop=1; 23} 24 25long 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 39int 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 66int 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