Re: [fluid-dev] invalid instrument/drum selection problem
Hi Josh, I couldn't do much with Stygmorgan and a few styles I wanted to try, using Qsynth/FluidSynth. As a side note, Timidity gives me some wicked distortion/noise on some fast notes and synth-instruments. FluidSynth handles it well with no distortion that I can tell. So I tried the folowing code, it falls back to use default drumset if the requested drumset is not found. It doesn't address other instruments (non-drums) at all, will wait for you patch ;-) Actually if you have a better, or more efficient way for instrument validation, please use that. I'm only hacking it for the drums right now. Keep in mind I don't know much of the code base at all. Best regards, Jimmy - changes in src/fluid_synth.c - /* * fluid_synth_program_change */ int fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum) { fluid_preset_t* preset = NULL; fluid_channel_t* channel; unsigned int banknum; unsigned int sfont_id; unsigned int tmpbank; unsigned int tmpprog; /* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */ /* fluid_mutex_unlock(synth->busy); */ if ((prognum >= 0) && (prognum < FLUID_NUM_PROGRAMS) && (chan >= 0) && (chan < synth->midi_channels)) { channel = synth->channel[chan]; banknum = fluid_channel_get_banknum(channel); /* inform the channel of the new program number */ fluid_channel_set_prognum(channel, prognum); if (synth->verbose) { FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum); } /* special handling of channel 10 (or 9 counting from 0). channel 10 is the percussion channel. */ if (channel->channum == 9) { /* try to search the drum instrument first */ tmpbank = banknum | DRUM_INST_MASK; tmpprog = prognum; preset = fluid_synth_find_preset(synth, tmpbank, tmpprog); /* if that fails try to use specified soundbank */ if (preset == NULL) { tmpbank = banknum; tmpprog = prognum; preset = fluid_synth_find_preset(synth, banknum, prognum); } /* if that fails try to use instrument 0 of specified soundbank */ if (preset == NULL) { tmpbank = banknum; tmpprog = 0; preset = fluid_synth_find_preset(synth, banknum, 0); if (synth->verbose) { if (preset) { FLUID_LOG(FLUID_WARN, "prog\t%d\t%d\t%d requested, no instrument found, substituted with: prog\t%d\t%d\t%d", chan, banknum, prognum, chan, tmpbank, tmpprog); } } } /* if that fails try to use sound bank 128 explicitly, instrument 0 */ if (preset == NULL) { tmpbank = 128; tmpprog = 0; preset = fluid_synth_find_preset(synth, banknum, 0); if (synth->verbose) { if (preset) { FLUID_LOG(FLUID_WARN, "prog\t%d\t%d\t%d requested, no instrument found, substituted with: prog\t%d\t%d\t%d", chan, banknum, prognum, chan, tmpbank, tmpprog); } } } /* if that fails try to use sound bank 0, instrument 0 */ if (preset == NULL) { tmpbank = 0; tmpprog = 0; preset = fluid_synth_find_preset(synth, banknum, 0); if (synth->verbose) { if (preset) { FLUID_LOG(FLUID_WARN, "prog\t%d\t%d\t%d requested, no instrument found, substituted with: prog\t%d\t%d\t%d", chan, banknum, prognum, chan, tmpbank, tmpprog); } } } } else { preset = fluid_synth_find_preset(synth, banknum, prognum); } if (preset) { sfont_id = fluid_sfont_get_id(preset->sfont); fluid_channel_set_sfontnum(channel, sfont_id); fluid_channel_set_preset(channel, preset); } return FLUID_OK; } FLUID_LOG(FLUID_ERR, "Index out of range (chan=%d, prog=%d)", chan, prognum); return FLUID_FAILED; } --- Josh Green <[EMAIL PROTECTED]> wrote: > Hello Jimmy, > > Seems reasonable to me to use the last selected > instrument when an > invalid bank and/or program change is received. > I've added it as ticket > #8: http://fluidsynth.resonance.org/trac/ticket/8 > > I'll try and get to this sometime soon, so that you > can take advantage > of its benefits. Hopefully you don't mind building > from subversion, > until a new release is made. Best regards, > > Josh Green > > > On Thu, 2008-01-03 at 05:16 -0800, jimmy wrote: > > Thanks for the soundfont pointers, I'll try those > > soundfonts. > > > > I still think FluidSynth should "ignores invalid > > request" rather than void the channel. Imagine a > > hardware sound-module, or any hardware > midi-connected > > keyboard that would silent the channel because you > > punch in an instrument number that is "out of > range" > > like 999 if it has only 100 instruments. That > would > > sound really awful, which is what FluidSynth does. > I > > don't think I heard anything that awful on any > > hardware keyboard
Re: [fluid-dev] invalid instrument/drum selection problem
Hi Josh, Below is the changes I tried. It does seem to keep the existing dromset for any invalid drum-bank requests. Also changed the constant DRUM_INST_MASK , which could potentially requires a re-compile of any other programss using this constant. I think the DRUM_INST_MASK should be 128, not a hex number, which I believe might have been change along with 8-bit, 16-bit, 32-bit porting that now breaks some midi drum bank select that needed the 120 offset added in the old 7-bit unsigned int days. FWIW, you could try the current FluidSynth and this patch with the midi files from: geocities.com/timessquare/lair/5396/midipark.html they are not mine, and you don't have to try these. In fact, you should try with other midi files you have to be sure. Jimmy - Patches for drumset validation below, also attached as a file if word-wrapping makes it hard to read - diff -r fluidsynth.svn.20071227/src/fluid_chan.c fluidsynth.test/src/fluid_chan.c 175,176c175,187 < chan->banknum = banknum; < return FLUID_OK; --- > int tmpchan; > unsigned int tmpbanknum; > > if (chan) { > tmpchan = fluid_channel_get_num(chan); > tmpbanknum = banknum; > if ((tmpchan == 9) && (tmpbanknum < DRUM_INST_MASK)) { > tmpbanknum = tmpbanknum | DRUM_INST_MASK; > } > chan->banknum = tmpbanknum; > return FLUID_OK; > } > return FLUID_FAILED; diff -r fluidsynth.svn.20071227/src/fluid_synth.c fluidsynth.test/src/fluid_synth.c 1171a1172 > unsigned int tmpbank; 1175a1177,1178 > > 1180d1182 < banknum = fluid_channel_get_banknum(channel); 1182,1183c1184,1185 < /* inform the channel of the new program number */ < fluid_channel_set_prognum(channel, prognum); --- > banknum = fluid_channel_get_banknum(channel); > preset = fluid_synth_find_preset(synth, banknum, prognum); 1193,1198c1195,1198 < /* try to search the drum instrument first */ < preset = fluid_synth_find_preset(synth, banknum | DRUM_INST_MASK, prognum); < < /* if that fails try to search the melodic instrument */ < if (preset == NULL) { < preset = fluid_synth_find_preset(synth, banknum, prognum); --- > /* try to search the drum instrument, drum bank number starts from 128 (DRUM_INST_MASK) */ > tmpbank = banknum; > if (tmpbank < DRUM_INST_MASK) { > tmpbank = tmpbank | DRUM_INST_MASK; 1199a1200 > preset = fluid_synth_find_preset(synth, tmpbank, prognum); 1205,1207c1206,1214 < sfont_id = preset? fluid_sfont_get_id(preset->sfont) : 0; < fluid_channel_set_sfontnum(channel, sfont_id); < fluid_channel_set_preset(channel, preset); --- > if (preset) { >sfont_id = fluid_sfont_get_id(preset->sfont); >fluid_channel_set_sfontnum(channel, sfont_id); >fluid_channel_set_preset(channel, preset); >fluid_channel_set_prognum(channel, prognum); > } > else { > FLUID_LOG(FLUID_WARN, "Ignoring invalid prog\t%d\t%d\t%d", chan, banknum, prognum); > } 1220a1228,1236 > > fluid_preset_t* preset = NULL; > fluid_preset_t* preset2 = NULL; > fluid_channel_t* channel; > unsigned int tmpbank; > unsigned int tmpprog; > > tmpbank = bank; > 1222c1238,1256 < fluid_channel_set_banknum(synth->channel[chan], bank); --- > channel = synth->channel[chan]; > > if ((channel) && (channel->channum == 9) && (bank < DRUM_INST_MASK)) { > tmpbank = tmpbank + DRUM_INST_MASK; > } > > tmpprog = fluid_channel_get_prognum(channel); > /* See if this bank has a valid instrument at 0 */ > preset = fluid_synth_find_preset(channel->synth, tmpbank, 0); > /* See if this bank has a valid instrument at tmpprog */ > preset2 = fluid_synth_find_preset(channel->synth, tmpbank, tmpprog); > > /* If it seems like a valid band, then change it */ > if ((preset) || (preset2)) { > fluid_channel_set_banknum(synth->channel[chan], tmpbank); > } > else { > FLUID_LOG(FLUID_WARN, "Ignoring invalid bank select (channel=%d,bank=%d)", chan, tmpbank); > } 1270a1305,1306 > FLUID_LOG(FLUID_INFO, "program select --- --- (banknum=%d,preset_num=%d)", bank_num, preset_num); > 1308a1345,1346 > FLUID_LOG(FLUID_INFO, "program select2 --- --- (banknum=%d,preset_num=%d)", bank_num, preset_num); > diff -r fluidsynth.svn.20071227/src/fluid_synth.h fluidsynth.test/src/fluid_synth.h 48c48 < #define DRUM_INST_MASK ((unsigned int)0x8000) --- > #define DRUM_INST_MASK ((unsigned int)128) Looking for last minute shopping deals? Find them fast with Yahoo! Search. http://tools.search.yahoo.com/newsearch/category.php?category=shoppingdiff -r fluidsynth.svn.20071227/src/fluid_chan.c fluidsynth.test/src/fluid_chan.c 175,176c175,187 < chan->banknum = banknum; < return FLUID_OK; --- > int tmpchan; > unsigned int tmpbanknum; > > if (chan) { > tmpchan = fluid_cha
Re: [fluid-dev] invalid instrument/drum selection problem
Hello Jimmy, I did a little research into this issue and found that it is a bit more involved than I had initially thought. I think it would help to start with looking at some example problem MIDI files. Can you point out specific ones which you are having issues with? Reading up on the subject of MIDI bank/program switching I came up with the following information: There are Sysex messages for switching into GM or GS mode. Looking at some of the MIDI files on the web page URL you posted, I found one that had a GS enable message. I'm curious how many MIDI files actually have these. When in GM mode, bank change messages should be ignored altogether. Different banks specify different "flavors" of similar sounds. A sound module should substitute an instrument with the same program number, if it does not have one in the requested bank. I'm not sure yet the best way to handle this in FluidSynth. I think a good start would be to listen for the GM and GS sysex init messages which would modify the behavior accordingly. Also a command line switch for selecting among these different standards manually. GM enable - Initialize all channels except #10 to Program 1 (Grand Piano). Set channel #10 to bank 128:0 Ignore bank change messages. GS enable - Setup channels like for GM Use bank 0 if an invalid bank is selected. Perhaps substituting bank 0 if an invalid bank/program is selected should be the default behavior, but that could cause unexpected behavior if someone isn't using a GM/GS bank. Any thoughts? Best regards, Josh On Sun, 2008-01-06 at 16:53 -0800, jimmy wrote: > Hi Josh, > > Below is the changes I tried. It does seem to keep > the existing dromset for any invalid drum-bank > requests. Also changed the constant DRUM_INST_MASK , > which could potentially requires a re-compile of any > other programss using this constant. I think the > DRUM_INST_MASK should be 128, not a hex number, which > I believe might have been change along with 8-bit, > 16-bit, 32-bit porting that now breaks some midi drum > bank select that needed the 120 offset added in the > old 7-bit unsigned int days. > > FWIW, you could try the current FluidSynth and this > patch with the midi files from: > >geocities.com/timessquare/lair/5396/midipark.html > > they are not mine, and you don't have to try these. > In fact, you should try with other midi files you have > to be sure. > > Jimmy > ___ fluid-dev mailing list fluid-dev@nongnu.org http://lists.nongnu.org/mailman/listinfo/fluid-dev