[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[fluid-dev] Propose changes for drum channels support
From: |
jimmy |
Subject: |
[fluid-dev] Propose changes for drum channels support |
Date: |
Tue, 25 Jan 2011 15:25:14 -0800 (PST) |
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] Propose changes for drum channels support,
jimmy <=
- Re: [fluid-dev] Propose changes for drum channels support, Matt Giuca, 2011/01/25
- Re: [fluid-dev] Propose changes for drum channels support, jimmy, 2011/01/26
- Re: [fluid-dev] Propose changes for drum channels support, Matt Giuca, 2011/01/26
- Re: [fluid-dev] Propose changes for drum channels support, jimmy, 2011/01/28
- Re: [fluid-dev] Propose changes for drum channels support, Matt Giuca, 2011/01/28
- Re: [fluid-dev] Propose changes for drum channels support, jimmy, 2011/01/28
- Re: [fluid-dev] Propose changes for drum channels support, Matt Giuca, 2011/01/28
Re: [fluid-dev] Propose changes for drum channels support, David Henningsson, 2011/01/26