mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-12-11 05:11:33 +00:00
Merge pull request #317 from FluidSynth/balance
Add support for balance control (CC 8)
This commit is contained in:
commit
825216f0b6
9 changed files with 98 additions and 13 deletions
|
@ -100,6 +100,7 @@ enum fluid_gen_type {
|
||||||
* modulator. */
|
* modulator. */
|
||||||
GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */
|
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 */
|
/* non-standard generator for an additional custom high- or low-pass filter */
|
||||||
GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */
|
GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */
|
||||||
GEN_CUSTOM_FILTERQ, /**< Custom filter Q */
|
GEN_CUSTOM_FILTERQ, /**< Custom filter Q */
|
||||||
|
|
|
@ -118,7 +118,9 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB ||
|
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;
|
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_MSB, 64);
|
||||||
fluid_channel_set_cc (chan, PAN_LSB, 0);
|
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 */
|
/* Reverb */
|
||||||
/* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
|
/* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
|
||||||
/* Note: although XG standard specifies the default amount of reverb to
|
/* Note: although XG standard specifies the default amount of reverb to
|
||||||
|
|
|
@ -86,6 +86,7 @@ static const fluid_gen_info_t fluid_gen_info[] = {
|
||||||
{ GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f },
|
{ GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||||
{ GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f },
|
{ GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f },
|
||||||
{ GEN_PITCH, 1, 0, 0.0f, 127.0f, 0.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_FILTERFC, 1, 2, 0.0f, 22050.0f, 0.0f },
|
||||||
{ GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }
|
{ GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }
|
||||||
};
|
};
|
||||||
|
|
|
@ -172,7 +172,26 @@ fluid_mod_get_source_value(const unsigned char mod_src,
|
||||||
|
|
||||||
if (mod_flags & FLUID_MOD_CC)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -523,6 +542,7 @@ void fluid_dump_modulator(fluid_mod_t * mod){
|
||||||
case GEN_CHORUSSEND: printf("Chorus send"); break;
|
case GEN_CHORUSSEND: printf("Chorus send"); break;
|
||||||
case GEN_REVERBSEND: printf("Reverb send"); break;
|
case GEN_REVERBSEND: printf("Reverb send"); break;
|
||||||
case GEN_PAN: printf("pan"); break;
|
case GEN_PAN: printf("pan"); break;
|
||||||
|
case GEN_CUSTOM_BALANCE: printf("balance"); break;
|
||||||
case GEN_ATTENUATION: printf("att"); break;
|
case GEN_ATTENUATION: printf("att"); break;
|
||||||
default: printf("dest %i",dest);
|
default: printf("dest %i",dest);
|
||||||
}; /* switch dest */
|
}; /* switch dest */
|
||||||
|
|
|
@ -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_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_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 default_pitch_bend_mod; /* SF2.01 section 8.4.10 */
|
||||||
|
static fluid_mod_t custom_balance_mod; /* Non-standard modulator */
|
||||||
|
|
||||||
|
|
||||||
/* reverb presets */
|
/* 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_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */
|
||||||
fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */
|
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)
|
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_reverb_mod, FLUID_SYNTH_ADD);
|
||||||
fluid_synth_add_default_mod(synth, &default_chorus_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, &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.*/
|
/* Create and initialize the Fx unit.*/
|
||||||
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
|
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
|
||||||
|
|
|
@ -545,8 +545,9 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice)
|
||||||
/* GEN_FINETUNE [1] #52 */
|
/* GEN_FINETUNE [1] #52 */
|
||||||
GEN_OVERRIDEROOTKEY, /* #58 */
|
GEN_OVERRIDEROOTKEY, /* #58 */
|
||||||
GEN_PITCH, /* --- */
|
GEN_PITCH, /* --- */
|
||||||
|
GEN_CUSTOM_BALANCE, /* --- */
|
||||||
GEN_CUSTOM_FILTERFC, /* --- */
|
GEN_CUSTOM_FILTERFC, /* --- */
|
||||||
GEN_CUSTOM_FILTERQ, /* --- */
|
GEN_CUSTOM_FILTERQ /* --- */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* When the voice is made ready for the synthesis process, a lot of
|
/* 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) {
|
switch (gen) {
|
||||||
|
|
||||||
case GEN_PAN:
|
case GEN_PAN:
|
||||||
/* range checking is done in the fluid_pan function */
|
case GEN_CUSTOM_BALANCE:
|
||||||
voice->pan = x;
|
/* 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 */
|
/* 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 */
|
/* 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;
|
break;
|
||||||
|
|
||||||
case GEN_ATTENUATION:
|
case GEN_ATTENUATION:
|
||||||
|
@ -1594,8 +1601,10 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain)
|
||||||
}
|
}
|
||||||
|
|
||||||
voice->synth_gain = gain;
|
voice->synth_gain = gain;
|
||||||
left = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 1));
|
left = fluid_voice_calculate_gain_amplitude(voice,
|
||||||
right = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 0));
|
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);
|
reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send);
|
||||||
chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);
|
chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,9 @@ struct _fluid_voice_t
|
||||||
/* pan */
|
/* pan */
|
||||||
fluid_real_t pan;
|
fluid_real_t pan;
|
||||||
|
|
||||||
|
/* balance */
|
||||||
|
fluid_real_t balance;
|
||||||
|
|
||||||
/* reverb */
|
/* reverb */
|
||||||
fluid_real_t reverb_send;
|
fluid_real_t reverb_send;
|
||||||
|
|
||||||
|
|
|
@ -252,15 +252,45 @@ fluid_pan(fluid_real_t c, int left)
|
||||||
if (left) {
|
if (left) {
|
||||||
c = -c;
|
c = -c;
|
||||||
}
|
}
|
||||||
if (c < -500) {
|
if (c <= -500) {
|
||||||
return (fluid_real_t) 0.0;
|
return (fluid_real_t) 0.0;
|
||||||
} else if (c > 500) {
|
} else if (c >= 500) {
|
||||||
return (fluid_real_t) 1.0;
|
return (fluid_real_t) 1.0;
|
||||||
} else {
|
} else {
|
||||||
return fluid_pan_tab[(int) (c + 500)];
|
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
|
* fluid_concave
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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_act2hz(fluid_real_t c);
|
||||||
fluid_real_t fluid_hz2ct(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_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_concave(fluid_real_t val);
|
||||||
fluid_real_t fluid_convex(fluid_real_t val);
|
fluid_real_t fluid_convex(fluid_real_t val);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue