diff --git a/Source/synth/lfo.c b/Source/synth/lfo.c index ec456aa..c99ddbd 100644 --- a/Source/synth/lfo.c +++ b/Source/synth/lfo.c @@ -14,10 +14,7 @@ // -------------------------------------------------------------- void LFO_set_omega(lfo_t *pObj, synth_float_t omega) { - if (omega < 0.0 || omega > 1.0) - { - return; - } + omega = fmin(0.5, fmax(-0.5, omega)); pObj->b = 2.0 * sin(omega*pi); pObj->dx = omega; } @@ -77,8 +74,21 @@ synth_float_t Sync_mod(synth_float_t x, synth_float_t y) return result; } +synth_float_t phase_det(synth_float_t lo, synth_float_t ref) +{ + lo = Sync_mod(lo - 0.5, 1.0); + synth_float_t perr = Sync_mod(lo - ref, 1.0) - (synth_float_t)0.5; + + return perr; +} + 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; @@ -88,6 +98,14 @@ void Sync_init(sync_t *pObj) pObj->phase_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) { pObj->phase_ref = phase_ref; @@ -98,21 +116,52 @@ int Sync_process(sync_t *pObj) { int do_lfo_update = 0; synth_float_t perr = 0; + if (pObj->funcSyncOnProcess) + { + (*pObj->funcSyncOnProcess)(pObj->pFuncObj); + } if (pObj->phase_update) { - do_lfo_update = 1; pObj->phase_update = 0; - synth_float_t phase_lo = Sync_mod(pObj->phase - 0.5, 1.0); - perr = (synth_float_t)Sync_mod(phase_lo - pObj->phase_ref, 1.0) - (synth_float_t)0.5; - SynthDebug("phase_ref=%f, phase_lo=%f, perr=%f\n", pObj->phase_ref, pObj->phase, perr); + do_lfo_update = 1; + 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 (pObj->funcSyncOnFreqUpdate) + { + (*pObj->funcSyncOnFreqUpdate)(pObj->pFuncObj, pObj->omega); + } } - pObj->phase = Sync_mod(pObj->phase + pObj->omega, 1.0); - pObj->omega = -(pObj->klag*pObj->accu + pObj->klead*perr); pObj->accu += perr; - + pObj->omega = -(pObj->klag*pObj->accu + pObj->klead*perr); + return do_lfo_update; } +void syncOnProcess(void *pFuncObj) +{ + lfo_t *pObj = (lfo_t*)pFuncObj; + pObj->sync.phase = Sync_mod(pObj->sync.phase + pObj->sync.omega, 1.0); +} + +synth_float_t syncOnGetPhase(void *pFuncObj) +{ + lfo_t *pObj = (lfo_t*)pFuncObj; + SynthDebug("syncOnGetPhase()\n"); + + return pObj->sync.phase; +} + +void syncOnFreqUpdate(void *pFuncObj, synth_float_t omega) +{ + lfo_t *pObj = (lfo_t*)pFuncObj; + SynthDebug("syncOnFreqUpdate(): BPM=%f\n", omega*pObj->fs*60); +} + + // -------------------------------------------------------------- // Exported functions // -------------------------------------------------------------- @@ -143,6 +192,7 @@ 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) @@ -276,10 +326,9 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) if (Sync_process(&pObj->sync)) { LFO_set_omega(pObj, pObj->sync.omega); - SynthDebug("BPM=%f\n", pObj->sync.omega*pObj->fs*60); } pObj->x = pObj->sync.phase; - + in = pObj->x + pObj->offset; pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in; out = pObj->out; @@ -289,11 +338,7 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) *(pOut++) = out*pObj->attack_y; pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - } + pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); if (pObj->freq_update_req) { @@ -317,11 +362,7 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) *(pOut++) = out*pObj->attack_y; pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - } + pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); if (pObj->freq_update_req) { @@ -567,11 +608,7 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) else pObj->tri = 2*(1-pObj->x); - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - } + pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); if (pObj->freq_update_req) { @@ -600,11 +637,7 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) else pObj->tri = 2*(1-pObj->x); - pObj->x += pObj->dx; - if (pObj->x >= 1.f) - { - pObj->x -= 1.f; - } + pObj->x = Sync_mod(pObj->x + pObj->dx, 1.0); if (pObj->freq_update_req) { diff --git a/Source/synth/lfo.h b/Source/synth/lfo.h index 9f2f6da..32ab42c 100644 --- a/Source/synth/lfo.h +++ b/Source/synth/lfo.h @@ -40,8 +40,16 @@ 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; @@ -62,6 +70,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); int Sync_process(sync_t *pObj);