/** Given a midi note number, return the accidental (if any) * that should be used when displaying the note in this key signature. * * The current measure is also required. Once we return an * accidental for a measure, the accidental remains for the * rest of the measure. So we must update the current keymap * with any new accidentals that we return. When we move to another * measure, we reset the keymap back to the key signature. */ public Accid GetAccidental(int notenumber, int measure) { if (measure != prevmeasure) { ResetKeyMap(); prevmeasure = measure; } Accid result = keymap[notenumber]; if (result == Accid.Sharp) { keymap[notenumber] = Accid.None; keymap[notenumber - 1] = Accid.Natural; } else if (result == Accid.Flat) { keymap[notenumber] = Accid.None; keymap[notenumber + 1] = Accid.Natural; } else if (result == Accid.Natural) { keymap[notenumber] = Accid.None; int nextkey = NoteScale.FromNumber(notenumber + 1); int prevkey = NoteScale.FromNumber(notenumber - 1); /* If we insert a natural, then either: * - the next key must go back to sharp, * - the previous key must go back to flat. */ if (notenumber > 0) { if (keymap[notenumber - 1] == Accid.None && keymap[notenumber + 1] == Accid.None && NoteScale.IsBlackKey(nextkey) && NoteScale.IsBlackKey(prevkey)) { if (num_flats == 0) { keymap[notenumber + 1] = Accid.Sharp; } else { keymap[notenumber - 1] = Accid.Flat; } } else if (keymap[notenumber - 1] == Accid.None && NoteScale.IsBlackKey(prevkey)) { keymap[notenumber - 1] = Accid.Flat; } else if (keymap[notenumber + 1] == Accid.None && NoteScale.IsBlackKey(nextkey)) { keymap[notenumber + 1] = Accid.Sharp; } else { /* Shouldn't get here */ } } } return(result); }
/** Given a midi note number, return the white note (the * non-sharp/non-flat note) that should be used when displaying * this note in this key signature. This should be called * before calling GetAccidental(). */ public WhiteNote GetWhiteNote(int notenumber) { int notescale = NoteScale.FromNumber(notenumber); int octave = (notenumber + 3) / 12 - 1; int letter = 0; int[] whole_sharps = { WhiteNote.A, WhiteNote.A, WhiteNote.B, WhiteNote.C, WhiteNote.C, WhiteNote.D, WhiteNote.D, WhiteNote.E, WhiteNote.F, WhiteNote.F, WhiteNote.G, WhiteNote.G }; int[] whole_flats = { WhiteNote.A, WhiteNote.B,WhiteNote.B, WhiteNote.C, WhiteNote.D,WhiteNote.D, WhiteNote.E,WhiteNote.E, WhiteNote.F, WhiteNote.G,WhiteNote.G, WhiteNote.A }; Accid accid = keymap[notenumber]; if (accid == Accid.Flat) { letter = whole_flats[notescale]; } else if (accid == Accid.Sharp) { letter = whole_sharps[notescale]; } else if (accid == Accid.Natural) { letter = whole_sharps[notescale]; } else if (accid == Accid.None) { letter = whole_sharps[notescale]; /* If the note number is a sharp/flat, and there's no accidental, * determine the white note by seeing whether the previous or next note * is a natural. */ if (NoteScale.IsBlackKey(notescale)) { if (keymap[notenumber - 1] == Accid.Natural && keymap[notenumber + 1] == Accid.Natural) { if (num_flats > 0) { letter = whole_flats[notescale]; } else { letter = whole_sharps[notescale]; } } else if (keymap[notenumber - 1] == Accid.Natural) { letter = whole_sharps[notescale]; } else if (keymap[notenumber + 1] == Accid.Natural) { letter = whole_flats[notescale]; } } } /* The above algorithm doesn't quite work for G-flat major. * Handle it here. */ if (num_flats == Gflat && notescale == NoteScale.B) { letter = WhiteNote.C; } if (num_flats == Gflat && notescale == NoteScale.Bflat) { letter = WhiteNote.B; } if (num_flats > 0 && notescale == NoteScale.Aflat) { octave++; } return(new WhiteNote(letter, octave)); }