commit ec8e5b1a049d2bd216c8df94d406d1193e0fe373
parent 513a920f614d38381fc1733aef5f9f7885d53aaa
Author: glenda <glenda@kobeni>
Date: Sat, 27 Jan 2024 17:28:06 +0000
src/midi: move piano from wave
Diffstat:
7 files changed, 127 insertions(+), 71 deletions(-)
diff --git a/src/midi/dump.c b/src/midi/dump.c
@@ -20,10 +20,9 @@ noteoff(MidiMes m)
void
main(void)
{
- char buf[256];
- int i, n;
+ char buf[4];
MidiMes m;
- while ((n = read(0, buf, 256)) > 0) {
+ while (read(0, buf, 4) >= 4) {
midifill(&m, buf, 4);
switch(m.status) {
case NOTE_ON:
@@ -33,7 +32,7 @@ main(void)
noteoff(m);
break;
default:
- print("%x %x | %x %x | %02x %02x\n",
+ print("%ux %ux | %ux %ux | %02ux %02ux\n",
m.cn, m.cin, m.status, m.channel,
m.param[0], m.param[1]);
}
diff --git a/src/midi/midi.c b/src/midi/midi.c
@@ -1,6 +1,7 @@
#include <u.h>
#include <libc.h>
#include "midi.h"
+
char *
midifill(MidiMes *m, char *p, int)
{
@@ -12,3 +13,21 @@ midifill(MidiMes *m, char *p, int)
m->param[1] = p[3];
return p + 4;
}
+
+void
+midinoteon(char *p, int chan, int note, int velocity)
+{
+ p[0] = CIN_NoteOn;
+ p[1] = (chan & 0x0f) | (NOTE_ON);
+ p[2] = note;
+ p[3] = velocity;
+}
+
+void
+midinoteoff(char *p, int chan, int note, int velocity)
+{
+ p[0] = CIN_NoteOff;
+ p[1] = (chan & 0x0f) | (NOTE_OFF);
+ p[2] = note;
+ p[3] = velocity;
+}
diff --git a/src/midi/midi.h b/src/midi/midi.h
@@ -37,3 +37,5 @@ struct MidiMes {
};
char * midifill(MidiMes *, char *, int);
+void midinoteon(char *, int, int, int);
+void midinoteoff(char *, int, int, int);
diff --git a/src/midi/mkfile b/src/midi/mkfile
@@ -1,5 +1,5 @@
</$objtype/mkfile
-TARG=dump
+TARG=dump piano
HFILES=midi.h
OFILES=midi.$O
</sys/src/cmd/mkmany
diff --git a/src/midi/piano.c b/src/midi/piano.c
@@ -0,0 +1,101 @@
+/*
+ * kbd in, midi out
+ */
+
+#include <u.h>
+#include <libc.h>
+
+#include "midi.h"
+
+enum {
+ BSIZE = 128,
+ ROSIZE = 32,
+};
+
+Rune *keys = L"zsxdcvgbhnjmq2w3er5t6y7ui9o0p[";
+Rune *notes = L"CCDDEFFGGAAB";
+Rune *semi = L"-#-#--#-#-#-";
+
+char m[4];
+
+typedef struct MKey MKey;
+struct MKey {
+ Rune r;
+ int state;
+ int count;
+};
+
+MKey ro[ROSIZE];
+
+int octave = 4;
+int channel = 0, velocity = 127;
+
+int
+key2note(int n)
+{
+ return octave * 12 + n;
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int i, rn, kbd;
+ long n;
+ char buf[BSIZE];
+
+ ARGBEGIN {
+ default:
+ usage();
+ } ARGEND
+ if (argc != 0) usage();
+
+ kbd = open("/dev/kbd", OREAD);
+ while((n = read(kbd, buf, BSIZE)) > 0) {
+ char *bp;
+ for (bp = buf; bp < buf + n; bp += strlen(bp) + 1) {
+ Rune r[BSIZE], *rp;
+ runesnprint(r, BSIZE, "%s", bp);
+ switch(r[0]) {
+ case 'c': //character out
+ if (r[1] == 0x7f) exits(nil);
+ break;
+ case 'k': /* key on */
+ for (i = 0; i < runestrlen(r); i++) {
+ if ((rp = runestrchr(keys, r[i])) == nil) continue;
+ rn = rp - keys;
+ if (ro[rn].state == 0) {
+ ro[rn].state = 1;
+ // fprint(2, "key on: %d\n", key2note(rn));
+ midinoteon(m, channel, key2note(rn), velocity);
+ write(1, m, 4);
+ }
+ }
+ break;
+ case 'K': /* key off */
+ for (i = 0; i < ROSIZE; i++) ro[i].count = 0;
+ for (i = 0; i < runestrlen(r); i++) {
+ if ((rp = runestrchr(keys, r[i])) == nil) continue;
+ rn = rp - keys;
+ ro[rn].count = 1;
+ }
+ for (i = 0; i < ROSIZE; i++) {
+ if (ro[i].state == 0) continue;
+ if (ro[i].count == 0) {
+ ro[i].state = 0;
+ // fprint(2, "key off: %d\n", key2note(i));
+ midinoteoff(m, channel, key2note(i), velocity);
+ write(1, m, 4);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/src/wave/mkfile b/src/wave/mkfile
@@ -1,6 +1,6 @@
</$objtype/mkfile
-TARG=draw loop fade piano sampler harm smoke inst wfedit track
+TARG=draw loop fade sampler harm smoke inst wfedit track
BIN=/$objtype/bin
HFILES=util.h wavetable.h prog.h
OFILES=wavetable.$O prog.$O util.$O
diff --git a/src/wave/piano.c b/src/wave/piano.c
@@ -1,65 +0,0 @@
-/*
- * lets user play samples from PCM files
- * using computer keyboard
- */
-
-#include <u.h>
-#include <libc.h>
-
-#include "util.h"
-
-#define BSIZE 4096
-
-Rune *keys = L"zsxdcvgbhnjmq2w3er5t6y7ui9o0p[";
-Rune *notes = L"CCDDEFFGGAAB";
-Rune *semi = L"-#-#--#-#-#-";
-
-void
-usage(void)
-{
- fprint(2, "usage: %s\n", argv0);
- exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
- int kbd;
- long n;
- char buf[BSIZE];
- Rune last;
-
- ARGBEGIN {
- default:
- usage();
- } ARGEND
- if (argc != 0) usage();
-
- kbd = open("/dev/kbd", OREAD);
- last = 0;
- while((n = read(kbd, buf, BSIZE)) > 0) {
- char *bp;
- for (bp = buf; bp < buf + n; bp += strlen(bp) + 1) {
- Rune r[BSIZE], *rp;
- runesnprint(r, BSIZE, "%s", bp);
- switch(r[0]) {
- case 'c':
- if (r[1] == 0x7f) exits(nil);
- break;
- case 'k':
- last = r[runestrlen(r) - 1];
- rp = runestrchr(keys, last);
- if (rp != nil) {
- fprint(1, "%f\n", note2freq(rp-keys));
- } else last = 0;
- break;
- case 'K':
- if ((last > 0) && (last != r[runestrlen(r) - 1])) {
- fprint(1, "0\n");
- last = 0;
- }
- break;
- }
- }
- }
-}