@libraz/libcantus 1.0.1 → 1.2.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.
Files changed (142) hide show
  1. package/README.md +27 -65
  2. package/README_ja.md +28 -66
  3. package/dist/analyze/index.cjs +11 -7
  4. package/dist/analyze/index.cjs.map +1 -1
  5. package/dist/analyze/index.d.cts +79 -144
  6. package/dist/analyze/index.d.ts +79 -144
  7. package/dist/analyze/index.js +20 -16
  8. package/dist/chunk-35NBV2FT.cjs +145 -0
  9. package/dist/chunk-35NBV2FT.cjs.map +1 -0
  10. package/dist/{chunk-UADYAYAT.cjs → chunk-3R3QVKY5.cjs} +1353 -580
  11. package/dist/chunk-3R3QVKY5.cjs.map +1 -0
  12. package/dist/{chunk-WWURE4XT.cjs → chunk-76ZBTRG2.cjs} +624 -729
  13. package/dist/chunk-76ZBTRG2.cjs.map +1 -0
  14. package/dist/{chunk-FVSI36UV.js → chunk-7KG3RTYS.js} +197 -110
  15. package/dist/chunk-7KG3RTYS.js.map +1 -0
  16. package/dist/{chunk-VTI6FOLB.js → chunk-AGOVW7U6.js} +709 -133
  17. package/dist/chunk-AGOVW7U6.js.map +1 -0
  18. package/dist/{chunk-E3F4AHAH.cjs → chunk-CGBADIO5.cjs} +221 -134
  19. package/dist/chunk-CGBADIO5.cjs.map +1 -0
  20. package/dist/{chunk-6XH6QZYQ.cjs → chunk-DSMJRXCZ.cjs} +1455 -849
  21. package/dist/chunk-DSMJRXCZ.cjs.map +1 -0
  22. package/dist/{chunk-PKFNUHDY.js → chunk-FBH75DAY.js} +1218 -612
  23. package/dist/chunk-FBH75DAY.js.map +1 -0
  24. package/dist/chunk-H2KJHBW4.js +3329 -0
  25. package/dist/chunk-H2KJHBW4.js.map +1 -0
  26. package/dist/chunk-HPVSH7SF.cjs +2294 -0
  27. package/dist/chunk-HPVSH7SF.cjs.map +1 -0
  28. package/dist/{chunk-MXO72PLY.cjs → chunk-HWHGOVO6.cjs} +21 -19
  29. package/dist/chunk-HWHGOVO6.cjs.map +1 -0
  30. package/dist/chunk-HYJJ2V2I.js +2294 -0
  31. package/dist/chunk-HYJJ2V2I.js.map +1 -0
  32. package/dist/{chunk-AFM2ULJH.cjs → chunk-J7FHVZII.cjs} +1567 -1067
  33. package/dist/chunk-J7FHVZII.cjs.map +1 -0
  34. package/dist/chunk-K6OZXIR6.js +1 -0
  35. package/dist/{chunk-H3VORETI.js → chunk-M5RYMAFI.js} +487 -592
  36. package/dist/chunk-M5RYMAFI.js.map +1 -0
  37. package/dist/chunk-NB25P3EH.js +363 -0
  38. package/dist/chunk-NB25P3EH.js.map +1 -0
  39. package/dist/{chunk-TTCLJX6D.js → chunk-NFJ4P6ZZ.js} +10 -8
  40. package/dist/chunk-NFJ4P6ZZ.js.map +1 -0
  41. package/dist/chunk-NM7UAMC3.cjs +457 -0
  42. package/dist/chunk-NM7UAMC3.cjs.map +1 -0
  43. package/dist/chunk-PM4XJE2Y.cjs +363 -0
  44. package/dist/chunk-PM4XJE2Y.cjs.map +1 -0
  45. package/dist/chunk-PUKJP2Z5.js +145 -0
  46. package/dist/chunk-PUKJP2Z5.js.map +1 -0
  47. package/dist/{chunk-VOHZB45S.js → chunk-Q6LFSAKV.js} +1321 -821
  48. package/dist/chunk-Q6LFSAKV.js.map +1 -0
  49. package/dist/{chunk-INHVXP6Z.js → chunk-RFIBF2RR.js} +1203 -430
  50. package/dist/chunk-RFIBF2RR.js.map +1 -0
  51. package/dist/{chunk-Q2WGKJNN.cjs → chunk-S5BKZZGM.cjs} +699 -123
  52. package/dist/chunk-S5BKZZGM.cjs.map +1 -0
  53. package/dist/chunk-SGLEQVJH.cjs +3329 -0
  54. package/dist/chunk-SGLEQVJH.cjs.map +1 -0
  55. package/dist/chunk-UGLFDG7L.cjs +1 -0
  56. package/dist/chunk-UGLFDG7L.cjs.map +1 -0
  57. package/dist/{chunk-YH3BIKHH.js → chunk-UMWZ4ZET.js} +146 -49
  58. package/dist/chunk-UMWZ4ZET.js.map +1 -0
  59. package/dist/{index-szBv3496.d.ts → coerce-DP0vYu-x.d.ts} +286 -199
  60. package/dist/{index-C_8o--VE.d.cts → coerce-DRERzdve.d.cts} +286 -199
  61. package/dist/core/index.cjs +9 -5
  62. package/dist/core/index.cjs.map +1 -1
  63. package/dist/core/index.d.cts +122 -108
  64. package/dist/core/index.d.ts +122 -108
  65. package/dist/core/index.js +32 -28
  66. package/dist/generate/index.cjs +8 -8
  67. package/dist/generate/index.d.cts +168 -84
  68. package/dist/generate/index.d.ts +168 -84
  69. package/dist/generate/index.js +7 -7
  70. package/dist/{index-CGpRv5sl.d.cts → index-9eoQs2C1.d.ts} +34 -19
  71. package/dist/{index-CCNJRG-P.d.cts → index-B9QLziDe.d.cts} +293 -56
  72. package/dist/{index-Dzr13q3d.d.cts → index-BBWNZS0f.d.cts} +135 -58
  73. package/dist/{index-9wcMhG73.d.ts → index-BHIUyjhZ.d.ts} +293 -56
  74. package/dist/{index-BGFW-8P2.d.cts → index-BJgP97N1.d.ts} +196 -114
  75. package/dist/{index-CunYKLiu.d.ts → index-BL5N2Oyz.d.cts} +1 -1
  76. package/dist/{index-Cj49F892.d.ts → index-BMweUlm5.d.cts} +63 -23
  77. package/dist/{index-CgHqxdps.d.ts → index-BNSM-DSk.d.cts} +196 -114
  78. package/dist/{index-D57QRbVn.d.ts → index-BRMbPkHE.d.ts} +480 -254
  79. package/dist/{index-Chbst3Jx.d.ts → index-CJBBiAmU.d.ts} +135 -58
  80. package/dist/{index-BkGmlyI3.d.cts → index-CL4b4gUQ.d.ts} +63 -23
  81. package/dist/{index-B9MNZboQ.d.ts → index-Cy15oTvh.d.cts} +52 -22
  82. package/dist/{index-B9MNZboQ.d.cts → index-Cy15oTvh.d.ts} +52 -22
  83. package/dist/{index-BO6xE9YU.d.cts → index-DGCNKAUr.d.cts} +480 -254
  84. package/dist/{index-B4o55NDr.d.cts → index-Dw2DP7vm.d.ts} +1 -1
  85. package/dist/{index-G1uwGGWQ.d.ts → index-cHvbYgJI.d.cts} +34 -19
  86. package/dist/index.cjs +42 -14
  87. package/dist/index.cjs.map +1 -1
  88. package/dist/index.d.cts +14 -14
  89. package/dist/index.d.ts +14 -14
  90. package/dist/index.js +82 -54
  91. package/dist/{masks-DYbE485J.d.cts → masks-Cc7-MzzY.d.ts} +49 -2
  92. package/dist/{masks-DYbE485J.d.ts → masks-pADfTOiD.d.cts} +49 -2
  93. package/dist/model/index.cjs +19 -12
  94. package/dist/model/index.cjs.map +1 -1
  95. package/dist/model/index.d.cts +504 -182
  96. package/dist/model/index.d.ts +504 -182
  97. package/dist/model/index.js +18 -11
  98. package/dist/{positional-Cptlj-xs.d.ts → positional-DJgs6ltD.d.ts} +85 -8
  99. package/dist/{positional-DvH_sd8u.d.cts → positional-DMZer-FM.d.cts} +85 -8
  100. package/dist/theory/index.cjs +35 -6
  101. package/dist/theory/index.cjs.map +1 -1
  102. package/dist/theory/index.d.cts +257 -62
  103. package/dist/theory/index.d.ts +257 -62
  104. package/dist/theory/index.js +41 -12
  105. package/package.json +7 -5
  106. package/dist/chunk-2LCPM3EG.js +0 -3224
  107. package/dist/chunk-2LCPM3EG.js.map +0 -1
  108. package/dist/chunk-6XH6QZYQ.cjs.map +0 -1
  109. package/dist/chunk-6XPTBE7Y.cjs +0 -49
  110. package/dist/chunk-6XPTBE7Y.cjs.map +0 -1
  111. package/dist/chunk-AFM2ULJH.cjs.map +0 -1
  112. package/dist/chunk-B6XNKWZV.cjs +0 -3224
  113. package/dist/chunk-B6XNKWZV.cjs.map +0 -1
  114. package/dist/chunk-E3F4AHAH.cjs.map +0 -1
  115. package/dist/chunk-ELCTZUJJ.js +0 -379
  116. package/dist/chunk-ELCTZUJJ.js.map +0 -1
  117. package/dist/chunk-FVSI36UV.js.map +0 -1
  118. package/dist/chunk-H3VORETI.js.map +0 -1
  119. package/dist/chunk-H42UHPYW.js +0 -1577
  120. package/dist/chunk-H42UHPYW.js.map +0 -1
  121. package/dist/chunk-HFPS7JFD.js +0 -1
  122. package/dist/chunk-INHVXP6Z.js.map +0 -1
  123. package/dist/chunk-K4ZJUGF4.cjs +0 -379
  124. package/dist/chunk-K4ZJUGF4.cjs.map +0 -1
  125. package/dist/chunk-KNJEKLKV.js +0 -49
  126. package/dist/chunk-KNJEKLKV.js.map +0 -1
  127. package/dist/chunk-MXO72PLY.cjs.map +0 -1
  128. package/dist/chunk-NLEU4QSE.cjs +0 -360
  129. package/dist/chunk-NLEU4QSE.cjs.map +0 -1
  130. package/dist/chunk-OE6WK2Y2.cjs +0 -1577
  131. package/dist/chunk-OE6WK2Y2.cjs.map +0 -1
  132. package/dist/chunk-PKFNUHDY.js.map +0 -1
  133. package/dist/chunk-Q2WGKJNN.cjs.map +0 -1
  134. package/dist/chunk-RHIJ3S4I.cjs +0 -1
  135. package/dist/chunk-RHIJ3S4I.cjs.map +0 -1
  136. package/dist/chunk-TTCLJX6D.js.map +0 -1
  137. package/dist/chunk-UADYAYAT.cjs.map +0 -1
  138. package/dist/chunk-VOHZB45S.js.map +0 -1
  139. package/dist/chunk-VTI6FOLB.js.map +0 -1
  140. package/dist/chunk-WWURE4XT.cjs.map +0 -1
  141. package/dist/chunk-YH3BIKHH.js.map +0 -1
  142. /package/dist/{chunk-HFPS7JFD.js.map → chunk-K6OZXIR6.js.map} +0 -0
