|
|
|
@ -87,14 +87,43 @@ func renderPitchInKey*(
|
|
|
|
|
|
|
|
|
|
var scaleNames: array[(ord(high(ChordChartPitch)) + 1), string]
|
|
|
|
|
if useSharps.isNone:
|
|
|
|
|
# If we aren't told to use sharps or flats, we render the diatonic pitches
|
|
|
|
|
# according to standard theory (C# in the key of D, Db in the key of Ab)
|
|
|
|
|
# but we render non-diatonic notes with flats (prefer the b6 and b7 over
|
|
|
|
|
# the #5 and #6).
|
|
|
|
|
#
|
|
|
|
|
# TODO: In the future, we should also remember the scale degree of the
|
|
|
|
|
# chord when parsing. So, for example, in the key of D we would parse Bb as
|
|
|
|
|
# the b6 and A# as the #5. The pitch would be the same, but the scale
|
|
|
|
|
# degree would differ. This would allow us to preserve intentional choices
|
|
|
|
|
# in the chart when transposing.
|
|
|
|
|
scaleNames = case key
|
|
|
|
|
of A, B, D, E, G:
|
|
|
|
|
["G#", "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G"]
|
|
|
|
|
of Af, Bf, C, Df, Ef, F:
|
|
|
|
|
of C:
|
|
|
|
|
["A♭", "A", "B♭", "B", "C", "D♭", "D", "E♭", "E", "F", "G♭", "G"]
|
|
|
|
|
of G:
|
|
|
|
|
["A♭", "A", "B♭", "B", "C", "D♭", "D", "E♭", "E", "F", "F#", "G"]
|
|
|
|
|
of D:
|
|
|
|
|
["A♭", "A", "B♭", "B", "C", "C#", "D", "E♭", "E", "F", "F#", "G"]
|
|
|
|
|
of A:
|
|
|
|
|
["G#", "A", "B♭", "B", "C", "C#", "D", "E♭", "E", "F", "F#", "G"]
|
|
|
|
|
of E:
|
|
|
|
|
["G#", "A", "B♭", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G"]
|
|
|
|
|
of B:
|
|
|
|
|
["G#", "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G"]
|
|
|
|
|
of Gf:
|
|
|
|
|
["A♭", "B𝄫", "B♭", "C♭", "D𝄫", "D♭", "E𝄫", "E♭", "F♭", "F", "G♭", "A𝄫"]
|
|
|
|
|
of Df:
|
|
|
|
|
["A♭", "B𝄫", "B♭", "C♭", "C", "D♭", "E𝄫", "E♭", "F♭", "F", "G♭", "A𝄫"]
|
|
|
|
|
of Af:
|
|
|
|
|
["A♭", "B𝄫", "B♭", "C♭", "C", "D♭", "E𝄫", "E♭", "F♭", "F", "G♭", "G"]
|
|
|
|
|
of Ef:
|
|
|
|
|
["A♭", "B𝄫", "B♭", "C♭", "C", "D♭", "D", "E♭", "F♭", "F", "G♭", "G"]
|
|
|
|
|
of Bf:
|
|
|
|
|
["A♭", "A", "B♭", "C♭", "C", "D♭", "D", "E♭", "F♭", "F", "G♭", "G"]
|
|
|
|
|
of F:
|
|
|
|
|
["A♭", "A", "B♭", "C♭", "C", "D♭", "D", "E♭", "E", "F", "G♭", "G"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif useSharps.isSome and useSharps.get:
|
|
|
|
|
scaleNames = case key
|
|
|
|
|
of A, B, C, D, E, G:
|
|
|
|
@ -112,7 +141,7 @@ func renderPitchInKey*(
|
|
|
|
|
of F:
|
|
|
|
|
["G#", "G𝄪", "A#", "B", "B#", "C#", "C𝄪", "D#", "D𝄪", "E#", "F#", "F𝄪"]
|
|
|
|
|
|
|
|
|
|
else: # useSharps.isSome and not useSharps.get
|
|
|
|
|
else: # !useSharps (useSharps.isSome and not useSharps.get)
|
|
|
|
|
scaleNames = case key
|
|
|
|
|
of C, Af, Bf, Df, Ef, F:
|
|
|
|
|
["A♭", "A", "B♭", "B", "C", "D♭", "D", "E♭", "E", "F", "G♭", "G"]
|
|
|
|
@ -348,7 +377,7 @@ let NOTE_START_PAT = re"\{\{"
|
|
|
|
|
let NOTE_END_PAT = re"\}\}"
|
|
|
|
|
let SPACE_PAT = re"\s"
|
|
|
|
|
let CHORD_IN_LYRICS_PAT = re"(\w+)(\[.+)"
|
|
|
|
|
let CHORD_AND_LYRICS_PAT = re"^\[([^\]]+)\]([^\s\[]+)(.*)$"
|
|
|
|
|
let CHORD_AND_LYRICS_PAT = re"^\[([^\]]*)\]([^\s\[]+)(.*)$"
|
|
|
|
|
let BRACED_CHORD_PAT = re"^\[([^\]]+)\]$"
|
|
|
|
|
let NAKED_CHORDS_ONLY_PAT = re("^\\s*(" & CHORD_REGEX & "\\s*\\|*\\s*)+$")
|
|
|
|
|
|
|
|
|
|