mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-01-31 13:40:35 +00:00
(Credit: jimmy) Allow channels to change state between melodic and drum channels
This commit is contained in:
parent
8e11587d4e
commit
d7b9767598
5 changed files with 52 additions and 9 deletions
|
@ -100,6 +100,15 @@ FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t* synth);
|
|||
FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t* synth);
|
||||
|
||||
|
||||
enum fluid_midi_channel_type
|
||||
{
|
||||
CHANNEL_TYPE_MELODIC = 0,
|
||||
CHANNEL_TYPE_DRUM = 1
|
||||
};
|
||||
|
||||
int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type);
|
||||
|
||||
|
||||
/* Low level access */
|
||||
FLUIDSYNTH_API fluid_preset_t* fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan);
|
||||
FLUIDSYNTH_API int fluid_synth_start(fluid_synth_t* synth, unsigned int id,
|
||||
|
|
|
@ -67,8 +67,9 @@ fluid_channel_init(fluid_channel_t* chan)
|
|||
fluid_preset_t *newpreset;
|
||||
int prognum, banknum;
|
||||
|
||||
chan->channel_type = (chan->channum == 9) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
|
||||
prognum = 0;
|
||||
banknum = (chan->channum == 9)? 128 : 0; /* ?? */
|
||||
banknum = (chan->channel_type == CHANNEL_TYPE_DRUM) ? DRUM_INST_BANK : 0;
|
||||
|
||||
chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL
|
||||
| prognum << PROG_SHIFTVAL;
|
||||
|
@ -233,7 +234,7 @@ fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb)
|
|||
style = chan->synth->bank_select;
|
||||
if (style == FLUID_BANK_STYLE_GM ||
|
||||
style == FLUID_BANK_STYLE_GS ||
|
||||
chan->channum == 9) //TODO: ask for channel drum mode, instead of number
|
||||
chan->channel_type == CHANNEL_TYPE_DRUM)
|
||||
return; /* ignored */
|
||||
|
||||
oldval = chan->sfont_bank_prog;
|
||||
|
@ -251,11 +252,19 @@ fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb)
|
|||
int oldval, newval, style;
|
||||
|
||||
style = chan->synth->bank_select;
|
||||
|
||||
if (style == FLUID_BANK_STYLE_XG)
|
||||
{
|
||||
/* XG bank (128*MSB+LSB), save MSB, do drum-channel auto-switch */
|
||||
/* The number "120" was based on several keyboards having drums at 120 - 127,
|
||||
reference: http://lists.nongnu.org/archive/html/fluid-dev/2011-02/msg00003.html */
|
||||
chan->channel_type = (120 <= bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (style == FLUID_BANK_STYLE_GM ||
|
||||
style == FLUID_BANK_STYLE_XG ||
|
||||
chan->channum == 9) //TODO: ask for channel drum mode, instead of number
|
||||
chan->channel_type == CHANNEL_TYPE_DRUM)
|
||||
return; /* ignored */
|
||||
//TODO: if style == XG and bankmsb == 127, convert the channel to drum mode
|
||||
|
||||
oldval = chan->sfont_bank_prog;
|
||||
if (style == FLUID_BANK_STYLE_GS)
|
||||
|
@ -263,6 +272,7 @@ fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb)
|
|||
else /* style == FLUID_BANK_STYLE_MMA */
|
||||
newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7));
|
||||
chan->sfont_bank_prog = newval;
|
||||
|
||||
}
|
||||
|
||||
/* Get SoundFont ID, MIDI bank and/or program. Use NULL to ignore a value. */
|
||||
|
|
|
@ -74,6 +74,10 @@ struct _fluid_channel_t
|
|||
* flag indicating whether the NRPN value is absolute or not.
|
||||
*/
|
||||
char gen_abs[GEN_LAST];
|
||||
|
||||
/* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */
|
||||
int channel_type;
|
||||
|
||||
};
|
||||
|
||||
fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num);
|
||||
|
|
|
@ -1876,13 +1876,13 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
|
|||
/* Special handling of channel 10 (or 9 counting from 0). channel
|
||||
* 10 is the percussion channel.
|
||||
*
|
||||
* FIXME - Shouldn't hard code bank selection for channel 10. I think this
|
||||
* FIXME - I think this
|
||||
* is a hack for MIDI files that do bank changes in GM mode. Proper way to
|
||||
* handle this would probably be to ignore bank changes when in GM mode. - JG
|
||||
*/
|
||||
if (prognum != FLUID_UNSET_PROGRAM)
|
||||
{
|
||||
if (channel->channum == 9)
|
||||
if (channel->channel_type == CHANNEL_TYPE_DRUM)
|
||||
preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum);
|
||||
else preset = fluid_synth_find_preset(synth, banknum, prognum);
|
||||
|
||||
|
@ -1893,7 +1893,7 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
|
|||
subst_prog = prognum;
|
||||
|
||||
/* Melodic instrument? */
|
||||
if (channel->channum != 9 && banknum != DRUM_INST_BANK)
|
||||
if ((channel->channel_type != CHANNEL_TYPE_DRUM) && (DRUM_INST_BANK != banknum))
|
||||
{
|
||||
subst_bank = 0;
|
||||
|
||||
|
@ -4990,3 +4990,23 @@ void fluid_synth_api_exit(fluid_synth_t* synth)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set midi channel type
|
||||
* @param synth FluidSynth instance
|
||||
* @param chan MIDI channel number (0 to MIDI channel count - 1)
|
||||
* @param type CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM
|
||||
* @return FLUID_OK on success, FLUID_FAILED otherwise
|
||||
* @since 1.1.3
|
||||
*/
|
||||
int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type)
|
||||
{
|
||||
fluid_return_val_if_fail ((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
|
||||
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
|
||||
|
||||
synth->channel[chan]->channel_type = type;
|
||||
|
||||
FLUID_API_RETURN(FLUID_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -1493,7 +1493,7 @@ fluid_voice_get_overflow_prio(fluid_voice_t* voice,
|
|||
* Then it is very important.
|
||||
* Also skip the released and sustained scores.
|
||||
*/
|
||||
if (voice->chan == 9){
|
||||
if (voice->channel->channel_type == CHANNEL_TYPE_DRUM){
|
||||
this_voice_prio += score->percussion;
|
||||
}
|
||||
else if (voice->has_noteoff) {
|
||||
|
|
Loading…
Reference in a new issue