GOAL FOR THIS PATCH: -------------------- This patch would allow the flexibility to set any individual channel to be drum channel, and/or unset them (revert back to melodic channel). --------------------
Add a flag to struct: _fluid_channel_t to indicate it is a drum channel, using int type, with value: 0: melodic channel 1: drum channel Previously all checking for drum channel was hard-coded to compare to the number 9 (i.e. chan == 9). So even with 32, 48, 64 channels, only channel 9 was drum channel. The channels 25, 41, 57 could not handle drums at all, even though each 16 midi channels were showing up as a separate ALSA-Midi port. XG allows multiple drum channels, some use channels 9 and 10 (8, 9 with zero-indexing) and FludSynth could not deal with this previously. GM2 allows 2 drum channels 10 and 11 (9, 10 with zero-indexing). This patch is based on somewhat dated fluidsynth.svn399.20101221 (5 week old) code. Let's hear if this is a reasonable change to the code base, or not. Jimmy ----- Patch starts below: ----- diff -rup fluidsynth.svn399.20101221/src/synth/fluid_chan.c fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_chan.c --- fluidsynth.svn399.20101221/src/synth/fluid_chan.c 2010-12-21 19:02:53.000000000 -0500 +++ fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_chan.c 2011-01-24 12:28:01.000000000 -0500 @@ -52,6 +52,7 @@ new_fluid_channel(fluid_synth_t* synth, chan->synth = synth; chan->channum = num; + chan->is_drum_channel = (9 == num) ? 1 : 0; chan->preset = NULL; chan->tuning = NULL; @@ -68,7 +69,7 @@ fluid_channel_init(fluid_channel_t* chan int prognum, banknum; prognum = 0; - banknum = (chan->channum == 9)? 128 : 0; /* ?? */ + banknum = (chan->is_drum_channel)? 128 : 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 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->is_drum_channel) return; /* ignored */ oldval = chan->sfont_bank_prog; @@ -252,10 +253,8 @@ fluid_channel_set_bank_msb(fluid_channel 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 + chan->is_drum_channel) 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 +262,15 @@ fluid_channel_set_bank_msb(fluid_channel else /* style == FLUID_BANK_STYLE_MMA */ newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7)); chan->sfont_bank_prog = newval; + + /* if style == XG and bankmsb == 127, convert the channel to drum mode. + * How should "newval" above be calculated (same as MMA style) ??? + * Anticipate a progChange after a bankSelect, so not much else to do here */ + if (style == FLUID_BANK_STYLE_XG && (127 == bankmsb)) + { + chan->is_drum_channel = 1; + } + } /* Get SoundFont ID, MIDI bank and/or program. Use NULL to ignore a value. */ diff -rup fluidsynth.svn399.20101221/src/synth/fluid_chan.h fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_chan.h --- fluidsynth.svn399.20101221/src/synth/fluid_chan.h 2010-12-21 19:02:53.000000000 -0500 +++ fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_chan.h 2011-01-25 13:07:49.000000000 -0500 @@ -74,6 +74,21 @@ struct _fluid_channel_t * flag indicating whether the NRPN value is absolute or not. */ char gen_abs[GEN_LAST]; + + /* Drum channel flag, 0 for melodic channel, 1 for drum channel. + * Previously, even for 32, 48, 64 channels only channel 9 can be drum, + * channel 25, 41, 57 were not treated as drum channel at all, even though + * ALSA shows 2, 3, 4 ports (each with 16 midi channels). + * We can optionally initialize channel 25, 41, 57 be GM drum channel if we + * want for each of those 16 midi channels -- need to change channel + * initialization, but may break existing apps unless they explicitly set + * these channels. + * Moreover, GM2 allows 2 drum channels 10 and 11 (9, 10 with zero-indexing). + * Some older XG may use drum channels 9 and 10 (8, 9 with zero-indexing). + * Added at end of structure, hopefully existing apps using this structure may + * still work without having to recompile for the time being. */ + int is_drum_channel; + }; fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num); diff -rup fluidsynth.svn399.20101221/src/synth/fluid_synth.c fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_synth.c --- fluidsynth.svn399.20101221/src/synth/fluid_synth.c 2010-12-21 19:02:53.000000000 -0500 +++ fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_synth.c 2011-01-25 13:12:11.000000000 -0500 @@ -51,7 +51,6 @@ static int fluid_synth_sysex_midi_tuning int len, char *response, int *response_len, int avail_response, int *handled, int dryrun); -static int fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan); static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan); static int fluid_synth_system_reset_LOCAL(fluid_synth_t* synth); static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, @@ -1875,14 +1874,10 @@ fluid_synth_program_change(fluid_synth_t /* 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 - * 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->is_drum_channel) preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum); else preset = fluid_synth_find_preset(synth, banknum, prognum); @@ -1893,7 +1888,7 @@ fluid_synth_program_change(fluid_synth_t subst_prog = prognum; /* Melodic instrument? */ - if (channel->channum != 9 && banknum != DRUM_INST_BANK) + if ((! channel->is_drum_channel) && banknum != DRUM_INST_BANK) { subst_bank = 0; @@ -4990,3 +4985,40 @@ void fluid_synth_api_exit(fluid_synth_t* } } + + +/** + * Set a midi channel to drum mode. + * @param synth FluidSynth instance + * @param chan MIDI channel number (0 to MIDI channel count - 1) + * @return FLUID_OK on success, FLUID_FAILED otherwise + */ +int +fluid_synth_set_drum_channel(fluid_synth_t* synth, int chan) +{ + fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); + + synth->channel[chan]->is_drum_channel = 1; + /* reset channel, or just leave it for prog_change to deal with soundbank ??? */ + + FLUID_API_RETURN(FLUID_OK); +} + + +/** + * Unset a midi channel from drum mode, GM2 allows 2 channels to be drum-channel. + * @param synth FluidSynth instance + * @param chan MIDI channel number (0 to MIDI channel count - 1) + * @return FLUID_OK on success, FLUID_FAILED otherwise + */ +int +fluid_synth_unset_drum_channel(fluid_synth_t* synth, int chan) +{ + fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); + + synth->channel[chan]->is_drum_channel = 0; + + FLUID_API_RETURN(FLUID_OK); +} diff -rup fluidsynth.svn399.20101221/src/synth/fluid_synth.h fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_synth.h --- fluidsynth.svn399.20101221/src/synth/fluid_synth.h 2010-12-21 19:02:53.000000000 -0500 +++ fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_synth.h 2011-01-23 13:42:24.000000000 -0500 @@ -230,4 +230,7 @@ void fluid_synth_api_exit(fluid_synth_t* void fluid_synth_settings(fluid_settings_t* settings); +int fluid_synth_set_drum_channel(fluid_synth_t* synth, int chan); +int fluid_synth_unset_drum_channel(fluid_synth_t* synth, int chan); + #endif /* _FLUID_SYNTH_H */ diff -rup fluidsynth.svn399.20101221/src/synth/fluid_voice.c fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_voice.c --- fluidsynth.svn399.20101221/src/synth/fluid_voice.c 2010-12-21 19:02:53.000000000 -0500 +++ fluidsynth.svn399.20101221.jnDrumChannel/src/synth/fluid_voice.c 2011-01-23 12:19:21.000000000 -0500 @@ -1493,7 +1493,7 @@ fluid_voice_get_overflow_prio(fluid_voic * Then it is very important. * Also skip the released and sustained scores. */ - if (voice->chan == 9){ + if (voice->channel->is_drum_channel){ this_voice_prio += score->percussion; } else if (voice->has_noteoff) { ----- Patch ended above ----- _______________________________________________ fluid-dev mailing list fluid-dev@nongnu.org http://lists.nongnu.org/mailman/listinfo/fluid-dev