Author Topic: Selecting non-bank 0 instruments has stopped working  (Read 175 times)

Wayne McHugh

  • Posts: 91
My BASS/BASSMIDI app, MyMIDI Player, stacks sound fonts and supports non-bank 0 instruments. Years back I had a conversion with Ian about getting the BASS_MIDI_StreamEvent call to set MIDI_EVENT_BANK (non-zero bank) to work, and that was successful.  At some point it has stopped working, and I'm trying to work out why.

There is no MIDI_SYSTEM_GM1 event sent, and BASS_MIDI_StreamEvent is called for MIDI_EVENT_PROGRAM after the BASS_MIDI_BANK call every time.  The bank and program values match those loaded by using BASS_MIDI_FontGetPreset, so the numbers are right.  I've traced the process of trying to activate the non-zero banks, the numbers all match, the calls return true, but the instrument never changes.

My key setup calls are:
BASS_MIDI_StreamCreateFile(0, this->getFilename(), 0, 0, BASS_MIDI_ASYNC | BASS_MIDI_DECAYEND | BASS_SAMPLE_FLOAT, 44100)
BASS_ChannelSetAttribute(chan, BASS_ATTRIB_MIDI_SRC, 2);   // used to be BASS_MIDI_SINCINTER in the BASS_MIDI_StreamCreateFile call, but that also fails
BASS_ChannelSetAttribute(chan, BASS_ATTRIB_MIDI_CHANS, 32); // allocate extra MIDI channels for MIDI stream accessing VSTi (I don't believe this is relevant, as this problem only relates to SF2 soundfonts, not VSTi)

There have been key changes since it worked in my earlier version:
- I've upgraded to the latest BASS and BASSMIDI versions.  Previous versions were BASS 2.4.10 and BASSMIDI 2.4.8 (32 bit).  Now using BASS 2.4.17 and BASSMIDI 2.4.14.9 (64 bit).
- I've moved from 32 bit to 64 bit
- I've built in VSTi support, but I don't believe this is related. With no VSTi plugins activated, therefore no VSTi related calls, the problem still occurs. The exception is the BASS_ChannelSetAttribute(chan, BASS_ATTRIB_MIDI_CHANS, 32) call when creating the stream. Removing that call for testing purposes does not fix the problem.

The problem is, I don't know when or why it stopped working.  All my focus was on implementing VST instruments, and eventually noticed the non-bank 0 instrument changes weren't working.

Any thoughts on what changes could cause the non-bank 0 calls to stop working would be greatly appreciated.

Ian @ un4seen

  • Administrator
  • Posts: 26015
BASS_MIDI_BANK seemed to be working OK in a little test I just did. That was with the latest BASSMIDI build, which you can find here:

   www.un4seen.com/stuff/bassmidi.zip

If you still have the problem with it, please provide an affected soundfont and bank:preset number to investigate. Your BASS_MIDI_StreamSetFonts call(s) too if it's not simply using all banks/presets.

Wayne McHugh

  • Posts: 91
All of the sf2 files I'm working with fail to activate non-bank 0 instruments, including the very common fluidr3_gm.sf2 soundfont, so it has to be what I am doing or not doing.

I have reduced it down to loading just the fluid soundfont, and the problem remains. The call to load the font is ...
midi_font[nFonts2Load].font = BASS_MIDI_FontInit(lpszFilename, 0);
midi_font[nFonts2Load].preset = -1;
midi_font[nFonts2Load].bank = 0;
nFonts2Load++;  // =1
...
BASS_MIDI_StreamSetFonts(chan, midi_font, nFonts2Load); // apply it/them to the stream

I later query for program/bank information ...
for (int nFont = 0; (nFont < nFontsLoaded); nFont++)
{   // have to process each sound font loaded
   if (BASS_MIDI_FontGetInfo(midi_font[nFont].font, &info))   // get the size required
   {
      DWORD *presets = (DWORD*)malloc(info.presets*sizeof(DWORD)); // allocate array for presets
         BASS_MIDI_FontGetPresets(midi_font[nFont].font, presets); // get the presets
      for (a = 0; a < info.presets; a++) {
         DWORD dwInstrument = LOWORD(presets[a]);   // extract preset
         DWORD dwBank = HIWORD(presets[a]); // extract bank number
         ...

I use this data to populate my controls, which then trigger the code which contains (in part)
BASS_MIDI_StreamEvent(chan, getChannel(), MIDI_EVENT_BANK, dwBank); // apply channel BANK setting, must come before MIDI_EVENT_PROGRAM (Bank # as verified in Polyphone soundfont editor)
... (in here I do set other non-program events like volume, reverb, chorus. Making the BANK and PROGRAM calls consecutive makes no difference.)
BASS_MIDI_StreamEvent(chan, getChannel(), MIDI_EVENT_PROGRAM, dwParam); // apply channel PROGRAM setting. must come after MIDI_EVENT_BANK

I've checked the soundfonts in Polyphone Soundfont Editor, and the banks are as expected. I've read back what is loaded and it is all there and correct, and at setting time the values are what they should be. However when I query the active program/bank after a program/bank change is made, I get the correct program but always bank 0.

I've tested the active program/bank immediately after it is set, including leaving a long sleep for execution to complete, in order to eliminate the possibility of other code overwriting with bank 0 without me realising -and it always reports bank 0 is active.

I've simplified it as far as I can without stripping the app, and at every point the data appears exactly as I understand it should be.

Ian @ un4seen

  • Administrator
  • Posts: 26015
As you have BASS_MIDI_ASYNC enabled, one thing to note is that BASS_MIDI_StreamEvent settings won't usually be applied immediately (instead asynchronously), and so you may not get back the same value if you call BASS_MIDI_StreamGetEvent straight after. That shouldn't affect what's heard though. To confirm the problem isn't (or is) related, please try removing the BASS_MIDI_ASYNC flag and see if it still happens then.

Wayne McHugh

  • Posts: 91
I tested it with a 5 second sleep to allow for async processing, assuming async meant it happens in another thread.  I removed BASS_MIDI_ASYNC and it made no difference.

To my surprise (shock) I've discovered that I am able to select non-0 banks for many of my MIDI files, but not for others!!  The ones I was testing on, I cannot.  Many others I can.  Since my processing path is generally common for all these I'm now testing, it remains to work out the reason why this is happening.  I'll update here when I learn more, or if I encounter another mystery I can't resolve.

Wayne McHugh

  • Posts: 91
Confession time: an old discovery you made for me and its fix was somehow lost. The problem was many files I have from an external source send a sysex MIDI_SYSTEM_GM1, hence limiting to bank 0.

Repeating your advice for anyone it helps:

1) When creating the stream for playing ...
midi = BASS_MIDI_StreamCreateFile(...);
system = BASS_MIDI_StreamGetEvent(midi, 0, MIDI_EVENT_SYSTEM);
if (system == MIDI_SYSTEM_GM1)
   BASS_MIDI_StreamEvent(midi, 0, MIDI_EVENT_SYSTEM, MIDI_SYSTEM_DEFAULT);

2) In the filter proc ...
if (event->event == MIDI_EVENT_SYSTEM && event->param == MIDI_SYSTEM_GM1) return FALSE;

... and hey presto, non-bank 0 selections work perfectly!

I am embarrassed at not finding that advice earlier, and scared that I have no memory of that earlier discovery at all!  I don't even remember it now that I looking at it!  :-X