/// <summary> /// Initialize key from a string. /// </summary> /// <param name="keyString">Format should be like /// "C: QC QD QE QF | QD QE QF QG" for C major /// "Ebm: QEb QF QGb QF | QEb QF QGb QAb" for Eb minor</param> public Key(string keyString) { Match m = Regex.Match(keyString, @"([A-G])([b#])?(m)?"); char name = m.Groups[1].Value[0]; Accidental accidental = Accidental.Natural; if (m.Groups[2].Value != "") { if (m.Groups[2].Value == "b") { accidental = Accidental.Flat; } else { accidental = Accidental.Sharp; } } Pitch p = new Pitch(name, 4, accidental); if (m.Groups[3].Value == "m") { mode = KeyMode.Minor; } else { mode = KeyMode.Major; } string keyName = p.ToString(); // TODO: all the parsing of accidental above, etc isn't necessary if we just use the string anyway. switch (keyName) { #region Silly Case Statements to set "fifths" case "C": fifths = 0; break; case "G": fifths = 1; break; case "D": fifths = 2; break; case "A": fifths = 3; break; case "E": fifths = 4; break; case "B": fifths = 5; break; case "F#": fifths = 6; break; case "C#": fifths = 7; break; case "G#": fifths = 8; break; case "D#": fifths = 9; break; case "A#": fifths = 10; break; case "E#": fifths = 11; break; case "B#": fifths = 12; break; case "F": fifths = -1; break; case "Bb": fifths = -2; break; case "Eb": fifths = -3; break; case "Ab": fifths = -4; break; case "Db": fifths = -5; break; case "Gb": fifths = -6; break; case "Cb": fifths = -7; break; case "Fb": fifths = -8; break; default: throw new ArgumentException("Unknown Key: " + keyName); #endregion } }
public override string ToString() { Pitch p = new Pitch(cOffset, accidental); return(p.ToString()); }
/// <summary> /// Returns an example Pitch in the given key on the given scale degree, in the given octave. /// </summary> /// <param name="degree">The scale degree to create.</param> /// <param name="octave">The c-based octave in which to create the Pitch instance.</param> /// <returns>The example pitch on the requested scale degree.</returns> public Pitch GetScaleDegreePitch(ScaleDegree degree, int octave) { int numFifths; bool progressUp; PitchInterval fifth; PitchInterval degreeInterval; numFifths = Math.Abs(Fifths); progressUp = (Fifths > 0); fifth = new PitchInterval(7); // First, find the tonic of the key. // Start on middle C and loop through the circle of fifths. Pitch tonic = new Pitch(35, Accidental.Natural); for (int i = 0; i < numFifths; i++) { if (progressUp) { tonic += fifth; tonic.FlipEnharmonic(true, true); // The first argument is true because B# and E# are not allowed. } else { tonic -= fifth; tonic.FlipEnharmonic(i < 6, false); // The first argument is used because Cb is allowed (fifths = -7; i=6); } } // Second, add the scale degree to the tonic note. // Convert the scale degree to a pitch interval. degreeInterval = new PitchInterval(); switch ((degree.Number - 1) % 7) { case 0: degreeInterval.Interval = 0; break; case 1: degreeInterval.Interval = 2; break; case 2: degreeInterval.Interval = 4; break; case 3: degreeInterval.Interval = 5; break; case 4: degreeInterval.Interval = 7; break; case 5: degreeInterval.Interval = 9; break; case 6: degreeInterval.Interval = 11; break; } // Add back in the # octaves. degreeInterval += new PitchInterval(12 * ((degree.Number - 1) / 7)); Pitch result = tonic + degreeInterval; // Pick the correct enharmonic version (assuming no alterations). We use sharps if we are going up on the circle of fifths. // Natural notes like B are used instead of Cb until we have 6 accidentals. This is a special mixed case where we need to // use one normal "white key" and one sharp "white key": both B natural and E# are in the key signature in F# major. Similarly, // in Gb major both Cb and F natural are in the key signature. // Once we have 7 accidentals, we don't use any natural white keys. if (numFifths < 6) { result.FlipEnharmonic(true, progressUp); } else if (numFifths > 6) { result.FlipEnharmonic(false, progressUp); } else if (fifths == 6) // F# Major. { if (degree.Number == 4) // B natural special case. { result.FlipEnharmonic(true, true); } else { result.FlipEnharmonic(false, true); } } else // Gb Major. { if (degree.Number == 7) // F natural special case. { result.FlipEnharmonic(true, false); } else { result.FlipEnharmonic(false, false); } } // Set the alteration (this function picks the right enharmonic version if the pitch is already set right for the no alteration case.) result.ApplyAlteration(degree.Alteration); // Finally, set the octave. result.Octave = octave; return(result); }