Skip to content

Commit

Permalink
Move envelope gain to IIR filter
Browse files Browse the repository at this point in the history
  • Loading branch information
derselbst committed Feb 22, 2025
1 parent 5cc6db7 commit b17700c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 54 deletions.
28 changes: 18 additions & 10 deletions src/rvoice/fluid_iir_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ fluid_iir_filter_apply_local(fluid_iir_filter_t *iir_filter, fluid_real_t *dsp_b

int fres_incr_count = iir_filter->fres_incr_count;
int q_incr_count = iir_filter->q_incr_count;

fluid_real_t dsp_centernode;
int dsp_i;
fluid_real_t dsp_amp = iir_filter->amp;
fluid_real_t dsp_amp_incr = iir_filter->amp_incr;

/* filter (implement the voice filter according to SoundFont standard) */

Expand All @@ -173,21 +173,30 @@ fluid_iir_filter_apply_local(fluid_iir_filter_t *iir_filter, fluid_real_t *dsp_b
* doesn't change.
*/

for (dsp_i = 0; dsp_i < count; dsp_i++)
for (int dsp_i = 0; dsp_i < count; dsp_i++)
{
/* The filter is implemented in Direct-II form. */
dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
fluid_real_t dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2;
fluid_real_t sample = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1;
dsp_hist2 = dsp_hist1;
dsp_hist1 = dsp_centernode;

dsp_buf[dsp_i] = AMPLIFY ? dsp_amp * sample : sample;
/* Alternatively, it could be implemented in Transposed Direct Form II */
// fluid_real_t dsp_input = dsp_buf[dsp_i];
// dsp_buf[dsp_i] = dsp_b02 * dsp_input + dsp_hist1;
// dsp_hist1 = dsp_b1 * dsp_input - dsp_a1 * dsp_buf[dsp_i] + dsp_hist2;
// dsp_hist2 = dsp_b02 * dsp_input - dsp_a2 * dsp_buf[dsp_i];

if(AMPLIFY)
{
dsp_buf[dsp_i] = dsp_amp * sample;
dsp_amp += dsp_amp_incr;
}
else
{
dsp_buf[dsp_i] = sample;
}

if (fres_incr_count > 0 || q_incr_count > 0)
{
if (fres_incr_count > 0)
Expand Down Expand Up @@ -221,6 +230,7 @@ fluid_iir_filter_apply_local(fluid_iir_filter_t *iir_filter, fluid_real_t *dsp_b

iir_filter->fres_incr_count = fres_incr_count;
iir_filter->q_incr_count = q_incr_count;
iir_filter->amp = dsp_amp;

fluid_check_fpe("voice_filter");
}
Expand All @@ -232,10 +242,8 @@ extern "C" void fluid_iir_filter_apply(fluid_iir_filter_t *resonant_filter,
int count,
fluid_real_t output_rate)
{
if (resonant_custom_filter->type != FLUID_IIR_DISABLED)
{
fluid_iir_filter_apply_local<false>(resonant_custom_filter, dsp_buf, count, output_rate);
}
fluid_iir_filter_apply_local<false>(resonant_custom_filter, dsp_buf, count, output_rate);
// This is the last filter in the chain, the default SF2 filter that always runs. This one must apply the final envelope gain.
fluid_iir_filter_apply_local<true>(resonant_filter, dsp_buf, count, output_rate);
}

Expand Down
7 changes: 6 additions & 1 deletion src/rvoice/fluid_iir_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,19 @@ struct _fluid_iir_filter_t
fluid_real_t last_fres; /* The filter's current (smoothed out) resonance frequency in Hz, which will converge towards its target fres once fres_incr_count has become zero */
fluid_real_t fres_incr; /* The linear increment of fres each sample */
int fres_incr_count; /* The number of samples left for the smoothed last_fres adjustment to complete */

fluid_real_t last_q; /* The filter's current (smoothed) Q-factor (or "bandwidth", or "resonance-friendlyness") on a linear scale. Just like fres, this will converge towards its target Q once q_incr_count has become zero. */
fluid_real_t q_incr; /* The linear increment of q each sample */
int q_incr_count; /* The number of samples left for the smoothed Q adjustment to complete */
#ifdef DBG_FILTER
fluid_real_t target_fres; /* The filter's target fres, that last_fres should converge towards - for debugging only */
fluid_real_t target_q; /* The filter's target Q - for debugging only */
#endif

// the final gain amplifier to be applied by the last filter in the chain, zero for all other filters
fluid_real_t amp; /* current linear amplitude */
fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */

};

typedef struct _fluid_iir_filter_t fluid_iir_filter_t;
Expand Down
3 changes: 0 additions & 3 deletions src/rvoice/fluid_rvoice.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,6 @@ struct _fluid_rvoice_dsp_t

/* Dynamic input to the interpolator below */

fluid_real_t amp; /* current linear amplitude */
fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */

fluid_phase_t phase; /* the phase (current sample offset) of the sample wave */
fluid_real_t phase_incr; /* the phase increment for the next FLUID_BUFSIZE samples */
};
Expand Down
54 changes: 14 additions & 40 deletions src/rvoice/fluid_rvoice_dsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ fluid_rvoice_dsp_interpolate_none_local(fluid_rvoice_t *rvoice, fluid_real_t *FL
fluid_phase_t dsp_phase_incr;
const short int *FLUID_RESTRICT dsp_data = voice->sample->data;
const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned short dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
Expand All @@ -154,12 +152,11 @@ fluid_rvoice_dsp_interpolate_none_local(fluid_rvoice_t *rvoice, fluid_real_t *FL
{
fluid_real_t sample = fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */
dsp_amp += dsp_amp_incr;
}

/* break out if not looping (buffer may not be full) */
Expand All @@ -183,7 +180,6 @@ fluid_rvoice_dsp_interpolate_none_local(fluid_rvoice_t *rvoice, fluid_real_t *FL
}

voice->phase = dsp_phase;
voice->amp = dsp_amp;

return (dsp_i);
}
Expand All @@ -201,8 +197,6 @@ fluid_rvoice_dsp_interpolate_linear_local(fluid_rvoice_t *rvoice, fluid_real_t *
fluid_phase_t dsp_phase_incr;
const short int *FLUID_RESTRICT dsp_data = voice->sample->data;
const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned short dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
Expand Down Expand Up @@ -238,12 +232,11 @@ fluid_rvoice_dsp_interpolate_linear_local(fluid_rvoice_t *rvoice, fluid_real_t *
sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

/* break out if buffer filled */
Expand All @@ -263,12 +256,11 @@ fluid_rvoice_dsp_interpolate_linear_local(fluid_rvoice_t *rvoice, fluid_real_t *
sample = (coeffs[0] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index)
+ coeffs[1] * point);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr; /* increment amplitude */
}

if(!LOOPING)
Expand All @@ -293,7 +285,6 @@ fluid_rvoice_dsp_interpolate_linear_local(fluid_rvoice_t *rvoice, fluid_real_t *
}

voice->phase = dsp_phase;
voice->amp = dsp_amp;

return (dsp_i);
}
Expand All @@ -311,8 +302,6 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
fluid_phase_t dsp_phase_incr;
const short int *FLUID_RESTRICT dsp_data = voice->sample->data;
const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned short dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
Expand Down Expand Up @@ -363,12 +352,11 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

/* interpolate the sequence of sample points */
Expand All @@ -382,12 +370,11 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

/* break out if buffer filled */
Expand All @@ -409,12 +396,11 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[2] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 1)
+ coeffs[3] * end_point1);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

end_index++; /* we're now interpolating the last point */
Expand All @@ -431,12 +417,11 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

if(!LOOPING)
Expand Down Expand Up @@ -467,7 +452,6 @@ fluid_rvoice_dsp_interpolate_4th_order_local(fluid_rvoice_t *rvoice, fluid_real_
}

voice->phase = dsp_phase;
voice->amp = dsp_amp;

return (dsp_i);
}
Expand All @@ -485,8 +469,6 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
fluid_phase_t dsp_phase_incr;
const short int *FLUID_RESTRICT dsp_data = voice->sample->data;
const char *FLUID_RESTRICT dsp_data24 = voice->sample->data24;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned short dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
Expand Down Expand Up @@ -550,12 +532,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

