add lfo, pitch bend, key stack (for unison trills), filter lfo, filter EG intensity, 24db/oct filter

master
vampirefrog 6 years ago
parent 7c84b45a03
commit 693332aa07

@ -1,10 +1,11 @@
CFLAGS=$(shell pkg-config alsa jack --cflags)
LDFLAGS=$(shell pkg-config alsa jack --libs)
PKGS=alsa jack gtk+-3.0
CFLAGS=$(shell pkg-config $(PKGS) --cflags)
LDFLAGS=$(shell pkg-config $(PKGS) --libs)
ifeq ($(DEBUG),true)
CFLAGS+=-Wall -g
endif
programs=vampisynth
vampisynth_SRCS=synth.c envelope.c filter.c oscillator.c voice.c main.c
vampisynth_SRCS=synth.c envelope.c filter.c oscillator.c voice.c sineosc.c main.c
include common.mk/common.mk

@ -1,30 +1,72 @@
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "filter.h"
void filter_init(struct Filter *filter, float cutoff, float resonance) {
filter->v0 = filter->v1 = 0;
memset(filter, 0, sizeof(struct Filter));
filter->cutoff = cutoff;
filter->resonance = resonance;
}
void filter_set_cutoff(struct Filter *filter, float cutoff) {
filter->cutoff = cutoff;
if(filter->cutoff > 0.9) filter->cutoff = 0.9;
else if(filter->cutoff < 0.0) filter->cutoff = 0.0;
}
void filter_set_resonance(struct Filter *filter, float resonance) {
filter->resonance = resonance;
}
// http://www.musicdsp.org/showone.php?id=25
// float filter_sample(struct Filter *filter, float input) {
// float q = 1.0f - filter->cutoff;
// float p = filter->cutoff + 0.8f * filter->cutoff * q;
// float f = p + p - 1.0f;
// q = filter->resonance * (1.0f + 0.5f * q * (1.0f - q + 5.6f * q * q));
// #define OVERSAMPLE 2
// float output = 0;
// for(int i = 0; i < OVERSAMPLE; i++) {
// input -= q * filter->b4; //feedback
// float t1 = filter->b1; filter->b1 = (input + filter->b0) * p - filter->b1 * f;
// float t2 = filter->b2; filter->b2 = (filter->b1 + t1) * p - filter->b2 * f;
// t1 = filter->b3; filter->b3 = (filter->b2 + t2) * p - filter->b3 * f;
// filter->b4 = (filter->b3 + t1) * p - filter->b4 * f;
// filter->b4 = filter->b4 - filter->b4 * filter->b4 * filter->b4 * 0.166667f; //clipping
// filter->b0 = input;
// output += filter->b4;
// }
// return output / (float)OVERSAMPLE;
// }
// mad's filter code
float filter_sample(struct Filter *filter, float input) {
float c = pow(0.5, (128-filter->cutoff) / 16.0);
float r = pow(0.5, (filter->resonance+24) / 16.0);
if(++filter->last_calc >= 16) {
filter->last_calc = 0;
filter->cutoff_calc = pow (0.5, 8.5 - (filter->cutoff)*8 );
filter->resonance_calc = filter->resonance;
}
float cutoff = filter->cutoff_calc;
float resonance = filter->resonance_calc;
float outputs[2]; // oversample
for(int i = 0; i < 2; i++) {
filter->v0 = (1-r*c)*filter->v0 - (c)*filter->v1 + (c)*input;
outputs[i] = filter->v1 = (1-r*c)*filter->v1 + (c)*filter->v0;
#define OVERSAMPLE 2
float output = 0;
for(int i = 0; i < OVERSAMPLE; i++) {
float in = filter->resonance_input;
if(in > 1) in = 1;
if(in < -1) in = -1;
in = 1.5*in - 0.5*in*in*in;
in = input - in;
filter->stage_1 += (in - filter->stage_1) * cutoff;
filter->stage_2 += (filter->stage_1 - filter->stage_2) * cutoff;
filter->stage_3 += (filter->stage_2 - filter->stage_3) * cutoff;
filter->stage_4 += (filter->stage_3 - filter->stage_4) * cutoff;
output += filter->stage_4;
filter->resonance_input = output * resonance;
}
return (outputs[0] + outputs[1]) / 2;
return output / OVERSAMPLE;
}

@ -2,13 +2,19 @@
#define FILTER_H_
struct Filter {
float v0, v1;
// public
float cutoff, resonance;
// private
float resonance_input, stage_1, stage_2, stage_3, stage_4;
float cutoff_calc, resonance_calc;
int last_calc;
float b0, b1, b2, b3, b4; //filter buffers (beware denormals!)
};
void filter_init(struct Filter *filter, float cutoff, float q);
void filter_set_cutoff(struct Filter *filter, float cutoff); // frequency in Hz
void filter_set_resonance(struct Filter *filter, float q);
void filter_set_cutoff_and_resonance(struct Filter *filter, float cutoff, float q); // both
void filter_set_cutoff(struct Filter *filter, float cutoff);
void filter_set_resonance(struct Filter *filter, float resonance);
float filter_sample(struct Filter *filter, float input);
#endif /* FILTER_H_ */

@ -42,7 +42,7 @@ int process (jack_nframes_t nframes, void *arg) {
buffers[0] = (sample_t *) jack_port_get_buffer (output_ports[0], nframes);
buffers[1] = (sample_t *) jack_port_get_buffer (output_ports[1], nframes);
for(int i = 0; i < nframes; i++) {
float out[2];
float out[2] = {0, 0};
synth_render_sample(&synth, out);
buffers[0][i] = out[0];
buffers[1][i] = out[1];
@ -154,25 +154,33 @@ void midi_action(snd_seq_t *seq_handle) {
printf("Note off %s (%d) %d\n", midi_note_name(ev->data.note.note), ev->data.note.note, ev->data.note.velocity);
synth_note_off(&synth, ev->data.note.note, ev->data.note.velocity);
break;
case SND_SEQ_EVENT_PITCHBEND:
synth_pitch_bend(&synth, ev->data.control.value);
break;
case SND_SEQ_EVENT_CONTROLLER:
if(verbose)
printf("CC 0x%02x (%s) %d\n", ev->data.control.param, midi_cc_name(ev->data.control.param), ev->data.control.value);
if(ev->data.control.param == 91) {
if(ev->data.control.param == 0x01) {
if(verbose)
printf("LFO Depth %d\n", ev->data.control.value);
synth_set_lfo_depth(&synth, ev->data.control.value);
} else if(ev->data.control.param == 7) {
if(verbose)
printf("Volume %d\n", ev->data.control.value);
synth_set_volume(&synth, ev->data.control.value);
} else if(ev->data.control.param == 91) {
if(verbose)
printf("Unison spread %d\n", ev->data.control.value);
synth_set_unison_spread(&synth, ev->data.control.value);
}
if(ev->data.control.param == 93) {
} else if(ev->data.control.param == 93) {
if(verbose)
printf("Stereo spread %d\n", ev->data.control.value);
synth_set_stereo_spread(&synth, ev->data.control.value);
}
if(ev->data.control.param == 74) {
} else if(ev->data.control.param == 74) {
if(verbose)
printf("Cutoff %d\n", ev->data.control.value);
synth_set_cutoff_freq(&synth, ev->data.control.value);
}
if(ev->data.control.param == 71) {
} else if(ev->data.control.param == 71) {
if(verbose)
printf("Resonance %d\n", ev->data.control.value);
synth_set_resonance(&synth, ev->data.control.value);
@ -236,6 +244,21 @@ int main(int argc, char **argv) {
sr = jack_get_sample_rate(client);
synth_init(&synth);
synth.osc_env.attack = 2;
synth.osc_env.decay = 200;
synth.osc_env.sustain = 100;
synth.osc_env.release = 100;
synth.filter_env.attack = 150;
synth.filter_env.decay = 100;
synth.filter_env.sustain = 100;
synth.filter_env.release = 100;
synth.filter_eg_intensity = .8;
synth.filter_kbd_track = .5;
sine_osc_set_freq(&synth.lfo_osc, 6);
synth.pitch_bend_range = 12; // semitones
// synth.monophonic = 1;
if (jack_activate(client)) {
fprintf (stderr, "cannot activate client");
exit (1);
@ -256,22 +279,6 @@ int main(int argc, char **argv) {
fprintf (stderr, "cannot connect input ports\n");
}
synth_init(&synth);
synth.osc_env.attack = 2;
synth.osc_env.decay = 100;
synth.osc_env.sustain = 90;
synth.osc_env.release = 100;
synth.filter_env.attack = 1000;
synth.filter_env.decay = 200;
synth.filter_env.sustain = 90;
synth.filter_env.release = 100;
synth.monophonic = 1;
if (jack_activate(client)) {
fprintf (stderr, "cannot activate client");
return 1;
}
snd_seq_t *seq_handle;
int npfd;
struct pollfd *pfd;

@ -1,4 +1,5 @@
#include "oscillator.h"
#include "config.h"
int16_t oscillator_render_sample(struct Oscillator *osc) {
if(osc->period == 0) return 0;
@ -15,3 +16,7 @@ int16_t oscillator_render_sample(struct Oscillator *osc) {
return (1 << 13) - (osc->phase << 3) / (osc->period >> 11) + (osc->sub_phase - osc->period / 2 > osc->period ? 4096 : -4096);
}
void oscillator_set_freq(struct Oscillator *osc, float freq) {
osc->period = ((float)SAMPLE_RATE / freq) * 65536.0;
}

@ -18,6 +18,6 @@ struct Oscillator {
};
int16_t oscillator_render_sample(struct Oscillator *osc);
void oscillator_set_freq(fixed freq); // fixed 16.16
void oscillator_set_freq(struct Oscillator *osc, float freq); // fixed 16.16
#endif /* OSCILLATOR_H_ */

@ -0,0 +1,19 @@
#include <math.h>
#include "sineosc.h"
#include "config.h"
void sine_osc_init(struct SineOsc *osc) {
osc->s0 = 1.0;
osc->s1 = 0.0;
}
void sine_osc_set_freq(struct SineOsc *osc, float freq) {
osc->a = 2.0 * sinf(M_PI * freq / SAMPLE_RATE);
}
float sine_osc_sample(struct SineOsc *osc) {
osc->s0 = osc->s0 - osc->a * osc->s1;
osc->s1 = osc->s1 + osc->a * osc->s0;
return osc->s0;
}

@ -0,0 +1,12 @@
#ifndef SINEOSC_H_
#define SINEOSC_H_
struct SineOsc {
float a, s0, s1;
};
void sine_osc_init(struct SineOsc *osc);
void sine_osc_set_freq(struct SineOsc *osc, float freq);
float sine_osc_sample(struct SineOsc *osc);
#endif /* SINEOSC_H_ */

@ -1,82 +1,159 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth.h"
#include "config.h"
#include "tables.inc"
// convert from 16.16 frequency to 16.16 period in samples
static fixed freq2period(fixed freq) {
uint64_t tmp = (uint64_t)SAMPLE_RATE << 32;
return tmp / freq;
}
void synth_init(struct Synth *synth) {
synth_set_cutoff_freq(synth, 127);
synth_set_resonance(synth, 0);
srandom(1234);
synth->key_stack_size = 0;
synth->tuning = 440.0;
synth->volume = 1.0;
synth->pitch_bend = 0.0;
synth->lfo_depth = 0.0;
sine_osc_init(&synth->lfo_osc);
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
synth->voices[i].synth = synth;
}
}
uint8_t midi_notes[128];
void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity) {
if(synth->monophonic) {
int freq = midi_note_freq_fixed[note];
int freq_below = freq - midi_note_freq_fixed[note - 1];
int freq_above = midi_note_freq_fixed[note + 1] - freq;
synth->voices[0].osc.freq = freq;
synth->voices[0].osc.period = freq2period(freq);
for(int i = 1; i <= 3; i++) {
struct Voice *voice = synth->voices + i;
voice->osc.freq = freq - synth->unison_spread * freq_below * i / 512;
voice->osc.period = freq2period(voice->osc.freq);
}
for(int i = 4; i < 7; i++) {
struct Voice *voice = synth->voices + i;
voice->osc.freq = freq + synth->unison_spread * freq_above * (i - 3) / 512;
voice->osc.period = freq2period(voice->osc.freq);
}
static float detune(float freq, float semitones) {
return freq * pow(2, semitones / 12.0);
}
synth->voices[0].pan = 0;
for(int i = 1; i <= 7; i++) {
synth->voices[i].pan = ((i&1) * 2 - 1) * synth->stereo_spread * ((i + 1) / 2) / 3;
}
static float midifreq(uint8_t note) {
return pow(2, (note - 69) / 12.0) * 440.0;
}
for(int i = 0; i < 7; i++) {
struct Voice *voice = synth->voices + i;
voice->osc.phase = random();
static void synth_set_pitch(struct Synth *synth) {
float lfo_detune = synth->lfo_depth * sine_osc_sample(&synth->lfo_osc);
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *voice = &synth->voices[i];
if(voice->osc_env.state != None)
oscillator_set_freq(&voice->osc, detune(midifreq(voice->note), voice->detune + synth->pitch_bend * synth->pitch_bend_range + lfo_detune));
}
}
voice->osc_env.attack = synth->osc_env.attack;
voice->osc_env.decay = synth->osc_env.decay;
voice->osc_env.sustain = synth->osc_env.sustain;
voice->osc_env.release = synth->osc_env.release;
static void synth_note_on_monophonic(struct Synth *synth, uint8_t note, uint8_t velocity) {
synth->voices[0].detune = 0;
for(int i = 1; i <= 3; i++) {
synth->voices[i].detune = i * synth->unison_spread / 6.0;
}
for(int i = 4; i < 7; i++) {
synth->voices[i].detune = (i - 3) * synth->unison_spread / 6.0;
}
synth->voices[0].pan = 0;
for(int i = 1; i <= 7; i++) {
synth->voices[i].pan = ((i&1) * 2 - 1) * synth->stereo_spread * ((i + 1) / 2) / 3;
}
voice->filter_env.attack = synth->filter_env.attack;
voice->filter_env.decay = synth->filter_env.decay;
voice->filter_env.sustain = synth->filter_env.sustain;
voice->filter_env.release = synth->filter_env.release;
for(int i = 0; i < 7; i++) {
struct Voice *voice = synth->voices + i;
voice->osc.phase = random();
voice->osc_env.attack = synth->osc_env.attack;
voice->osc_env.decay = synth->osc_env.decay;
voice->osc_env.sustain = synth->osc_env.sustain;
voice->osc_env.release = synth->osc_env.release;
voice->filter_env.attack = synth->filter_env.attack;
voice->filter_env.decay = synth->filter_env.decay;
voice->filter_env.sustain = synth->filter_env.sustain;
voice->filter_env.release = synth->filter_env.release;
voice_note_start(voice, note, i == 0 ? velocity : velocity / 4);
}
}
voice_note_start(voice, note, i == 0 ? velocity : velocity / 4);
void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity) {
if(synth->monophonic) {
synth->key_stack[synth->key_stack_size].note = note;
synth->key_stack[synth->key_stack_size].velocity = velocity;
synth->key_stack_size++;
if(synth->key_stack_size >= SYNTH_NUM_VOICES) {
memmove(synth->key_stack, synth->key_stack + 1, sizeof(synth->key_stack[0]) * (SYNTH_NUM_VOICES - 1));
synth->key_stack_size--;
}
synth_note_on_monophonic(synth, note, velocity);
} else {
struct Voice *found = 0;
uint32_t oldest_time = 0;
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *voice = &synth->voices[i];
if(voice->osc_env.state == None) {
found = voice;
break;
}
if(voice->time > oldest_time) {
oldest_time = voice->time;
found = voice;
}
}
found->osc_env.attack = synth->osc_env.attack;
found->osc_env.decay = synth->osc_env.decay;
found->osc_env.sustain = synth->osc_env.sustain;
found->osc_env.release = synth->osc_env.release;
found->filter_env.attack = synth->filter_env.attack;
found->filter_env.decay = synth->filter_env.decay;
found->filter_env.sustain = synth->filter_env.sustain;
found->filter_env.release = synth->filter_env.release;
voice_note_start(found, note, velocity);
}
}
void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity) {
(void)velocity;
static void synth_note_off_monophonic(struct Synth *synth) {
for(int i = 0; i < 7; i++) {
struct Voice *voice = synth->voices + i;
voice_stop(voice);
}
}
void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity) {
if(synth->monophonic) {
if(synth->key_stack_size > 1) {
synth_note_on_monophonic(synth, synth->key_stack[synth->key_stack_size - 2].note, synth->key_stack[synth->key_stack_size - 2].velocity);
} else {
synth_note_off_monophonic(synth);
}
synth->key_stack_size--;
} else {
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *voice = synth->voices + i;
if(voice->note == note && voice->osc_env.state != None && voice->osc_env.state != Release) {
voice_stop(&synth->voices[i]);
}
}
printf("voices: ");
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
printf("%d%d ", synth->voices[i].osc_env.state, synth->voices[i].filter_env.state);
}
printf("\n");
}
}
void synth_render_sample(struct Synth *synth, float *out) {
float smpl[2] = { 0, 0 };
synth_set_pitch(synth);
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
struct Voice *v = synth->voices + i;
struct Voice *v = &synth->voices[i];
if(v->osc_env.state == None) continue;
float vsmpl[2];
voice_render_sample(v, vsmpl);
for(int j = 0; j < 2; j++) {
smpl[j] += vsmpl[j] / 2.0;
smpl[j] += vsmpl[j];
if(smpl[j] > 1) smpl[j] = 1;
else if(smpl[j] < -1) smpl[j] = -1;
}
@ -84,17 +161,16 @@ void synth_render_sample(struct Synth *synth, float *out) {
out[0] = smpl[0];
out[1] = smpl[1];
synth->time++;
}
void synth_set_cutoff_freq(struct Synth *synth, uint8_t f) {
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
filter_set_cutoff(&synth->voices[i].filter, f);
}
synth->cutoff = f / 127.0;
}
void synth_set_resonance(struct Synth *synth, uint8_t f) {
for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
filter_set_resonance(&synth->voices[i].filter, f);
filter_set_resonance(&synth->voices[i].filter, f / 127.0);
}
}
@ -105,3 +181,18 @@ void synth_set_unison_spread(struct Synth *synth, uint8_t w) {
void synth_set_stereo_spread(struct Synth *synth, uint8_t w) {
synth->stereo_spread = w;
}
void synth_set_volume(struct Synth *s, uint8_t vol) {
s->volume = vol / 127.0;
}
void synth_pitch_bend(struct Synth *s, int16_t bend) {
s->pitch_bend = bend / 8191.0;
if(s->pitch_bend < -1.0) s->pitch_bend = -1.0;
if(s->pitch_bend > 1.0) s->pitch_bend = 1.0;
synth_set_pitch(s);
}
void synth_set_lfo_depth(struct Synth *s, uint8_t mod) {
s->lfo_depth = mod / 127.0;
}

@ -11,6 +11,11 @@ typedef uint32_t fixed;
#include "filter.h"
#include "oscillator.h"
#include "voice.h"
#include "sineosc.h"
struct Key {
uint8_t note, velocity;
};
struct Synth {
struct Voice voices[SYNTH_NUM_VOICES];
@ -18,6 +23,17 @@ struct Synth {
uint8_t unison_spread;
uint8_t stereo_spread;
uint8_t monophonic;
float tuning; // 440.0Hz
float pitch_bend_range;
float cutoff, filter_eg_intensity, filter_kbd_track, lfo_freq;
// private
struct Key key_stack[SYNTH_NUM_VOICES];
struct SineOsc lfo_osc;
uint8_t key_stack_size;
float volume, pitch_bend, lfo_depth;
uint32_t time;
};
void synth_init(struct Synth *synth);
@ -28,6 +44,9 @@ void synth_set_pulse_width(struct Synth *s, uint8_t width);
void synth_set_unison_spread(struct Synth *s, uint8_t spread);
void synth_set_stereo_spread(struct Synth *s, uint8_t spread);
void synth_set_cutoff_freq(struct Synth *s, uint8_t freq);
void synth_set_resonance(struct Synth *s, uint8_t freq);
void synth_set_resonance(struct Synth *s, uint8_t res);
void synth_set_volume(struct Synth *s, uint8_t vol);
void synth_pitch_bend(struct Synth *s, int16_t bend);
void synth_set_lfo_depth(struct Synth *s, uint8_t mod);
#endif /* SYNTH_H_ */

@ -1,16 +1,16 @@
#include "voice.h"
#include "synth.h"
void voice_render_sample(struct Voice *v, float *out) {
//if(v->osc_env.state == None) return;
float amplitude = envelope_sample(&v->osc_env); // calculate based on key velocity and envelope
float cutoff = envelope_sample(&v->filter_env);
int32_t ret[2] = { 0, 0 };
float s = oscillator_render_sample(&v->osc);
filter_set_cutoff(&v->filter, cutoff * 127);
filter_set_cutoff(&v->filter, v->synth->cutoff + cutoff * v->synth->filter_eg_intensity);
float f = filter_sample(&v->filter, v->volume * amplitude * s / 32768.0);
out[0] = (127 + v->pan) * f / 255.0;
out[1] = (127 - v->pan) * f / 255.0;
v->time++;
}
void voice_note_start(struct Voice *voice, uint8_t note, uint8_t velocity) {
@ -20,6 +20,7 @@ void voice_note_start(struct Voice *voice, uint8_t note, uint8_t velocity) {
envelope_start(&voice->filter_env);
note &= 0x7f;
voice->time = 0;
voice->note = note;
voice->osc.sub_phase = voice->osc.phase;
voice->osc.sub_oct = 1;

@ -6,10 +6,15 @@
#include "oscillator.h"
#include "filter.h"
struct Synth;
struct Voice {
struct Synth *synth;
uint8_t note;
float detune;
float volume;
int8_t pan;
uint32_t time;
struct Envelope osc_env, filter_env;
struct Oscillator osc;

Loading…
Cancel
Save