usynth

simple midi synth for sndio
git clone git://nsmpr.xyz/usynth.git
Log | Files | Refs

commit 190530f304f50e4c845f129e5b801f99b92bdddb
parent 896187714eb29e5a8f219facc7f89205ca619026
Author: zavok <an2qzavok@gmail.com>
Date:   Tue,  5 Nov 2019 14:22:17 +0300

started coding operators

Diffstat:
MMakefile | 4++--
Mfm.c | 52+++++++++++++++++++++++++++++++++++-----------------
Aoperator.c | 13+++++++++++++
Aoperator.h | 13+++++++++++++
Mtune.h | 1+
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 }; +