Author Topic: Determining what MIDI channels are drum channels  (Read 398 times)

Wayne McHugh

  • Posts: 100
I am in the process of adding support for drum kits on multiple channels.  It works in my app, which is to say it works on stream and playing side of BASSMIDI, once the MIDI_EVENT_DRUMS event has been sent to the stream.  My trouble is in detecting it from the MIDI file itself.  I see that setting drum channels is done differently for GM/2, GS and XG. In this forum I've also explanations of the different ways they are encoded, however I don't feel confident to code all those detections.  Could a way be created in BASSMIDI to query which channels in a MIDI stream are drum channels, where the query takes into account all the ways it might be encoded?  The question does keep resurfacing, and a comprehensive BASSMIDI query would be very neat.

My technique: In Cakewalk I create a MIDI file and set channel 5 to being drums.  I save the MIDI file, close Cakewalk, reopen Cakewalk and the MIDI file.  It correctly sets channel 5 to a drum kit.  I therefore deduce that it is being encoded in the MIDI file.  I look at the MIDI file in a MIDI analyzer, and I see nothing among SYSEX or channel events that suggest declaring the channel to be a drum kit. In BASSMIDI query for MIDI_EVENT_DRUMS events, and there are none (I didn't expect there would be).  However I'm in the dark what to test for, and in any case it is only this one MIDI file that I created this one way.  If there was an "intelligent" query in BASSMIDI that knew all the techniques and correctly identified drum channels, it would make it clean on the user end.

Just asking - thanks.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #1 on: 28 Oct '24 - 10:16 »
Hi,
This capability is already present in Bassmidi.
Similarly to the way you can set you can also query the current value of MIDI_EVENT_DRUMS on a channel. This works regardless it is set by you or a Midi file.
Code: [Select]
isDrumChannel = BASS_MIDI_StreamGetEvent(midistream, channel, MIDI_EVENT_DRUMS);
« Last Edit: 28 Oct '24 - 10:21 by Falcosoft »

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #2 on: 28 Oct '24 - 10:19 »
As I tried to explain, that is exactly how I'm testing for drum channels, but it is returning 0 events.  Yet that same MIDI file loads into Cakewalk and correctly loads channels 4 and 10 as drums.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #3 on: 28 Oct '24 - 10:21 »
As I tried to explain, that is exactly how I'm testing for drum channels, but it is returning 0 events.  Yet that same MIDI file loads into Cakewalk and correctly loads channels 4 and 10 as drums.
I have just tested and for me it works perfectly even if a Drum channel is set by a GS SysEx message or Bank MSB 127/120 in XG/GM2 Midi files.
I do not know other ways that is recognized by BassMidi to set a channel to be a drum channel.
Be aware that setting drum channel by Bank MSB is Midi system dependent. That is Bank MSB 127 only means a drum channel in XG mode. The same is true for Bank MSB 120 and GM2 mode.

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #4 on: 28 Oct '24 - 10:27 »
There is a minor difference between your code and mine - I've used

BASS_MIDI_StreamGetEvents(chan, -1, MIDI_EVENT_DRUMS, NULL);

... and would extract the channel from the events returned, if it returned anything.  Is there a reason it has to be done one channel at a time?

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #5 on: 28 Oct '24 - 10:35 »
I changed my code over to testing each channel, as suggested by Falcosoft, and there is a different outcome.  It test positive for channel 9 (ie channel 10), the standard drum channel.  However it does not test positive for the extra drum channel.

Curious that the result is different, and unfortunate it didn't get it right.  Maybe the means I'm using to set the extra drum channel in Cakewalk isn't the "correct" way, and therefore is only recognised by Cakewalk.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #6 on: 28 Oct '24 - 10:39 »
There is a minor difference between your code and mine - I've used

BASS_MIDI_StreamGetEvents(chan, -1, MIDI_EVENT_DRUMS, NULL);

... and would extract the channel from the events returned, if it returned anything.  Is there a reason it has to be done one channel at a time?

AFAIK, BASS_MIDI_StreamGetEvents has a track context while BASS_MIDI_StreamGetEvent has a channel context. That is the 2nd paramater has different meaning (track vs. channel).
I do not know if BASS_MIDI_StreamGetEvents() gets back such "virtual" events like MIDI_EVENT_DRUMS or not.
But it is sure that "drum channel" only has precise meaning in the context of channels not tracks. 
E.g. In casae of a Type 0 Midi file (typical for early XG files form Yamaha) all the messages can be found on a single track but that single track can contain messages for all 16 channels.
So in the above case you cannot tell if track 0 is a drum track or not. But you can always tell if channel 0 is a drum channel or not.

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #7 on: 28 Oct '24 - 10:46 »
Thanks Falcosoft, that is a helpful distinction.  Yet BASS_MIDI_StreamGetEvent is not recognising my extra drum channel  - only the standard drum channel.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #8 on: 28 Oct '24 - 10:51 »
Thanks Falcosoft, that is a helpful distinction.  Yet BASS_MIDI_StreamGetEvent is not recognising my extra drum channel  - only the standard drum channel.
How exactly have you set your channel to be a drum channel in Cakewalk? As I said above only GS SysEx messages and Bank MSB 127/120 work in Bassmidi.
GS SysEx messages look like this:
F0 41 10 42 12 40 1F 15 02 0A F7 - set Channel 16 to be a drum channel

@Edit:
You should attach your Cakewalk modified Midi file so I can have a look at it.
« Last Edit: 28 Oct '24 - 11:31 by Falcosoft »

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #9 on: 28 Oct '24 - 11:32 »
Cakewalk: For a channel, you get to set channel, preset and program.  Channel=5, preset=15360-Preset Rhythm, and Program=Orchestra set.  This is the only way I've been able to find to create the drum channel.  Despite searching online for help on finding the technique for viewing and editing sysex data or banks, I have not been able to locate it.  Nor have I been able to locate a specification to help understand the sysex codes required.

I've seen:
For channel 9:   F0 41 10 42 12 40 19 15 02 10 F7
For channel 11: F0 41 10 42 12 40 1A 15 02 0F F7
and now:
For channel 16: F0 41 10 42 12 40 1F 15 02 0A F7

From which I deduce the LSB of the 7th word is the channel, but not divine what the 2nd last word is.  I confess in this space I'm simply trying to learn what I need to achieve this outcome.  I'm a newcomer to these corners of MIDI and Cakewalk.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #10 on: 28 Oct '24 - 11:52 »
Cakewalk: For a channel, you get to set channel, preset and program.  Channel=5, preset=15360-Preset Rhythm, and Program=Orchestra set.  This is the only way I've been able to find to create the drum channel.  Despite searching online for help on finding the technique for viewing and editing sysex data or banks, I have not been able to locate it.  Nor have I been able to locate a specification to help understand the sysex codes required.

I've seen:
For channel 9:   F0 41 10 42 12 40 19 15 02 10 F7
For channel 11: F0 41 10 42 12 40 1A 15 02 0F F7
and now:
For channel 16: F0 41 10 42 12 40 1F 15 02 0A F7

From which I deduce the LSB of the 7th word is the channel, but not divine what the 2nd last word is.  I confess in this space I'm simply trying to learn what I need to achieve this outcome.  I'm a newcomer to these corners of MIDI and Cakewalk.

Hi,
15360 means that you set Bank MSB to 120 (15360 / 128 = 120). That is Cakewalk used the GM2 metod to set the channel to be a drum channel. As I said above be aware that this method only works with Bassmidi if you set it explicitly to GM2 mode (the default is GS like). Check if Cakewalk has put a GM2 reset at the beginning of the Midi file (F0 7E 7F 09 03 F7). If it has then you do not have to do anything.
Else you have to insert the GM2 reset SysEx manually into the beginning of the Midi file or you have to send MIDI_SYSTEM_GM2 event with Bassmidi (right at the beginning).
Then BASS_MIDI_StreamGetEvent(midistream, 5, MIDI_EVENT_DRUMS) should return true during playback.
This should happen after the Midi file has already sent the Bank MSB 120 + Program Orchestra messages. Notice that unitil this happens the channel is not considered to be a drum channel by Bassmidi.

« Last Edit: 28 Oct '24 - 12:00 by Falcosoft »

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #11 on: 28 Oct '24 - 12:04 »
I have added

Code: [Select]
BASS_MIDI_StreamEvent(chan_temp, -1, MIDI_EVENT_SYSTEMEX, MIDI_SYSTEM_GM2);

immediately after I create the stream, but it makes no difference. Only channel 10 reports true for drums.  I'll have to take it up again tomorrow.

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #12 on: 28 Oct '24 - 12:26 »
I have added

Code: [Select]
BASS_MIDI_StreamEvent(chan_temp, -1, MIDI_EVENT_SYSTEMEX, MIDI_SYSTEM_GM2);

immediately after I create the stream, but it makes no difference. Only channel 10 reports true for drums.  I'll have to take it up again tomorrow.

As I have written above you should wait calling the drum status query until the corresponding events are sent.
BTW, I have written a GM2 test file that sets the 1st channel (channel 0) to be a drum channel and sets program to Orchestra (48). It works on my side. That is BASS_MIDI_StreamGetEvent(midistream, 0, MIDI_EVENT_DRUMS) returns true after the playback is started.
You should test your code with this file.

@Edit:
To be clear: You have to start playback before calling BASS_MIDI_StreamEvent() to query the drum channel status. It does not work in "offline" state. Until playback is started you always get the default configuration (that is only channel 10 is reported as Drum channel). It is because the drum channel status is only valid for an exact time/tick. It can change during playback any time (and even many times).
I have attached another test example (GM2TEST_MOD) that shows how channel 0 is not a drum channel during the 1st half of the song but it is a drum channel during the 2nd half of the song.
Correspondingly Bassmidi reports channel 0 to be a drum channel only from 01.82 (tick: 438).

 

 
« Last Edit: 28 Oct '24 - 13:25 by Falcosoft »

Ian @ un4seen

  • Administrator
  • Posts: 26172
Re: Determining what MIDI channels are drum channels
« Reply #13 on: 28 Oct '24 - 16:45 »
BASSMIDI will pre-apply a MIDI file's tick 0 events, so you should see those from BASS_MIDI_StreamGetEvent even before starting playback, but any later events won't be seen until playback reaches them. Note that even though they were pre-applied, tick 0 events will still be played, so if you do override them before starting playback then your overrides will be overridden (BASS_MIDI_StreamSetFilter can be used to prevent that). So it could be that your MIDI_EVENT_SYSTEM(EX) = MIDI_SYSTEM_GM2 event is overridden by the MIDI file's own MIDI_EVENT_SYSTEM event. Would really need to see the file in question to be sure of what's happening.

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #14 on: 28 Oct '24 - 20:59 »
I cut my file back to only the channel in question - attached.

Falcosoft, I tested both your files with my code, and the first of them reports channel 0 and 9 as drums, the second (MOD) only channel 9 (counting channels 0->15).

I just ran a test using BASS_MIDI_StreamGetEvents to get all MIDI_EVENT_BANK events, testing for bank 120. It found both drum tracks in my original MIDI file.  Still not really understanding all the MIDI variations, under what condition is this a valid test?

Falcosoft

  • Posts: 210
Re: Determining what MIDI channels are drum channels
« Reply #15 on: 28 Oct '24 - 21:40 »
I cut my file back to only the channel in question - attached.

Falcosoft, I tested both your files with my code, and the first of them reports channel 0 and 9 as drums, the second (MOD) only channel 9 (counting channels 0->15).

I just ran a test using BASS_MIDI_StreamGetEvents to get all MIDI_EVENT_BANK events, testing for bank 120. It found both drum tracks in my original MIDI file.  Still not really understanding all the MIDI variations, under what condition is this a valid test?

Hi,
1. You got the results that you should get. As I said the 2nd MOD version should only show channel 0 as drum channel from the middle of the file during playback, not at the beginning. 

2. It's interesting since my Bassmidi based VSTi plugin that also uses BASS_MIDI_StreamGetEvent() to get drum channel status recognized channel 5 as drum channel in GM2 mode perfectly when I played your file (screenshot attached).

3. BTW, your file does not contain a GM2 reset message. Here is a modified version that contains a GM2 reset message. Do you get the same result this way?
« Last Edit: 28 Oct '24 - 21:48 by Falcosoft »

Wayne McHugh

  • Posts: 100
Re: Determining what MIDI channels are drum channels
« Reply #16 on: 28 Oct '24 - 23:27 »
Thanks Falcosoft, I took the sysx message from your modified file and added it into mine.

The result on testing for MIDI_EVENT_DRUMS is unchanged - it only succeeds on channel 9 (counting 0->15). However I added a test for MIDI_EVENT_SYSTEM and checked for MIDI_SYSTEM_GM2 and it succeeded.  I used that as a prior condition for looking for channels using bank 120, and this finds 4 and 9.  Is that a satisfactory pathway for identifying drum tracks in GM2 without playing the stream?

Ian, you said that another sysex might be overriding the GM2, but there is no other MIDI_EVENT_SYSTEM events found, and looking the the binary file confirms that.

I am not playing the stream, I am only inspecting the stream, determining instruments and therefore also drum channels.  I've been doing instrument inspection this way for years, but the drum channel identification is the new thing I'm trying to add.

Ian @ un4seen

  • Administrator
  • Posts: 26172
Re: Determining what MIDI channels are drum channels
« Reply #17 on: 29 Oct '24 - 17:38 »
Ian, you said that another sysex might be overriding the GM2, but there is no other MIDI_EVENT_SYSTEM events found, and looking the the binary file confirms that.

Indeed, there are no MIDI_EVENT_SYSTEM events in the posted MIDI file, but looking again at the posted BASS_MIDI_StreamEvent call to enable GM2 mode, I see it will be failing (BASS_ERROR_ILLPARAM error) due to the chan=-1 parameter. Even though MIDI_EVENT_SYSTEM(EX) is a global event affecting all channels, you currently still need to use a valid channel number with it. Changing -1 to 0 should get it working.