Re: [fluid-dev] invalid instrument/drum selection problem

2008-01-06 Thread jimmy
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

2008-01-06 Thread jimmy
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

2008-01-06 Thread Josh Green
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