commit 3c2f6c0e4068f93d6d1efe833633fee7705490c8
parent 9129563bedd9b5a7833d910e682ebea66a119e45
Author: zavok <an2qzavok@gmail.com>
Date: Wed, 1 Jan 2020 21:54:40 +0300
programmability is almost done
Diffstat:
M | fm.c | | | 97 | ++++++++++++++++++++++++++++--------------------------------------------------- |
M | fm.h | | | 9 | +++++---- |
M | machine.c | | | 205 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
M | machine.h | | | 18 | ++++++++++++++---- |
M | midi.h | | | 1 | + |
M | usynth.c | | | 5 | +++-- |
M | wavetable.c | | | 4 | ++-- |
7 files changed, 180 insertions(+), 159 deletions(-)
diff --git a/fm.c b/fm.c
@@ -1,48 +1,51 @@
#include <stdio.h>
#include <stdlib.h>
#include "operator.h"
-#include "fm.h"
#include "wavetable.h"
-#include "tune.h"
+#include "fm.h"
+#include "machine.h"
-size_t c;
int16_t vol;
+int16_t
+clip(int64_t in)
+{
+ if (in > 0x7fff) return 0x7fff;
+ if (in < -0x7fff) return -0x7fff;
+ return in;
+}
+
void
-fm_note_on(uint8_t *mm)
+fm_key_on(uint8_t *mm)
{
- int i, nmin, nmax;
+ int i;
+ int nmin, nmax;
Voice *v;
- nmin = 0;
- nmax = 0;
- for (i=0;i<32;i++){
+ nmin = nmax = 0;
+ for (i = 0; i < 32; i++) {
if (fm_voices[i].id<fm_voices[nmin].id) nmin = i;
if (fm_voices[i].id>fm_voices[nmax].id) nmax = i;
}
v = &fm_voices[nmin];
- v->op[0].p = 0;
- v->op[0].conf.waveform = wavetable[1];
- v->op[0].conf.gain = 0xff;
- v->op[0].conf.freq_multiplier = 1;
- v->op[1].p = 0;
- v->op[1].conf.waveform = wavetable[1];
- v->op[1].conf.gain = 0xff;
- v->op[1].conf.freq_multiplier = 1;
- v->id = nmax+1;
- v->channel = mm[1];
- v->note = mm[2];
- v->velocity = mm[3];
- v->pressure = 0;
+ v->id = fm_voices[nmax].id+1;
+ //v->channel = mm[1];
+ //v->key = mm[2];
+ //v->velocity = mm[3];
+ vms[nmin].status = 1;
+ vms[nmin].key = mm[2];
+ //v->pressure = 0;
+ vm_set(&vms[nmin], 0, 0);
}
void
-fm_note_off(uint8_t *mm)
+fm_key_off(uint8_t *mm)
{
int i;
for (i=0; i<32; i++){
- if (fm_voices[i].note == mm[2]){
- fm_voices[i].velocity = mm[3];
- fm_voices[i].id = -1;
+ if (vms[i].key == mm[2]){
+ //fm_voices[i].velocity = mm[3];
+ vms[i].status = 0;
+ fm_voices[i].id = 0;
}
}
}
@@ -62,55 +65,22 @@ fm_prog_change(uint8_t *mm)
void
fm_init(void)
{
- int i;
+ Channel *ch;
wt_init();
- for (i=0; i<16; i++){
- Channel *ch;
- ch = &fm_channels[i];
+ for (ch=fm_channels; ch<fm_channels+16; ch++){
ch->control[7]=0x7f;
- ch->program = i;
+ ch->program = ch - fm_channels;
}
}
-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;
+ for (i=0; i<32; i++) out += vm_run(&vms[i]);
+ return clip(out);
}
void
@@ -121,3 +91,4 @@ fm_fillbuf(int16_t *buf, size_t nsamples)
buf[i] = buf[i+1] = fm_mix();
}
}
+
diff --git a/fm.h b/fm.h
@@ -1,6 +1,8 @@
typedef struct Voice Voice;
struct Voice {
int id;
+ int status;
+ uint8_t key;
uint8_t channel;
uint8_t note;
uint8_t velocity;
@@ -22,11 +24,10 @@ 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*);
-void fm_note_off(uint8_t*);
+void fm_key_on(uint8_t*);
+void fm_key_off(uint8_t*);
void fm_ctl_change(uint8_t*);
void fm_prog_change(uint8_t*);
+
diff --git a/machine.c b/machine.c
@@ -1,98 +1,170 @@
+#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
-
#include "operator.h"
#include "fm.h"
+#include "wavetable.h"
#include "machine.h"
+#include "tune.h"
+
+typedef void (*instruction)(VM*, uint8_t);
+
+void vm_fatal(VM*, char*);
+void vm_adsr(VM*);
+
+void i_halt(VM*, uint8_t);
+void i_lit(VM*, uint8_t);
+void i_fetch(VM*, uint8_t);
+void i_op(VM*, uint8_t);
+void i_adsr(VM*, uint8_t);
+void i_wave(VM*, uint8_t);
+void i_note(VM*, uint8_t);
+void i_2dt(VM*, uint8_t);
+void i_dup(VM*, uint8_t);
+void i_drop(VM*, uint8_t);
+void i_swap(VM*, uint8_t);
+void i_add(VM*, uint8_t);
+void i_comb(VM*, uint8_t);
+instruction instructions[128] = {
+ [I_HALT] = i_halt,
+ [I_LIT] = i_lit,
+ [I_FETCH] = i_fetch,
+ [I_OP] = i_op,
+ [I_ADSR] = i_adsr,
+ [I_WAVE] = i_wave,
+ [I_NOTE] = i_note,
+ [I_2DT] = i_2dt,
+ [I_DUP] = i_dup,
+ [I_DROP] = i_drop,
+ [I_SWAP] = i_swap,
+ [I_ADD] = i_add,
+ [I_COMB] = i_comb,
+};
+
+int16_t sprog[] = {
+ I_NOTE,
+ I_2DT,
+ I_OP|0x0000,
+ I_WAVE|0x0000,
+ I_ADSR|0x0000,
+ I_COMB,
+ I_HALT
+};
+
+void
+vm_set(VM *vm, Channel *channel, Voice *voice)
+{
+ vm->prog = sprog;
+}
+
+int16_t
+vm_run(VM *vm)
+{
+ instruction inst;
+ if (vm->prog == 0) return 0;
+ vm->halted = 0;
+ vm->pc = 0;
+ vm->sp = 0;
+ vm_adsr(vm);
+ while (vm->halted == 0) {
+ inst = instructions[0xff & vm->prog[vm->pc]];
+ if (inst == 0)
+ vm_fatal(vm, "illegal instruction");
+ vm->pc++;
+ inst(vm, vm->prog[vm->pc]>>8);
+ }
+ return vm->stack[vm->sp-1];
+}
-typedef void (*instruction)(VM*);
+void
+vm_adsr(VM *vm)
+{
+ int i;
+ for (i=0; i<16; i++) {
+ vm->adsr[i] = vm->status * 0x7fff;
+ }
+}
+void
+vm_fatal(VM* vm, char *errstr)
+{
+ dprintf(2, "VM FATAL: %s\n", errstr);
+ dprintf(2, "pc = \n", vm->pc);
+ exit(-1);
+}
void
-i_halt(VM *vm)
+i_halt(VM *vm, uint8_t arg)
{
vm->halted = 1;
}
-
void
-i_lit(VM *vm)
+i_lit(VM *vm, uint8_t arg)
{
vm->stack[vm->sp] = vm->prog[vm->pc];
vm->sp++;
vm->pc++;
}
-
void
-i_fetch(VM *vm)
+i_fetch(VM *vm, uint8_t arg)
{
vm->stack[vm->sp-1] = vm->prog[vm->stack[vm->sp-1]];
}
-
void
-i_chan(VM *vm)
+i_op(VM *vm, uint8_t arg)
{
- 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]];
- }
+ vm->op[arg] += vm->stack[vm->sp-1];
+ vm->stack[vm->sp-1] = vm->op[arg];
}
-
void
-i_voic(VM *vm)
+i_adsr(VM *vm, uint8_t arg)
{
- 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;
- }
+ vm->stack[vm->sp] = vm->adsr[arg];
+ vm->sp++;
}
+void
+i_wave(VM *vm, uint8_t arg)
+{
+ vm->stack[vm->sp-1] =
+ wavetable[0][vm->stack[vm->sp-1]>>8];
+}
void
-i_op(VM *vm)
+i_note(VM *vm, uint8_t arg)
{
- 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;
+ vm->stack[vm->sp] = vm->key;
+ vm->sp++;
}
+void
+i_2dt(VM *vm, uint8_t arg)
+{
+ uint8_t note = vm->stack[vm->sp-1];
+ int16_t dt = tune[note%12] * (1 << (note/12));
+ vm->stack[vm->sp-1] = dt;
+}
void
-i_dup(VM *vm)
+i_dup(VM *vm, uint8_t arg)
{
vm->stack[vm->sp] = vm->stack[vm->sp-1];
vm->sp++;
}
-
void
-i_drop(VM *vm)
+i_drop(VM *vm, uint8_t arg)
{
vm->sp--;
}
-
void
-i_swap(VM *vm)
+i_swap(VM *vm, uint8_t arg)
{
int16_t b;
b = vm->stack[vm->sp-1];
@@ -100,54 +172,19 @@ i_swap(VM *vm)
vm->stack[vm->sp-2] = b;
}
-
void
-i_add(VM *vm)
+i_add(VM *vm, uint8_t arg)
{
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)
+i_comb(VM *vm, uint8_t arg)
{
- 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;
+ vm->stack[vm->sp-2] =
+ vm->stack[vm->sp-1] * vm->stack[vm->sp-2]
+ / 0x7fff;
+ vm->sp--;
}
-int16_t
-vm_run(VM *vm)
-{
- instruction inst;
- vm->halted = 0;
- vm->pc = 0;
- vm->sp = 0;
- while (vm->halted == 0) {
- inst = instructions[vm->prog[vm->pc]];
- vm->pc++;
- inst(vm);
- }
- return vm->stack[vm->sp-1];
-}
diff --git a/machine.h b/machine.h
@@ -3,15 +3,18 @@ enum {
/* * * * * */
I_LIT,
I_FETCH,
- I_CHAN,
- I_VOIC,
I_OP,
+ I_ADSR,
+ I_WAVE,
+ I_NOTE,
+ I_2DT,
/* * * * * */
I_DUP,
I_DROP,
I_SWAP,
/* * * * * */
I_ADD,
+ I_COMB,
};
#define SDEPTH 256
@@ -19,7 +22,11 @@ enum {
typedef struct VM VM;
struct VM {
int halted;
+ int status;
+ uint8_t key;
int16_t stack[SDEPTH];
+ int16_t op[16];
+ int16_t adsr[16];
int16_t sp;
int16_t *prog;
int16_t pc;
@@ -27,4 +34,8 @@ struct VM {
Channel *channel;
};
-void vm_set(VM*, Channel*, Voice*);
-\ No newline at end of file
+VM vms[32];
+
+void vm_set(VM*, Channel*, Voice*);
+int16_t vm_run(VM*);
+
diff --git a/midi.h b/midi.h
@@ -14,3 +14,4 @@ Mvector m_vector;
void m_init(char *mdev);
void m_read(void);
+
diff --git a/usynth.c b/usynth.c
@@ -6,6 +6,7 @@
#include "midi.h"
#include "operator.h"
#include "fm.h"
+#include "machine.h"
struct sio_hdl *sh;
size_t bs;
@@ -40,8 +41,8 @@ main(int argc, char **argv)
s_init();
m_init("rmidi/0");
fm_init();
- m_vector.note_on = fm_note_on;
- m_vector.note_off = fm_note_off;
+ m_vector.note_on = fm_key_on;
+ m_vector.note_off = fm_key_off;
m_vector.ctl_change = fm_ctl_change;
m_vector.prog_change = fm_prog_change;
while (1){
diff --git a/wavetable.c b/wavetable.c
@@ -15,8 +15,8 @@ wt_init(void)
wavetable = malloc(sizeof(int16_t*) * WT_SIZE);
for (i=0;i<8;i++) wavetable[i] = malloc(sizeof(int16_t) * WT_LENGTH);
//wt_sin(wavetable[0]);
- wt_triangle(wavetable[1]);
- wt_pulse(wavetable[2]);
+ wt_triangle(wavetable[0]);
+ wt_pulse(wavetable[1]);
}
void