stew

a monorepo of some sort
git clone git://git.nsmpr.xyz/stew.git
Log | Files | Refs

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 }