diff --git a/src/rvoice/fluid_rvoice.h b/src/rvoice/fluid_rvoice.h index 610afd725..5b13695ab 100644 --- a/src/rvoice/fluid_rvoice.h +++ b/src/rvoice/fluid_rvoice.h @@ -131,9 +131,23 @@ struct _fluid_rvoice_dsp_t fluid_real_t phase_incr; /* the phase increment for the next FLUID_BUFSIZE samples */ }; +#define STEREO_FX + +typedef enum { +DRY_L = 0, +DRY_R, +REV_L, +CHO_L, +#ifdef STEREO_FX +REV_R, +CHO_R, +#endif +RBUF_COUNT +} fluid_rvoice_bufidx_t; + /* Currently left, right, reverb, chorus. To be changed if we ever add surround positioning, or stereo reverb/chorus */ -#define FLUID_RVOICE_MAX_BUFS (4) +#define FLUID_RVOICE_MAX_BUFS (RBUF_COUNT) /* * rvoice mixer-related parameters diff --git a/src/rvoice/fluid_rvoice_mixer.c b/src/rvoice/fluid_rvoice_mixer.c index c1e2fb2e8..cb3479eed 100644 --- a/src/rvoice/fluid_rvoice_mixer.c +++ b/src/rvoice/fluid_rvoice_mixer.c @@ -306,6 +306,24 @@ fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbu ? &base_ptr[(fx_idx + SYNTH_CHORUS_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] : NULL; } + #ifdef STEREO_FX + base_ptr = fluid_align_ptr(buffers->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < buffers->mixer->fx_units; i++) + { + int fx_idx = i * fx_channels_per_unit; + + outbufs[offset + fx_idx + SYNTH_REVERB_CHANNEL + 2] = + (with_reverb) + ? &base_ptr[(fx_idx + SYNTH_REVERB_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] + : NULL; + + outbufs[offset + fx_idx + SYNTH_CHORUS_CHANNEL + 2] = + (with_chorus) + ? &base_ptr[(fx_idx + SYNTH_CHORUS_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] + : NULL; + } + #endif /* The output associated with a MIDI channel is wrapped around * using the number of audio groups as modulo divider. This is @@ -333,7 +351,7 @@ fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbu outbufs[i * 2 + 1] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; } - return offset + buffers->fx_buf_count; + return offset + 2 * buffers->fx_buf_count; } @@ -667,8 +685,13 @@ static void fluid_render_loop_singlethread(fluid_rvoice_mixer_t *mixer, int blockcount) { int i; + #ifdef STEREO_FX FLUID_DECLARE_VLA(fluid_real_t *, bufs, mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); + #else + FLUID_DECLARE_VLA(fluid_real_t *, bufs, + mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2 * 2); // *2 as stereo fx + #endif int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT); @@ -738,7 +761,7 @@ fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *m buffers->fx_left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); buffers->fx_right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); - + if((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL)) { FLUID_LOG(FLUID_ERR, "Out of memory"); @@ -964,9 +987,19 @@ void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer, fluid_real_t *rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); fluid_real_t *chor = rev; + #ifdef STEREO_FX + fluid_real_t *rev_r = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT); + fluid_real_t *chor_r = rev_r; + #endif + rev = &rev[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; chor = &chor[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; + #ifdef STEREO_FX + rev_r = &rev_r[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; + chor_r = &chor_r[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; + #endif + fluid_ladspa_add_host_ports(ladspa_fx, "Main:L", audio_groups, main_l, FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); @@ -975,13 +1008,32 @@ void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer, main_r, FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); - fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:Send", 1, + #ifdef STEREO_FX + fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:SendL", 1, + rev, + FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); + + fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:SendR", 1, + rev_r, + FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); + + fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:SendL", 1, + chor, + FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); + + fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:SendR", 1, + chor_r, + FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); + #else + fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:Send", 1, rev, FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:Send", 1, chor, FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT); + + #endif } } #endif diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c index e827f9ff2..f55cbe8c9 100644 --- a/src/synth/fluid_voice.c +++ b/src/synth/fluid_voice.c @@ -357,12 +357,17 @@ fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample, /* Set up buffer mapping, should be done more flexible in the future. */ i = 2 * channel->synth->audio_groups; i += (voice->chan % channel->synth->effects_groups) * channel->synth->effects_channels; - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 2, i + SYNTH_REVERB_CHANNEL); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 3, i + SYNTH_CHORUS_CHANNEL); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, REV_L, i + SYNTH_REVERB_CHANNEL); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, CHO_L, i + SYNTH_CHORUS_CHANNEL); + + #ifdef STEREO_FX + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, REV_R, i + SYNTH_REVERB_CHANNEL + 2); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, CHO_R, i + SYNTH_CHORUS_CHANNEL + 2); + #endif i = 2 * (voice->chan % channel->synth->audio_groups); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 0, i); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 1, i + 1); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, DRY_L, i); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, DRY_R, i + 1); return FLUID_OK; } @@ -769,12 +774,12 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen) voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE); /* left amp */ - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, DRY_L, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); /* right amp */ - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, DRY_R, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); break; @@ -805,15 +810,29 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen) case GEN_REVERBSEND: /* The generator unit is 'tenths of a percent'. */ voice->reverb_send = x / 1000.0f; - fluid_clip(voice->reverb_send, 0.f, 1.f); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send)); + fluid_clip(voice->reverb_send, 0.f, 1.f); + #ifdef STEREO_FX + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, REV_L, fluid_voice_calculate_gain_amplitude(voice, + voice->reverb_send * fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, REV_R, fluid_voice_calculate_gain_amplitude(voice, + voice->reverb_send * fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); + #else + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, REV_L, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send)); + #endif break; case GEN_CHORUSSEND: /* The generator unit is 'tenths of a percent'. */ voice->chorus_send = x / 1000.0f; fluid_clip(voice->chorus_send, 0.f, 1.f); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send)); + #ifdef STEREO_FX + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, CHO_L, fluid_voice_calculate_gain_amplitude(voice, + voice->chorus_send * fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, CHO_R, fluid_voice_calculate_gain_amplitude(voice, + voice->chorus_send * fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); + #else + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, CHO_L, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send)); + #endif break; case GEN_OVERRIDEROOTKEY: @@ -1848,6 +1867,9 @@ int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t nrpn_value int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain) { fluid_real_t left, right, reverb, chorus; + #ifdef STEREO_FX + fluid_real_t reverb_right, chorus_right; + #endif /* avoid division by zero*/ if(gain < 0.0000001f) @@ -1860,14 +1882,29 @@ int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain) fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)); right = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)); + #ifdef STEREO_FX + reverb = fluid_voice_calculate_gain_amplitude(voice, + voice->reverb_send * fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)); + reverb_right = fluid_voice_calculate_gain_amplitude(voice, + voice->reverb_send * fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)); + chorus = fluid_voice_calculate_gain_amplitude(voice, + voice->chorus_send * fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)); + chorus_right = fluid_voice_calculate_gain_amplitude(voice, + voice->chorus_send * fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)); + #else reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send); chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send); + #endif UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, left); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, right); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, reverb); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, chorus); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, DRY_L, left); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, DRY_R, right); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, REV_L, reverb); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, CHO_L, chorus); + #ifdef STEREO_FX + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, REV_R, reverb_right); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, CHO_R, chorus_right); + #endif return FLUID_OK; }