/** Find the Midi notes that occur in the current time. * Shade those notes on the piano displayed. * Un-shade the those notes played in the previous time. */ public void ShadeNotes(int currentPulseTime, int prevPulseTime) { if (notes == null || notes.Count == 0) { return; } if (graphics == null) { graphics = CreateGraphics(); } graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; graphics.TranslateTransform(margin + BlackBorder, margin + BlackBorder); /* Loop through the Midi notes. * Unshade notes where StartTime <= prevPulseTime < next StartTime * Shade notes where StartTime <= currentPulseTime < next StartTime */ int lastShadedIndex = FindClosestStartTime(prevPulseTime - maxShadeDuration * 2); for (int i = lastShadedIndex; i < notes.Count; i++) { int start = notes[i].StartTime; int end = notes[i].EndTime; int notenumber = notes[i].Number; int nextStart = NextStartTime(i); int nextStartTrack = NextStartTimeSameTrack(i); end = Math.Max(end, nextStartTrack); end = Math.Min(end, start + maxShadeDuration - 1); /* If we've past the previous and current times, we're done. */ if ((start > prevPulseTime) && (start > currentPulseTime)) { break; } /* If shaded notes are the same, we're done */ if ((start <= currentPulseTime) && (currentPulseTime < nextStart) && (currentPulseTime < end) && (start <= prevPulseTime) && (prevPulseTime < nextStart) && (prevPulseTime < end)) { break; } /* If the note is in the current time, shade it */ if ((start <= currentPulseTime) && (currentPulseTime < end)) { if (useTwoColors) { if (notes[i].Channel == 1) { ShadeOneNote(graphics, notenumber, shade2Brush); } else { ShadeOneNote(graphics, notenumber, shadeBrush); } } else { ShadeOneNote(graphics, notenumber, shadeBrush); } } /* If the note is in the previous time, un-shade it, draw it white. */ else if ((start <= prevPulseTime) && (prevPulseTime < end)) { int num = notenumber % 12; if (num == 1 || num == 3 || num == 6 || num == 8 || num == 10) { ShadeOneNote(graphics, notenumber, gray1Brush); } else { ShadeOneNote(graphics, notenumber, Brushes.White); } } } graphics.TranslateTransform(-(margin + BlackBorder), -(margin + BlackBorder)); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; }
/* Shade the given note with the given brush. * We only draw notes from notenumber 24 to 96. * (Middle-C is 60). */ private void ShadeOneNote(Graphics g, int notenumber, Brush brush) { int octave = notenumber / 12; int notescale = notenumber % 12; octave -= 2; if (octave < 0 || octave >= MaxOctave) { return; } g.TranslateTransform(octave * WhiteKeyWidth * KeysPerOctave, 0); int x1, x2, x3; int bottomHalfHeight = WhiteKeyHeight - (BlackKeyHeight + 3); /* notescale goes from 0 to 11, from C to B. */ switch (notescale) { case 0: /* C */ x1 = 2; x2 = blackKeyOffsets[0] - 2; g.FillRectangle(brush, x1, 0, x2 - x1, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 1: /* C# */ x1 = blackKeyOffsets[0]; x2 = blackKeyOffsets[1]; g.FillRectangle(brush, x1, 0, x2 - x1, BlackKeyHeight); if (brush == gray1Brush) { g.FillRectangle(gray2Brush, x1 + 1, BlackKeyHeight - BlackKeyHeight / 8, BlackKeyWidth - 2, BlackKeyHeight / 8); } break; case 2: /* D */ x1 = WhiteKeyWidth + 2; x2 = blackKeyOffsets[1] + 3; x3 = blackKeyOffsets[2] - 2; g.FillRectangle(brush, x2, 0, x3 - x2, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 3: /* D# */ x1 = blackKeyOffsets[2]; x2 = blackKeyOffsets[3]; g.FillRectangle(brush, x1, 0, BlackKeyWidth, BlackKeyHeight); if (brush == gray1Brush) { g.FillRectangle(gray2Brush, x1 + 1, BlackKeyHeight - BlackKeyHeight / 8, BlackKeyWidth - 2, BlackKeyHeight / 8); } break; case 4: /* E */ x1 = WhiteKeyWidth * 2 + 2; x2 = blackKeyOffsets[3] + 3; x3 = WhiteKeyWidth * 3 - 1; g.FillRectangle(brush, x2, 0, x3 - x2, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 5: /* F */ x1 = WhiteKeyWidth * 3 + 2; x2 = blackKeyOffsets[4] - 2; x3 = WhiteKeyWidth * 4 - 2; g.FillRectangle(brush, x1, 0, x2 - x1, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 6: /* F# */ x1 = blackKeyOffsets[4]; x2 = blackKeyOffsets[5]; g.FillRectangle(brush, x1, 0, BlackKeyWidth, BlackKeyHeight); if (brush == gray1Brush) { g.FillRectangle(gray2Brush, x1 + 1, BlackKeyHeight - BlackKeyHeight / 8, BlackKeyWidth - 2, BlackKeyHeight / 8); } break; case 7: /* G */ x1 = WhiteKeyWidth * 4 + 2; x2 = blackKeyOffsets[5] + 3; x3 = blackKeyOffsets[6] - 2; g.FillRectangle(brush, x2, 0, x3 - x2, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 8: /* G# */ x1 = blackKeyOffsets[6]; x2 = blackKeyOffsets[7]; g.FillRectangle(brush, x1, 0, BlackKeyWidth, BlackKeyHeight); if (brush == gray1Brush) { g.FillRectangle(gray2Brush, x1 + 1, BlackKeyHeight - BlackKeyHeight / 8, BlackKeyWidth - 2, BlackKeyHeight / 8); } break; case 9: /* A */ x1 = WhiteKeyWidth * 5 + 2; x2 = blackKeyOffsets[7] + 3; x3 = blackKeyOffsets[8] - 2; g.FillRectangle(brush, x2, 0, x3 - x2, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; case 10: /* A# */ x1 = blackKeyOffsets[8]; x2 = blackKeyOffsets[9]; g.FillRectangle(brush, x1, 0, BlackKeyWidth, BlackKeyHeight); if (brush == gray1Brush) { g.FillRectangle(gray2Brush, x1 + 1, BlackKeyHeight - BlackKeyHeight / 8, BlackKeyWidth - 2, BlackKeyHeight / 8); } break; case 11: /* B */ x1 = WhiteKeyWidth * 6 + 2; x2 = blackKeyOffsets[9] + 3; x3 = WhiteKeyWidth * KeysPerOctave - 1; g.FillRectangle(brush, x2, 0, x3 - x2, BlackKeyHeight + 3); g.FillRectangle(brush, x1, BlackKeyHeight + 3, WhiteKeyWidth - 3, bottomHalfHeight); break; default: break; } g.TranslateTransform(-(octave * WhiteKeyWidth * KeysPerOctave), 0); }