Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support stereo fx send to LADSPA #1170

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/rvoice/fluid_rvoice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
58 changes: 55 additions & 3 deletions src/rvoice/fluid_rvoice_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}


Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
63 changes: 50 additions & 13 deletions src/synth/fluid_voice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down