From 5f3058f662b7222ea47a49ea2a450aa0491b5496 Mon Sep 17 00:00:00 2001 From: grm Date: Thu, 27 Nov 2025 18:33:13 +0200 Subject: feat: add global lfo index and viz for cutoff lfo --- src/synth_engine.h | 4 +++- src/synth_engine_v2.c | 33 ++++++++++++++++++++++++++------- src/synth_gui.c | 9 +++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/synth_engine.h b/src/synth_engine.h index a29c389..254bf21 100644 --- a/src/synth_engine.h +++ b/src/synth_engine.h @@ -110,6 +110,8 @@ typedef struct { adsr_t adsr; adsr_t f_adsr; + int lfo_on_cutoff; + float lfo_index; lfo_t lfo; int octave; @@ -119,7 +121,7 @@ typedef struct { int deli; cc_t cc_del_time; cc_t cc_del_feedback; - unsigned long long counter; + unsigned long long delay_counter; int f_adsr_enabled; int filter; diff --git a/src/synth_engine_v2.c b/src/synth_engine_v2.c index e15df85..41cbcf4 100644 --- a/src/synth_engine_v2.c +++ b/src/synth_engine_v2.c @@ -147,9 +147,16 @@ do_fliter(synth_t *synth, float *sample, unsigned int sample_rate, int frame) note->noteOffSample); if (adsr < 0.1) adsr = 0.1; cutoff = cutoff * adsr; + reso = reso * adsr; } } + if (synth->lfo_on_cutoff) { + cutoff = cutoff + 22000 * CC_GET(lfo_amp) * osc_sin(synth->lfo_index); + if (cutoff <= 0) cutoff = 0.001; + synth->lfo_index = osc_sin_next(CC_GET(lfo_freq), synth->lfo_index); + } + if (synth->filter) { if (cutoff == 0) cutoff = 0.001; lpf_update(reso, cutoff, sample_rate); @@ -251,6 +258,10 @@ make_sample(synth_t * synth, unsigned int sample_rate, int frame) synth->adsr.d = CC_GET(adsr_d); synth->adsr.s = CC_GET(adsr_s); synth->adsr.r = CC_GET(adsr_r); + + // global lfo + /* float glfo_value = osc_sin(synth->lfo_index); */ + /* synth->lfo_index = osc_sin_next(CC_GET(lfo_freq), synth->lfo_index); */ for (int i = 0; i < synth->midi_active_n; i++) { note = synth->midi_active[i]; @@ -261,7 +272,9 @@ make_sample(synth_t * synth, unsigned int sample_rate, int frame) note->noteOffSample); float targ_freq = note->freq * CC_GET(pitch); - targ_freq = targ_freq + targ_freq * CC_GET(lfo_amp) * osc_sin(note->lfo_index); + float lfo_value = osc_sin(note->lfo_index); + + targ_freq = targ_freq + targ_freq * CC_GET(lfo_amp) * lfo_value; //can switch to glfo note->lfo_index = osc_sin_next(CC_GET(lfo_freq), note->lfo_index); @@ -346,17 +359,18 @@ get_frame(void *outputBuffer, synth_t *synth, int frame) if (!notes_active(synth)) { synth->f_adsr.elapsed = 0; synth->active = 0; + synth->lfo_index = 0.0f; // auto gain test //synth->cc_gain.target = 1; } if (!synth->delay) { - synth->counter = 0; + synth->delay_counter = 0; } sample = make_sample(synth, SAMPLE_RATE, frame); - synth->counter++; - if (synth->counter >= (unsigned long long)(synth->cc_del_time.target * SAMPLE_RATE)) { + synth->delay_counter++; + if (synth->delay_counter >= (unsigned long long)(synth->cc_del_time.target * SAMPLE_RATE)) { int idx = (synth->deli - (int)(synth->cc_del_time.target * SAMPLE_RATE)) % (SAMPLE_RATE * 10); float tmp; if (idx >= 0) { @@ -545,6 +559,9 @@ init_synth(void) synth->f_adsr.r = 0.4; synth->f_adsr.elapsed = 0; + synth->lfo_on_cutoff = 0; + synth->lfo_index = 0.0f; + synth->lfo.freq = 1.0f; synth->lfo.amp = 0.0f; synth->lfo.elapsed = 0; @@ -569,11 +586,11 @@ init_synth(void) synth->delay = 0; synth->del = (float *) calloc(sizeof(float), SAMPLE_RATE * 30); synth->deli = 0; - synth->counter = 0; + synth->delay_counter = 0; synth->f_adsr_enabled = 0; - synth->filter = 1; - synth->biquad = 0; + synth->filter = 0; + synth->biquad = 1; synth->biquad_type = 'l'; synth->clamp = 1; @@ -654,6 +671,8 @@ free_synth(synth_t * synth) free(synth->del); + lpf_close(); + if (synth->patch_name) free(synth->patch_name); free(synth); } diff --git a/src/synth_gui.c b/src/synth_gui.c index db37bf7..4cdf37d 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -1234,6 +1234,15 @@ draw_main(synth_t *synth) draw_cc_circle(&synth->cc_f_adsr_r, 30 + (30 + foffset) * fb++, 260, 30, 30); draw_cc_hbar(&synth->cc_cutoff, 30, 300, 256, 24); + synth->lfo_on_cutoff = GuiCheckBox((Rectangle){30 + 256 + 6, 300, 12, 24}, + "lfo", synth->lfo_on_cutoff); + if (synth->lfo_on_cutoff) { + float cutoff = synth->cc_cutoff.target; + cutoff = cutoff + 22000 * synth->cc_lfo_amp.target * osc_sin(synth->lfo_index); + if (cutoff <= 0) cutoff = 0.001; + + generic_hbar(cutoff, 50, synth->cc_cutoff.min, synth->cc_cutoff.max, 30, 300, 256, 24); + } draw_cc_vbar(&synth->cc_resonance, 330, 20, 24, 256); //draw_cc_vbar(&synth->cc_adsr_s, 30, 250, 30, 30); -- cgit v1.2.3