Support for number charts, transposition when generating charts.

This commit is contained in:
2023-07-19 13:26:01 -05:00
parent 9ca5a1b99c
commit 5b1238f038
5 changed files with 115 additions and 34 deletions

View File

@ -4,7 +4,7 @@ import zero_functional
type
ChordChartMetadata* = object
title*: string
key*: ChordChartPitch
key*: ChordChartChord
optionalProps: StringTableRef
ChordChart* = ref object
@ -26,7 +26,7 @@ type
ChordChartPitch* = enum Af, A, Bf, B, C, Df, D, Ef, E, F, Fs, G
ChordChartChord* = object
original*: string
original*: Option[string]
rootPitch*: ChordChartPitch
flavor*: Option[string]
bassPitch*: Option[ChordChartPitch]
@ -133,13 +133,15 @@ func dump*(ccn: ChordChartNode, indent = ""): string =
if ccn.chord.isSome:
let chord = ccn.chord.get
result &= "["
if chord.flavor.isNone and chord.bassPitch.isNone:
result &= chord.original
if chord.original.isSome and chord.flavor.isNone and
chord.bassPitch.isNone:
result &= chord.original.get
else:
result &= $chord.rootPitch
if chord.flavor.isSome:
result &= $chord.rootPitch & "_" & chord.flavor.get
result &= "_" & chord.flavor.get
if chord.bassPitch.isSome:
result &= $chord.rootPitch & "/" & $chord.bassPitch.get
result &= "/" & $chord.bassPitch.get
result &= "]"
if ccn.word.isSome: result &= ccn.word.get
@ -185,8 +187,9 @@ template addToCurSection(n: ChordChartNode): untyped =
if ctx.curSection.kind == ccnkSection: ctx.curSection.sectionContents.add(n)
else: result.add(n)
func parsePitch*(ctx: ParserContext, keyValue: string): ChordChartPitch =
case keyValue.strip.toLower
proc parsePitch*(ctx: ParserContext, keyValue: string): ChordChartPitch =
let normK = keyValue.strip.toLower
case normK
of "gs", "gis", "g#", "ab", "a♭", "af", "aes": return ChordChartPitch.Af
of "g𝄪", "a", "a♮", "b𝄫": return ChordChartPitch.A
of "as", "ais", "a#", "bf", "bb", "b♭", "bes", "c𝄫": return ChordChartPitch.Bf
@ -199,6 +202,13 @@ func parsePitch*(ctx: ParserContext, keyValue: string): ChordChartPitch =
of "es", "eis", "e#", "f", "g𝄫": return ChordChartPitch.F
of "e𝄪", "fs", "fis", "f#", "gf", "gb", "ges": return ChordChartPitch.Fs
of "f𝄪", "g", "a𝄫": return ChordChartPitch.G
of "1": return ctx.curKeyCenter
of "2": return ctx.curKeyCenter + 2
of "3": return ctx.curKeyCenter + 4
of "4": return ctx.curKeyCenter + 5
of "5": return ctx.curKeyCenter + 7
of "6": return ctx.curKeyCenter + 9
of "7": return ctx.curKeyCenter + 11
else: raise ctx.makeError(keyValue.strip & " is not a recognized key.")
# see regexr.com/70nv1
@ -226,7 +236,7 @@ proc parseChord*(
else: none[ChordChartPitch]()
return some(ChordChartChord(
original: chordValue,
original: some(chordValue),
rootPitch: ctx.parsePitch(m.get.captures[0]),
flavor: flavor,
bassPitch: bassPitch))
@ -236,8 +246,8 @@ let METADATA_END_PAT = re"^-+$"
proc parseMetadata(ctx: var ParserContext): ChordChartMetadata =
var title = "MISSING"
var songKey = "MISSING"
var optProps = newStringTable()
var songKey: Option[ChordChartChord]
while ctx.curLineNum < ctx.lines.len:
let line = ctx.nextLine
@ -252,18 +262,21 @@ proc parseMetadata(ctx: var ParserContext): ChordChartMetadata =
let key = m.get.captures[0].strip.tolower
let value = m.get.captures[1].strip
if key == "title": title = value
elif key == "key": songKey = value
elif key == "key":
songKey = ctx.parseChord(value)
if songKey.isNone:
raise ctx.makeError("unrecognized key: " & value)
else: optProps[key] = value
if title == "MISSING":
raise ctx.makeError("metadata is missing the 'title' property")
if songKey == "MISSING":
if songKey.isNone:
raise ctx.makeError("metadata is missing the 'key' property")
result = ChordChartMetadata(
title: title,
key: ctx.parsePitch(songKey),
key: songKey.get,
optionalProps: optProps)
const KNOWN_SECTION_NAMES = [
@ -447,7 +460,7 @@ proc parseChordChart*(s: string): ChordChart =
unparsedLineParts: @[])
let metadata = parseMetadata(parserCtx)
parserCtx.curKeyCenter = metadata.key
parserCtx.curKeyCenter = metadata.key.rootPitch
result = ChordChart(
rawContent: s,