@@ -1,21 +1,20 @@
1
- import { d as KeyScale, S as SpelledInterval, f as Note, h as NoteLike } from '../index-B9MNZboQ.cjs';
2
- export { B as BudgetExceededError, I as IntervalLike, b as IntervalQualityLabel, c as InvalidInputError, L as LibcantusError, N as NoSolutionError, i as NoteNameOptions, j as NoteNameSystem, P as ParseResult } from '../index-B9MNZboQ.cjs';
1
+ import { e as KeyScale, j as NoteNameOptions, P as ParseResult, S as SpelledInterval, g as Note, i as NoteLike } from '../index-Cy15oTvh.cjs';
2
+ export { B as BudgetExceededError, I as IntervalData, b as IntervalLike, c as IntervalQualityLabel, d as InvalidInputError, L as LibcantusError, N as NoSolutionError, k as NoteNameSystem } from '../index-Cy15oTvh.cjs';
3
3
  import { C as ConsonanceClass } from '../index-DInQqT8Q.cjs';
4
- import { K as KeyLike, c as ChordLike, b as Chord } from '../index-C_8o--VE.cjs';
5
- export { A as Alteration, a as AlteredDegree, C as ChordBase, d as ChordQuality, e as ChordSegment, f as ChordSeventh, g as ChordSpan, h as ChordSpec, i as ChordSymbolOptions, j as ChordToneRole, E as EvaluateSafetyOptions, k as KeyRelation, N as NoteSafety, P as PROFILE_WEIGHTS, l as PitchSpelling, m as ProfileWeights, R as ReasonFlag, S as SafetyProfile, n as SafetyQuery, o as SafetyResult, p as SpelledKey, V as VoiceSnapshot, q as chordFromDegree, r as chordFromSpan, s as chordFromSpec, t as chordPitchClasses, u as chordQualities, v as chordSpecIntervals, w as chordSpecOf, x as chordSpecQuality, y as chordToneRole, z as diatonicSeventh, B as diatonicTriad, D as dominantKeyOf, F as enharmonicKeyOf, G as enumerateSafePitches, H as evaluateSafety, I as formatChordSymbol, J as intervalAboveRoot, L as isChordMember, M as keyRelationBetween, O as makeChord, Q as parallelKeyOf, T as parseChordSymbol, U as profileWeights, W as relatedKeysOf, X as relativeKeyOf, Y as spanFromChord, Z as spelledKeyOf, _ as subdominantKeyOf, $ as toChordData, a0 as toKeyScale, a1 as transposeChord, a2 as transposeChordSymbol, a3 as tryParseChordSymbol } from '../index-C_8o--VE.cjs';
6
- import { q as VoicingOptions } from '../index-CCNJRG-P.cjs';
7
- export { A as AvailableTensionsOptions, a as AvoidNoteUse, b as AvoidNotesOptions, C as ChordScaleMatch, c as ChordScaleReportEntry, K as KeyMode, P as PartWritingOptions, d as PartWritingViolation, e as PartWritingViolationKind, S as SATB_RANGES, f as SCALE_SYSTEMS, g as ScaleChoice, h as ScaleSystem, i as Species, j as SpeciesOptions, k as SpelledVoicing, l as StyledVoicingOptions, T as TRANSPOSING_INSTRUMENTS, m as TransposingInstrument, n as TransposingInstrumentName, V as VoiceIndependenceOptions, o as VoiceIndependenceReport, p as VoiceRange, r as VoicingStyle, s as availableTensions, t as avoidNotes, u as checkPartWriting, v as checkSpecies, w as chordScaleReport, x as chordScales, y as instrumentTransposition, z as keyFromFifths, B as keySignatureFifths, D as scaleMatchesChord, E as scaleSystemOf, F as scalesForChanges, G as spellVoicing, H as supportsFunctionalHarmony, I as toSoundingPitch, J as toWrittenPitch, L as voiceChord, M as voiceChordStyled, N as voiceIndependence, O as voiceProgression } from '../index-CCNJRG-P.cjs';
8
- export { H as HarmonyRole, L as LockLevel, V as VoicedRole, r as roleOf } from '../index-B4o55NDr.cjs';
9
- import { s as ScaleNameInput } from '../masks-DYbE485J.cjs';
10
- export { A as ALTERED_MASK, B as BLUES_MASK, C as CHROMATIC_MASK, D as DORIAN_MASK, a as DOUBLE_HARMONIC_MASK, H as HARMONIC_MINOR_MASK, L as LOCRIAN_MASK, b as LOCRIAN_NATURAL2_MASK, c as LYDIAN_DOMINANT_MASK, d as LYDIAN_MASK, M as MAJOR_MASK, e as MAJOR_PENTATONIC_MASK, f as MARWA_MASK, g as MELODIC_MINOR_MASK, h as MINOR_PENTATONIC_MASK, i as MIXOLYDIAN_B13_MASK, j as MIXOLYDIAN_MASK, k as MIYAKO_BUSHI_MASK, N as NAMED_SCALES, l as NATURAL_MINOR_MASK, O as OCTATONIC_HALF_WHOLE_MASK, m as OCTATONIC_WHOLE_HALF_MASK, P as PHRYGIAN_DOMINANT_MASK, n as PHRYGIAN_MASK, o as PURVI_MASK, R as RITSU_MASK, p as RYUKYU_MASK, S as SCALE_ALIASES, q as ScaleAliasName, r as ScaleName, T as TODI_MASK, W as WHOLE_TONE_MASK, t as WORLD_SCALES, u as WorldScaleName, v as maskFromOffsets, w as namedScaleMask, x as requireScaleMask, y as resolveScaleName } from '../masks-DYbE485J.cjs';
4
+ import { K as KeyLike, n as ResolvedKey, s as SpelledKeyScale, c as ChordLike, b as Chord, r as SpelledKeyLike } from '../coerce-DRERzdve.cjs';
5
+ export { A as Alteration, a as AlteredDegree, C as ChordBase, d as ChordQuality, e as ChordSegment, f as ChordSeventh, g as ChordSpan, h as ChordSpec, i as ChordToneRole, E as EvaluateSafetyOptions, j as KeyRelation, k as KeyVariant, N as NoteSafety, P as PROFILE_WEIGHTS, l as PitchSpelling, m as ProfileWeights, R as ReasonFlag, S as SafetyPartner, o as SafetyProfile, p as SafetyQuery, q as SafetyResult, V as VoiceSnapshot, t as chordFromDegree, u as chordFromSpan, v as chordFromSpec, w as chordPitchClasses, x as chordQualities, y as chordSpecIntervals, z as chordSpecOf, B as chordSpecQuality, D as chordToneRole, F as diatonicSeventh, G as diatonicTriad, H as dominantKeyOf, I as enharmonicKeyOf, J as enumerateSafePitches, L as evaluateSafety, M as intervalAboveRoot, O as isChordMember, Q as keyRelationBetween, T as makeChord, U as parallelKeyOf, W as profileWeights, X as relatedKeysOf, Y as relativeKeyOf, Z as spanFromChord, _ as spelledKeyOf, $ as subdominantKeyOf, a0 as toChordData, a1 as toKeyScale, a2 as transposeChord } from '../coerce-DRERzdve.cjs';
6
+ import { r as VoicingOptions } from '../index-B9QLziDe.cjs';
7
+ export { A as AvailableTensionsOptions, a as AvoidNoteUse, b as AvoidNotesOptions, C as ChordScaleMatch, c as ChordScaleReportEntry, d as ChordSymbolOptions, K as KeyMode, P as PartWritingOptions, e as PartWritingViolation, f as PartWritingViolationKind, S as SATB_RANGES, g as SCALE_SYSTEMS, h as ScaleChoice, i as ScaleSystem, j as Species, k as SpeciesOptions, l as SpelledVoicing, m as StyledVoicingOptions, T as TRANSPOSING_INSTRUMENTS, n as TransposingInstrument, o as TransposingInstrumentName, V as VoiceIndependenceOptions, p as VoiceIndependenceReport, q as VoiceRange, s as VoicingStyle, t as availableTensions, u as avoidNotes, v as checkPartWriting, w as checkSpecies, x as chordScaleReport, y as chordScales, z as formatChordSymbol, B as instrumentTransposition, D as isSignatureKey, E as keyFromFifths, F as keySignatureFifths, G as parseChordSymbol, H as scaleMatchesChord, I as scaleSystemOf, J as scalesForChanges, L as spellVoicing, M as supportsFunctionalHarmony, N as toSoundingPitch, O as toWrittenPitch, Q as transposeChordSymbol, R as tryParseChordSymbol, U as voiceChord, W as voiceChordStyled, X as voiceIndependence, Y as voiceProgression } from '../index-B9QLziDe.cjs';
8
+ export { H as HarmonyRole, L as LockLevel, V as VoicedRole, r as roleOf } from '../index-BL5N2Oyz.cjs';
9
+ import { s as ScaleNameInput } from '../masks-pADfTOiD.cjs';
10
+ export { A as ALTERED_MASK, B as BLUES_MASK, C as CHROMATIC_MASK, D as DORIAN_MASK, a as DOUBLE_HARMONIC_MASK, H as HARMONIC_MINOR_MASK, L as LOCRIAN_MASK, b as LOCRIAN_NATURAL2_MASK, c as LYDIAN_DOMINANT_MASK, d as LYDIAN_MASK, M as MAJOR_MASK, e as MAJOR_PENTATONIC_MASK, f as MARWA_MASK, g as MELODIC_MINOR_MASK, h as MINOR_PENTATONIC_MASK, i as MIXOLYDIAN_B13_MASK, j as MIXOLYDIAN_MASK, k as MIYAKO_BUSHI_MASK, N as NAMED_SCALES, l as NATURAL_MINOR_MASK, O as OCTATONIC_HALF_WHOLE_MASK, m as OCTATONIC_WHOLE_HALF_MASK, P as PHRYGIAN_DOMINANT_MASK, n as PHRYGIAN_MASK, o as PURVI_MASK, R as RITSU_MASK, p as RYUKYU_MASK, S as SCALE_ALIASES, q as ScaleAliasName, r as ScaleName, T as TODI_MASK, W as WHOLE_TONE_MASK, t as WORLD_SCALES, u as WorldScaleName, v as assertKeyVariant, w as assertModeMask, x as maskFromOffsets, y as namedScaleMask, z as requireScaleMask, E as resolveScaleName, F as variantOfMask } from '../masks-pADfTOiD.cjs';
11
11
 
