Merge pull request #317 from FluidSynth/balance

Add support for balance control (CC 8)
This commit is contained in:
Tom M 2018-02-11 16:15:00 +01:00 committed by GitHub
commit 825216f0b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 98 additions and 13 deletions

View file

@ -100,6 +100,7 @@ enum fluid_gen_type {
* modulator. */
GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */
GEN_CUSTOM_BALANCE, /**< Balance @note Not a real SoundFont generator */
/* non-standard generator for an additional custom high- or low-pass filter */
GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */
GEN_CUSTOM_FILTERQ, /**< Custom filter Q */

View file

@ -118,7 +118,9 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
continue;
}
if (i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB ||
i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB) {
i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB ||
i == BALANCE_MSB || i == BALANCE_LSB
) {
continue;
}
@ -165,6 +167,10 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
fluid_channel_set_cc (chan, PAN_MSB, 64);
fluid_channel_set_cc (chan, PAN_LSB, 0);
/* Balance (MSB & LSB) */
fluid_channel_set_cc (chan, BALANCE_MSB, 64);
fluid_channel_set_cc (chan, BALANCE_LSB, 0);
/* Reverb */
/* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
/* Note: although XG standard specifies the default amount of reverb to

View file

@ -86,6 +86,7 @@ static const fluid_gen_info_t fluid_gen_info[] = {
{ GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f },
{ GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f },
{ GEN_PITCH, 1, 0, 0.0f, 127.0f, 0.0f },
{ GEN_CUSTOM_BALANCE, 1, 0, -960.0f, 960.0f, 0.0f },
{ GEN_CUSTOM_FILTERFC, 1, 2, 0.0f, 22050.0f, 0.0f },
{ GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }
};

View file

@ -172,7 +172,26 @@ fluid_mod_get_source_value(const unsigned char mod_src,
if (mod_flags & FLUID_MOD_CC)
{
val = fluid_channel_get_cc(chan, mod_src);
/* From MIDI Recommended Practice (RP-036) Default Pan Formula:
* "Since MIDI controller values range from 0 to 127, the exact center
* of the range, 63.5, cannot be represented. Therefore, the effective
* range for CC#10 is modified to be 1 to 127, and values 0 and 1 both
* pan hard left. The recommended method is to subtract 1 from the
* value of CC#10, and saturate the result to be non-negative."
*
* We treat the balance control in exactly the same way, as the same
* problem applies here as well.
*/
if (mod_src == PAN_MSB || mod_src == BALANCE_MSB) {
*range = 126;
val = fluid_channel_get_cc(chan, mod_src) - 1;
if (val < 0) {
val = 0;
}
}
else {
val = fluid_channel_get_cc(chan, mod_src);
}
}
else
{
@ -523,6 +542,7 @@ void fluid_dump_modulator(fluid_mod_t * mod){
case GEN_CHORUSSEND: printf("Chorus send"); break;
case GEN_REVERBSEND: printf("Reverb send"); break;
case GEN_PAN: printf("pan"); break;
case GEN_CUSTOM_BALANCE: printf("balance"); break;
case GEN_ATTENUATION: printf("att"); break;
default: printf("dest %i",dest);
}; /* switch dest */

View file

@ -138,6 +138,7 @@ static fluid_mod_t default_expr_mod; /* SF2.01 section 8.4.7 */
static fluid_mod_t default_reverb_mod; /* SF2.01 section 8.4.8 */
static fluid_mod_t default_chorus_mod; /* SF2.01 section 8.4.9 */
static fluid_mod_t default_pitch_bend_mod; /* SF2.01 section 8.4.10 */
static fluid_mod_t custom_balance_mod; /* Non-standard modulator */
/* reverb presets */
@ -405,6 +406,19 @@ fluid_synth_init(void)
);
fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */
fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */
/* Non-standard MIDI continuous controller 8 to channel stereo balance */
fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */
FLUID_MOD_CC /* CC=1 */
| FLUID_MOD_CONCAVE /* type=1 */
| FLUID_MOD_BIPOLAR /* P=1 */
| FLUID_MOD_POSITIVE /* D=0 */
);
fluid_mod_set_source2(&custom_balance_mod, 0, 0);
fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */
/* Amount: 96 dB of attenuation (on the opposite channel) */
fluid_mod_set_amount(&custom_balance_mod, 960.0);
}
static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t* synth)
@ -672,7 +686,7 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD);
fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD);
fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD);
fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD);
/* Create and initialize the Fx unit.*/
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);

View file

@ -545,8 +545,9 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice)
/* GEN_FINETUNE [1] #52 */
GEN_OVERRIDEROOTKEY, /* #58 */
GEN_PITCH, /* --- */
GEN_CUSTOM_BALANCE, /* --- */
GEN_CUSTOM_FILTERFC, /* --- */
GEN_CUSTOM_FILTERQ, /* --- */
GEN_CUSTOM_FILTERQ /* --- */
};
/* When the voice is made ready for the synthesis process, a lot of
@ -696,14 +697,20 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
switch (gen) {
case GEN_PAN:
/* range checking is done in the fluid_pan function */
voice->pan = x;
case GEN_CUSTOM_BALANCE:
/* range checking is done in the fluid_pan and fluid_balance functions */
voice->pan = fluid_voice_gen_value(voice, GEN_PAN);
voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE);
/* left amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(x, 1)));
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0,
fluid_voice_calculate_gain_amplitude(voice,
fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)));
/* right amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(x, 0)));
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1,
fluid_voice_calculate_gain_amplitude(voice,
fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)));
break;
case GEN_ATTENUATION:
@ -1594,8 +1601,10 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain)
}
voice->synth_gain = gain;
left = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 1));
right = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 0));
left = fluid_voice_calculate_gain_amplitude(voice,
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));
reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send);
chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);

View file

@ -92,6 +92,9 @@ struct _fluid_voice_t
/* pan */
fluid_real_t pan;
/* balance */
fluid_real_t balance;
/* reverb */
fluid_real_t reverb_send;

View file

@ -252,15 +252,45 @@ fluid_pan(fluid_real_t c, int left)
if (left) {
c = -c;
}
if (c < -500) {
if (c <= -500) {
return (fluid_real_t) 0.0;
} else if (c > 500) {
} else if (c >= 500) {
return (fluid_real_t) 1.0;
} else {
return fluid_pan_tab[(int) (c + 500)];
}
}
/*
* Return the amount of attenuation based on the balance for the specified
* channel. If balance is negative (turned toward left channel, only the right
* channel is attenuated. If balance is positive, only the left channel is
* attenuated.
*
* @params balance left/right balance, range [-960;960] in absolute centibels
* @return amount of attenuation [0.0;1.0]
*/
fluid_real_t fluid_balance(fluid_real_t balance, int left)
{
/* This is the most common case */
if (balance == 0)
{
return 1.0f;
}
if ((left && balance < 0) || (!left && balance > 0))
{
return 1.0f;
}
if (balance < 0)
{
balance = -balance;
}
return fluid_cb2amp(balance);
}
/*
* fluid_concave
*/

View file

@ -40,6 +40,7 @@ fluid_real_t fluid_tc2sec_release(fluid_real_t tc);
fluid_real_t fluid_act2hz(fluid_real_t c);
fluid_real_t fluid_hz2ct(fluid_real_t c);
fluid_real_t fluid_pan(fluid_real_t c, int left);
fluid_real_t fluid_balance(fluid_real_t balance, int left);
fluid_real_t fluid_concave(fluid_real_t val);
fluid_real_t fluid_convex(fluid_real_t val);