piano.c (1818B)
1 /* 2 * kbd in, midi out 3 */ 4 5 #include <u.h> 6 #include <libc.h> 7 8 #include "midi.h" 9 10 enum { 11 BSIZE = 128, 12 ROSIZE = 32, 13 }; 14 15 Rune *keys = L"zsxdcvgbhnjmq2w3er5t6y7ui9o0p["; 16 Rune *notes = L"CCDDEFFGGAAB"; 17 Rune *semi = L"-#-#--#-#-#-"; 18 19 char m[4]; 20 21 typedef struct MKey MKey; 22 struct MKey { 23 Rune r; 24 int state; 25 int count; 26 }; 27 28 MKey ro[ROSIZE]; 29 30 int octave = 4; 31 int channel = 0, velocity = 127; 32 33 int 34 key2note(int n) 35 { 36 return octave * 12 + n; 37 } 38 39 void 40 usage(void) 41 { 42 fprint(2, "usage: %s\n", argv0); 43 exits("usage"); 44 } 45 46 void 47 main(int argc, char **argv) 48 { 49 int i, rn, kbd; 50 long n; 51 char buf[BSIZE]; 52 53 ARGBEGIN { 54 default: 55 usage(); 56 } ARGEND 57 if (argc != 0) usage(); 58 59 kbd = open("/dev/kbd", OREAD); 60 while((n = read(kbd, buf, BSIZE)) > 0) { 61 char *bp; 62 for (bp = buf; bp < buf + n; bp += strlen(bp) + 1) { 63 Rune r[BSIZE], *rp; 64 runesnprint(r, BSIZE, "%s", bp); 65 switch(r[0]) { 66 case 'c': //character out 67 if (r[1] == 0x7f) exits(nil); 68 break; 69 case 'k': /* key on */ 70 for (i = 0; i < runestrlen(r); i++) { 71 if ((rp = runestrchr(keys, r[i])) == nil) continue; 72 rn = rp - keys; 73 if (ro[rn].state == 0) { 74 ro[rn].state = 1; 75 // fprint(2, "key on: %d\n", key2note(rn)); 76 midinoteon(m, channel, key2note(rn), velocity); 77 write(1, m, 4); 78 } 79 } 80 break; 81 case 'K': /* key off */ 82 for (i = 0; i < ROSIZE; i++) ro[i].count = 0; 83 for (i = 0; i < runestrlen(r); i++) { 84 if ((rp = runestrchr(keys, r[i])) == nil) continue; 85 rn = rp - keys; 86 ro[rn].count = 1; 87 } 88 for (i = 0; i < ROSIZE; i++) { 89 if (ro[i].state == 0) continue; 90 if (ro[i].count == 0) { 91 ro[i].state = 0; 92 // fprint(2, "key off: %d\n", key2note(i)); 93 midinoteoff(m, channel, key2note(i), velocity); 94 write(1, m, 4); 95 } 96 } 97 break; 98 } 99 } 100 } 101 }