12
12
  /**
13
13
  * Test whether a pitch belongs to the scale.
14
14
  *
15
15
  * @param pitch MIDI pitch or bare pitch class.
16
- * @param key The key/scale to test against. This predicate reads the mask as
17
- * given rather than taking a key name: the spelling search runs it over
18
- * masks that name no key, which resolving a name would refuse.
16
+ * @param key The key/scale to test against, as a key name, a key/scale, or a
17
+ * `Key`.
19
18
  * @returns True if the pitch class is a member of the scale.
20
19
  *
21
20
  * @example
@@ -28,7 +27,7 @@ export { A as ALTERED_MASK, B as BLUES_MASK, C as CHROMATIC_MASK, D as DORIAN_MA
28
27
  *
29
28
  * @category Scales
30
29
  */
31
- declare function isScaleTone(pitch: number, key: KeyScale): boolean;
30
+ declare function isScaleTone(pitch: number, key: KeyLike): boolean;
32
31
  /**
33
32
  * Find the nearest MIDI pitch whose pitch class is in the scale.
34
33
  *
@@ -42,6 +41,71 @@ declare function isScaleTone(pitch: number, key: KeyScale): boolean;
42
41
  * @category Scales
43
42
  */
44
43
  declare function nearestScaleTone(pitch: number, key: KeyLike): number;
