From 23260bc63572f5941ddb76b0f721074680e5a560 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Wed, 12 Aug 2020 06:11:29 +0000 Subject: [PATCH] - LFO: use common synced phase generator calc sin and cos using math functions git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@723 b431acfa-c32f-4a4a-93f1-934dc6c82436 --- Source/JaySynth.cpp | 2 +- Source/synth/lfo.c | 253 ++++++++++---------------------------------- Source/synth/lfo.h | 26 ++--- 3 files changed, 68 insertions(+), 213 deletions(-) diff --git a/Source/JaySynth.cpp b/Source/JaySynth.cpp index 4dae68d..8a36354 100644 --- a/Source/JaySynth.cpp +++ b/Source/JaySynth.cpp @@ -30,7 +30,7 @@ #ifndef WITH_DEV_SYNCED_LFO #define WITH_DEV_SYNCED_LFO 0 #endif -#define DEV_SYNCED_LFO_FACTOR 2 +#define DEV_SYNCED_LFO_FACTOR 1 //============================================================================== /** A JaySynth that just plays incredible sounds.. */ diff --git a/Source/synth/lfo.c b/Source/synth/lfo.c index a2cb80b..f73aa4e 100644 --- a/Source/synth/lfo.c +++ b/Source/synth/lfo.c @@ -12,21 +12,10 @@ // -------------------------------------------------------------- // internal funcs // -------------------------------------------------------------- -void LFO_set_omega(lfo_t *pObj, synth_float_t omega) -{ - omega = fmin(0.5, fmax(-0.5, omega)); - pObj->b = 2.0 * sin(omega*pi); - pObj->dx = omega; -} - void LFO_freq_update(lfo_t *pObj) { - synth_float_t omega; + pObj->omega = pObj->param[LFO_PARAM2_FREQ]/ pObj->fs; - omega = pObj->param[LFO_PARAM2_FREQ]/ pObj->fs; - - LFO_set_omega(pObj, omega); - if (pObj->param[LFO_PARAM2_DELAY] > 0) { pObj->delay_dx = 1.0/(pObj->fs*pObj->param[LFO_PARAM2_DELAY]); @@ -84,11 +73,6 @@ synth_float_t phase_det(synth_float_t lo, synth_float_t ref) void Sync_init(sync_t *pObj) { - pObj->pFuncObj = NULL; - pObj->funcSyncOnProcess = NULL; - pObj->funcSyncOnGetPhase = NULL; - pObj->funcSyncOnFreqUpdate = NULL; - pObj->phase = 0; pObj->phase_ref = 0; pObj->omega = 0.0; @@ -96,16 +80,6 @@ void Sync_init(sync_t *pObj) pObj->klead = 1.0; pObj->klag = 0.04/200; pObj->phase_update = 0; - pObj->freq_update = 0; - -} - -void Sync_set_callback(sync_t *pObj, void *pFuncObj, SyncOnProcess funcSyncOnProcess, SyncOnGetPhase funcSyncOnGetPhase, SyncOnFreqUpdate funcSyncOnFreqUpdate) -{ - pObj->pFuncObj = pFuncObj; - pObj->funcSyncOnProcess = funcSyncOnProcess; - pObj->funcSyncOnGetPhase = funcSyncOnGetPhase; - pObj->funcSyncOnFreqUpdate = funcSyncOnFreqUpdate; } void Sync_phase_update(sync_t *pObj, synth_float_t phase_ref) @@ -114,164 +88,28 @@ void Sync_phase_update(sync_t *pObj, synth_float_t phase_ref) pObj->phase_update = 1; } -void Sync_process(sync_t *pObj) +sync_result_t Sync_process(sync_t *pObj, synth_float_t omega_base) { + sync_result_t result; + result.phase = Sync_mod(pObj->phase + pObj->omega, 1.0); + result.is_cycle_start = (pObj->phase > result.phase); + pObj->phase = result.phase; + synth_float_t perr = 0; - if (pObj->funcSyncOnProcess) - { - (*pObj->funcSyncOnProcess)(pObj->pFuncObj); - } if (pObj->phase_update) { pObj->phase_update = 0; - if (pObj->funcSyncOnGetPhase) - { - synth_float_t phase = (*pObj->funcSyncOnGetPhase)(pObj->pFuncObj); - perr = phase_det(phase, pObj->phase_ref); - SynthDebug("phase_ref=%f, phase_lo=%f, perr=%f\n", pObj->phase_ref, pObj->phase, perr); - } - } - if (perr != 0 || pObj->freq_update) - { - synth_float_t omega = -(pObj->klag*pObj->accu + pObj->klead*perr); - if (pObj->funcSyncOnFreqUpdate) - { - (*pObj->funcSyncOnFreqUpdate)(pObj->pFuncObj, omega); - } - } - pObj->accu += perr; - pObj->freq_update = perr != 0; -} - -void syncOnProcess(void *pFuncObj) -{ - lfo_t *pObj = (lfo_t*)pFuncObj; - - switch((int)pObj->param[LFO_PARAM2_WAVEFORM]) - { - case LFO_WAVEFORM_SAW: - case LFO_WAVEFORM_SAW_REV: - pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); - break; + perr = phase_det(pObj->phase, pObj->phase_ref); + SynthDebug("phase_ref=%f, phase_lo=%f, perr=%f\n", pObj->phase_ref, pObj->phase, perr); +// SynthDebug("syncOnFreqUpdate(): BPM=%f\n", omega*pObj->fs*60); - case LFO_WAVEFORM_SH_UNI: - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - pObj->sh_sample = Noise_Uniform(&pObj->noise, 1, 0.5); - } - break; - - case LFO_WAVEFORM_SH_GAUSS: - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - do - { - pObj->sh_sample = Noise_Gaussian(&pObj->noise, sqrt(1.f/36), 0.5); - - } while ((pObj->sh_sample < 0) || (pObj->sh_sample > 1.f)); - } - break; - - case LFO_WAVEFORM_SQUARE: - case LFO_WAVEFORM_SQUARE_REV: - pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); - pObj->sqr = (int)(pObj->x < 0.5); - break; - - case LFO_WAVEFORM_SINE: - case LFO_WAVEFORM_SINE_REV: - case LFO_WAVEFORM_COSINE: - case LFO_WAVEFORM_COSINE_REV: - pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1]; - pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0]; - break; - - case LFO_WAVEFORM_TRIANGLE: - case LFO_WAVEFORM_TRIANGLE_REV: - pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); - if (pObj->x < 0.5) - pObj->tri = 2*pObj->x; - else - pObj->tri = 2*(1-pObj->x); - break; - - default: - pObj->sync.phase = Sync_mod(pObj->sync.phase + pObj->sync.omega, 1.0); - break; - } -} - -synth_float_t syncOnGetPhase(void *pFuncObj) -{ - synth_float_t result = 0; - lfo_t *pObj = (lfo_t*)pFuncObj; - - switch((int)pObj->param[LFO_PARAM2_WAVEFORM]) - { - case LFO_WAVEFORM_SAW: - case LFO_WAVEFORM_SAW_REV: - case LFO_WAVEFORM_SH_UNI: - case LFO_WAVEFORM_SH_GAUSS: - case LFO_WAVEFORM_SQUARE: - case LFO_WAVEFORM_SQUARE_REV: - case LFO_WAVEFORM_TRIANGLE: - case LFO_WAVEFORM_TRIANGLE_REV: - result = Sync_mod(pObj->x, 1.0); - break; - - case LFO_WAVEFORM_SINE: - case LFO_WAVEFORM_SINE_REV: - case LFO_WAVEFORM_COSINE: - case LFO_WAVEFORM_COSINE_REV: - result = 0.5 + 0.5*atan2(pObj->y[0], -pObj->y[1])/M_PI; - break; - - default: - result = pObj->sync.phase; - break; } + pObj->omega = omega_base-(pObj->klag*pObj->accu + pObj->klead*perr); + pObj->accu += perr; return result; - } -void syncOnFreqUpdate(void *pFuncObj, synth_float_t omega) -{ - lfo_t *pObj = (lfo_t*)pFuncObj; - - switch((int)pObj->param[LFO_PARAM2_WAVEFORM]) - { - case LFO_WAVEFORM_SAW: - case LFO_WAVEFORM_SAW_REV: - case LFO_WAVEFORM_SH_UNI: - case LFO_WAVEFORM_SH_GAUSS: - case LFO_WAVEFORM_SQUARE: - case LFO_WAVEFORM_SQUARE_REV: - case LFO_WAVEFORM_TRIANGLE: - case LFO_WAVEFORM_TRIANGLE_REV: - pObj->dx = omega; - break; - - case LFO_WAVEFORM_SINE: - case LFO_WAVEFORM_SINE_REV: - case LFO_WAVEFORM_COSINE: - case LFO_WAVEFORM_COSINE_REV: - pObj->b = 2.0 * sin(omega*pi); - break; - - default: - pObj->sync.omega = omega; - break; - } - - SynthDebug("syncOnFreqUpdate(): BPM=%f\n", omega*pObj->fs*60); -} - - // -------------------------------------------------------------- // Exported functions // -------------------------------------------------------------- @@ -302,7 +140,6 @@ void LFO_Init(lfo_t *pObj, synth_float_t fs) Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock()); Sync_init(&pObj->sync); - Sync_set_callback(&pObj->sync, pObj, syncOnProcess, syncOnGetPhase, syncOnFreqUpdate); } void LFO_Free(lfo_t *pObj) @@ -337,9 +174,6 @@ void LFO_SetFS(lfo_t *pObj, synth_float_t fs) void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase) { pObj->a = 0.5; - pObj->y[0] = pObj->a*cos(2*pi*initial_phase); - pObj->y[1] = pObj->a*sin(2*pi*initial_phase); - pObj->x = initial_phase; pObj->out = 0; pObj->sqr = 0; pObj->tri = 0; @@ -433,9 +267,9 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); - in = pObj->x + pObj->offset; + in = sync_result.phase + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -457,9 +291,9 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); - in = (1-pObj->x) + pObj->offset; + in = (1-sync_result.phase) + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -481,8 +315,11 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for S/H for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); - + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + if (sync_result.is_cycle_start) + { + pObj->sh_sample = Noise_Uniform(&pObj->noise, 1, 0.5); + } in = pObj->sh_sample + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; @@ -505,7 +342,15 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for S/H for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + if (sync_result.is_cycle_start) + { + do + { + pObj->sh_sample = Noise_Gaussian(&pObj->noise, sqrt(1.f/36), 0.5); + + } while ((pObj->sh_sample < 0) || (pObj->sh_sample > 1.f)); + } in = pObj->sh_sample + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; @@ -529,9 +374,10 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) { for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + synth_float_t y = sin(2*M_PI*sync_result.phase); - in = pObj->y[1]+pObj->a + pObj->offset; + in = y + pObj->a + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -552,9 +398,10 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) { for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + synth_float_t y = sin(2*M_PI*sync_result.phase); - in = (1-(pObj->y[1]+pObj->a)) + pObj->offset; + in = (1-(y+pObj->a)) + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -575,9 +422,10 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) { for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + synth_float_t y = cos(2*M_PI*sync_result.phase); - in = pObj->y[0]+pObj->a + pObj->offset; + in = y+pObj->a + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -598,9 +446,10 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) { for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + synth_float_t y = cos(2*M_PI*sync_result.phase); - in = (1-(pObj->y[0]+pObj->a)) + pObj->offset; + in = (1-(y+pObj->a)) + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; if (pObj->smooth_is_negative) @@ -622,7 +471,8 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + pObj->sqr = (int)(sync_result.phase < 0.5); in = (synth_float_t)pObj->sqr + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; @@ -646,7 +496,8 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + pObj->sqr = (int)(sync_result.phase < 0.5); in = (1-((synth_float_t)pObj->sqr)) + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; @@ -670,7 +521,11 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + if (sync_result.phase < 0.5) + pObj->tri = 2*sync_result.phase; + else + pObj->tri = 2*(1-sync_result.phase); in = (synth_float_t)pObj->tri + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; @@ -694,7 +549,11 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) // Create phase for (i=i0; i< len; i++) { - Sync_process(&pObj->sync); + sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + if (sync_result.phase < 0.5) + pObj->tri = 2*sync_result.phase; + else + pObj->tri = 2*(1-sync_result.phase); in = (1-((synth_float_t)pObj->tri)) + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; diff --git a/Source/synth/lfo.h b/Source/synth/lfo.h index 21bd598..74d0430 100644 --- a/Source/synth/lfo.h +++ b/Source/synth/lfo.h @@ -40,16 +40,8 @@ enum LFO_NUM_PARAMS }; -typedef void (*SyncOnProcess)(void *pFuncObj); -typedef void (*SyncOnFreqUpdate)(void *pFuncObj, synth_float_t omega); -typedef synth_float_t (*SyncOnGetPhase)(void *pFuncObj); typedef struct _ssync_t { - void *pFuncObj; - SyncOnProcess funcSyncOnProcess; - SyncOnGetPhase funcSyncOnGetPhase; - SyncOnFreqUpdate funcSyncOnFreqUpdate; - synth_float_t phase; synth_float_t phase_ref; synth_float_t omega; @@ -59,10 +51,16 @@ typedef struct _ssync_t synth_float_t accu; int phase_update; - int freq_update; - + } sync_t; +typedef struct _ssync_result_t +{ + synth_float_t phase; + int is_cycle_start; + +} sync_result_t; + #if defined(__cplusplus) extern "C" { #endif @@ -71,10 +69,8 @@ extern "C" { // Exported functions // -------------------------------------------------------------- void Sync_init(sync_t *pObj); -void Sync_set_callback(sync_t *pObj, void *pFuncObj, SyncOnProcess funcSyncOnProcess, SyncOnGetPhase funcSyncOnGetPhase, SyncOnFreqUpdate funcSyncOnFreqUpdate); - void Sync_phase_update(sync_t *pObj, synth_float_t phase_ref); -void Sync_process(sync_t *pObj); +sync_result_t Sync_process(sync_t *pObj, synth_float_t omega_base); synth_float_t Sync_mod(synth_float_t x, synth_float_t y); #if defined(__cplusplus) @@ -86,8 +82,8 @@ synth_float_t Sync_mod(synth_float_t x, synth_float_t y); typedef struct _slfo_t { synth_float_t param[LFO_NUM_PARAMS]; - synth_float_t fs; - synth_float_t a, b, y[2], x, dx, out, sh_sample, tri; + synth_float_t omega, fs; + synth_float_t a, b, out, sh_sample, tri; int freq_update_req, sqr; synth_float_t *pOut; UINT32 bufsize;