From b628115092dabafc1c02a066a8c513cb4a7d6050 Mon Sep 17 00:00:00 2001 From: derselbst Date: Wed, 31 Oct 2018 09:23:39 +0100 Subject: [PATCH] optimize rounding and clipping to int16 samples --- src/synth/fluid_synth.c | 90 +++++++++++------------------------------ 1 file changed, 24 insertions(+), 66 deletions(-) diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c index 50028c5f..172abdaf 100644 --- a/src/synth/fluid_synth.c +++ b/src/synth/fluid_synth.c @@ -88,7 +88,7 @@ static void fluid_synth_update_presets(fluid_synth_t *synth); static void fluid_synth_update_gain_LOCAL(fluid_synth_t *synth); static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony); static void init_dither(void); -static FLUID_INLINE int roundi(float x); +static FLUID_INLINE int16_t round_clip_to_i16(float x); static int fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount); static fluid_voice_t *fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth); @@ -3808,17 +3808,28 @@ init_dither(void) } /* A portable replacement for roundf(), seems it may actually be faster too! */ -static FLUID_INLINE int -roundi(float x) +static FLUID_INLINE int16_t +round_clip_to_i16(float x) { + long i; if(x >= 0.0f) { - return (int)(x + 0.5f); + i = (long)(x + 0.5f); + if (FLUID_UNLIKELY(i > 32767)) + { + i = 32767; + } } else { - return (int)(x - 0.5f); + i = (long)(x - 0.5f); + if (FLUID_UNLIKELY(i < -32768)) + { + i = -32768; + } } + + return (int16_t)i; } /** @@ -3847,12 +3858,10 @@ fluid_synth_write_s16(fluid_synth_t *synth, int len, void *rout, int roff, int rincr) { int i, j, k, cur; - signed short *left_out = (signed short *) lout; - signed short *right_out = (signed short *) rout; + int16_t *left_out = lout; + int16_t *right_out = rout; fluid_real_t *left_in; fluid_real_t *right_in; - int left_sample; - int right_sample; double time = fluid_utime(); int di; float cpu_load; @@ -3877,37 +3886,13 @@ fluid_synth_write_s16(fluid_synth_t *synth, int len, cur = 0; } - left_sample = roundi(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]); - right_sample = roundi(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]); + left_out[j] = round_clip_to_i16(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]); + right_out[k] = round_clip_to_i16(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]); if(++di >= DITHER_SIZE) { di = 0; } - - /* digital clipping */ - if(left_sample > 32767) - { - left_sample = 32767; - } - - if(left_sample < -32768) - { - left_sample = -32768; - } - - if(right_sample > 32767) - { - right_sample = 32767; - } - - if(right_sample < -32768) - { - right_sample = -32768; - } - - left_out[j] = (signed short) left_sample; - right_out[k] = (signed short) right_sample; } synth->cur = cur; @@ -3946,47 +3931,20 @@ fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin, void *rout, int roff, int rincr) { int i, j, k; - signed short *left_out = (signed short *) lout; - signed short *right_out = (signed short *) rout; - int left_sample; - int right_sample; + int16_t *left_out = lout; + int16_t *right_out = rout; int di = *dither_index; fluid_profile_ref_var(prof_ref); for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) { - - left_sample = roundi(lin[i] * 32766.0f + rand_table[0][di]); - right_sample = roundi(rin[i] * 32766.0f + rand_table[1][di]); + left_out[j] = round_clip_to_i16(lin[i] * 32766.0f + rand_table[0][di]); + right_out[k] = round_clip_to_i16(rin[i] * 32766.0f + rand_table[1][di]); if(++di >= DITHER_SIZE) { di = 0; } - - /* digital clipping */ - if(left_sample > 32767) - { - left_sample = 32767; - } - - if(left_sample < -32768) - { - left_sample = -32768; - } - - if(right_sample > 32767) - { - right_sample = 32767; - } - - if(right_sample < -32768) - { - right_sample = -32768; - } - - left_out[j] = (signed short) left_sample; - right_out[k] = (signed short) right_sample; } *dither_index = di; /* keep dither buffer continous */