@pepperhorn/chordl-core 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/audio/midi-export.d.ts +23 -0
- package/dist/audio/midi-export.js +155 -0
- package/dist/audio/midi-export.js.map +1 -0
- package/dist/chord-sheet/codec.d.ts +14 -0
- package/dist/chord-sheet/codec.js +119 -0
- package/dist/chord-sheet/codec.js.map +1 -0
- package/dist/chord-sheet/defaults.d.ts +13 -0
- package/dist/chord-sheet/defaults.js +48 -0
- package/dist/chord-sheet/defaults.js.map +1 -0
- package/dist/chord-sheet/index.d.ts +3 -0
- package/dist/chord-sheet/index.js +4 -0
- package/dist/chord-sheet/index.js.map +1 -0
- package/dist/chord-sheet/schema.d.ts +6 -0
- package/dist/chord-sheet/schema.js +17 -0
- package/dist/chord-sheet/schema.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -0
- package/dist/engine/auto-fingering.d.ts +36 -0
- package/dist/engine/auto-fingering.js +344 -0
- package/dist/engine/auto-fingering.js.map +1 -0
- package/dist/engine/highlight-mapper.d.ts +3 -0
- package/dist/engine/highlight-mapper.js +46 -0
- package/dist/engine/highlight-mapper.js.map +1 -0
- package/dist/engine/keyboard-layout.d.ts +6 -0
- package/dist/engine/keyboard-layout.js +65 -0
- package/dist/engine/keyboard-layout.js.map +1 -0
- package/dist/engine/note-spelling.d.ts +54 -0
- package/dist/engine/note-spelling.js +103 -0
- package/dist/engine/note-spelling.js.map +1 -0
- package/dist/engine/scale-fingering.d.ts +21 -0
- package/dist/engine/scale-fingering.js +130 -0
- package/dist/engine/scale-fingering.js.map +1 -0
- package/dist/engine/staff-constants.d.ts +16 -0
- package/dist/engine/staff-constants.js +20 -0
- package/dist/engine/staff-constants.js.map +1 -0
- package/dist/engine/staff-glyphs.d.ts +17 -0
- package/dist/engine/staff-glyphs.js +59 -0
- package/dist/engine/staff-glyphs.js.map +1 -0
- package/dist/engine/staff-layout.d.ts +28 -0
- package/dist/engine/staff-layout.js +238 -0
- package/dist/engine/staff-layout.js.map +1 -0
- package/dist/engine/svg-constants.d.ts +19 -0
- package/dist/engine/svg-constants.js +40 -0
- package/dist/engine/svg-constants.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.d.ts +70 -0
- package/dist/logging.js +24 -0
- package/dist/logging.js.map +1 -0
- package/dist/parser/natural-language.d.ts +9 -0
- package/dist/parser/natural-language.js +406 -0
- package/dist/parser/natural-language.js.map +1 -0
- package/dist/parser/progression-parser.d.ts +16 -0
- package/dist/parser/progression-parser.js +97 -0
- package/dist/parser/progression-parser.js.map +1 -0
- package/dist/pipeline.d.ts +33 -0
- package/dist/pipeline.js +203 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/progression/form-templates.d.ts +11 -0
- package/dist/progression/form-templates.js +105 -0
- package/dist/progression/form-templates.js.map +1 -0
- package/dist/progression/index.d.ts +5 -0
- package/dist/progression/index.js +4 -0
- package/dist/progression/index.js.map +1 -0
- package/dist/progression/progression-resolver.d.ts +29 -0
- package/dist/progression/progression-resolver.js +135 -0
- package/dist/progression/progression-resolver.js.map +1 -0
- package/dist/progression/roman-numeral.d.ts +14 -0
- package/dist/progression/roman-numeral.js +78 -0
- package/dist/progression/roman-numeral.js.map +1 -0
- package/dist/resolver/auto-layout.d.ts +20 -0
- package/dist/resolver/auto-layout.js +195 -0
- package/dist/resolver/auto-layout.js.map +1 -0
- package/dist/resolver/chord-resolver.d.ts +8 -0
- package/dist/resolver/chord-resolver.js +172 -0
- package/dist/resolver/chord-resolver.js.map +1 -0
- package/dist/resolver/scale-resolver.d.ts +9 -0
- package/dist/resolver/scale-resolver.js +45 -0
- package/dist/resolver/scale-resolver.js.map +1 -0
- package/dist/themes/boomwhacker.d.ts +2 -0
- package/dist/themes/boomwhacker.js +35 -0
- package/dist/themes/boomwhacker.js.map +1 -0
- package/dist/themes/crf.d.ts +19 -0
- package/dist/themes/crf.js +34 -0
- package/dist/themes/crf.js.map +1 -0
- package/dist/themes/index.d.ts +3 -0
- package/dist/themes/index.js +25 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/themes/simple.d.ts +2 -0
- package/dist/themes/simple.js +13 -0
- package/dist/themes/simple.js.map +1 -0
- package/dist/theory/chord-tones.d.ts +56 -0
- package/dist/theory/chord-tones.js +215 -0
- package/dist/theory/chord-tones.js.map +1 -0
- package/dist/theory/degree-labels.d.ts +31 -0
- package/dist/theory/degree-labels.js +74 -0
- package/dist/theory/degree-labels.js.map +1 -0
- package/dist/types.d.ts +123 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { MAX_EXAMPLES } from "../config";
|
|
2
|
+
import { resolveChord } from "../resolver/chord-resolver";
|
|
3
|
+
import { resolveProgression, tokenizeProgression } from "./roman-numeral";
|
|
4
|
+
import { findTemplate } from "./form-templates";
|
|
5
|
+
import { findVoicing, voicingPitchClasses, mapToVoicingQuality, queryVoicings, inferStyle, } from "@pepperhorn/chordl-voicings";
|
|
6
|
+
/**
|
|
7
|
+
* A set of contrasting styles to auto-cycle through when no style hint is given.
|
|
8
|
+
* Ordered by musical diversity.
|
|
9
|
+
*/
|
|
10
|
+
const CONTRASTING_STYLES = [
|
|
11
|
+
"Rootless Type A",
|
|
12
|
+
"Drop 2",
|
|
13
|
+
"Shell",
|
|
14
|
+
"Quartal",
|
|
15
|
+
"Spread",
|
|
16
|
+
"4-Note Closed",
|
|
17
|
+
"Rootless Type B",
|
|
18
|
+
"Upper Structure",
|
|
19
|
+
"Drop 2+4",
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Given a style hint, return variations within that family.
|
|
23
|
+
* e.g. "Bill Evans" → [Rootless Type A, Rootless Type B, Shell]
|
|
24
|
+
*/
|
|
25
|
+
function getStyleVariations(styleHint) {
|
|
26
|
+
const primary = inferStyle(styleHint);
|
|
27
|
+
if (!primary)
|
|
28
|
+
return CONTRASTING_STYLES.slice(0, MAX_EXAMPLES);
|
|
29
|
+
const variations = [primary];
|
|
30
|
+
// Add related styles
|
|
31
|
+
if (primary === "Rootless Type A") {
|
|
32
|
+
variations.push("Rootless Type B", "Shell");
|
|
33
|
+
}
|
|
34
|
+
else if (primary === "Rootless Type B") {
|
|
35
|
+
variations.push("Rootless Type A", "Shell");
|
|
36
|
+
}
|
|
37
|
+
else if (primary === "Shell") {
|
|
38
|
+
variations.push("Rootless Type A", "Drop 2");
|
|
39
|
+
}
|
|
40
|
+
else if (primary === "Drop 2") {
|
|
41
|
+
variations.push("Drop 2+4", "Shell");
|
|
42
|
+
}
|
|
43
|
+
else if (primary === "Drop 2+4") {
|
|
44
|
+
variations.push("Drop 2", "Spread");
|
|
45
|
+
}
|
|
46
|
+
else if (primary === "Quartal") {
|
|
47
|
+
variations.push("Upper Structure", "Rootless Type A");
|
|
48
|
+
}
|
|
49
|
+
else if (primary === "Upper Structure") {
|
|
50
|
+
variations.push("Quartal", "Spread");
|
|
51
|
+
}
|
|
52
|
+
else if (primary === "Spread") {
|
|
53
|
+
variations.push("Drop 2", "4-Note Closed");
|
|
54
|
+
}
|
|
55
|
+
else if (primary === "4-Note Closed") {
|
|
56
|
+
variations.push("Spread", "Drop 2");
|
|
57
|
+
}
|
|
58
|
+
return variations.slice(0, MAX_EXAMPLES);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Voice a single chord symbol using a specific voicing style.
|
|
62
|
+
* Falls back to plain resolution if no voicing matches.
|
|
63
|
+
*/
|
|
64
|
+
function voiceChord(symbol, style) {
|
|
65
|
+
const resolved = resolveChord(symbol);
|
|
66
|
+
const quality = mapToVoicingQuality(resolved.type, resolved.notes);
|
|
67
|
+
let notes = resolved.notes;
|
|
68
|
+
let voicingStyle;
|
|
69
|
+
if (quality && style) {
|
|
70
|
+
const matches = queryVoicings({ quality, style });
|
|
71
|
+
if (matches.length > 0) {
|
|
72
|
+
const pcs = voicingPitchClasses(resolved.root, matches[0]);
|
|
73
|
+
if (pcs.length > 0) {
|
|
74
|
+
notes = pcs;
|
|
75
|
+
voicingStyle = style;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Fallback: try any voicing for this quality
|
|
80
|
+
if (!voicingStyle && quality) {
|
|
81
|
+
const voicing = findVoicing(quality);
|
|
82
|
+
if (voicing) {
|
|
83
|
+
const pcs = voicingPitchClasses(resolved.root, voicing);
|
|
84
|
+
if (pcs.length > 0) {
|
|
85
|
+
notes = pcs;
|
|
86
|
+
voicingStyle = voicing.tags.style;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
symbol,
|
|
92
|
+
root: resolved.root,
|
|
93
|
+
notes,
|
|
94
|
+
voicingStyle,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolve a progression request into multiple voicing examples.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveProgressionRequest(req) {
|
|
101
|
+
const numExamples = Math.min(req.numExamples ?? MAX_EXAMPLES, MAX_EXAMPLES);
|
|
102
|
+
// Try form template first
|
|
103
|
+
const template = findTemplate(req.progression);
|
|
104
|
+
let numerals;
|
|
105
|
+
let progressionName;
|
|
106
|
+
if (template) {
|
|
107
|
+
numerals = template.numerals;
|
|
108
|
+
progressionName = template.name;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
numerals = tokenizeProgression(req.progression);
|
|
112
|
+
progressionName = numerals.join("-");
|
|
113
|
+
}
|
|
114
|
+
// Resolve roman numerals to chord symbols in the key
|
|
115
|
+
const chords = resolveProgression(numerals, req.key);
|
|
116
|
+
// Determine voicing styles for each example
|
|
117
|
+
const styles = req.styleHint
|
|
118
|
+
? getStyleVariations(req.styleHint)
|
|
119
|
+
: CONTRASTING_STYLES.slice(0, numExamples);
|
|
120
|
+
const examples = [];
|
|
121
|
+
for (let i = 0; i < numExamples; i++) {
|
|
122
|
+
const style = styles[i % styles.length];
|
|
123
|
+
const voicedChords = chords.map((c) => voiceChord(c.symbol, style));
|
|
124
|
+
examples.push({
|
|
125
|
+
label: `Example ${i + 1} — ${style}`,
|
|
126
|
+
chords: voicedChords,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
progressionName,
|
|
131
|
+
key: req.key,
|
|
132
|
+
examples,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=progression-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progression-resolver.js","sourceRoot":"","sources":["../../src/progression/progression-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface RomanNumeralChord {
|
|
2
|
+
root: string;
|
|
3
|
+
symbol: string;
|
|
4
|
+
degree: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a roman numeral progression in a given key.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveProgression(numerals: string[], key: string): RomanNumeralChord[];
|
|
10
|
+
/**
|
|
11
|
+
* Parse a progression string like "ii-V-I" or "ii V7 Imaj7" into tokens.
|
|
12
|
+
*/
|
|
13
|
+
export declare function tokenizeProgression(input: string): string[];
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Note } from "tonal";
|
|
2
|
+
import { spellWithPreference } from "../engine/note-spelling";
|
|
3
|
+
const ROMAN_TO_SEMITONE = {
|
|
4
|
+
i: 0, ii: 2, iii: 4, iv: 5, v: 7, vi: 9, vii: 11,
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Parse a single roman numeral token like "ii", "V7", "bIII", "#ivø7", "viio7"
|
|
8
|
+
*/
|
|
9
|
+
function parseRomanToken(token) {
|
|
10
|
+
// Alternation order matters: "iv" before "i" (otherwise "i" matches first
|
|
11
|
+
// in "iv"), "vi{1,2}" before "v" (otherwise "v" matches first in "vi").
|
|
12
|
+
// "i{1,3}" handles i, ii, iii. Suffix group (.*) captures quality markers.
|
|
13
|
+
const re = /^([#b]?)(iv|vi{1,2}|i{1,3}|v)(.*)/i;
|
|
14
|
+
const m = token.match(re);
|
|
15
|
+
if (!m)
|
|
16
|
+
return null;
|
|
17
|
+
const accidental = m[1];
|
|
18
|
+
const numeral = m[2];
|
|
19
|
+
const suffix = m[3];
|
|
20
|
+
const lower = numeral.toLowerCase();
|
|
21
|
+
const base = ROMAN_TO_SEMITONE[lower];
|
|
22
|
+
if (base === undefined)
|
|
23
|
+
return null;
|
|
24
|
+
let semitones = base;
|
|
25
|
+
if (accidental === "b")
|
|
26
|
+
semitones -= 1;
|
|
27
|
+
if (accidental === "#")
|
|
28
|
+
semitones += 1;
|
|
29
|
+
semitones = ((semitones % 12) + 12) % 12;
|
|
30
|
+
const isMinor = numeral === numeral.toLowerCase();
|
|
31
|
+
let quality = "";
|
|
32
|
+
if (suffix) {
|
|
33
|
+
let norm = suffix
|
|
34
|
+
.replace(/^°7/, "dim7")
|
|
35
|
+
.replace(/^°/, "dim")
|
|
36
|
+
.replace(/^ø7?/, "m7b5")
|
|
37
|
+
.replace(/^Δ7?/, "maj7");
|
|
38
|
+
if (isMinor && !norm.startsWith("m") && !norm.startsWith("dim") && !norm.startsWith("M")) {
|
|
39
|
+
quality = "m" + norm;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
quality = norm;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
quality = isMinor ? "m" : "";
|
|
47
|
+
}
|
|
48
|
+
return { semitones, quality, hasFlat: accidental === "b" };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a roman numeral progression in a given key.
|
|
52
|
+
*/
|
|
53
|
+
export function resolveProgression(numerals, key) {
|
|
54
|
+
const keyMidi = Note.midi(`${key}4`);
|
|
55
|
+
if (keyMidi == null)
|
|
56
|
+
throw new Error(`Invalid key: ${key}`);
|
|
57
|
+
return numerals.map((token) => {
|
|
58
|
+
const parsed = parseRomanToken(token);
|
|
59
|
+
if (!parsed)
|
|
60
|
+
throw new Error(`Can't parse roman numeral: "${token}"`);
|
|
61
|
+
const rootMidi = keyMidi + parsed.semitones;
|
|
62
|
+
const rootNote = Note.pitchClass(Note.fromMidi(rootMidi));
|
|
63
|
+
const root = spellWithPreference(rootNote, key, parsed.hasFlat);
|
|
64
|
+
const symbol = root + parsed.quality;
|
|
65
|
+
return { root, symbol, degree: parsed.semitones };
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parse a progression string like "ii-V-I" or "ii V7 Imaj7" into tokens.
|
|
70
|
+
*/
|
|
71
|
+
export function tokenizeProgression(input) {
|
|
72
|
+
return input
|
|
73
|
+
.split(/[\s\-–—→>]+/)
|
|
74
|
+
.map((t) => t.trim())
|
|
75
|
+
.filter((t) => t.length > 0);
|
|
76
|
+
}
|
|
77
|
+
// preferredEnharmonic is now spellWithPreference from note-spelling.ts
|
|
78
|
+
//# sourceMappingURL=roman-numeral.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roman-numeral.js","sourceRoot":"","sources":["../../src/progression/roman-numeral.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { WhiteNote } from "../types";
|
|
2
|
+
/** Check if a white-key index (mod 7) has a sharp. */
|
|
3
|
+
export declare function whiteIdxHasSharp(idx: number): boolean;
|
|
4
|
+
export interface LayoutOptions {
|
|
5
|
+
padding?: number;
|
|
6
|
+
startingNote?: string;
|
|
7
|
+
spanFrom?: string;
|
|
8
|
+
spanTo?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LayoutResult {
|
|
11
|
+
startFrom: WhiteNote;
|
|
12
|
+
size: number;
|
|
13
|
+
/** Relative octave where the lowest chord note sits (for octave-qualified highlights). */
|
|
14
|
+
chordOctave: number;
|
|
15
|
+
/** True when the left edge was extended for black-key context (crop half a key). */
|
|
16
|
+
clipLeft?: boolean;
|
|
17
|
+
/** True when the right edge was extended for black-key context (crop half a key). */
|
|
18
|
+
clipRight?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function calculateLayout(notes: string[], options?: LayoutOptions): LayoutResult;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { WHITE_NOTE_ORDER } from "../engine/svg-constants";
|
|
2
|
+
import { normalizeToSharps } from "../engine/note-spelling";
|
|
3
|
+
// White notes that have a sharp (black key to their right)
|
|
4
|
+
const HAS_SHARP = new Set(["C", "D", "F", "G", "A"]);
|
|
5
|
+
/** Check if a white-key index (mod 7) has a sharp. */
|
|
6
|
+
export function whiteIdxHasSharp(idx) {
|
|
7
|
+
return HAS_SHARP.has(WHITE_NOTE_ORDER[((idx % 7) + 7) % 7]);
|
|
8
|
+
}
|
|
9
|
+
// Map a note to its nearest white key (the white key it sits on or just below)
|
|
10
|
+
function nearestWhiteKey(note) {
|
|
11
|
+
const normalized = normalizeToSharps(note);
|
|
12
|
+
const base = normalized.replace("#", "");
|
|
13
|
+
return base;
|
|
14
|
+
}
|
|
15
|
+
// Count white keys from one white note to another (inclusive of start, exclusive of end)
|
|
16
|
+
function whiteKeySpan(from, to) {
|
|
17
|
+
const fromIdx = WHITE_NOTE_ORDER.indexOf(from);
|
|
18
|
+
let toIdx = WHITE_NOTE_ORDER.indexOf(to);
|
|
19
|
+
if (toIdx < fromIdx)
|
|
20
|
+
toIdx += 7;
|
|
21
|
+
return toIdx - fromIdx;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Ensure the visible keyboard range doesn't cut through the middle of a
|
|
25
|
+
* black-key group, making orientation difficult.
|
|
26
|
+
*
|
|
27
|
+
* Piano keys form repeating groups:
|
|
28
|
+
* - 2-group: C(0), D(1), E(2) — black keys C#, D#
|
|
29
|
+
* - 3-group: F(3), G(4), A(5), B(6) — black keys F#, G#, A#
|
|
30
|
+
*
|
|
31
|
+
* Rule: if the keyboard starts or ends in the INTERIOR of a group
|
|
32
|
+
* (not at its boundary), extend outward to the nearest group boundary.
|
|
33
|
+
* Starting/ending at a group boundary (C, F, E, B) is fine — the edge
|
|
34
|
+
* itself provides enough orientation context.
|
|
35
|
+
*/
|
|
36
|
+
function ensureFullBlackKeyGroups(startIdx, endIdx) {
|
|
37
|
+
// Determine which position within a group the start/end falls
|
|
38
|
+
// Group boundaries: C(0)=start of 2-group, F(3)=start of 3-group
|
|
39
|
+
// Interior: D(1), E(2) are interior of 2-group; G(4), A(5) are interior of 3-group
|
|
40
|
+
// B(6) is the end of the 3-group — a boundary, fine to start/end on
|
|
41
|
+
const startMod = ((startIdx % 7) + 7) % 7;
|
|
42
|
+
const endMod = ((endIdx % 7) + 7) % 7;
|
|
43
|
+
// Fix left edge: if we start in the interior of a group, extend left to group start.
|
|
44
|
+
// Group boundaries (OK to start on): C(0), F(3), E(2)→end of 2-group, B(6)→end of 3-group
|
|
45
|
+
// Interior (confusing): D(1), G(4), A(5)
|
|
46
|
+
if (startMod === 1)
|
|
47
|
+
startIdx -= 1; // D → extend to C
|
|
48
|
+
if (startMod === 4)
|
|
49
|
+
startIdx -= 1; // G → extend to F
|
|
50
|
+
if (startMod === 5)
|
|
51
|
+
startIdx -= 2; // A → extend to F
|
|
52
|
+
// Fix right edge: if we end in the interior of a group, extend right to group end.
|
|
53
|
+
// Group boundaries (OK to end on): E(2), B(6), C(0)→start of 2-group, F(3)→start of 3-group
|
|
54
|
+
// Interior (confusing): D(1), G(4), A(5)
|
|
55
|
+
if (endMod === 1)
|
|
56
|
+
endIdx += 1; // D → extend to E
|
|
57
|
+
if (endMod === 4)
|
|
58
|
+
endIdx += 2; // G → extend to B
|
|
59
|
+
if (endMod === 5)
|
|
60
|
+
endIdx += 1; // A → extend to B
|
|
61
|
+
return { startIdx, endIdx };
|
|
62
|
+
}
|
|
63
|
+
export function calculateLayout(notes, options = {}) {
|
|
64
|
+
const { padding = 1, startingNote, spanFrom, spanTo } = options;
|
|
65
|
+
// Explicit starting note: anchor the keyboard there
|
|
66
|
+
if (startingNote) {
|
|
67
|
+
const anchorKey = nearestWhiteKey(startingNote);
|
|
68
|
+
let startIdx = WHITE_NOTE_ORDER.indexOf(anchorKey) - padding;
|
|
69
|
+
// Black-key context: extend left edge if it has a sharp
|
|
70
|
+
let clipLeft = false;
|
|
71
|
+
if (whiteIdxHasSharp(startIdx)) {
|
|
72
|
+
startIdx -= 1;
|
|
73
|
+
clipLeft = true;
|
|
74
|
+
}
|
|
75
|
+
const start = WHITE_NOTE_ORDER[((startIdx % 7) + 7) % 7];
|
|
76
|
+
// Size the keyboard to fit all notes with padding on the right
|
|
77
|
+
if (notes.length > 0) {
|
|
78
|
+
const whiteKeys = notes.map(nearestWhiteKey);
|
|
79
|
+
// Treat notes as ascending from the anchor: each note at or below
|
|
80
|
+
// the previous wraps into the next octave (matches voicing rotation).
|
|
81
|
+
const anchorWhiteIdx = WHITE_NOTE_ORDER.indexOf(anchorKey);
|
|
82
|
+
const indices = [];
|
|
83
|
+
for (const w of whiteKeys) {
|
|
84
|
+
let idx = WHITE_NOTE_ORDER.indexOf(w);
|
|
85
|
+
if (indices.length === 0) {
|
|
86
|
+
// First note: place relative to anchor (must be >= anchor)
|
|
87
|
+
while (idx < anchorWhiteIdx)
|
|
88
|
+
idx += 7;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Subsequent notes: must be above the previous
|
|
92
|
+
const lastIdx = indices[indices.length - 1];
|
|
93
|
+
while (idx <= lastIdx)
|
|
94
|
+
idx += 7;
|
|
95
|
+
}
|
|
96
|
+
indices.push(idx);
|
|
97
|
+
}
|
|
98
|
+
const maxIdx = Math.max(...indices);
|
|
99
|
+
let endIdx = maxIdx + padding;
|
|
100
|
+
// Black-key context: extend right edge if it lands on a sharp key
|
|
101
|
+
let clipRight = false;
|
|
102
|
+
if (whiteIdxHasSharp(endIdx)) {
|
|
103
|
+
endIdx += 1;
|
|
104
|
+
clipRight = true;
|
|
105
|
+
}
|
|
106
|
+
// Ensure full black-key groups are visible
|
|
107
|
+
const expanded = ensureFullBlackKeyGroups(startIdx, endIdx);
|
|
108
|
+
startIdx = expanded.startIdx;
|
|
109
|
+
endIdx = expanded.endIdx;
|
|
110
|
+
const finalStart = WHITE_NOTE_ORDER[((startIdx % 7) + 7) % 7];
|
|
111
|
+
let span = endIdx - startIdx + 1;
|
|
112
|
+
// chordOctave: count C crossings from start to the anchor note
|
|
113
|
+
const anchorIdx = WHITE_NOTE_ORDER.indexOf(anchorKey);
|
|
114
|
+
const startNoteIdx = WHITE_NOTE_ORDER.indexOf(finalStart);
|
|
115
|
+
const rawSteps = ((anchorIdx - startNoteIdx) % 7 + 7) % 7;
|
|
116
|
+
// Only add a full octave if the modular distance is 0 (anchor == start)
|
|
117
|
+
// AND there is padding (meaning the anchor is actually one octave away)
|
|
118
|
+
const stepsToAnchor = rawSteps === 0 && padding > 0 ? 7 : rawSteps;
|
|
119
|
+
let chordOctave = 0;
|
|
120
|
+
for (let i = 1; i <= stepsToAnchor; i++) {
|
|
121
|
+
if (WHITE_NOTE_ORDER[(startNoteIdx + i) % 7] === "C")
|
|
122
|
+
chordOctave++;
|
|
123
|
+
}
|
|
124
|
+
return { startFrom: finalStart, size: Math.max(span, notes.length + 2), chordOctave, clipLeft, clipRight };
|
|
125
|
+
}
|
|
126
|
+
return { startFrom: start, size: 8, chordOctave: 0, clipLeft };
|
|
127
|
+
}
|
|
128
|
+
if (spanFrom && spanTo) {
|
|
129
|
+
const from = nearestWhiteKey(spanFrom);
|
|
130
|
+
const to = nearestWhiteKey(spanTo);
|
|
131
|
+
const span = whiteKeySpan(from, to);
|
|
132
|
+
return {
|
|
133
|
+
startFrom: from,
|
|
134
|
+
size: span === 0 ? 8 : span + 1,
|
|
135
|
+
chordOctave: 0,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (notes.length === 0) {
|
|
139
|
+
return { startFrom: "C", size: 8, chordOctave: 0 };
|
|
140
|
+
}
|
|
141
|
+
// Treat notes as an ascending sequence: each note that is at or below
|
|
142
|
+
// the previous one (in white-key index) wraps into the next octave.
|
|
143
|
+
const whiteKeys = notes.map(nearestWhiteKey);
|
|
144
|
+
const ascending = [];
|
|
145
|
+
for (const w of whiteKeys) {
|
|
146
|
+
let idx = WHITE_NOTE_ORDER.indexOf(w);
|
|
147
|
+
if (ascending.length > 0) {
|
|
148
|
+
const lastIdx = ascending[ascending.length - 1];
|
|
149
|
+
while (idx <= lastIdx)
|
|
150
|
+
idx += 7;
|
|
151
|
+
}
|
|
152
|
+
ascending.push(idx);
|
|
153
|
+
}
|
|
154
|
+
const minAsc = ascending[0];
|
|
155
|
+
const maxAsc = ascending[ascending.length - 1];
|
|
156
|
+
let startIdx = minAsc - padding;
|
|
157
|
+
let endIdx = maxAsc + padding;
|
|
158
|
+
// Black-key context padding: if an edge white key has a sharp, extend by 1
|
|
159
|
+
// so the neighboring black key is visible, giving orientation landmarks.
|
|
160
|
+
let clipLeft = false;
|
|
161
|
+
let clipRight = false;
|
|
162
|
+
if (whiteIdxHasSharp(startIdx)) {
|
|
163
|
+
startIdx -= 1;
|
|
164
|
+
clipLeft = true;
|
|
165
|
+
}
|
|
166
|
+
if (whiteIdxHasSharp(endIdx)) {
|
|
167
|
+
endIdx += 1;
|
|
168
|
+
clipRight = true;
|
|
169
|
+
}
|
|
170
|
+
// Ensure full black-key groups are visible for keyboard orientation.
|
|
171
|
+
// If we can see part of the 3-group (F-B) or 2-group (C-E), show all of it.
|
|
172
|
+
const expanded = ensureFullBlackKeyGroups(startIdx, endIdx);
|
|
173
|
+
startIdx = expanded.startIdx;
|
|
174
|
+
endIdx = expanded.endIdx;
|
|
175
|
+
const startNote = WHITE_NOTE_ORDER[((startIdx % 7) + 7) % 7];
|
|
176
|
+
const keyCount = endIdx - startIdx + 1;
|
|
177
|
+
// Calculate which relative octave the chord notes live in.
|
|
178
|
+
// Count how many times we cross C going from startNote to the first chord note.
|
|
179
|
+
const actualPadding = minAsc - startIdx;
|
|
180
|
+
const startNoteIdx = WHITE_NOTE_ORDER.indexOf(startNote);
|
|
181
|
+
let chordOctave = 0;
|
|
182
|
+
for (let i = 1; i <= actualPadding; i++) {
|
|
183
|
+
const noteIdx = (startNoteIdx + i) % 7;
|
|
184
|
+
if (WHITE_NOTE_ORDER[noteIdx] === "C")
|
|
185
|
+
chordOctave++;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
startFrom: startNote,
|
|
189
|
+
size: Math.max(keyCount, notes.length + 2),
|
|
190
|
+
chordOctave,
|
|
191
|
+
clipLeft,
|
|
192
|
+
clipRight,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=auto-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-layout.js","sourceRoot":"","sources":["../../src/resolver/auto-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ResolvedChord {
|
|
2
|
+
notes: string[];
|
|
3
|
+
root: string;
|
|
4
|
+
type: string;
|
|
5
|
+
/** Tonal interval names when available (e.g. ["1P", "3M", "5P", "7M"]) */
|
|
6
|
+
intervals?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveChord(chordName: string, inversion?: number): ResolvedChord;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Chord, Note } from "tonal";
|
|
2
|
+
/**
|
|
3
|
+
* Simplify a note name via Tonal without forcing sharp spelling.
|
|
4
|
+
* Tonal's simplify already respects musical context (e.g. Bb stays Bb).
|
|
5
|
+
*/
|
|
6
|
+
function simplifyNote(note) {
|
|
7
|
+
const simplified = Note.simplify(note);
|
|
8
|
+
return simplified || note;
|
|
9
|
+
}
|
|
10
|
+
// Alteration tokens we can strip and re-apply as intervals
|
|
11
|
+
const ALTERATION_RE = /([#b](?:5|9|11|13)|add(?:9|11|13|b9|#9|b13|#11))$/;
|
|
12
|
+
const ALTERATION_TO_INTERVAL = {
|
|
13
|
+
"#5": "5A",
|
|
14
|
+
"b5": "5d",
|
|
15
|
+
"#9": "2A",
|
|
16
|
+
"b9": "2m",
|
|
17
|
+
"#11": "4A",
|
|
18
|
+
"b11": "4d",
|
|
19
|
+
"#13": "6A",
|
|
20
|
+
"b13": "6m",
|
|
21
|
+
"add9": "2M",
|
|
22
|
+
"add11": "4P",
|
|
23
|
+
"add13": "6M",
|
|
24
|
+
"addb9": "2m",
|
|
25
|
+
"add#9": "2A",
|
|
26
|
+
"add#11": "4A",
|
|
27
|
+
"addb13": "6m",
|
|
28
|
+
};
|
|
29
|
+
// Try to resolve by stripping trailing alterations one at a time,
|
|
30
|
+
// then transposing the root by those intervals to get extra notes
|
|
31
|
+
function resolveWithFallback(chordName) {
|
|
32
|
+
// Extract root note
|
|
33
|
+
const rootMatch = chordName.match(/^([A-G][#b]?)/);
|
|
34
|
+
if (!rootMatch)
|
|
35
|
+
return null;
|
|
36
|
+
const root = rootMatch[1];
|
|
37
|
+
let suffix = chordName.slice(root.length);
|
|
38
|
+
const extraIntervals = [];
|
|
39
|
+
// Strip alterations from the end until Tonal recognizes the base
|
|
40
|
+
let attempts = 0;
|
|
41
|
+
while (suffix && attempts < 5) {
|
|
42
|
+
const match = suffix.match(ALTERATION_RE);
|
|
43
|
+
if (!match)
|
|
44
|
+
break;
|
|
45
|
+
const token = match[1];
|
|
46
|
+
const interval = ALTERATION_TO_INTERVAL[token];
|
|
47
|
+
if (!interval)
|
|
48
|
+
break;
|
|
49
|
+
extraIntervals.unshift(interval);
|
|
50
|
+
suffix = suffix.slice(0, -token.length);
|
|
51
|
+
attempts++;
|
|
52
|
+
const chord = Chord.get(root + suffix);
|
|
53
|
+
if (!chord.empty) {
|
|
54
|
+
let notes = chord.notes.map(simplifyNote);
|
|
55
|
+
// Add extra notes from stripped alterations
|
|
56
|
+
for (const ivl of extraIntervals) {
|
|
57
|
+
const extra = Note.transpose(root, ivl);
|
|
58
|
+
if (extra) {
|
|
59
|
+
const normalized = simplifyNote(extra);
|
|
60
|
+
// Replace if same degree already exists, otherwise add
|
|
61
|
+
if (!notes.includes(normalized)) {
|
|
62
|
+
notes.push(normalized);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { notes, root: simplifyNote(root), type: chord.type + " (extended)" };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Normalize chord symbols that Tonal doesn't recognize into equivalents
|
|
72
|
+
function normalizeChordName(name) {
|
|
73
|
+
// Extract root note first
|
|
74
|
+
const rootMatch = name.match(/^([A-G][#b]?)/i);
|
|
75
|
+
if (!rootMatch)
|
|
76
|
+
return name;
|
|
77
|
+
const root = rootMatch[1];
|
|
78
|
+
let suffix = name.slice(root.length);
|
|
79
|
+
// m7sus is special — handled by buildSpecialChord, don't normalize it away
|
|
80
|
+
// Cmaug → Cm#5 (minor augmented)
|
|
81
|
+
suffix = suffix.replace(/^maug$/i, "m#5");
|
|
82
|
+
// Cm6/9 → Cm6add9 (Tonal doesn't know m6/9 but knows the notes)
|
|
83
|
+
// Actually build it manually below via special handling
|
|
84
|
+
// CmMaj → CmM (Tonal recognizes mM but not mmaj for some roots)
|
|
85
|
+
// Dbmmaj7 → DbmMaj7 — ensure proper casing
|
|
86
|
+
suffix = suffix.replace(/mmaj/i, "mMaj");
|
|
87
|
+
// omit3 → remove, we'll handle it post-resolution
|
|
88
|
+
// Keep it for now, handle in resolveChord
|
|
89
|
+
return root + suffix;
|
|
90
|
+
}
|
|
91
|
+
// Special chord builders for symbols Tonal can't handle at all
|
|
92
|
+
function buildSpecialChord(name) {
|
|
93
|
+
const rootMatch = name.match(/^([A-G][#b]?)/i);
|
|
94
|
+
if (!rootMatch)
|
|
95
|
+
return null;
|
|
96
|
+
const root = rootMatch[1];
|
|
97
|
+
const suffix = name.slice(root.length);
|
|
98
|
+
// X7omit3 → root, 5th, b7 (no 3rd)
|
|
99
|
+
if (/^7omit3$/i.test(suffix)) {
|
|
100
|
+
return {
|
|
101
|
+
notes: [root, Note.transpose(root, "5P"), Note.transpose(root, "7m")].map(simplifyNote),
|
|
102
|
+
root: simplifyNote(root),
|
|
103
|
+
type: "7omit3",
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Xm7sus / Xm7sus4 → root, m3, P4, m7
|
|
107
|
+
if (/^m7sus4?$/i.test(suffix)) {
|
|
108
|
+
return {
|
|
109
|
+
notes: [
|
|
110
|
+
root,
|
|
111
|
+
Note.transpose(root, "3m"),
|
|
112
|
+
Note.transpose(root, "4P"),
|
|
113
|
+
Note.transpose(root, "7m"),
|
|
114
|
+
].map(simplifyNote),
|
|
115
|
+
root: simplifyNote(root),
|
|
116
|
+
type: "m7sus4",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Xm6/9 → root, m3, 5, 6, 9
|
|
120
|
+
if (/^m6\/9$/i.test(suffix)) {
|
|
121
|
+
return {
|
|
122
|
+
notes: [
|
|
123
|
+
root,
|
|
124
|
+
Note.transpose(root, "3m"),
|
|
125
|
+
Note.transpose(root, "5P"),
|
|
126
|
+
Note.transpose(root, "6M"),
|
|
127
|
+
Note.transpose(root, "2M"),
|
|
128
|
+
].map(simplifyNote),
|
|
129
|
+
root: simplifyNote(root),
|
|
130
|
+
type: "m6/9",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
export function resolveChord(chordName, inversion) {
|
|
136
|
+
chordName = normalizeChordName(chordName);
|
|
137
|
+
const chord = Chord.get(chordName);
|
|
138
|
+
let notes;
|
|
139
|
+
let root;
|
|
140
|
+
let type;
|
|
141
|
+
let intervals;
|
|
142
|
+
// Try special chord builders first (omit3, m6/9, etc.)
|
|
143
|
+
const special = buildSpecialChord(chordName);
|
|
144
|
+
if (special) {
|
|
145
|
+
notes = special.notes;
|
|
146
|
+
root = special.root;
|
|
147
|
+
type = special.type;
|
|
148
|
+
}
|
|
149
|
+
else if (!chord.empty) {
|
|
150
|
+
notes = chord.notes.map(simplifyNote);
|
|
151
|
+
root = simplifyNote(chord.tonic ?? notes[0]);
|
|
152
|
+
type = chord.type;
|
|
153
|
+
intervals = chord.intervals;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Fallback: strip trailing alterations and reapply as intervals
|
|
157
|
+
const fallback = resolveWithFallback(chordName);
|
|
158
|
+
if (!fallback) {
|
|
159
|
+
throw new Error(`Unknown chord: "${chordName}"`);
|
|
160
|
+
}
|
|
161
|
+
notes = fallback.notes;
|
|
162
|
+
root = fallback.root;
|
|
163
|
+
type = fallback.type;
|
|
164
|
+
}
|
|
165
|
+
// Apply inversion: rotate notes array
|
|
166
|
+
if (inversion && inversion > 0) {
|
|
167
|
+
const rotation = inversion % notes.length;
|
|
168
|
+
notes = [...notes.slice(rotation), ...notes.slice(0, rotation)];
|
|
169
|
+
}
|
|
170
|
+
return { notes, root, type, intervals };
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=chord-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chord-resolver.js","sourceRoot":"","sources":["../../src/resolver/chord-resolver.ts"],"names":[],"mappings":"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"}
|