44
+ /**
45
+ * Where a pitch sits on the key's ladder of scale tones.
46
+ *
47
+ * `rung` counts scale tones from the tonic and continues across octaves, so
48
+ * adding to it moves by scale degrees; it is negative below the tonic of octave
49
+ * 0. `offset` is how many semitones the pitch sounds above that rung, which is 0
50
+ * for a scale tone and positive for one between two of them.
51
+ */
52
+ type ScaleLadderPosition = {
53
+ rung: number;
54
+ offset: number;
55
+ };
56
+ /**
57
+ * Locate a pitch on the key's ladder of scale tones.
58
+ *
59
+ * Anything counting in scale degrees has to put a pitch on this ladder and back
60
+ * again afterwards. Keeping the chromatic offset apart from the rung is what
61
+ * lets a note between two scale tones survive the arithmetic as the note it was:
62
+ * without it a shift by any number of degrees — including none — would first
63
+ * flatten every chromatic pitch onto the scale.
64
+ *
65
+ * In C major, C# sits on the tonic's rung with an offset of one semitone.
66
+ *
67
+ * Layer-internal: the generators count degrees with it, and callers reach the
68
+ * same arithmetic through the transforms that use it.
69
+ *
70
+ * @param pitch MIDI pitch.
71
+ * @param key The key/scale to count along, as a key name, a key/scale, or a
72
+ * `Key`.
73
+ * @returns The rung the pitch sits on and its semitone offset above it.
74
+ */
75
+ declare function scaleLadderPosition(pitch: number, key: KeyLike): ScaleLadderPosition;
76
+ /**
77
+ * The pitch a rung of the key's ladder of scale tones stands for.
78
+ *
79
+ * The inverse of {@link scaleLadderPosition}'s `rung`: adding the position's
80
+ * `offset` back to the result returns the pitch it came from.
81
+ *
82
+ * Layer-internal, like {@link scaleLadderPosition}.
83
+ *
84
+ * @param rung Scale tones counted from the tonic, negative below it.
85
+ * @param key The key/scale to count along, as a key name, a key/scale, or a
86
+ * `Key`.
87
+ * @returns The MIDI pitch of that scale tone.
88
+ */
89
+ declare function scaleLadderPitch(rung: number, key: KeyLike): number;
90
+ /**
91
+ * Shift a pitch by scale degrees along the key's ladder of scale tones.
92
+ *
93
+ * A pitch between two scale tones keeps its distance above the one below it, so
94
+ * a chromatic passing note is still a chromatic passing note after the shift,
95
+ * and a shift of no degrees returns the pitch untouched: a step up the C-major
96
+ * ladder answers C# with D#, not with D.
97
+ *
98
+ * Layer-internal. It is what `transposeDiatonic` and a tonal imitation both
99
+ * count along, so the two answer the same shift the same way; a caller reaches
100
+ * it through either of them.
101
+ *
102
+ * @param pitch MIDI pitch to shift.
103
+ * @param degrees Scale degrees to move by; negative moves down.
104
+ * @param key The key/scale to count along, as a key name, a key/scale, or a
105
+ * `Key`.
106
+ * @returns The shifted pitch.
107
+ */
108
+ declare function shiftByScaleDegrees(pitch: number, degrees: number, key: KeyLike): number;
45
109
  /**
46
110
  * Get the scale degree of a pitch, counted from 1: the tonic is degree 1.
47
111
  *
@@ -60,28 +124,74 @@ declare function pitchToScaleDegree(pitch: number, key: KeyLike): number;
60
124
  /**
61
125
  * List the pitch classes of a key's scale.
62
126
  *
63
- * @param key The key/scale to enumerate. The two enumerators here take a plain
64
- * key/scale rather than a key name: they read the mask as given, including
65
- * the tonic-less masks the spelling search works through, which no key name
66
- * describes.
127
+ * @param key The key/scale to enumerate, as a key name, a key/scale, or a `Key`.
67
128
  * @returns The member pitch classes, sorted ascending in [0, 11].
68
129
  *
69
130
  * @category Scales
70
131
  */
