piano.c (1660B)
1 /* 2 * lets user play samples from PCM files 3 * using computer keyboard 4 */ 5 6 #include <u.h> 7 #include <libc.h> 8 9 #define BSIZE 4096 10 11 Rune *keys = L"zsxdcvgbhnjmq2w3er5t6y7ui9o0p["; 12 Rune *notes = L"CCDDEFFGGAAB"; 13 Rune *semi = L"-#-#--#-#-#-"; 14 15 /* 16 * Frequencies for equal-tempered scale 17 * from https://pages.mtu.edu/~suits/notefreqs.html 18 */ 19 20 double freq[] = { 21 261.63, // C-4 22 277.18, 23 293.66, 24 311.13, 25 329.63, 26 349.23, 27 369.99, 28 392.00, 29 415.30, 30 440.00, // A-4 31 466.16, 32 493.88, 33 523.25, // C-5 34 554.37, 35 587.33, 36 622.25, 37 659.25, 38 698.46, 39 739.99, 40 783.99, 41 830.61, 42 880.00, // A-5 43 932.33, 44 987.77, 45 1046.50, 46 1108.73, 47 1174.66, 48 1244.51, 49 1318.51, 50 1396.91 // F-6 51 }; 52 53 void 54 usage(void) 55 { 56 fprint(2, "usage: %s\n", argv0); 57 exits("usage"); 58 } 59 60 void 61 main(int argc, char **argv) 62 { 63 int kbd; 64 long n; 65 char buf[BSIZE]; 66 Rune last; 67 68 ARGBEGIN { 69 default: 70 usage(); 71 } ARGEND 72 if (argc != 0) usage(); 73 74 kbd = open("/dev/kbd", OREAD); 75 last = 0; 76 while((n = read(kbd, buf, BSIZE)) > 0) { 77 char *bp; 78 for (bp = buf; bp < buf + n; bp += strlen(bp) + 1) { 79 Rune r[BSIZE], *rp; 80 runesnprint(r, BSIZE, "%s", bp); 81 switch(r[0]) { 82 case 'c': 83 if (r[1] == 0x7f) exits(nil); 84 break; 85 case 'k': 86 last = r[runestrlen(r) - 1]; 87 rp = runestrchr(keys, last); 88 if (rp != nil) { 89 int k = (rp - keys) % 12; 90 int o = (rp - keys) / 12; 91 fprint(1, "%C%C%d\n", notes[k], semi[k], o + 3); 92 } else { 93 if (last == ' ') fprint(1, "k\n"); 94 last = 0; 95 } 96 break; 97 case 'K': 98 if ((last > 0) && (last != r[runestrlen(r) - 1])) { 99 // fprint(2, "off\n"); 100 // fprint(1, "0\n"); 101 last = 0; 102 } 103 break; 104 } 105 } 106 } 107 } 108