commit 2cb921c89ee168d42e552f1cd438ddc3eb2d3741
parent 428fdf59a82f5b9315caaaaca136292dfc0f00d1
Author: zavok <an2qzavok@gmail.com>
Date: Mon, 30 Dec 2019 00:25:19 +0300
working on programmability
Diffstat:
M | Makefile | | | 2 | +- |
M | fm.c | | | 127 | ++++++++++++++++++++++++++++++++----------------------------------------------- |
M | fm.h | | | 26 | ++++++++++++++++++++++++++ |
M | machine.c | | | 155 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | machine.h | | | 31 | +++++++++++++++++++++++++++++++ |
M | operator.c | | | 2 | +- |
M | operator.h | | | 2 | +- |
M | tune.h | | | 24 | ++++++++++++------------ |
M | usynth.c | | | 1 | + |
9 files changed, 280 insertions(+), 90 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ MANDIR = $(PREFIX)/share/man/man1
BIN = usynth
MAN = $(BIN).1
-OBJ = $(BIN:=.o) audio.o fm.o midi.o \
+OBJ = $(BIN:=.o) audio.o fm.o midi.o\
machine.o operator.o wavetable.o
LDFLAGS=-lsndio
diff --git a/fm.c b/fm.c
@@ -1,90 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
-#include "fm.h"
#include "operator.h"
+#include "fm.h"
#include "wavetable.h"
#include "tune.h"
size_t c;
int16_t vol;
-struct voice{
- int id;
- uint8_t channel;
- uint8_t note;
- uint8_t velocity;
- uint8_t pressure;
- struct op_state op[2];
-};
-
-struct channel{
- uint8_t program;
- uint8_t pressure;
- uint8_t control[128];
- int16_t pitch;
-
-};
-
-struct channel fm_channels[16];
-struct voice fm_voices[32];
-
-int64_t fm_synth(struct voice*);
-int16_t fm_mix(void);
-
-int64_t
-fm_synth(struct voice *v)
-{
- struct channel *ch;
- size_t dt;
- int64_t out;
- if (v->id < 0) return 0;
- if (v->velocity == 0) return 0;
- ch = &fm_channels[v->channel];
- dt = (double)(0xff00)*(tune[v->note%12] * (1 << (v->note/12)))/44100.0;
- out = op_fetch(&v->op[1], dt*2, 0);
- out = op_fetch(&v->op[0], dt*3, out) * v->velocity / 0x7f;
- return out;
-}
-
-int64_t
-fm_mix_channel(int n)
-{
- struct voice *vs;
- int64_t out;
- int i;
- out = 0;
- vs = fm_voices;
- for (i = 0; i < 32; i++) if (vs[i].channel == n) out += fm_synth(&vs[i]);
- out = out * fm_channels[n].control[7] / 0x7f;
- return out;
-}
-
-int16_t
-fm_mix(void)
-{
- int64_t out;
- int i;
- c++;
- out = 0;
- for (i=0; i<16; i++) out += fm_mix_channel(i);
- if (out > 0x7fff) out = 0x7fff;
- if (out < -0x7fff) out = -0x7fff;
- return out;
-}
-
-void
-fm_fillbuf(int16_t *buf, size_t nsamples)
-{
- size_t i;
- for (i=0; i < nsamples; i+=2){
- buf[i] = buf[i+1] = fm_mix();
- }
-}
void
fm_note_on(uint8_t *mm)
{
int i, nmin, nmax;
- struct voice *v;
+ Voice *v;
nmin = 0;
nmax = 0;
for (i=0;i<32;i++){
@@ -137,10 +65,59 @@ fm_init(void)
int i;
wt_init();
for (i=0; i<16; i++){
- struct channel *ch;
+ Channel *ch;
ch = &fm_channels[i];
ch->control[7]=0x7f;
ch->program = i;
}
}
+int64_t
+fm_synth(Voice *v)
+{
+ Channel *ch;
+ size_t dt;
+ int64_t out;
+ if (v->id < 0) return 0;
+ if (v->velocity == 0) return 0;
+ ch = &fm_channels[v->channel];
+ dt = (double)(0xff00)*(tune[v->note%12] * (1 << (v->note/12)))/44100.0;
+ out = op_fetch(&v->op[1], dt*2, 0);
+ out = op_fetch(&v->op[0], dt*3, out) * v->velocity / 0x7f;
+ return out;
+}
+
+int64_t
+fm_mix_channel(int n)
+{
+ Voice *vs;
+ int64_t out;
+ int i;
+ out = 0;
+ vs = fm_voices;
+ for (i = 0; i < 32; i++) if (vs[i].channel == n) out += fm_synth(&vs[i]);
+ out = out * fm_channels[n].control[7] / 0x7f;
+ return out;
+}
+
+int16_t
+fm_mix(void)
+{
+ int64_t out;
+ int i;
+ c++;
+ out = 0;
+ for (i=0; i<16; i++) out += fm_mix_channel(i);
+ if (out > 0x7fff) out = 0x7fff;
+ if (out < -0x7fff) out = -0x7fff;
+ return out;
+}
+
+void
+fm_fillbuf(int16_t *buf, size_t nsamples)
+{
+ size_t i;
+ for (i=0; i < nsamples; i+=2){
+ buf[i] = buf[i+1] = fm_mix();
+ }
+}
diff --git a/fm.h b/fm.h
@@ -1,3 +1,29 @@
+typedef struct Voice Voice;
+struct Voice {
+ int id;
+ uint8_t channel;
+ uint8_t note;
+ uint8_t velocity;
+ uint8_t pressure;
+ struct op_state op[2];
+};
+
+typedef struct Channel Channel;
+struct Channel {
+ uint8_t program;
+ uint8_t pressure;
+ uint8_t control[128];
+ int16_t pitch;
+};
+
+Channel fm_channels[16];
+Voice fm_voices[32];
+
+int64_t fm_synth(Voice*);
+int16_t fm_mix(void);
+
+
+
void fm_fillbuf(int16_t*, size_t);
void fm_init(void);
void fm_note_on(uint8_t*);
diff --git a/machine.c b/machine.c
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#include "operator.h"
+#include "fm.h"
+#include "tune.h"
+
+#include "machine.h"
+
+
+typedef void (*instruction)(VM*);
+
+
+void
+i_halt(VM *vm)
+{
+ vm->halted = 1;
+}
+
+
+void
+i_lit(VM *vm)
+{
+ vm->stack[vm->sp] = vm->prog[vm->pc];
+ vm->sp++;
+ vm->pc++;
+}
+
+
+void
+i_fetch(VM *vm)
+{
+ vm->stack[vm->sp-1] = vm->prog[vm->stack[vm->sp-1]];
+}
+
+
+void
+i_chan(VM *vm)
+{
+ switch (vm->stack[vm->sp-1]) {
+ case 0x80:
+ vm->stack[vm->sp-1] = vm->channel->pressure;
+ case 0x81:
+ vm->stack[vm->sp-1] = vm->channel->pitch;
+ default:
+ vm->stack[vm->sp-1] = vm->channel->control[vm->stack[vm->sp-1]];
+ }
+}
+
+
+void
+i_voic(VM *vm)
+{
+ switch (vm->stack[vm->sp-1]) {
+ case 0x00:
+ vm->stack[vm->sp-1] = vm->voice->note;
+ break;
+ case 0x01:
+ vm->stack[vm->sp-1] = vm->voice->velocity;
+ break;
+ case 0x02:
+ vm->stack[vm->sp-1] = vm->voice->pressure;
+ break;
+ }
+}
+
+
+void
+i_op(VM *vm)
+{
+ int16_t opn, dp, mod;
+ opn = vm->stack[vm->sp-1];
+ dp = vm->stack[vm->sp-2];
+ mod = vm->stack[vm->sp-3];
+ vm->stack[vm->sp-3] = op_fetch(&vm->voice->op[opn], dp, mod);
+ vm->sp -= 2;
+}
+
+
+void
+i_dup(VM *vm)
+{
+ vm->stack[vm->sp] = vm->stack[vm->sp-1];
+ vm->sp++;
+}
+
+
+void
+i_drop(VM *vm)
+{
+ vm->sp--;
+}
+
+
+void
+i_swap(VM *vm)
+{
+ int16_t b;
+ b = vm->stack[vm->sp-1];
+ vm->stack[vm->sp-1] = vm->stack[vm->sp-2];
+ vm->stack[vm->sp-2] = b;
+}
+
+
+void
+i_add(VM *vm)
+{
+ vm->stack[vm->sp-2] += vm->stack[vm->sp-2];
+ vm->sp--;
+}
+
+
+instruction instructions[128] = {
+ i_halt,
+ i_lit,
+ i_fetch,
+ i_chan,
+ i_voic,
+ i_op,
+ i_dup,
+ i_drop,
+ i_swap,
+ i_add,
+};
+
+void
+vm_set(VM *vm, Channel *channel, Voice *voice)
+{
+ int16_t *sprog = {
+ I_LIT, 0x00,
+ I_LIT, 0x00, I_VOIC,
+ I_LIT, 0x00,
+ I_OP,
+ I_HALT
+ };
+ vm->voice = voice;
+ vm->channel = channel;
+ vm->prog = sprog;
+}
+
+int16_t
+vm_run(VM *vm)
+{
+ instruction *inst;
+ vm->halted = 0;
+ vm->pc = 0;
+ vm->sp = 0;
+ while (vm->halted == 0) {
+ inst = vm->prog[vm->pc];
+ vm->pc++;
+ inst(vm);
+ }
+ return vm->stack[vm->sp-1];
+}
+\ No newline at end of file
diff --git a/machine.h b/machine.h
@@ -0,0 +1,30 @@
+enum {
+ I_HALT = 0,
+ /* * * * * */
+ I_LIT,
+ I_FETCH,
+ I_CHAN,
+ I_VOIC,
+ I_OP,
+ /* * * * * */
+ I_DUP,
+ I_DROP,
+ I_SWAP,
+ /* * * * * */
+ I_ADD,
+};
+
+#define SDEPTH 256
+
+typedef struct VM VM;
+struct VM {
+ int halted;
+ int16_t stack[SDEPTH];
+ int16_t sp;
+ int16_t *prog;
+ int16_t pc;
+ Voice *voice;
+ Channel *channel;
+};
+
+void vm_set(VM*, Channel*, Voice*);
+\ No newline at end of file
diff --git a/operator.c b/operator.c
@@ -2,7 +2,7 @@
#include <stdint.h>
#include "operator.h"
-int64_t
+int16_t
op_fetch(struct op_state *op, size_t dp, int16_t mod)
{
uint8_t pos;
diff --git a/operator.h b/operator.h
@@ -9,5 +9,5 @@ struct op_state {
size_t p;
};
-int64_t op_fetch(struct op_state*, size_t, int16_t);
+int16_t op_fetch(struct op_state*, size_t, int16_t);
diff --git a/tune.h b/tune.h
@@ -1,15 +1,15 @@
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
+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
};
diff --git a/usynth.c b/usynth.c
@@ -5,6 +5,7 @@
#include <sndio.h>
#include "midi.h"
#include "audio.h"
+#include "operator.h"
#include "fm.h"
struct sio_hdl *sh;