- 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
This commit is contained in:
+56
-197
@@ -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;
|
||||
|
||||
+11
-15
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user