diff --git a/Source/synth/lfo.c b/Source/synth/lfo.c index 5ca82cc..c7e4d97 100644 --- a/Source/synth/lfo.c +++ b/Source/synth/lfo.c @@ -147,7 +147,9 @@ void LFO_Init(lfo_t *pObj, synth_float_t fs) pObj->fs = fs; pObj->pOut = NULL; pObj->bufsize = 0; - + pObj->pPhase = NULL; + pObj->pWave = NULL; + pObj->param[LFO_PARAM2_WAVEFORM] = LFO_WAVEFORM_SINE; pObj->param[LFO_PARAM2_FREQ] = 1; pObj->param[LFO_PARAM2_SMOOTH] = 0.001; // seconds @@ -185,10 +187,23 @@ void LFO_SetBufsize(lfo_t *pObj, UINT32 size) pObj->pOut = NULL; + if (pObj->pPhase) + free(pObj->pPhase); + + pObj->pPhase = NULL; + + if (pObj->pWave) + free(pObj->pWave); + + pObj->pWave = NULL; + if (!size) return; pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t)); + pObj->pPhase = (sync_result_t*)malloc(pObj->bufsize*sizeof(sync_result_t)); + pObj->pWave = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t)); + } void LFO_SetFS(lfo_t *pObj, synth_float_t fs) @@ -262,118 +277,68 @@ void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value) synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) { - synth_float_t *pOut, out, in; - UINT32 i, i0; + UINT32 i; - pOut = pObj->pOut; - - // Process Delay + sync_result_t *pPhase = pObj->pPhase; + + // Process Phase and Frequency for (i=0; i< len; i++) { - pObj->delay_x += pObj->delay_dx; - - if (pObj->delay_x >= 1.0) - break; - - in = (synth_float_t)0; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out; - + *(pPhase++) = Sync_process(&pObj->sync, pObj->omega); if (pObj->freq_update_req) { pObj->freq_update_req = 0; LFO_freq_update(pObj); } } - i0 = i; + pPhase = pObj->pPhase; + synth_float_t *pWave = pObj->pWave; + if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SAW) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*sync_result.phase - 1.0; - in = 0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = 0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SAW_REV) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*sync_result.phase - 1.0; - in = -0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = -0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_UNI) { // Create phase for S/H - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); if (sync_result.is_cycle_start) { pObj->sh_sample = Noise_Uniform(&pObj->noise, 1, 0.5); } - in = pObj->sh_sample + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = pObj->sh_sample + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_GAUSS) { // Create phase for S/H - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); if (sync_result.is_cycle_start) { do @@ -383,227 +348,132 @@ synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len) } while ((pObj->sh_sample < 0) || (pObj->sh_sample > 1.f)); } - in = pObj->sh_sample + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = pObj->sh_sample + pObj->offset; } } // Create output if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SINE) { - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = sin(2*M_PI*sync_result.phase); - in = 0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = 0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SINE_REV) { - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = sin(2*M_PI*sync_result.phase); - in = -0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = -0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_COSINE) { - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = cos(2*M_PI*sync_result.phase); - in = 0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = 0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_COSINE_REV) { - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = cos(2*M_PI*sync_result.phase); - in = -0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = -0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SQUARE) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*(synth_float_t)(sync_result.phase < 0.5) - 1.0; - in = 0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = 0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SQUARE_REV) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*(synth_float_t)(sync_result.phase < 0.5) - 1.0; - in = -0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = -0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_TRIANGLE) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*(1-sync_result.phase) - 1.0; if (sync_result.phase < 0.5) { y = 2*sync_result.phase - 1.0; } - in = 0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = 0.5*y + pObj->offset; } } if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_TRIANGLE_REV) { // Create phase - for (i=i0; i< len; i++) + for (i=0; i< len; i++) { - sync_result_t sync_result = Sync_process(&pObj->sync, pObj->omega); + sync_result_t sync_result = *(pPhase++); synth_float_t y = 2*(1-sync_result.phase) - 0.5; if (sync_result.phase < 0.5) { y = 2*sync_result.phase - 0.5; } - in = -0.5*y + pObj->offset; - pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; - out = pObj->smooth_out; - if (pObj->smooth_is_negative) - out = 2*in - pObj->smooth_out; - - *(pOut++) = out*pObj->attack_y; - pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); - - if (pObj->freq_update_req) - { - pObj->freq_update_req = 0; - LFO_freq_update(pObj); - } + *(pWave++) = -0.5*y + pObj->offset; + } } + // Output smoothing and delay + pWave = pObj->pWave; + synth_float_t *pOut = pObj->pOut; + for (i=0; i< len; i++) + { + synth_float_t in = *(pWave++); + pObj->delay_x += pObj->delay_dx; + if (pObj->delay_x < 1.0) + { + in = 0; + } + pObj->smooth_out = pObj->smooth_a*pObj->smooth_out + pObj->smooth_b*in; + synth_float_t out = pObj->smooth_out; + if (pObj->smooth_is_negative) + out = 2*in - pObj->smooth_out; + + *(pOut++) = out*pObj->attack_y; + pObj->attack_y += pObj->attack_a*(1-pObj->attack_y); + + } + return pObj->pOut; } diff --git a/Source/synth/lfo.h b/Source/synth/lfo.h index 4b37513..d8917ea 100644 --- a/Source/synth/lfo.h +++ b/Source/synth/lfo.h @@ -106,6 +106,8 @@ typedef struct _slfo_t synth_float_t delay_x, delay_dx, attack_y, attack_a; synth_float_t offset; sync_t sync; + sync_result_t *pPhase; + synth_float_t *pWave; } lfo_t;