From a8961d2d1b76cf4d42152424c7d464d8334c0f3f Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 11 Jan 2025 20:55:21 +0100 Subject: [PATCH] do not read from sample buffer when voice is in delay --- src/rvoice/fluid_rvoice.c | 2 +- src/rvoice/fluid_rvoice.h | 1 + src/rvoice/fluid_rvoice_dsp.cpp | 75 +++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/rvoice/fluid_rvoice.c b/src/rvoice/fluid_rvoice.c index a4bac2869..5738d7410 100644 --- a/src/rvoice/fluid_rvoice.c +++ b/src/rvoice/fluid_rvoice.c @@ -465,7 +465,7 @@ fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf) // // Currently, this does access the sample buffers, which is redundant and could be optimized away. // On the other hand, entering this if-clause is not supposed to happen often. - return fluid_rvoice_dsp_interpolate_none(voice, dsp_buf, is_looping); + return fluid_rvoice_dsp_silence(voice, dsp_buf, is_looping); } switch(voice->dsp.interp_method) diff --git a/src/rvoice/fluid_rvoice.h b/src/rvoice/fluid_rvoice.h index b394f7d55..a2521b308 100644 --- a/src/rvoice/fluid_rvoice.h +++ b/src/rvoice/fluid_rvoice.h @@ -203,6 +203,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample); /* defined in fluid_rvoice_dsp.c */ void fluid_rvoice_dsp_config(void); +int fluid_rvoice_dsp_silence(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping); int fluid_rvoice_dsp_interpolate_none(fluid_rvoice_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); int fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); int fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); diff --git a/src/rvoice/fluid_rvoice_dsp.cpp b/src/rvoice/fluid_rvoice_dsp.cpp index dc5959bf6..8ca8e101e 100644 --- a/src/rvoice/fluid_rvoice_dsp.cpp +++ b/src/rvoice/fluid_rvoice_dsp.cpp @@ -64,6 +64,66 @@ fluid_rvoice_get_float_sample(const short int *FLUID_RESTRICT dsp_msb, const cha return (fluid_real_t)sample; } +/* Special case of interpolate_none for rendering silent voices, i.e. in delay phase or zero volume */ +template +static int fluid_rvoice_dsp_silence_local(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) +{ + fluid_rvoice_dsp_t *voice = &rvoice->dsp; + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr; + 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; + + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float(dsp_phase_incr, voice->phase_incr); + + end_index = LOOPING ? voice->loopend - 1 : voice->end; + + while (1) + { + dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */ + + /* interpolate sequence of sample points */ + for (; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + fluid_real_t sample = 0; + dsp_buf[dsp_i] = sample; + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_amp += dsp_amp_incr; + } + + /* break out if not looping (buffer may not be full) */ + if (!LOOPING) + { + break; + } + + dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */ + /* go back to loop start */ + if (dsp_phase_index > end_index) + { + fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); + voice->has_looped = 1; + } + + /* break out if filled buffer */ + if (dsp_i >= FLUID_BUFSIZE) + { + break; + } + } + + voice->phase = dsp_phase; + voice->amp = dsp_amp; + + return (dsp_i); +} + /* No interpolation. Just take the sample, which is closest to * the playback pointer. Questionable quality, but very * efficient. */ @@ -767,6 +827,15 @@ fluid_rvoice_dsp_interpolate_7th_order_local(fluid_rvoice_t *rvoice, fluid_real_ return (dsp_i); } +struct ProcessSilence +{ + template + int operator()(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf) const + { + return fluid_rvoice_dsp_silence_local(rvoice, dsp_buf); + } +}; + struct InterpolateNone { template @@ -862,6 +931,12 @@ int dsp_invoker(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, in } } +extern "C" int +fluid_rvoice_dsp_silence(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) +{ + return dsp_invoker(rvoice, dsp_buf, looping); +} + extern "C" int fluid_rvoice_dsp_interpolate_none(fluid_rvoice_t *rvoice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) {