commit 6b918683b79ecfedb68a649f8a450910f4537475
Author: zavok <an2qzavok@gmail.com>
Date: Mon, 4 Nov 2019 11:31:26 +0300
time for version control
Diffstat:
A | Makefile | | | 34 | ++++++++++++++++++++++++++++++++++ |
A | audio.c | | | 2 | ++ |
A | audio.h | | | 0 | |
A | fm.c | | | 2 | ++ |
A | fm.h | | | 0 | |
A | midi.c | | | 82 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | midi.h | | | 11 | +++++++++++ |
A | usynth.c | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
8 files changed, 270 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,34 @@
+.POSIX:
+
+PREFIX = /usr/local
+MANDIR = $(PREFIX)/share/man/man1
+
+BIN = usynth
+MAN = $(BIN).1
+OBJ = $(BIN:=.o) audio.o fm.o midi.o
+
+LDFLAGS=-lsndio
+
+all: $(BIN)
+
+$(BIN): $(OBJ)
+ $(CC) $(OBJ) $(LDFLAGS) $(LIBS) -o $@
+
+$(OBJ): audio.c fm.c midi.c usynth.c
+
+install: $(BIN)
+ mkdir -p $(DESTDIR)$(PREFIX)/bin/
+ cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin/
+ chmod 555 $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ mkdir -p $(DESTDIR)$(MANDIR)
+ cp -f $(MAN) $(DESTDIR)$(MANDIR)
+
+uninstall:
+ rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ rm -f $(DESTDIR)$(MANDIR)/$(MAN)
+
+clean:
+ rm -f $(BIN) $(OBJ)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
diff --git a/audio.c b/audio.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+#include <sndio.h>
diff --git a/audio.h b/audio.h
diff --git a/fm.c b/fm.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+#include "fm.h"
diff --git a/fm.h b/fm.h
diff --git a/midi.c b/midi.c
@@ -0,0 +1,82 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <sndio.h>
+#include "midi.h"
+
+uint8_t mmessage[8];
+uint8_t mlen;
+uint8_t mi;
+enum {
+ NOTE_OFF 0x80,
+ NOTE_ON 0x90,
+ KEY_PRESSURE 0xa0,
+ CTL_CHANGE 0xb0,
+ PROG_CHANGE 0xc0,
+ CHAN_PRESSURE 0xe0,
+ PITCH_WHEEL 0xe0,
+ SYS_MESSAGE 0xf0,
+};
+
+void
+m_status(uint8_t b)
+{
+ if ((b && 0x80)==0) return; /* not a status byte */
+ uint8_t t, ch;
+ t = b & 0xf0;
+ c = b & 0x0f;
+ if (t == SYS_MESSAGE){
+ return;
+ }
+ mmesage[0] = t;
+ mmesage[1] = c;
+ mi=2;
+ switch (t){
+ case NOTE_OFF:
+ mlen = 4;
+ m_update = m_data;
+ break;
+ case NOTE_ON:
+ mlen = 4;
+ m_update = m_data;
+ break;
+ }
+}
+
+m_data(uint_t b)
+{
+ mmessage[mi] = b;
+ mi++;
+ if (mi = mlen){
+ mi = 0;
+ mlen = 0;
+ m_exec();
+ m_update = m_status;
+ }
+}
+
+void
+m_exec(void)
+{
+ switch(mmesage[0]){
+ case NOTE_OFF:
+ break;
+ case NOTE_ON:
+ break;
+ }
+}
+
+void
+m_init(void)
+{
+// char *mdev;
+// mdev = "rmidi/0";
+// mh = mio_open(mdev, MIO_IN, 1);
+// if (mh == 0){
+// fprintf(stderr, "error: couldn't open midi device %s\n" mdev);
+// exit(-1);
+// }
+ m_update = m_status;
+ mlen = 0;
+ mi = 0;
+}
+
diff --git a/midi.h b/midi.h
@@ -0,0 +1,11 @@
+struct m_vector{
+ void(*note_on)(uint8_t*);
+ void(*note_off)(uint8_t*);
+};
+
+struct m_vector m_vector;
+
+void (*m_update)(uint8_t);
+
+void m_init(void);
+
diff --git a/usynth.c b/usynth.c
@@ -0,0 +1,139 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sndio.h>
+#include "midi.h"
+#include "audio.h"
+#include "fm.h"
+
+enum{
+ STATUS,
+ DATA,
+};
+
+struct mpstate{
+ int s;
+ uint8_t m[8];
+ int dc;
+};
+
+struct mpstate mparser;
+
+
+struct sio_hdl *sh;
+struct mio_hdl *mh;
+size_t bs;
+int16_t vol, dt;
+
+double tune[]={
+16.35, //C 36
+17.32, //C# 37
+18.35, //D 38
+19.45, //D# 39
+20.60, //E 40
+21.83, //F 41
+23.12, //F# 42
+24.50, //G 43
+25.96, //G# 44
+27.50, //A 45 - 440 - 100
+29.14, //A# 46
+30.87, //B 47
+};
+
+size_t rt, wt;
+
+void
+cb(void *arg, int delta)
+{
+ rt += delta * 4;
+}
+
+void
+sinit(void)
+{
+ char *sdev = "rsnd/0";//SIO_DEVANY;
+ struct sio_par par;
+ sh = sio_open(sdev, SIO_PLAY, 0);
+ sio_initpar(&par);
+ par.pchan = 2;
+ par.sig = 1;
+ par.bits = 16;
+ par.le = 0;
+ par.rate = 44100;
+ par.xrun = SIO_SYNC;
+ par.appbufsz = 1024;
+ sio_setpar(sh, &par);
+ sio_getpar(sh, &par);
+ //bs = 256 + par.round;
+ //bs -= bs % par.round;
+ bs = par.round;
+ printf("bufsz=%d\nappbufsz=%d\nround=%d\nbs=%lu\n",
+ par.bufsz, par.appbufsz, par.round, bs);
+ sio_onmove(sh, cb, 0);
+ sio_start(sh);
+}
+
+void
+mparse(uint8_t b){
+ switch (mparser.s){
+ case STATUS:
+ if (b&0x80){
+ mparser.m[0] = b;
+ mparser.dc = 1;
+ mparser.s = DATA;
+ }
+ return;
+ case DATA:
+ mparser.m[1] = b;
+ mparser.dc--;
+ mparser.s = STATUS;
+ break;
+ }
+ if (mparser.dc == 0){
+ uint8_t ctl = mparser.m[0]>>4;
+ if (ctl == 9) {
+ vol = 250;
+ uint8_t note = mparser.m[1];
+ dt = 44100.0 / (tune[note%12] * (double)(0x1<<(note/12)));
+ }
+ if (ctl == 8) vol = 0;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ char *mdev;
+ int64_t c;
+ int16_t *sbuf;
+ uint8_t *mbuf;
+ vol = 0;
+ wt = 0;
+ rt = 0;
+ mdev = "rmidi/0";
+ mh = mio_open(mdev, MIO_IN, 1);
+ sinit();
+ sbuf = malloc(bs * 2 * sizeof(int16_t));
+ mbuf = malloc(32);
+ c = 0;
+ dt = 100;
+ while (1){
+ size_t n;
+ int i;
+ n = mio_read(mh, mbuf, 32);
+ for (i=0; i < n; i++){
+ mparse(mbuf[i]);
+ }
+ for (i=0; i<bs * 2; i+=2){
+ c++;
+ sbuf[i] = (c%dt > (dt/2))? vol : -vol;
+ sbuf[i+1] = sbuf[i];
+ }
+ n = 0;
+ n = sio_write(sh, sbuf, bs * 2 * sizeof(int16_t));
+ wt += n;
+ }
+ return 0;
+}
+