diff --git a/engine.c b/engine.c index b99737e..aebe1c4 100644 --- a/engine.c +++ b/engine.c @@ -5,8 +5,8 @@ #include "env.h" #include "osc.h" #include "filter.h" -#include "voice.h" #include "control.h" +#include "voice.h" #include "engine.h" #include "psyn.h" @@ -23,15 +23,15 @@ void engine_init() } osc_init(); - env_init(&_env, 0.0125, 0.025, 5.0, 0.0, 0.25); - env_init(&_env2, 0.0, 0.0, 0.5, 0.0, 0.25); + env_init(&_engine.params[0].env, 0.0125, 0.025, 5.0, 0.0, 0.25); + env_init(&_engine.params[1].env, 0.0, 0.0, 0.5, 0.0, 0.25); - osc_setfreq(&_engine.osc[0], 10.0); - osc_setfreq(&_engine.osc[1], 2.0); - osc_setfreq(&_engine.osc[2], 1.0); - _engine.osc[0].level = 1.0; - _engine.osc[1].level = 1.0; - _engine.osc[2].level = 1.0; + osc_setfreq(&_engine.lfo[0], 10.0); + osc_setfreq(&_engine.lfo[1], 2.0); + osc_setfreq(&_engine.lfo[2], 1.0); + _engine.lfo[0].level = 1.0; + _engine.lfo[1].level = 1.0; + _engine.lfo[2].level = 1.0; } void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *right) @@ -47,7 +47,7 @@ void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *r right[pos] = 0.0; for (i = 0; i < NUM_LFO; i++) { - osc_tick(&_engine.osc[i]); + osc_tick(&_engine.lfo[i]); } v = _engine.voice; diff --git a/engine.h b/engine.h index d070059..a2027e7 100644 --- a/engine.h +++ b/engine.h @@ -1,5 +1,4 @@ -#define NUM_LFO 4 #define NUM_POLYPHONY 32 struct engine_t @@ -10,12 +9,12 @@ struct engine_t struct control_t pitchbend; struct control_t aftertouch; - struct control_t osc_shape[4]; - struct control_t osc_level[4]; - int monosynth; - struct osc_t osc[NUM_LFO]; + struct osc_t lfo[NUM_LFO]; + struct voice_param_t params[VOICE_OSCILLATORS]; + struct envelope_t cutoff_env; + struct voice_t voice[NUM_POLYPHONY]; }; diff --git a/env.c b/env.c index 9a0f8b5..3b0dced 100644 --- a/env.c +++ b/env.c @@ -3,9 +3,6 @@ #include "env.h" #include "psyn.h" -struct envelope_t _env; -struct envelope_t _env2; - void env_init(struct envelope_t *env, double attack, double attack_hold, double decay, double sustain, double release) { env->attack = attack; diff --git a/env.h b/env.h index 0064f10..8a7c77f 100644 --- a/env.h +++ b/env.h @@ -15,9 +15,6 @@ struct envelope_t double release_s; }; -extern struct envelope_t _env; -extern struct envelope_t _env2; - void env_init(struct envelope_t *env, double attack, double attack_hold, double decay, double sustain, double release); double env_getamplitude(struct envelope_t *env, uint32_t sample, uint32_t released); diff --git a/osc.h b/osc.h index 245aed0..1d44c5c 100644 --- a/osc.h +++ b/osc.h @@ -3,6 +3,15 @@ extern double _lookup_table[6][LOOKUP_SAMPLES + 1]; +enum { + OSC_SINE, + OSC_SAW, + OSC_TRIANGLE, + OSC_SQUARE, + OSC_MOOGSAW, + OSC_EXP, +}; + struct osc_t { double freq; diff --git a/psyn.c b/psyn.c index ed04cd9..5899b93 100644 --- a/psyn.c +++ b/psyn.c @@ -7,8 +7,9 @@ #include "lv2_uri_map.h" #include "osc.h" #include "filter.h" -#include "voice.h" +#include "env.h" #include "control.h" +#include "voice.h" #include "engine.h" #include "psyn.h" @@ -117,8 +118,8 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count) control_setstep(&_engine.lowpass, *psyn->ctrlLP, sample_count); _engine.monosynth = (int)*psyn->ctrlMono; for (i = 0; i < 4; i++) { - _engine.osc_shape[i].value = *psyn->ctrlOscShape[i]; - _engine.osc_level[i].value = *psyn->ctrlOscLevel[i]; + _engine.params[i].shape.value = *psyn->ctrlOscShape[i]; + _engine.params[i].level.value = *psyn->ctrlOscLevel[i]; } while (frame < sample_count) { diff --git a/voice.c b/voice.c index 7c94f06..4b2dd6c 100644 --- a/voice.c +++ b/voice.c @@ -5,8 +5,8 @@ #include "osc.h" #include "env.h" #include "filter.h" -#include "voice.h" #include "control.h" +#include "voice.h" #include "engine.h" #include "psyn.h" #include "rng.h" @@ -27,18 +27,12 @@ void voice_init(struct voice_t *voice, double freq) // bw_filter_init_lp(&voice->bw[0], _engine.lowpass.value, 1.0); for (i = 0; i < VOICE_OSCILLATORS; i++) { - voice->osc[i].shape = _engine.osc_shape[i].value; - voice->osc[i].level = _engine.osc_level[i].value; - } + voice->osc[i].shape = _engine.params[i].shape.value; + voice->osc[i].level = _engine.params[i].level.value; - osc_setfreq(&voice->osc[0], freq); - osc_setphase(&voice->osc[0], 0.0); - osc_setfreq(&voice->osc[1], freq);// * 1.4983); - osc_setphase(&voice->osc[1], 0.25); - osc_setfreq(&voice->osc[2], freq * 2); - osc_setphase(&voice->osc[2], 0.0); - osc_setfreq(&voice->osc[3], 2500.0); - osc_setphase(&voice->osc[3], 0.0); + osc_setfreq(&voice->osc[i], freq * _engine.params[i].freq_mult.value); + osc_setphase(&voice->osc[i], _engine.params[i].phase.value); + } } static inline void voice_tick(struct voice_t *voice) @@ -54,37 +48,34 @@ static inline void voice_tick(struct voice_t *voice) void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *right) { // uint32_t pos; - double amplitude; - double l; - double r; + int i; + double a[VOICE_OSCILLATORS]; + double l = 0.0; + double r = 0.0; //for (pos = 0; pos < samples; pos++) { voice_tick(voice); - amplitude = env_getamplitude(&_env, voice->sample, voice->released); + double amplitude = 0.0; + for (i = 0; i < VOICE_OSCILLATORS; i++) { + a[i] = env_getamplitude(&_engine.params[i].env, voice->sample, voice->released); + amplitude += a[i]; + a[i] *= voice->velocity; + } if (amplitude <= 0.0001) { voice->playing = false; return; } - amplitude *= voice->velocity; + for (i = 0; i < VOICE_OSCILLATORS; i++) { + float s = osc_getsample(&voice->osc[i]); - float s; - - s = osc_getsample(&voice->osc[0]); - l = amplitude * s;// * (1.0 + rng() * 0.25); - r = amplitude * s;// * (1.0 + rng() * 0.25); + // Mix + l += a[i] * s; + r += a[i] * s; + } - s = osc_getsample(&voice->osc[1]); - l += amplitude * s; - r += amplitude * s; - - s = osc_getsample(&voice->osc[2]); - l += amplitude * s; - r += amplitude * s; - - s = osc_getsample(&_engine.osc[0]); // Amplitude mod // l *= 1.0 + s; // r *= 1.0 + s; @@ -109,7 +100,7 @@ void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *righ double out_l, out_r; - double cutoff = max(env_getamplitude(&_env2, voice->sample, 0), _engine.aftertouch.value) * 8000.0; + double cutoff = max(env_getamplitude(&_engine.cutoff_env, voice->sample, 0), _engine.aftertouch.value) * 8000.0; bw_filter_init_lp(&voice->bw[0], _engine.lowpass.value + cutoff, 1.0); bw_filter_run(&voice->bw[0], l, r, &out_l, &out_r); // filter_run_lp(&voice->fil[0], l, r); diff --git a/voice.h b/voice.h index 334f9c1..e430e57 100644 --- a/voice.h +++ b/voice.h @@ -1,5 +1,29 @@ #define VOICE_OSCILLATORS 4 #define VOICE_FILTERS 2 +#define NUM_LFO 4 + +enum { + PAN_FIXED, + PAN_OSC, + PAN_LFO, +}; + +struct voice_param_t +{ + uint8_t pan_type; + union { + float pan; + uint8_t pan_osc; + uint8_t pan_lfo; + } u; + + struct control_t shape; + struct control_t level; + struct control_t freq_mult; + struct control_t phase; + + struct envelope_t env; +}; struct voice_t { @@ -9,6 +33,7 @@ struct voice_t uint32_t released; double velocity; + struct osc_t osc[VOICE_OSCILLATORS]; //struct filter_t fil[VOICE_FILTERS];