Add support for channel balance control (CC 8)

This commit is contained in:
Marcus Weseloh 2018-01-03 16:49:43 +01:00 committed by Marcus Weseloh
parent f3903d1a2f
commit 8f9b89588a
9 changed files with 81 additions and 11 deletions

View file

@ -99,6 +99,7 @@ enum fluid_gen_type {
* is used, however, as the destination for the default pitch wheel
* modulator. */
GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */
GEN_BALANCE, /**< Balance @note Not a real SoundFont generator */
#ifndef __DOXYGEN__
GEN_LAST /**< @internal Value defines the count of generators (#fluid_gen_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
#endif

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

@ -85,7 +85,8 @@ static const fluid_gen_info_t fluid_gen_info[] = {
{ GEN_SCALETUNE, 0, 1, 0.0f, 1200.0f, 100.0f },
{ 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_PITCH, 1, 0, 0.0f, 127.0f, 0.0f },
{ GEN_BALANCE, 1, 0, -1000.0f, 1000.0f, 0.0f }
};

View file

@ -497,6 +497,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_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 default_balance_mod; /* Non-standard modulator */
/* reverb presets */
static const fluid_revmodel_presets_t revmodel_preset[] = {
@ -408,6 +409,18 @@ 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(&default_balance_mod, BALANCE_MSB, /* Index=8 */
FLUID_MOD_CC /* CC=1 */
| FLUID_MOD_LINEAR /* type=0 */
| FLUID_MOD_BIPOLAR /* P=1 */
| FLUID_MOD_POSITIVE /* D=0 */
);
fluid_mod_set_source2(&default_balance_mod, 0, 0);
fluid_mod_set_dest(&default_balance_mod, GEN_BALANCE); /* Destination: stereo balance */
fluid_mod_set_amount(&default_balance_mod, 1000.0); /* Amount: 1000 tens of a percent */
}
static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t* synth)
@ -694,7 +707,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, &default_balance_mod, FLUID_SYNTH_ADD);
/* Create and initialize the Fx unit.*/
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);

View file

@ -537,7 +537,8 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice)
/* GEN_COARSETUNE [1] #51 */
/* GEN_FINETUNE [1] #52 */
GEN_OVERRIDEROOTKEY, /* #58 */
GEN_PITCH /* --- */
GEN_PITCH, /* --- */
GEN_BALANCE /* --- */
};
/* When the voice is made ready for the synthesis process, a lot of
@ -691,14 +692,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_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_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:
@ -1605,8 +1612,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

@ -301,6 +301,41 @@ fluid_pan(fluid_real_t c, int left)
}
}
/*
* 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 [-1000;1000] in tens of percent
* @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;
}
if (balance >= 1000)
{
return 0.0f;
}
return 1.0f - balance * 0.001f;
}
/*
* fluid_concave
*/

View file

@ -46,6 +46,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);