From 907ec27a9ee3cb22217d61e045ec36ae164e3ee0 Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 21 Apr 2018 10:28:27 +0200 Subject: [PATCH] optimize away memset/mix if voice is quiet --- src/rvoice/fluid_rvoice.c | 6 +-- src/rvoice/fluid_rvoice.h | 2 +- src/rvoice/fluid_rvoice_mixer.c | 92 +++++++++++++-------------------- 3 files changed, 39 insertions(+), 61 deletions(-) diff --git a/src/rvoice/fluid_rvoice.c b/src/rvoice/fluid_rvoice.c index 0c3e2c03..240591cc 100644 --- a/src/rvoice/fluid_rvoice.c +++ b/src/rvoice/fluid_rvoice.c @@ -425,7 +425,7 @@ get_dest_buf(fluid_rvoice_buffers_t* buffers, int index, */ void fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, - fluid_real_t* dsp_buf, int samplecount, + fluid_real_t* dsp_buf, int start, int samplecount, fluid_real_t** dest_bufs, int dest_bufcount) { int bufcount = buffers->count; @@ -444,7 +444,7 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, multiplication per sample */ next_buf = (i+1 >= bufcount ? NULL : get_dest_buf(buffers, i+1, dest_bufs, dest_bufcount)); if (next_buf && buffers->bufs[i+1].amp == amp) { - for (dsp_i = 0; dsp_i < samplecount; dsp_i++) { + for (dsp_i = start; dsp_i < samplecount; dsp_i++) { fluid_real_t samp = amp * dsp_buf[dsp_i]; buf[dsp_i] += samp; next_buf[dsp_i] += samp; @@ -452,7 +452,7 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, i++; } else { - for (dsp_i = 0; dsp_i < samplecount; dsp_i++) + for (dsp_i = start; dsp_i < samplecount; dsp_i++) buf[dsp_i] += amp * dsp_buf[dsp_i]; } } diff --git a/src/rvoice/fluid_rvoice.h b/src/rvoice/fluid_rvoice.h index 9518be00..5f36a12e 100644 --- a/src/rvoice/fluid_rvoice.h +++ b/src/rvoice/fluid_rvoice.h @@ -165,7 +165,7 @@ struct _fluid_rvoice_t int fluid_rvoice_write(fluid_rvoice_t* voice, fluid_real_t *dsp_buf); void fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, - fluid_real_t* dsp_buf, int samplecount, + fluid_real_t* dsp_buf, int start, int samplecount, fluid_real_t** dest_bufs, int dest_bufcount); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp); diff --git a/src/rvoice/fluid_rvoice_mixer.c b/src/rvoice/fluid_rvoice_mixer.c index 2ac07f90..8378a194 100644 --- a/src/rvoice/fluid_rvoice_mixer.c +++ b/src/rvoice/fluid_rvoice_mixer.c @@ -166,36 +166,6 @@ void fluid_rvoice_mixer_set_finished_voices_callback( } - -/** - * Synthesize one voice and add to buffer. - * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means - * voice has been finished, removed and possibly replaced with another voice. - * @return Number of samples written - */ -static int -fluid_mix_one(fluid_rvoice_t* rvoice, fluid_real_t** bufs, unsigned int bufcount, int blockcount) -{ - int i, result = 0; - - FLUID_DECLARE_VLA(fluid_real_t, local_buf, FLUID_BUFSIZE*blockcount); - - for (i=0; i < blockcount; i++) { - int s = fluid_rvoice_write(rvoice, &local_buf[FLUID_BUFSIZE*i]); - if (s == -1) { - s = FLUID_BUFSIZE; /* Voice is quiet, TODO: optimize away memset/mix */ - FLUID_MEMSET(&local_buf[FLUID_BUFSIZE*i], 0, FLUID_BUFSIZE*sizeof(fluid_real_t)); - } - result += s; - if (s < FLUID_BUFSIZE) { - break; - } - } - fluid_rvoice_buffers_mix(&rvoice->buffers, local_buf, result, bufs, bufcount); - - return result; -} - /** * Glue to get fluid_rvoice_buffers_mix what it wants * Note: Make sure outbufs has 2 * (buf_count + fx_buf_count) elements before calling @@ -257,15 +227,17 @@ fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t* buffers) int i,j; for (i=0; i < buffers->finished_voice_count; i++) { fluid_rvoice_t* v = buffers->finished_voices[i]; - int* av = &buffers->mixer->active_voices; - for (j=0; j < *av; j++) { + int av = buffers->mixer->active_voices; + for (j=0; j < av; j++) { if (v == buffers->mixer->rvoices[j]) { - (*av)--; + av--; /* Pack the array */ - if (j < *av) - buffers->mixer->rvoices[j] = buffers->mixer->rvoices[*av]; + if (j < av) + buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av]; } } + buffers->mixer->active_voices = av; + if (buffers->mixer->remove_voice_callback) buffers->mixer->remove_voice_callback( buffers->mixer->remove_voice_callback_userdata, v); @@ -283,33 +255,39 @@ static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice fluid_mixer_buffer_process_finished_voices(&mixer->buffers); } + +/** + * Synthesize one voice and add to buffer. + * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means + * voice has been finished, removed and possibly replaced with another voice. + */ static FLUID_INLINE void fluid_mixer_buffers_render_one(fluid_mixer_buffers_t* buffers, - fluid_rvoice_t* voice, fluid_real_t** bufs, - unsigned int bufcount) + fluid_rvoice_t* rvoice, fluid_real_t** dest_bufs, + unsigned int dest_bufcount) { - int s = fluid_mix_one(voice, bufs, bufcount, buffers->mixer->current_blockcount); - if (s < buffers->mixer->current_blockcount * FLUID_BUFSIZE) { - fluid_finish_rvoice(buffers, voice); + int blockcount = buffers->mixer->current_blockcount; + int i, result = 0, start = 0; + + FLUID_DECLARE_VLA(fluid_real_t, local_buf, FLUID_BUFSIZE*blockcount); + + for (i=0; i < blockcount; i++) { + int s = fluid_rvoice_write(rvoice, &local_buf[FLUID_BUFSIZE*i]); + if (s == -1) { + start += FLUID_BUFSIZE; + s = FLUID_BUFSIZE; + } + result += s; + if (s < FLUID_BUFSIZE) { + break; + } + } + fluid_rvoice_buffers_mix(&rvoice->buffers, local_buf, start, result-start, dest_bufs, dest_bufcount); + + if (result < buffers->mixer->current_blockcount * FLUID_BUFSIZE) { + fluid_finish_rvoice(buffers, rvoice); } } -/* -static int fluid_mixer_buffers_replace_voice(fluid_mixer_buffers_t* buffers, - fluid_rvoice_t* voice) -{ - int i, retval=0; - int fvc = buffers->finished_voice_count; - for (i=0; i < fvc; i++) - if (buffers->finished_voices[i] == voice) { - fvc--; - if (i < fvc) - buffers->finished_voices[i] = buffers->finished_voices[fvc]; - retval++; - } - fvc = buffers->finished_voice_count; - return retval; -} -*/ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice) {