71
- declare function diatonicPitchClasses(key: KeyScale): number[];
132
+ declare function diatonicPitchClasses(key: KeyLike): number[];
72
133
  /**
73
134
  * List the pitch classes of a key's scale in ascending scale-degree order.
74
135
  *
75
136
  * The first entry is the root (degree 1); degrees follow the mask bits in
76
137
  * offset order rather than sorted pitch-class order.
77
138
  *
78
- * @param key The key/scale to enumerate, read as given for the reason
79
- * {@link diatonicPitchClasses} gives.
139
+ * @param key The key/scale to enumerate, as a key name, a key/scale, or a `Key`.
80
140
  * @returns The member pitch classes ordered by scale degree.
81
141
  *
82
142
  * @category Scales
83
143
  */
84
- declare function scaleTonesInDegreeOrder(key: KeyScale): number[];
144
+ declare function scaleTonesInDegreeOrder(key: KeyLike): number[];
145
+
146
+ /**
147
+ * Resolve any key-shaped value to the whole key it names.
148
+ *
149
+ * The counterpart of {@link toKeyScale}, and the one to prefer: both read the
150
+ * same shapes, but this one keeps what it read. A caller that genuinely wants
151
+ * only the pitch classes asks for them with {@link scaleOf}, which says so at
152
+ * the place it happens.
153
+ *
154
+ * What the value does not carry is derived rather than dropped: a bare scale is
155
+ * spelled by {@link spelledKeyOf}, the same reading the rest of the library
156
+ * uses, and its form is read from its mask. A key that carries a spelled tonic
157
+ * keeps that one — the caller's spelling outranks any the library would pick.
158
+ * A name carries one too, and it is kept: `'Ab minor'` resolves to an A flat
159
+ * minor rather than being reduced to pitch classes and spelled back as the G#
160
+ * minor those read best as.
161
+ *
162
+ * What it carries is checked rather than trusted. Accepting a wide range of
163
+ * shapes is not the same as accepting whatever those shapes hold, and a key
164
+ * whose tonic or form contradicts its own scale is refused here in the words
165
+ * `Key.of` refuses it — the two APIs answer the same input alike, and the
166
+ * refusal reaches every entry point built on this one.
167
+ *
168
+ * @param value A key name, a plain key/scale, a resolved key, or a value whose
169
+ * `toJSON` returns one of those.
170
+ * @returns The key, whole.
171
+ * @throws If the value names no key, its mask is out of range or excludes its
172
+ * own root, its tonic spells a pitch class its scale is not rooted on, or its
173
+ * form is not one that mask holds.
174
+ * @example
175
+ * ```ts
176
+ * import { formatNote, resolveKey } from '@libraz/libcantus';
177
+ * formatNote(resolveKey('Ab minor').tonic); // 'Ab'
178
+ * resolveKey('C major').tonic.letter; // 0
179
+ * ```
180
+ * @category Scales
181
+ */
182
+ declare function resolveKey(value: KeyLike): ResolvedKey;
183
+ /**
184
+ * The pitch classes of a key, with its spelling and form deliberately dropped.
185
+ *
186
+ * Named so that dropping them is something a reader can see. A layer that
187
+ * reduces a key silently is where an Ab minor becomes a G# minor, and the only
188
+ * way to keep finding those is to make the reduction say its own name.
189
+ *
190
+ * @param key The key to read.
191
+ * @returns Its pitch classes alone.
192
+ * @category Scales
193
+ */
194
+ declare function scaleOf(key: ResolvedKey): KeyScale;
85
195
 
86
196
  /**
87
197
  * Build a `KeyScale` for a major key on the given root pitch class.
@@ -94,7 +204,7 @@ declare function scaleTonesInDegreeOrder(key: KeyScale): number[];
94
204
  *
95
205
  * @category Scales
96
206
  */
97
- declare function majorKey(rootPc: number): KeyScale;
207
+ declare function majorKey(rootPc: number): SpelledKeyScale;
98
208
  /**
99
209
  * Build a `KeyScale` for a natural-minor key on the given root pitch class.
100
210
  *
@@ -106,7 +216,7 @@ declare function majorKey(rootPc: number): KeyScale;
106
216
  *
107
217
  * @category Scales
108
218
  */
109
- declare function minorKey(rootPc: number): KeyScale;
219
+ declare function minorKey(rootPc: number): SpelledKeyScale;
110
220
  /**
111
221
  * Build a `KeyScale` from a named scale (see {@link NAMED_SCALES}).
112
222
  *
@@ -123,7 +233,31 @@ declare function minorKey(rootPc: number): KeyScale;
123
233
  *
124
234
  * @category Scales
125
235
  */
