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

@@ -9,6 +9,8 @@ type
currentKey: ChordChartPitch
sourceKey: ChordChartPitch
currentSection: ChordChartNode
numberChart: bool
transposeSteps: int
const DEFAULT_STYLESHEET* = """
<style>
@@ -69,6 +71,10 @@ h3 .section-text {
margin-right: 0.5em;
}
.chord .flavor {
font-variant-position: super;
}
.song-order h3 {
font-style: italic;
font-weight: normal;
@@ -89,17 +95,58 @@ h3 .section-text {
</style>
"""
proc transpose(ctx: FormatContext, chord: ChordChartChord): string =
let distance = ctx.currentKey - ctx.sourceKey
func scaleDegree(root: ChordChartPitch, p: ChordChartPitch): string =
let distance = p - root
case distance:
of 0: "1"
of 1: "♭2"
of 2: "2"
of 3: "♭3"
of 4: "3"
of 5: "4"
of 6: "♭5"
of 7: "5"
of 8: "♭6"
of 9: "6"
of 10: "♭7"
of 11: "7"
else: raise newException(Exception, "Impossible")
if distance != 0:
result = $(chord.rootPitch + distance)
func format(ctx: FormatContext, chord: ChordChartChord, useNumber = false): string =
if not useNumber and chord.original.isSome: return chord.original.get
elif useNumber:
result = "<span class=root>" &
ctx.currentKey.scaleDegree(chord.rootPitch) & "</span>"
if chord.flavor.isSome:
result &= "<span class=flavor>" & chord.flavor.get & "</span>"
if chord.bassPitch.isSome:
result &= "<span class=bass>/" &
ctx.currentKey.scaleDegree(chord.bassPitch.get) & "</span>"
else:
result = $chord.rootPitch
if chord.flavor.isSome: result &= chord.flavor.get
if chord.bassPitch.isSome: result &= "/" & $(chord.bassPitch.get + distance)
if chord.bassPitch.isSome: result &= "/" & $chord.bassPitch.get
#debug "transposed " & $ctx.sourceKey & " -> " & $ctx.currentKey &
# " (distance " & $distance & ")\p\tchord: " & $chord & " to " & result
else: result = chord.original
proc transpose(ctx: FormatContext, chord: ChordChartChord): ChordChartChord =
result = chord
let distance = ctx.currentKey - ctx.sourceKey
if distance != 0:
result = ChordChartChord(
original: none[string](),
rootPitch: chord.rootPitch + distance,
flavor:
if chord.flavor.isSome: some(chord.flavor.get)
else: none[string](),
bassPitch:
if chord.bassPitch.isSome: some(chord.bassPitch.get + distance)
else: none[ChordChartPitch]())
func makeSongOrder(songOrder, indent: string): string =
result = indent & "<section class=song-order>\p" &
@@ -143,7 +190,8 @@ proc toHtml(ctx: var FormatContext, node: ChordChartNode, indent: string): strin
result &= "'>"
if node.chord.isSome:
result &= "<span class=chord>" & ctx.transpose(node.chord.get) & "</span>"
result &= "<span class=chord>" &
ctx.format(ctx.transpose(node.chord.get), ctx.numberChart) & "</span>"
result &= "<span class=lyric>"
if node.word.isSome: result &= node.word.get
@@ -169,8 +217,8 @@ proc toHtml(ctx: var FormatContext, node: ChordChartNode, indent: string): strin
result &= "</section><section>" & headingVal & "</section><section>"
of ccnkRedefineKey:
let oldKey = ctx.sourceKey
ctx.sourceKey = node.newKey
let oldKey = ctx.currentKey
ctx.sourceKey = node.newKey + ctx.transposeSteps
ctx.currentKey = ctx.sourceKey
if oldKey != ctx.currentKey:
@@ -183,14 +231,21 @@ proc toHtml(ctx: var FormatContext, node: ChordChartNode, indent: string): strin
proc toHtml*(
cc: ChordChart,
transpose = 0,
numberChart = false,
stylesheets = @[DEFAULT_STYLESHEET],
scripts: seq[string] = @[]): string =
var ctx = FormatContext(
chart: cc,
currentKey: cc.metadata.key,
sourceKey: cc.metadata.key,
currentSection: EMPTY_CHORD_CHART_NODE)
currentKey: cc.metadata.key.rootPitch + transpose,
sourceKey: cc.metadata.key.rootPitch,
currentSection: EMPTY_CHORD_CHART_NODE,
numberChart: numberChart,
transposeSteps: transpose)
debug "Formatting:\p\tsource key: " & $ctx.sourceKey & "\p\ttransposing: " &
$transpose & "\p\ttarget key: " & $ctx.currentKey
result = """<!doctype html>
<html>
@@ -210,11 +265,11 @@ proc toHtml*(
result &= " </head>\p <body>"
var indent = " "
#
# Title
result &= indent & "<h1>" & cc.metadata.title & "</h1>\p"
var metadataPieces = @["Key: " & $cc.metadata.key]
var metadataPieces = @["Key: " & ctx.format(ctx.transpose(cc.metadata.key))]
if cc.metadata.contains("time signature"):
metadataPieces.add(cc.metadata["time signature"])
if cc.metadata.contains("bpm"):