start_index++;
Expand All @@ -574,12 +555,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

start_index++;
Expand All @@ -598,12 +578,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

start_index -= 2; /* set back to original start index */
Expand All @@ -623,12 +602,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 3));

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

/* break out if buffer filled */
Expand All @@ -653,12 +631,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * fluid_rvoice_get_float_sample<IS_24BIT>(dsp_data, dsp_data24, dsp_phase_index + 2)
+ coeffs[6] * end_points[0]);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

end_index++; /* we're now interpolating the 2nd to last point */
Expand All @@ -677,12 +654,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * end_points[0]
+ coeffs[6] * end_points[1]);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

end_index++; /* we're now interpolating the last point */
Expand All @@ -701,12 +677,11 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
+ coeffs[5] * end_points[1]
+ coeffs[6] * end_points[2]);

dsp_buf[dsp_i] = dsp_amp * sample;
dsp_buf[dsp_i] = sample;

/* increment phase and amplitude */
fluid_phase_incr(dsp_phase, dsp_phase_incr);
dsp_phase_index = fluid_phase_index(dsp_phase);
dsp_amp += dsp_amp_incr;
}

if(!LOOPING)
Expand Down Expand Up @@ -743,7 +718,6 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_
fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000);

voice->phase = dsp_phase;
voice->amp = dsp_amp;

return (dsp_i);
}
Expand Down

0 comments on commit b17700c

Please sign in to comment.