126
- declare function scaleByName(name: ScaleNameInput, rootPc: number): KeyScale;
236
+ declare function scaleByName(name: ScaleNameInput, rootPc: number): SpelledKeyScale;
237
+
238
+ /**
239
+ * Read a key name, reporting failure instead of throwing it.
240
+ *
241
+ * The scale-word form is tried first, because a name ending in a mode word —
242
+ * `'D harmonic minor'` — would otherwise be read as the plain minor key that
243
+ * word names and lose the scale it was written with. It is English-only, so a
244
+ * name asked for in another notation system goes straight to the key-name
245
+ * parser, which reads that system.
246
+ *
247
+ * @param text The key name.
248
+ * @param opts `system` reads the name in that notation system instead of
249
+ * detecting it.
250
+ * @returns The key the name denotes, or the error explaining why the text is
251
+ * not one.
252
+ * @example
253
+ * ```ts
254
+ * import { tryResolveKeyName } from '@libraz/libcantus';
255
+ * const result = tryResolveKeyName('D dorian');
256
+ * result.ok ? result.value.variant : result.error.message; // 'modal'
257
+ * ```
258
+ * @category Scales
259
+ */
260
+ declare function tryResolveKeyName(text: string, opts?: NoteNameOptions): ParseResult<ResolvedKey>;
127
261
 
128
262
  /**
129
263
  * Shared interval reading for the counterpoint rules.
@@ -177,6 +311,20 @@ declare function classifySpelledInterval(interval: SpelledInterval, twoVoice?: b
177
311
  * written. Those keep their integer form as an equal partner.
178
312
  */
179
313
 
314
+ /**
315
+ * The readings {@link createsHiddenParallelPerfect} judges an approach by.
316
+ *
317
+ * Named once so the three places the choice is spelled — the two overloads and
318
+ * the implementation — cannot fall out of step with the check that a caller's
319
+ * value is one of them.
320
+ */
321
+ declare const HIDDEN_PARALLEL_READINGS: readonly ["fourPart", "twoVoice"];
322
+ /**
323
+ * Which reading of hidden parallels an approach is judged by.
324
+ *
325
+ * @category Voicing & Counterpoint
326
+ */
327
+ type HiddenParallelReading = (typeof HIDDEN_PARALLEL_READINGS)[number];
180
328
  /**
181
329
  * Whether an upper voice has crossed below a lower voice.
182
330
  *
@@ -309,14 +457,24 @@ declare function createsParallelUnison(aPrev: number, aCur: number, bPrev: numbe
309
457
  * Whether two voices reach a perfect interval by similar motion from an
310
458
  * imperfect one (a hidden/direct fifth or octave).
311
459
  *
312
- * The traditional step exception is applied: the approach is allowed when the
313
- * upper of the two voices moves by step, so only leaps into the perfect
314
- * interval are flagged.
460
+ * How strictly the approach is judged is the caller's to say, because the two
461
+ * textures do not agree about it:
315
462
  *
463
+ * - `fourPart` (the default) applies the step exception of the chorale — the
464
+ * approach is allowed when the upper of the two voices moves by step, so only
465
+ * leaps into the perfect interval are flagged. That exception is written for
466
+ * the outer voices of a four-part texture, where the other two cover the
467
+ * arrival.
468
+ * - `twoVoice` exempts no approach. With nothing between them, two voices
469
+ * moving the same way into a perfect fifth or octave expose it however the
470
+ * upper one got there, and strict sixteenth-century writing forbids it
471
+ * outright.
472
+ *
473
+ * @param strictness Which reading to judge the approach by.
316
474
  * @category Voicing & Counterpoint
317
475
  */
318
- declare function createsHiddenParallelPerfect(aPrev: Note, aCur: Note, bPrev: Note, bCur: Note): boolean;
319
- declare function createsHiddenParallelPerfect(aPrev: number, aCur: number, bPrev: number, bCur: number): boolean;
476
+ declare function createsHiddenParallelPerfect(aPrev: Note, aCur: Note, bPrev: Note, bCur: Note, strictness?: HiddenParallelReading): boolean;
477
+ declare function createsHiddenParallelPerfect(aPrev: number, aCur: number, bPrev: number, bCur: number, strictness?: HiddenParallelReading): boolean;
320
478
  /**
321
479
  * Whether two voices arrive at a perfect octave or unison by contrary motion
322
480
  * with the upper voice leaping down — the *ottava battuta* the sixteenth-century
@@ -324,6 +482,10 @@ declare function createsHiddenParallelPerfect(aPrev: number, aCur: number, bPrev
324
482
  *
325
483
  * The stepwise arrival is allowed, as is the same octave reached with the upper
326
484
  * voice rising, so only the downward leap into the perfect class is flagged.
485
+ * Arriving at a perfect class the voices were already sitting on (e.g. octave
486
+ * to octave by contrary motion) is the anti-parallel case owned by
487
+ * {@link createsParallelPerfect}; battuta is reserved for a perfect class that
488
+ * was not already there.
327
489
  *
328
490
  * @category Voicing & Counterpoint
329
491
  */
