commit 190530f304f50e4c845f129e5b801f99b92bdddb
parent 896187714eb29e5a8f219facc7f89205ca619026
Author: zavok <an2qzavok@gmail.com>
Date: Tue, 5 Nov 2019 14:22:17 +0300
started coding operators
Diffstat:
5 files changed, 64 insertions(+), 19 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 operator.o
LDFLAGS=-lsndio
@@ -14,7 +14,7 @@ all: $(BIN)
$(BIN): $(OBJ)
$(CC) $(OBJ) $(LDFLAGS) $(LIBS) -o $@
-$(OBJ): audio.c fm.c midi.c usynth.c
+$(OBJ): audio.c fm.c midi.c operator.c usynth.c
install: $(BIN)
mkdir -p $(DESTDIR)$(PREFIX)/bin/
diff --git a/fm.c b/fm.c
@@ -1,5 +1,7 @@
#include <stdio.h>
+#include <stdlib.h>
#include "fm.h"
+#include "operator.h"
#include "tune.h"
@@ -11,6 +13,7 @@ struct voice{
uint8_t note;
uint8_t velocity;
uint8_t pressure;
+ struct op_state op[2];
};
struct channel{
@@ -24,23 +27,21 @@ struct channel{
struct channel fm_channels[16];
struct voice fm_voices[32];
-int64_t fm_synth(int);
+int16_t *triangle;
+
+int64_t fm_synth(struct voice*);
int16_t fm_mix(void);
int64_t
-fm_synth(int i)
+fm_synth(struct voice *v)
{
size_t dt;
int64_t out;
- struct voice *v;
- struct channel *ch;
- v = &fm_voices[i];
- ch = &fm_channels[v->channel];
if (v->id < 0) return 0;
if (v->velocity == 0) return 0;
- out = ch->control[7] * v->velocity;
- dt = 44100.0 / (tune[v->note%12] * (1 << (v->note/12)));
- if (c%dt > dt/2) out = -out;
+ dt = (double)(0xff00)*(tune[v->note%12] * (1 << (v->note/12)))/44100.0;
+ out = op_fetch(&v->op[1], dt);
+ out = op_fetch(&v->op[0], dt + out) * v->velocity / 0x7f;
return out;
}
@@ -52,7 +53,8 @@ fm_mix_channel(int n)
int i;
out = 0;
vs = fm_voices;
- for (i = 0; i < 32; i++) if (vs[i].channel == n) out += fm_synth(i);
+ 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;
}
@@ -82,17 +84,25 @@ void
fm_note_on(uint8_t *mm)
{
int i, nmin, nmax;
- nmin = 32;
- nmax = 32;
+ struct voice *v;
+ nmin = 0;
+ 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;
}
- fm_voices[nmin].id = nmax+1;
- fm_voices[nmin].channel = mm[1];
- fm_voices[nmin].note = mm[2];
- fm_voices[nmin].velocity = mm[3];
- fm_voices[nmin].pressure = 0;
+ v = &fm_voices[nmin];
+ v->op[0].conf.waveform = triangle;
+ v->op[0].conf.gain = 0x7f;
+ v->op[0].conf.freq_multiplier = 1;
+ v->op[1].conf.waveform = triangle;
+ v->op[1].conf.gain = 0x1f;
+ v->op[1].conf.freq_multiplier = 0.5;
+ v->id = nmax+1;
+ v->channel = mm[1];
+ v->note = mm[2];
+ v->velocity = mm[3];
+ v->pressure = 0;
}
void
@@ -123,6 +133,13 @@ void
fm_init(void)
{
int i;
+ int16_t d;
+ triangle = malloc(sizeof(int16_t) * 0xff);
+ d = 0;
+ for (i=0x00; i<0x40; i++) triangle[i] = d+=0x01ff;
+ for (i=0x40; i<0x80; i++) triangle[i] = d-=0x01ff;
+ for (i=0x80; i<0xc0; i++) triangle[i] = d-=0x01ff;
+ for (i=0xc0; i<0xff; i++) triangle[i] = d+=0x01ff;
for (i=0; i<16; i++){
struct channel *ch;
ch = &fm_channels[i];
@@ -130,3 +147,4 @@ fm_init(void)
ch->program = i;
}
}
+
diff --git a/operator.c b/operator.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "operator.h"
+
+int64_t
+op_fetch(struct op_state *op, size_t dp)
+{
+ uint8_t pos;
+ op->p += dp * op->conf.freq_multiplier;
+ pos = op->p >> 8;
+ return op->conf.waveform[pos] * op->conf.gain / 0x7f;
+}
+
diff --git a/operator.h b/operator.h
@@ -0,0 +1,13 @@
+struct op_conf {
+ int16_t *waveform;
+ uint8_t gain;
+ double freq_multiplier;
+};
+
+struct op_state {
+ struct op_conf conf;
+ size_t p;
+};
+
+int64_t op_fetch(struct op_state*, size_t);
+
diff --git a/tune.h b/tune.h
@@ -12,3 +12,4 @@ double tune[]={
29.14, //A# 46
30.87, //B 47
};
+