diff --git a/fluidsynth/include/fluidsynth/synth.h b/fluidsynth/include/fluidsynth/synth.h index 0e7dec7..94b06d2 100644 --- a/fluidsynth/include/fluidsynth/synth.h +++ b/fluidsynth/include/fluidsynth/synth.h @@ -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, diff --git a/fluidsynth/src/synth/fluid_chan.c b/fluidsynth/src/synth/fluid_chan.c index 50850e7..235a16a 100644 --- a/fluidsynth/src/synth/fluid_chan.c +++ b/fluidsynth/src/synth/fluid_chan.c @@ -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; @@ -231,9 +232,9 @@ fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb) int oldval, newval, style; 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 + if (FLUID_BANK_STYLE_GM == style || + FLUID_BANK_STYLE_GS == style || + chan->channel_type == CHANNEL_TYPE_DRUM) return; /* ignored */ oldval = chan->sfont_bank_prog; @@ -251,11 +252,10 @@ 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_GM || - style == FLUID_BANK_STYLE_XG || - chan->channum == 9) //TODO: ask for channel drum mode, instead of number + if (FLUID_BANK_STYLE_GM == style || + FLUID_BANK_STYLE_XG == style || + 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 +263,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. */ diff --git a/fluidsynth/src/synth/fluid_chan.h b/fluidsynth/src/synth/fluid_chan.h index 879dc6f..38caf8f 100644 --- a/fluidsynth/src/synth/fluid_chan.h +++ b/fluidsynth/src/synth/fluid_chan.h @@ -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); diff --git a/fluidsynth/src/synth/fluid_synth.c b/fluidsynth/src/synth/fluid_synth.c index d583154..b134704 100644 --- a/fluidsynth/src/synth/fluid_synth.c +++ b/fluidsynth/src/synth/fluid_synth.c @@ -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); +} + diff --git a/fluidsynth/src/synth/fluid_voice.c b/fluidsynth/src/synth/fluid_voice.c index f6e773c..7d7e49c 100644 --- a/fluidsynth/src/synth/fluid_voice.c +++ b/fluidsynth/src/synth/fluid_voice.c @@ -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) {