@@ -363,20 +525,20 @@ declare function exceedsSpacing(upper: number, lower: number, maxSemitones?: num
363
525
  * @returns True when `prev` is the leading tone and `cur` is the tonic a step above.
364
526
  * @category Voicing & Counterpoint
365
527
  */
366
- declare function isLeadingToneResolution(prev: Note, cur: Note, key: KeyScale): boolean;
367
- declare function isLeadingToneResolution(prev: number, cur: number, key: KeyScale): boolean;
528
+ declare function isLeadingToneResolution(prev: Note, cur: Note, key: KeyLike): boolean;
529
+ declare function isLeadingToneResolution(prev: number, cur: number, key: KeyLike): boolean;
368
530
 
369
531
  /**
370
532
  * Total voice-leading cost between two voicings: the sum of absolute semitone
371
- * motion across voices, plus a moderate hidden-perfect penalty when the
372
- * outer-voice (bass–soprano) pair reaches a hidden/direct perfect fifth or
373
- * octave by similar motion. The arrays must be the same length; when they
374
- * differ the voicings are not comparable and the cost is `Infinity`.
533
+ * motion across voices, and nothing besides. The rules the search also weighs —
534
+ * parallels, hidden perfects, unresolved tendency tones — are judged and
535
+ * reported by {@link checkPartWriting}, so measuring distance stays a
536
+ * measurement. The arrays must be the same length; when they differ the
537
+ * voicings are not comparable and the cost is `Infinity`.
375
538
  *
376
539
  * @param from The previous voicing, one MIDI pitch per voice.
377
540
  * @param to The next voicing, one MIDI pitch per voice.
378
- * @returns The summed absolute motion (plus any hidden-perfect penalty), or
379
- * `Infinity` when lengths differ.
541
+ * @returns The summed absolute motion, or `Infinity` when lengths differ.
380
542
  * @category Voicing & Counterpoint
381
543
  */
382
544
  declare function voiceLeadingCost(from: number[], to: number[]): number;
@@ -390,6 +552,14 @@ declare function voiceLeadingCost(from: number[], to: number[]): number;
390
552
  * from `current`, and a large penalty per counterpoint violation; the lowest
391
553
  * scoring candidate is returned, ascending.
392
554
  *
555
+ * The rules read from the chord being left — the resolution of a chordal
556
+ * seventh, the resolution of a leading tone, and the cross relation between the
557
+ * two chords — are scored only when `opts.previousChord` names it: what a
558
+ * voicing is written on cannot be read back from the pitches it holds. An
559
+ * editor moving from one chord to the next has that chord, and passing it is
560
+ * what keeps this generator and {@link checkPartWriting} agreeing about the
561
+ * pair.
562
+ *
393
563
  * @param current The current voicing to lead from, ascending (index 0 = lowest).
394
564
  * @param chord The next chord to voice, as a chord symbol, chord data, or a
395
565
  * `Chord`.
@@ -411,9 +581,13 @@ declare function nextVoicing(current: number[], chord: ChordLike, opts?: Voicing
411
581
  * major triad over one degree of C major and a diminished one over another.
412
582
  *
413
583
  * The bass arrives spelled, so the intervals above it are spelled too. The
414
- * third above a G in C minor is the Bb the signature gives, and the bare `#`
415
- * that raises it names B natural rather than an enharmonic Cb — which is what
416
- * makes the figures of a real exercise readable as written.
584
+ * third above a G in C minor is the Bb the signature gives, and the accidental
585
+ * that changes it is the one a score prints in front of that note: the leading
586
+ * tone there is a B natural, so the figure is `n`. That is the whole convention
587
+ * for accidentals here — a sign on a figure names its note exactly as it does on
588
+ * the staff — and it is what makes the figures of a real exercise readable as
589
+ * written. The crossed or slashed figure, typed `+`, is the one sign that raises
590
+ * instead of naming.
417
591
  */
418
592
 
419
593
  /**
@@ -468,13 +642,18 @@ type FiguredBassRealization = {
468
642
  * `653`, `643` and `642` name the same four chords.
469
643
  * - Stacked figures may be written run together (`64`) or separated by a slash,
470
644
  * a comma or a space (`6/4`), which is the same figure either way.
471
- * - An accidental in front of a figure alters that interval: `#6`, `b7`, `#43`.
472
- * A slashed or crossed figure raises its interval, and is typed `+` — `+6` is
473
- * `#6`. An accidental with no figure alters the third above the bass, so a
474
- * lone `#` over the dominant of a minor key raises its third to the leading
475
- * tone. `#` and `b` move the interval a semitone from what the key gives,
476
- * `##` and `bb` a whole tone, and `n` names the natural note whatever the key
477
- * gives. The Unicode accidentals are accepted alongside the typed ones.
645
+ * - An accidental in front of a figure names that interval's note, exactly as
646
+ * the same sign does on the staff: `#6`, `b7`, `#43`, and `n3` for a note the
647
+ * signature would otherwise flatten. `##` and `bb` name the double
648
+ * accidentals. An accidental with no figure applies to the third above the
649
+ * bass, so a lone `n` over the dominant of C minor names its leading tone. The
650
+ * Unicode accidentals are accepted alongside the typed ones.
651
+ * - A slashed or crossed figure raises the interval the key gives by a semitone,
652
+ * whatever accidental that lands on, and is typed `+`. It is the one sign here
653
+ * that moves an interval rather than naming it, which is why the notation
654
+ * carries it beside the printed accidentals: `+3` over the dominant of C minor
655
+ * and `+3` over the dominant of A minor are each that key's leading tone,
656
+ * written `n3` and `#3` respectively.
478
657
  * - A figure that moves is written with a hyphen: `4-3`, `9-8`, `7-6`, and any
479
658
  * other pair. Each side may carry its own accidental, as `4-#3` does in a
480
659
  * minor key. Moving figures may stand beside static ones (`5 4-3`).
@@ -542,8 +721,8 @@ declare function figuredBassRealization(bass: NoteLike, figures: string, key: Ke
542
721
  * import { majorKey, minorKey, parseNote, realizeFiguredBass } from '@libraz/libcantus';
543
722
  * realizeFiguredBass(parseNote('B'), '6', majorKey(0));
544
723
  * // G major with B in the bass: { rootPc: 7, quality: 'maj', bassPc: 11, ... }
545
- * realizeFiguredBass(parseNote('G'), '#', minorKey(0));
546
- * // G major in C minor: the raised third is a B natural
724
+ * realizeFiguredBass(parseNote('G'), 'n', minorKey(0));
725
+ * // G major in C minor: the leading tone is the B natural the score prints
547
726
  * ```
548
727
  * @category Functional Harmony
549
728
  */
@@ -554,15 +733,21 @@ declare function realizeFiguredBass(bass: NoteLike, figures: string, key: KeyLik
554
733
  * The inverse of {@link realizeFiguredBass} for every chord the figure grammar
555
734
  * reaches: the conventional abbreviation for the inversion (`6`, `64`, `7`,
556
735
  * `65`, `43`, `42`, or nothing at all for a root-position triad), with an
557
- * accidental on any interval the key does not already give. An altered
558
- * interval the abbreviation would leave implied is written out, so the raised
559
- * third of a dominant in a minor key emits `#3` rather than the bare `#` a
560
- * score would print — the figures this returns read back as the same chord.
736
+ * accidental on any interval the key does not already give. The accidental is
737
+ * the sign the score prints in front of that note, so the third of the dominant
738
+ * in C minor — a B natural under a signature carrying B flat — is written `n3`
739
+ * rather than as a raise from the flat the key gives. An altered interval the
740
+ * abbreviation would leave implied is written out, so the figure names the
741
+ * interval it lands on rather than the bare accidental a score puts under the
742
+ * bass — the figures this returns read back as the same chord.
561
743
  *
562
744
  * What this returns is read back before it is returned, so the two directions
563
- * cannot disagree: a chord the digits would name only approximately — an
564
- * augmented sixth, whose tones do not stack in thirds over its bass — has no
565
- * figures rather than figures that fail to realize.
745
+ * cannot disagree: a chord the digits would name only approximately has no
746
+ * figures rather than figures that fail to realize. What that excludes is a
747
+ * stack, not a family of chords — the Italian and German sixths stack in thirds
748
+ * over no root of their own and have no figures, while the French sixth stacks
749
+ * from its lowered supertonic and is written `#643`, which realizes back to the
750
+ * chord it was written from.
566
751
  *
567
752
  * @param chord The chord to figure, as a chord symbol, chord data, or a
568
753
  * `Chord`; its `bassPc`, when present, is the bass the intervals are measured
@@ -583,7 +768,7 @@ declare function realizeFiguredBass(bass: NoteLike, figures: string, key: KeyLik
583
768
  * ```
584
769
  * @category Functional Harmony
585
770
  */
586
- declare function figuredBassOf(chord: ChordLike, key: KeyLike): string;
771
+ declare function figuredBassOf(chord: ChordLike, key: SpelledKeyLike): string;
587
772
 
588
773
  /**
589
774
  * Spelling: derive letter-name notes for scales and chords from a spelled tonic.
@@ -608,6 +793,15 @@ declare function figuredBassOf(chord: ChordLike, key: KeyLike): string;
608
793
  * @category Pitch & Intervals
609
794
  */
610
795
  type SpellingContext = {
796
+ /**
797
+ * The chord sounding under the pitch, when the caller holds it.
798
+ *
799
+ * A chord names its own tones better than its root alone can: it carries the
800
+ * degree it writes each tone as, so a pitch that is one of its tones is
801
+ * spelled exactly as {@link spellChord} spells it. Supersedes `chordRoot`,
802
+ * which stays for callers holding nothing but a root pitch class.
803
+ */
804
+ chord?: Chord;
611
805
  /** Root pitch class of the chord sounding under the pitch, when known. */
612
806
  chordRoot?: number;
613
807
  /** The pitch immediately before this one (MIDI pitch or bare pitch class). */
@@ -682,10 +876,11 @@ declare function spellPitchClass(pc: number, tonic: NoteLike, key: KeyLike, cont
682
876
  *
683
877
  * @param tonic The spelled tonic, as a note name, a MIDI number, note data, or a
684
878
  * `Note`.
685
- * @param key The key/scale. This one stays a plain key/scale: the key-spelling
686
- * search reads scales through it that no key name describes.
879
+ * @param key The key/scale, as a key name, a key/scale, or a `Key` — the same
880
+ * forms its sibling spellers take.
687
881
  * @returns Spelled notes, one per scale degree.
688
- * @throws If `tonic` does not sound the key's root pitch class.
882
+ * @throws If `key` names no key, or if `tonic` does not sound the key's root
883
+ * pitch class.
689
884
  * @example
690
885
  * ```ts
691
886
  * import { spellScale, noteNames, parseNote, majorKey } from '@libraz/libcantus';
@@ -694,7 +889,7 @@ declare function spellPitchClass(pc: number, tonic: NoteLike, key: KeyLike, cont
694
889
  * ```
695
890
  * @category Pitch & Intervals
696
891
  */
697
- declare function spellScale(tonic: NoteLike, key: KeyScale): Note[];
892
+ declare function spellScale(tonic: NoteLike, key: KeyLike): Note[];
698
893
  /**
699
894
  * Spell an arbitrary list of pitch classes relative to a key.
700
895
  *
@@ -790,4 +985,4 @@ declare function spellPitch(pitch: number, tonic: NoteLike, key: KeyLike, contex
790
985
  */
791
986
  declare function noteNames(notes: readonly NoteLike[]): string[];
792
987
 
793
- export { Chord as ChordData, ChordLike, ConsonanceClass, type FiguredBassRealization, type FiguredBassSuspension, KeyLike, KeyScale, Note as NoteData, NoteLike, ScaleNameInput, SpelledInterval, type SpellingContext, VoicingOptions, classifySpelledInterval, createsBattuta, createsHiddenParallelPerfect, createsParallelOctave, createsParallelPerfect, createsParallelUnison, createsVerticalDissonance, createsVoiceCrossing, createsVoiceOverlap, diatonicPitchClasses, exceedsSpacing, figuredBassOf, figuredBassRealization, isAugmentedMelodicInterval, isForbiddenMelodicLeap, isLeadingToneResolution, isScaleTone, majorKey, minorKey, nearestScaleTone, nextVoicing, noteNames, pitchToScaleDegree, realizeFiguredBass, scaleByName, scaleTonesInDegreeOrder, spellChord, spellChordFromRoot, spellPitch, spellPitchClass, spellPitchClasses, spellScale, voiceLeadingCost };
988
+ export { Chord as ChordData, ChordLike, ConsonanceClass, type FiguredBassRealization, type FiguredBassSuspension, type HiddenParallelReading, KeyLike, KeyScale, Note as NoteData, NoteLike, NoteNameOptions, ParseResult, ResolvedKey, type ScaleLadderPosition, ScaleNameInput, SpelledInterval, SpelledKeyLike, SpelledKeyScale, type SpellingContext, VoicingOptions, classifySpelledInterval, createsBattuta, createsHiddenParallelPerfect, createsParallelOctave, createsParallelPerfect, createsParallelUnison, createsVerticalDissonance, createsVoiceCrossing, createsVoiceOverlap, diatonicPitchClasses, exceedsSpacing, figuredBassOf, figuredBassRealization, isAugmentedMelodicInterval, isForbiddenMelodicLeap, isLeadingToneResolution, isScaleTone, majorKey, minorKey, nearestScaleTone, nextVoicing, noteNames, pitchToScaleDegree, realizeFiguredBass, resolveKey, scaleByName, scaleLadderPitch, scaleLadderPosition, scaleOf, scaleTonesInDegreeOrder, shiftByScaleDegrees, spellChord, spellChordFromRoot, spellPitch, spellPitchClass, spellPitchClasses, spellScale, tryResolveKeyName, voiceLeadingCost };