MidiKeyboardComponent: different overlay colours for different MIDI channels?


#1

I’m trying to draw different key colours on a MidiKeyboardComponent depending on which channel the incoming notes are.

What I have so far (simplified):

A CustomMidiKeyboardComponent, derived from MidiKeybOardComponent with overriden drawBlackNote(), drawWhiteNote() and handleNoteOn() methods.

void CustomMidiKeyboardComponent::handleNoteOn(MidiKeyboardState* state, int midiChannel, int midiNoteNumber, float velocity)
{
	curMidiChannel = midiChannel;
	MidiKeyboardComponent::handleNoteOn(state, midiChannel, midiNoteNumber, velocity);
	
}

void CustomMidiKeyboardComponent::drawWhiteNote(int midiNoteNumber, Graphics & g, int x, int y, int w, int h, bool isDown, bool isOver, const Colour & lineColour, const Colour & textColour)
{
	Colour c(Colours::transparentWhite);
	
	if (isDown) {
		if (curMidiChannel == 1) {
			c = c.overlaidWith(chan1Colour);
		}
		if (curMidiChannel == 2) {
			c = c.overlaidWith(chan2Colour);
		}
	}

       // ...
}
void CustomMidiKeyboardComponent::drawBlackNote(int midiNoteNumber, Graphics & g, int x, int y, int w, int h, bool isDown, bool isOver, const Colour & noteFillColour)
{
	 
		Colour c(noteFillColour);

		if (isDown) {
			if (curMidiChannel == 1) {
				c = c.overlaidWith(chan1Colour);
			}
			if (curMidiChannel == 2) {
				c = c.overlaidWith(chan2Colour);
			}
		} 

                // ...
}

This basically kind of works, but it breaks (= sometimes drawn notes have the wrong colour) if there are more than just a few notes incoming on each channel.

I think I kinda get why this happens (setting the channel and notes drawing can overlap ?) but what would be a better (correct) approach to do this ?


#2

Hmm, from the sound of it I think it’s basically a threading issue whereby incoming events are changing the current channel during the draw function.

I’m not sure I understand exactly how you intend it to look, but if you always want all keys to be the same colour, perhaps you could do something as simple as
curDisplayChannel = curMidiChannel;
(i.e. keep a local copy for display purposes) and update it once every graphics update?

Hope that helps. :slight_smile:


#3

Thanks for your reply.
This is what it does currently (draft version):

gif

Below C3 there are only notes incoming on channel 1 (and above C3 only notes on channel 2), so as you can see, some of the notes are drawn in the wrong colour initially, but as soon as I point with the mouse on them to trigger a redraw they are drawn correctly.

Do you think your suggestion could help fix this (tbh not sure currently how I should implement it) or any other ideas how to solve this ?


#4

You’re welcome.

Ah okay, I think I understand this a little more. We’re losing a lot of detail in only updating the colour at certain (unreliable) times from the MIDI and then having this single colour apply to everything.

Perhaps another way of doing this would be to have an array (or similar) of 128 slots, one per key, in which you save/clear the current channel/s for each key, then use these values directly in the display? There shouldn’t be any major problems with sync in that case.