diff --git a/engine.c b/engine.c index b6288d9..9bc9125 100644 --- a/engine.c +++ b/engine.c @@ -11,29 +11,25 @@ #include "engine.h" #include "psyn.h" -static double _freqs[128]; - -struct engine_t _engine; - -void engine_init() +void engine_init(struct engine_t *engine) { uint32_t i; for (i = 0; i < 128; i++) { - _freqs[i] = 440.0 * pow(2.0, (i - 69.0) / 12.0); + engine->freqs[i] = 440.0 * pow(2.0, (i - 69.0) / 12.0); } osc_init(); - engine_load_program(); + engine_load_program(engine); } -void engine_load_program() +void engine_load_program(struct engine_t *engine) { FILE *f = fopen("program.txt", "r"); while (!feof(f)) { char buf[1024]; - size_t l = fgets(buf, sizeof buf, f); + fgets(buf, sizeof buf, f); if (!strncmp(buf, "voice", 5)) { // Ignore voice @@ -42,8 +38,8 @@ void engine_load_program() float freq; int r = sscanf(buf, "lfo %d %f", &lfo, &freq); if (r >= 2 && lfo >= 0 && lfo < NUM_LFO) { - osc_setfreq(&_engine.lfo[lfo], freq); - _engine.lfo[lfo].level = 1.0; + osc_setfreq(&engine->lfo[lfo], freq); + engine->lfo[lfo].level = 1.0; } } else if (!strncmp(buf, "osc", 3)) { int osc; @@ -61,10 +57,10 @@ void engine_load_program() else if (!strcmp(sshape, "MOOGSAW")) shape = OSC_MOOGSAW; else if (!strcmp(sshape, "EXP")) shape = OSC_EXP; - _engine.params[osc].shape.value = shape; - _engine.params[osc].level.value = level; - _engine.params[osc].freq_mult.value = freq; - _engine.params[osc].phase.value = phase; + engine->params[osc].shape.value = shape; + engine->params[osc].level.value = level; + engine->params[osc].freq_mult.value = freq; + engine->params[osc].phase.value = phase; } } else if (!strncmp(buf, "pan", 3)) { int pan; @@ -75,17 +71,17 @@ void engine_load_program() if (r >= 4 && pan >= 0 && pan <= VOICE_OSCILLATORS) { int source = 0; if (!strcmp(ssource, "FIXED")) { - _engine.params[pan].pan_type = PAN_FIXED; - _engine.params[pan].pan_level = parm1; - _engine.params[pan].pan_level_r = parm2; + engine->params[pan].pan_type = PAN_FIXED; + engine->params[pan].pan_level = parm1; + engine->params[pan].pan_level_r = parm2; } else if (!strcmp(ssource, "OSC")) { - _engine.params[pan].pan_type = PAN_OSC; - _engine.params[pan].pan_source = parm1; - _engine.params[pan].pan_level = parm2; + engine->params[pan].pan_type = PAN_OSC; + engine->params[pan].pan_source = parm1; + engine->params[pan].pan_level = parm2; } else if (!strcmp(ssource, "LFO")) { - _engine.params[pan].pan_type = PAN_LFO; - _engine.params[pan].pan_source = parm1; - _engine.params[pan].pan_level = parm2; + engine->params[pan].pan_type = PAN_LFO; + engine->params[pan].pan_source = parm1; + engine->params[pan].pan_level = parm2; } } } else if (!strncmp(buf, "env", 3)) { @@ -97,7 +93,7 @@ void engine_load_program() float release; int r = sscanf(buf, "env %d %f %f %f %f %f", &env, &attack, &hold, &decay, &sustain, &release); if (r >= 6 && env >= 0 && env < VOICE_OSCILLATORS) { - env_init(&_engine.params[env].env, attack, hold, decay, sustain, release); + env_init(&engine->params[env].env, attack, hold, decay, sustain, release); } } else if (!strncmp(buf, "cutoff_env", 10)) { int env; @@ -108,7 +104,7 @@ void engine_load_program() float release; int r = sscanf(buf, "cutoff_env %d %f %f %f %f %f", &env, &attack, &hold, &decay, &sustain, &release); if (r >= 6 && env >= 0 && env < 1) { - env_init(&_engine.cutoff_env, attack, hold, decay, sustain, release); + env_init(&engine->cutoff_env, attack, hold, decay, sustain, release); } } } @@ -122,20 +118,20 @@ void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *r uint32_t i; for (pos = 0; pos < samples; pos++) { - control_tick(&_engine.lowpass); + control_tick(&engine->lowpass); left[pos] = 0.0; right[pos] = 0.0; for (i = 0; i < NUM_LFO; i++) { - osc_tick(&_engine.lfo[i]); + osc_tick(&engine->lfo[i]); } - v = _engine.voice; + v = engine->voice; for (i = 0; i < NUM_POLYPHONY; i++, v++) { if (!v->playing) continue; - voice_run(v, 1, left + pos, right + pos); + voice_run(v, engine, 1, left + pos, right + pos); } } } @@ -154,7 +150,7 @@ void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity) v->velocity = velocity / 127.0; /* Voice parameters which determine sound */ - voice_init(v, _freqs[note]); + voice_init(v, engine, engine->freqs[note]); return; } @@ -169,7 +165,7 @@ void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity) v->velocity = velocity / 127.0; /* Voice parameters which determine sound */ - voice_init(v, _freqs[note]); + voice_init(v, engine, engine->freqs[note]); return; } diff --git a/engine.h b/engine.h index 94c78f9..db4e410 100644 --- a/engine.h +++ b/engine.h @@ -16,12 +16,12 @@ struct engine_t struct envelope_t cutoff_env; struct voice_t voice[NUM_POLYPHONY]; + + double freqs[128]; }; -extern struct engine_t _engine; - -void engine_init(); -void engine_load_program(); +void engine_init(struct engine_t *engine); +void engine_load_program(struct engine_t *engine); void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *right); void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity); void engine_endvoice(struct engine_t *engine, uint8_t note, uint8_t velocity); diff --git a/env.c b/env.c index d60f6d7..18187a3 100644 --- a/env.c +++ b/env.c @@ -17,7 +17,7 @@ void env_init(struct envelope_t *env, double attack, double attack_hold, double env->release_s = env->release * _sample_rate; } -double env_getamplitude(struct envelope_t *env, uint32_t sample, uint32_t released) +double env_getamplitude(const struct envelope_t *env, uint32_t sample, uint32_t released) { double amplitude; diff --git a/env.h b/env.h index 8a7c77f..69030ca 100644 --- a/env.h +++ b/env.h @@ -16,5 +16,5 @@ struct envelope_t }; 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); +double env_getamplitude(const struct envelope_t *env, uint32_t sample, uint32_t released); diff --git a/osc.h b/osc.h index 1d44c5c..fa9fd47 100644 --- a/osc.h +++ b/osc.h @@ -42,13 +42,13 @@ static inline void osc_tick(struct osc_t *osc) //osc->tri = _tri_table[pos]; } -static inline double osc_getsample(struct osc_t *osc) +static inline double osc_getsample(const struct osc_t *osc) { uint32_t pos = osc->ramp; return _lookup_table[osc->shape][pos] * osc->level; } -static inline double osc_getsamplewithphase(struct osc_t *osc, float phase) +static inline double osc_getsamplewithphase(const struct osc_t *osc, float phase) { double sample = osc->ramp + phase * LOOKUP_SAMPLES; if (sample < 0.0) sample += LOOKUP_SAMPLES; diff --git a/psyn.c b/psyn.c index 96cdcdb..af140fe 100644 --- a/psyn.c +++ b/psyn.c @@ -26,13 +26,15 @@ struct psyn_t float *ctrlLP; float *ctrlOscShape[4]; float *ctrlOscLevel[4]; + + struct engine_t engine; }; static void psyn_init(struct psyn_t *psyn, uint32_t sample_rate) { _sample_rate = sample_rate; - engine_init(); + engine_init(&psyn->engine); } static LV2_Handle instantiate( @@ -107,6 +109,7 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count) { uint8_t i; struct psyn_t *psyn = (struct psyn_t *)lv2instance; + struct engine_t *engine = &psyn->engine; uint32_t frame = 0; LV2_Event *ev = NULL; LV2_Event_Iterator iterator; @@ -115,8 +118,8 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count) if (lv2_event_is_valid(&iterator)) ev = lv2_event_get(&iterator, NULL); - control_setstep(&_engine.lowpass, *psyn->ctrlLP, sample_count); - _engine.monosynth = (int)*psyn->ctrlMono; + control_setstep(&engine->lowpass, *psyn->ctrlLP, sample_count); + engine->monosynth = (int)*psyn->ctrlMono; // for (i = 0; i < 4; i++) { // _engine.params[i].shape.value = *psyn->ctrlOscShape[i]; // _engine.params[i].level.value = *psyn->ctrlOscLevel[i]; @@ -131,7 +134,7 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count) to = sample_count; } - engine_run(&_engine, to - frame, psyn->out_l + frame, psyn->out_r + frame); + engine_run(engine, to - frame, psyn->out_l + frame, psyn->out_r + frame); frame = to; if (ev != NULL) { @@ -142,31 +145,31 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count) switch (data[0] & 0xF0) { case 0x80: - engine_endvoice(&_engine, data[1], data[2]); + engine_endvoice(engine, data[1], data[2]); break; case 0x90: - engine_startvoice(&_engine, data[1], data[2]); + engine_startvoice(engine, data[1], data[2]); break; case 0xA0: - engine_aftertouch(&_engine, data[2]); + engine_aftertouch(engine, data[2]); break; case 0xC0: - engine_programchange(&_engine, data[1]); + engine_programchange(engine, data[1]); break; case 0xB0: - engine_controlchange(&_engine, data[1], data[2]); + engine_controlchange(engine, data[1], data[2]); break; case 0xD0: - engine_aftertouch(&_engine, data[1]); + engine_aftertouch(engine, data[1]); break; case 0xE0: - engine_pitchchange(&_engine, (data[1] | data[2] << 7) - 0x2000); + engine_pitchchange(engine, (data[1] | data[2] << 7) - 0x2000); break; } } diff --git a/voice.c b/voice.c index 179f333..5c8f0e4 100644 --- a/voice.c +++ b/voice.c @@ -16,7 +16,7 @@ static inline double max(double a, double b) return a > b ? a : b; } -void voice_init(struct voice_t *voice, double freq) +void voice_init(struct voice_t *voice, const struct engine_t *engine, double freq) { uint8_t i; // filter_init_rc(&voice->fil[0], 1000.0, 0.000000047); @@ -27,11 +27,11 @@ 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.params[i].shape.value; - voice->osc[i].level = _engine.params[i].level.value; + voice->osc[i].shape = engine->params[i].shape.value; + voice->osc[i].level = engine->params[i].level.value; - osc_setfreq(&voice->osc[i], freq * _engine.params[i].freq_mult.value); - osc_setphase(&voice->osc[i], _engine.params[i].phase.value); + osc_setfreq(&voice->osc[i], freq * engine->params[i].freq_mult.value); + osc_setphase(&voice->osc[i], engine->params[i].phase.value); } } @@ -45,7 +45,7 @@ static inline void voice_tick(struct voice_t *voice) voice->sample++; } -void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *right) +void voice_run(struct voice_t *voice, const struct engine_t *engine, uint32_t samples, float *left, float *right) { // uint32_t pos; int i; @@ -58,7 +58,7 @@ void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *righ double amplitude = 0.0; for (i = 0; i < VOICE_OSCILLATORS; i++) { - a[i] = env_getamplitude(&_engine.params[i].env, voice->sample, voice->released); + a[i] = env_getamplitude(&engine->params[i].env, voice->sample, voice->released); amplitude += a[i]; a[i] *= voice->velocity; } @@ -69,23 +69,24 @@ void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *righ } for (i = 0; i < VOICE_OSCILLATORS; i++) { + const struct voice_param_t *params = &engine->params[i]; float ss; float pl = osc_getsample(&voice->osc[i]); float pr = pl; // Mix - switch (_engine.params[i].pan_type) { + switch (params->pan_type) { case PAN_FIXED: - pl *= _engine.params[i].pan_level; - pr *= _engine.params[i].pan_level_r; + pl *= params->pan_level; + pr *= params->pan_level_r; break; case PAN_OSC: - ss = osc_getsample(&voice->osc[_engine.params[i].pan_source]) * _engine.params[i].pan_level * 0.5; + ss = osc_getsample(&voice->osc[params->pan_source]) * params->pan_level * 0.5; pl *= 0.5 + ss; pr *= 0.5 - ss; break; case PAN_LFO: - ss = osc_getsample(&_engine.lfo[_engine.params[i].pan_source]) * _engine.params[i].pan_level * 0.5; + ss = osc_getsample(&engine->lfo[params->pan_source]) * params->pan_level * 0.5; pl *= 0.5 + ss; pr *= 0.5 - ss; break; @@ -119,8 +120,8 @@ void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *righ double out_l, out_r; - 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); + 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); // filter_run_hp(&voice->fil[1], voice->fil[0].last_out_l, voice->fil[0].last_out_r); diff --git a/voice.h b/voice.h index 44eff7a..8c0e8d3 100644 --- a/voice.h +++ b/voice.h @@ -38,5 +38,7 @@ struct voice_t struct bw_filter_t bw[VOICE_FILTERS]; }; -void voice_init(struct voice_t *voice, double freq); -void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *right); +struct engine_t; + +void voice_init(struct voice_t *voice, const struct engine_t *engine, double freq); +void voice_run(struct voice_t *voice, const struct engine_t *engine, uint32_t samples, float *left, float *right);