@libraz/libcantus 0.9.4 → 1.0.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 (186) hide show
  1. package/README.md +61 -261
  2. package/README_ja.md +115 -0
  3. package/dist/analyze/index.cjs +54 -7
  4. package/dist/analyze/index.cjs.map +1 -1
  5. package/dist/analyze/index.d.cts +213 -456
  6. package/dist/analyze/index.d.ts +213 -456
  7. package/dist/analyze/index.js +56 -9
  8. package/dist/chunk-3JXCW6DX.cjs +3220 -0
  9. package/dist/chunk-3JXCW6DX.cjs.map +1 -0
  10. package/dist/chunk-4A2RMUCC.js +7647 -0
  11. package/dist/chunk-4A2RMUCC.js.map +1 -0
  12. package/dist/chunk-6XPTBE7Y.cjs +49 -0
  13. package/dist/chunk-6XPTBE7Y.cjs.map +1 -0
  14. package/dist/chunk-AFM2ULJH.cjs +5121 -0
  15. package/dist/chunk-AFM2ULJH.cjs.map +1 -0
  16. package/dist/chunk-E3F4AHAH.cjs +690 -0
  17. package/dist/chunk-E3F4AHAH.cjs.map +1 -0
  18. package/dist/chunk-ELCTZUJJ.js +379 -0
  19. package/dist/chunk-ELCTZUJJ.js.map +1 -0
  20. package/dist/chunk-FVSI36UV.js +690 -0
  21. package/dist/chunk-FVSI36UV.js.map +1 -0
  22. package/dist/chunk-GEDTJHAC.cjs +1 -0
  23. package/dist/chunk-GEDTJHAC.cjs.map +1 -0
  24. package/dist/chunk-GOZG57ER.js +3220 -0
  25. package/dist/chunk-GOZG57ER.js.map +1 -0
  26. package/dist/chunk-H3VORETI.js +2243 -0
  27. package/dist/chunk-H3VORETI.js.map +1 -0
  28. package/dist/chunk-H42UHPYW.js +1577 -0
  29. package/dist/chunk-H42UHPYW.js.map +1 -0
  30. package/dist/chunk-HFPS7JFD.js +1 -0
  31. package/dist/chunk-INHVXP6Z.js +3053 -0
  32. package/dist/chunk-INHVXP6Z.js.map +1 -0
  33. package/dist/chunk-K4ZJUGF4.cjs +379 -0
  34. package/dist/chunk-K4ZJUGF4.cjs.map +1 -0
  35. package/dist/chunk-KNJEKLKV.js +49 -0
  36. package/dist/chunk-KNJEKLKV.js.map +1 -0
  37. package/dist/chunk-M4CWTJWJ.cjs +7647 -0
  38. package/dist/chunk-M4CWTJWJ.cjs.map +1 -0
  39. package/dist/chunk-MXO72PLY.cjs +211 -0
  40. package/dist/chunk-MXO72PLY.cjs.map +1 -0
  41. package/dist/chunk-NLEU4QSE.cjs +360 -0
  42. package/dist/chunk-NLEU4QSE.cjs.map +1 -0
  43. package/dist/chunk-OE6WK2Y2.cjs +1577 -0
  44. package/dist/chunk-OE6WK2Y2.cjs.map +1 -0
  45. package/dist/chunk-Q2WGKJNN.cjs +1064 -0
  46. package/dist/chunk-Q2WGKJNN.cjs.map +1 -0
  47. package/dist/chunk-QYQQ5J6E.js +1 -0
  48. package/dist/chunk-QYQQ5J6E.js.map +1 -0
  49. package/dist/chunk-RHIJ3S4I.cjs +1 -0
  50. package/dist/chunk-RHIJ3S4I.cjs.map +1 -0
  51. package/dist/chunk-TTCLJX6D.js +211 -0
  52. package/dist/chunk-TTCLJX6D.js.map +1 -0
  53. package/dist/chunk-UADYAYAT.cjs +3053 -0
  54. package/dist/chunk-UADYAYAT.cjs.map +1 -0
  55. package/dist/chunk-VOHZB45S.js +5121 -0
  56. package/dist/chunk-VOHZB45S.js.map +1 -0
  57. package/dist/chunk-VTI6FOLB.js +1064 -0
  58. package/dist/chunk-VTI6FOLB.js.map +1 -0
  59. package/dist/chunk-WWURE4XT.cjs +2243 -0
  60. package/dist/chunk-WWURE4XT.cjs.map +1 -0
  61. package/dist/chunk-YH3BIKHH.js +360 -0
  62. package/dist/chunk-YH3BIKHH.js.map +1 -0
  63. package/dist/core/index.cjs +103 -6
  64. package/dist/core/index.cjs.map +1 -1
  65. package/dist/core/index.d.cts +96 -345
  66. package/dist/core/index.d.ts +96 -345
  67. package/dist/core/index.js +104 -7
  68. package/dist/generate/index.cjs +89 -10
  69. package/dist/generate/index.cjs.map +1 -1
  70. package/dist/generate/index.d.cts +437 -1095
  71. package/dist/generate/index.d.ts +437 -1095
  72. package/dist/generate/index.js +94 -15
  73. package/dist/index-9wcMhG73.d.ts +1095 -0
  74. package/dist/{index-D6b6na69.d.cts → index-B4o55NDr.d.cts} +13 -9
  75. package/dist/index-B9MNZboQ.d.cts +770 -0
  76. package/dist/index-B9MNZboQ.d.ts +770 -0
  77. package/dist/index-BGFW-8P2.d.cts +2307 -0
  78. package/dist/index-BO6xE9YU.d.cts +1804 -0
  79. package/dist/index-BkGmlyI3.d.cts +470 -0
  80. package/dist/index-CCNJRG-P.d.cts +1095 -0
  81. package/dist/index-CGpRv5sl.d.cts +643 -0
  82. package/dist/index-C_8o--VE.d.cts +1242 -0
  83. package/dist/index-CgHqxdps.d.ts +2307 -0
  84. package/dist/index-Chbst3Jx.d.ts +1343 -0
  85. package/dist/index-Cj49F892.d.ts +470 -0
  86. package/dist/{index-tSQh-xwY.d.ts → index-CunYKLiu.d.ts} +13 -9
  87. package/dist/index-D57QRbVn.d.ts +1804 -0
  88. package/dist/index-DInQqT8Q.d.cts +66 -0
  89. package/dist/index-DInQqT8Q.d.ts +66 -0
  90. package/dist/index-Dzr13q3d.d.cts +1343 -0
  91. package/dist/index-G1uwGGWQ.d.ts +643 -0
  92. package/dist/index-szBv3496.d.ts +1242 -0
  93. package/dist/index.cjs +358 -15
  94. package/dist/index.cjs.map +1 -1
  95. package/dist/index.d.cts +17 -15
  96. package/dist/index.d.ts +17 -15
  97. package/dist/index.js +407 -64
  98. package/dist/masks-DYbE485J.d.cts +445 -0
  99. package/dist/masks-DYbE485J.d.ts +445 -0
  100. package/dist/model/index.cjs +39 -7
  101. package/dist/model/index.cjs.map +1 -1
  102. package/dist/model/index.d.cts +4685 -243
  103. package/dist/model/index.d.ts +4685 -243
  104. package/dist/model/index.js +40 -8
  105. package/dist/positional-Cptlj-xs.d.ts +287 -0
  106. package/dist/positional-DvH_sd8u.d.cts +287 -0
  107. package/dist/theory/index.cjs +101 -7
  108. package/dist/theory/index.cjs.map +1 -1
  109. package/dist/theory/index.d.cts +513 -173
  110. package/dist/theory/index.d.ts +513 -173
  111. package/dist/theory/index.js +118 -24
  112. package/package.json +16 -11
  113. package/dist/chunk-36N73KZ3.cjs +0 -246
  114. package/dist/chunk-36N73KZ3.cjs.map +0 -1
  115. package/dist/chunk-4HLLZPXT.cjs +0 -3077
  116. package/dist/chunk-4HLLZPXT.cjs.map +0 -1
  117. package/dist/chunk-7MGZ7D62.cjs +0 -498
  118. package/dist/chunk-7MGZ7D62.cjs.map +0 -1
  119. package/dist/chunk-7NKDPF74.js +0 -3077
  120. package/dist/chunk-7NKDPF74.js.map +0 -1
  121. package/dist/chunk-CAN76NCU.cjs +0 -679
  122. package/dist/chunk-CAN76NCU.cjs.map +0 -1
  123. package/dist/chunk-D2FAJBYL.js +0 -479
  124. package/dist/chunk-D2FAJBYL.js.map +0 -1
  125. package/dist/chunk-EHVEBWM5.js +0 -1449
  126. package/dist/chunk-EHVEBWM5.js.map +0 -1
  127. package/dist/chunk-FCANXBAT.cjs +0 -30
  128. package/dist/chunk-FCANXBAT.cjs.map +0 -1
  129. package/dist/chunk-FNDWXRRI.cjs +0 -479
  130. package/dist/chunk-FNDWXRRI.cjs.map +0 -1
  131. package/dist/chunk-GQSGS2N4.js +0 -173
  132. package/dist/chunk-GQSGS2N4.js.map +0 -1
  133. package/dist/chunk-HKGYCQ34.js +0 -53
  134. package/dist/chunk-HKGYCQ34.js.map +0 -1
  135. package/dist/chunk-I24MV65U.js +0 -106
  136. package/dist/chunk-I24MV65U.js.map +0 -1
  137. package/dist/chunk-KMHOICIY.js +0 -679
  138. package/dist/chunk-KMHOICIY.js.map +0 -1
  139. package/dist/chunk-LW53AHQU.cjs +0 -1117
  140. package/dist/chunk-LW53AHQU.cjs.map +0 -1
  141. package/dist/chunk-N6IHQUOX.js +0 -1
  142. package/dist/chunk-NKIBQ6PT.js +0 -30
  143. package/dist/chunk-NKIBQ6PT.js.map +0 -1
  144. package/dist/chunk-NP4NA2FB.cjs +0 -106
  145. package/dist/chunk-NP4NA2FB.cjs.map +0 -1
  146. package/dist/chunk-NVE34YGZ.cjs +0 -1449
  147. package/dist/chunk-NVE34YGZ.cjs.map +0 -1
  148. package/dist/chunk-NYYWMV2C.js +0 -327
  149. package/dist/chunk-NYYWMV2C.js.map +0 -1
  150. package/dist/chunk-Q2XUP227.js +0 -845
  151. package/dist/chunk-Q2XUP227.js.map +0 -1
  152. package/dist/chunk-Q6OP4U43.cjs +0 -327
  153. package/dist/chunk-Q6OP4U43.cjs.map +0 -1
  154. package/dist/chunk-RC6GBMCD.cjs +0 -845
  155. package/dist/chunk-RC6GBMCD.cjs.map +0 -1
  156. package/dist/chunk-RK35RIN7.js +0 -1117
  157. package/dist/chunk-RK35RIN7.js.map +0 -1
  158. package/dist/chunk-RUMU3UA6.cjs +0 -53
  159. package/dist/chunk-RUMU3UA6.cjs.map +0 -1
  160. package/dist/chunk-T64C7ZD7.cjs +0 -1
  161. package/dist/chunk-T64C7ZD7.cjs.map +0 -1
  162. package/dist/chunk-XEBG3G53.js +0 -498
  163. package/dist/chunk-XEBG3G53.js.map +0 -1
  164. package/dist/chunk-YLEMGEFH.js +0 -246
  165. package/dist/chunk-YLEMGEFH.js.map +0 -1
  166. package/dist/chunk-ZEJR4TKL.cjs +0 -173
  167. package/dist/chunk-ZEJR4TKL.cjs.map +0 -1
  168. package/dist/function-BtiZb9i9.d.ts +0 -208
  169. package/dist/function-DNugAOrt.d.cts +0 -208
  170. package/dist/index-6VR8-kit.d.ts +0 -143
  171. package/dist/index-70p168VM.d.ts +0 -192
  172. package/dist/index-Be74mcon.d.cts +0 -152
  173. package/dist/index-BtXT6UQ0.d.cts +0 -192
  174. package/dist/index-C5UBbQ4G.d.ts +0 -152
  175. package/dist/index-C83mZI1P.d.ts +0 -242
  176. package/dist/index-DXd9JikN.d.cts +0 -246
  177. package/dist/index-DXd9JikN.d.ts +0 -246
  178. package/dist/index-OG65ocOr.d.cts +0 -272
  179. package/dist/index-OG65ocOr.d.ts +0 -272
  180. package/dist/index-tJhkmQgE.d.cts +0 -143
  181. package/dist/index-y_ak9_Hi.d.cts +0 -242
  182. package/dist/styled-DIRkk9Uz.d.ts +0 -506
  183. package/dist/styled-DJbkJQfj.d.cts +0 -506
  184. package/dist/types-BN6_Q9Kl.d.cts +0 -39
  185. package/dist/types-BN6_Q9Kl.d.ts +0 -39
  186. /package/dist/{chunk-N6IHQUOX.js.map → chunk-HFPS7JFD.js.map} +0 -0
@@ -0,0 +1,1242 @@
1
+ import { d as KeyScale, f as Note, h as NoteLike, i as NoteNameOptions, P as ParseResult } from './index-B9MNZboQ.cjs';
2
+
3
+ /**
4
+ * Anything that names a key: a key name, a plain {@link KeyScale}, or a value
5
+ * that serializes to one such as the `Key` class.
6
+ *
7
+ * @category Scales
8
+ */
9
+ type KeyLike = string | KeyScale | {
10
+ /** The key data this value stands for, carrying the scale it denotes. */
11
+ toJSON(): {
12
+ scale: KeyScale;
13
+ };
14
+ };
15
+ /**
16
+ * Resolve any key-shaped value to a plain {@link KeyScale}.
17
+ *
18
+ * The counterpart of {@link toSpelledInterval} for keys: an entry point takes
19
+ * whatever form the caller has — the name a key field holds, the scale the
20
+ * theory module returns, or a `Key` instance — and gets one shape back. An
21
+ * instance is accepted through its `toJSON` method rather than by its type, so
22
+ * the layers below the model can read a class without importing it.
23
+ *
24
+ * A name is read by {@link parseKeyName} and nothing else, so every entry point
25
+ * that takes a key accepts exactly the names a key field already accepts, in
26
+ * every notation system it already reads. The mode word decides the scale: a
27
+ * major name gives the major scale, a minor name the natural minor. The
28
+ * harmonic and melodic forms have no name of their own, so a caller who needs
29
+ * one builds it with {@link scaleByName} and passes the scale.
30
+ *
31
+ * @param value A key name, a plain key/scale, or a value whose `toJSON`
32
+ * returns data carrying one.
33
+ * @returns The validated key/scale, with its root reduced to a pitch class.
34
+ * @throws If the value names no key, or its mode mask is out of range or
35
+ * excludes its own root.
36
+ * @example
37
+ * ```ts
38
+ * import { toKeyScale } from '@libraz/libcantus';
39
+ * toKeyScale('C major').rootPc; // 0
40
+ * toKeyScale('A minor').rootPc; // 9
41
+ * ```
42
+ * @category Scales
43
+ */
44
+ declare function toKeyScale(value: KeyLike): KeyScale;
45
+
46
+ /**
47
+ * How keys stand to one another: the relative, parallel, dominant and
48
+ * subdominant keys, the enharmonic respelling of a key, and the relation that
49
+ * holds between two given keys.
50
+ *
51
+ * Every relation but {@link parallelKeyOf} is computed in fifths space, on top
52
+ * of {@link keySignatureFifths} and {@link keyFromFifths}. Stepping around the
53
+ * circle of fifths and reading the tonic back off it is what keeps the spelling
54
+ * right: the relative of Db major comes out as Bb minor, not A# minor.
55
+ *
56
+ * A relation always returns a plain major or minor key, because those are the
57
+ * only keys these relations name; {@link enharmonicKeyOf} is the exception that
58
+ * proves it, since a respelling is the same key rather than another one and so
59
+ * keeps the mask it was handed. A key that is not a plain major or minor —
60
+ * a church mode, harmonic minor, a pentatonic, an octatonic — is read through
61
+ * the mode its third names, and the fifths are counted from where its tonic
62
+ * stands on the circle rather than from the key's own signature: a mode's
63
+ * signature carries its own offset (D dorian is two fifths flatter than D
64
+ * major), which {@link keyFromFifths} does not know how to give back.
65
+ * {@link parallelKeyOf} travels no fifths at all, so it keeps the tonic
66
+ * spelling it was given.
67
+ */
68
+
69
+ /**
70
+ * A key paired with the spelled tonic that anchors its letter names.
71
+ *
72
+ * The tonic carries no octave: a key is rooted on a pitch class, and its
73
+ * spelling is what decides whether the key is written Db major or C# major.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import type { SpelledKey } from '@libraz/libcantus';
78
+ * import { majorKey, parseNote } from '@libraz/libcantus';
79
+ * const dbMajor: SpelledKey = { tonic: parseNote('Db'), key: majorKey(1) };
80
+ * ```
81
+ * @category Scales
82
+ */
83
+ type SpelledKey = {
84
+ tonic: Note;
85
+ key: KeyScale;
86
+ };
87
+ /**
88
+ * How one key stands to another, as reported by {@link keyRelationBetween} and
89
+ * tagged onto every entry of {@link relatedKeysOf}.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import type { KeyRelation } from '@libraz/libcantus';
94
+ * const relation: KeyRelation = 'relative'; // C major -> A minor
95
+ * ```
96
+ * @category Scales
97
+ */
98
+ type KeyRelation = 'same' | 'enharmonic' | 'relative' | 'parallel' | 'dominant' | 'subdominant' | 'relativeOfDominant' | 'relativeOfSubdominant';
99
+ /**
100
+ * Spell a key's tonic the conventional way: the letter and accidental the key
101
+ * is written with, paired with the key exactly as given.
102
+ *
103
+ * The candidates are the tonics keys are actually written on — everything from
104
+ * Cb to A#, which names each pitch class once or twice (C, but Db and C#) — and
105
+ * which of them names the key depends on whether the key has a signature of its
106
+ * own. A major or minor key, a church mode, and the harmonic and melodic minor
107
+ * are spelled on the tonic their signature is written on: pitch class 1 in
108
+ * major is Db, five flats, rather than C#, seven sharps; pitch class 8 in minor
109
+ * is G#, five sharps, rather than Ab, seven flats; and G# harmonic minor writes
110
+ * its raised seventh F## as an accidental over that signature rather than
111
+ * respelling the key. Where two signatures are equally long — pitch class 6 in
112
+ * major is F# at +6 and Gb at -6 — the flat side is taken.
113
+ *
114
+ * Every other scale only borrows the signature of its parallel major or minor,
115
+ * so nothing follows from it and the scale is spelled on the tonic it reads
116
+ * best from: the fewest double accidentals first, then the fewest accidentals
117
+ * altogether, and only then the shorter signature. That is why pitch class 1
118
+ * altered is C# — C# D E F G A B — rather than Db, which would have to write
119
+ * four double flats to say the same thing, and why pitch class 8 minor
120
+ * pentatonic is G# B C# D# F# rather than Ab B Db Eb Gb, which reads its third
121
+ * as an augmented second.
122
+ *
123
+ * The mask's third picks the mode the signature is measured in — a minor third
124
+ * and no major third reads as minor, anything else as major — and the key is
125
+ * returned unchanged, so a scale keeps its own mask and only borrows a tonic
126
+ * spelling. A caller that has a tonic spelling of its own always keeps it: this
127
+ * only answers for a key that arrives as a bare pitch class.
128
+ *
129
+ * Every 12-bit mask and every integer root is answered — a root outside [0, 11]
130
+ * is reduced first, and a mask with no third at all counts as major.
131
+ *
132
+ * The key is paired with the answer exactly as it was handed in, root and mask
133
+ * untouched, so this takes a plain key/scale rather than the wider forms the
134
+ * relations below accept: a coerced key could not be given back verbatim.
135
+ *
136
+ * @param key The key/scale to spell.
137
+ * @returns The conventional tonic spelling, paired with `key` verbatim.
138
+ * @example
139
+ * ```ts
140
+ * import { formatNote, majorKey, scaleByName, spelledKeyOf } from '@libraz/libcantus';
141
+ * formatNote(spelledKeyOf(majorKey(1)).tonic); // 'Db'
142
+ * formatNote(spelledKeyOf(scaleByName('harmonicMinor', 8)).tonic); // 'G#'
143
+ * formatNote(spelledKeyOf(scaleByName('altered', 1)).tonic); // 'C#'
144
+ * ```
145
+ * @category Scales
146
+ */
147
+ declare function spelledKeyOf(key: KeyScale): SpelledKey;
148
+ /**
149
+ * The relative key: the same key signature read in the other mode.
150
+ *
151
+ * C major and A minor share a signature, and so are each other's relative; the
152
+ * relation is its own inverse for a plain major or minor key. Because the new
153
+ * tonic is read off the circle of fifths rather than transposed by semitones,
154
+ * the relative of Db major is Bb minor and not its enharmonic A# minor.
155
+ *
156
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
157
+ * `Note`.
158
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`; its mask
159
+ * decides which mode the relative is in.
160
+ * @returns The relative key and the tonic spelling it is written with.
161
+ * @throws If the tonic or the mask is malformed, or if the key's signature
162
+ * falls outside [-12, 12] fifths.
163
+ * @example
164
+ * ```ts
165
+ * import { formatNote, majorKey, parseNote, relativeKeyOf } from '@libraz/libcantus';
166
+ * formatNote(relativeKeyOf(parseNote('C'), majorKey(0)).tonic); // 'A'
167
+ * formatNote(relativeKeyOf('Db', majorKey(1)).tonic); // 'Bb'
168
+ * ```
169
+ * @category Scales
170
+ */
171
+ declare function relativeKeyOf(tonic: NoteLike, key: KeyLike): SpelledKey;
172
+ /**
173
+ * The parallel key: the other mode on the same tonic.
174
+ *
175
+ * The tonic keeps the spelling it was given — the parallel minor of C major is
176
+ * C minor, never B# minor — which is why this is the one relation here that
177
+ * does not travel the circle of fifths.
178
+ *
179
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
180
+ * `Note`; its letter and alteration are kept.
181
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`; its mask
182
+ * decides which mode the parallel is in.
183
+ * @returns The parallel key on the same tonic.
184
+ * @throws If the tonic or the mask is malformed.
185
+ * @example
186
+ * ```ts
187
+ * import { formatNote, majorKey, parallelKeyOf, parseNote } from '@libraz/libcantus';
188
+ * const parallel = parallelKeyOf(parseNote('C'), majorKey(0));
189
+ * formatNote(parallel.tonic); // 'C'
190
+ * ```
191
+ * @category Scales
192
+ */
193
+ declare function parallelKeyOf(tonic: NoteLike, key: KeyLike): SpelledKey;
194
+ /**
195
+ * The dominant key: the key a fifth above, in the mode this key's third names.
196
+ *
197
+ * The fifth is measured from the tonic, so a key that is not a plain major or
198
+ * minor answers with the same move: the dominant of G mixolydian is D major and
199
+ * the dominant of D dorian is A minor.
200
+ *
201
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
202
+ * `Note`.
203
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`; its mask
204
+ * decides the mode of the result.
205
+ * @returns The key a fifth above, in the mode this key's third names.
206
+ * @throws If the tonic or the mask is malformed, or if the resulting signature
207
+ * falls outside [-12, 12] fifths — the dominant of a key already at +12.
208
+ * @example
209
+ * ```ts
210
+ * import { dominantKeyOf, formatNote, majorKey, parseNote } from '@libraz/libcantus';
211
+ * formatNote(dominantKeyOf(parseNote('C'), majorKey(0)).tonic); // 'G'
212
+ * ```
213
+ * @category Scales
214
+ */
215
+ declare function dominantKeyOf(tonic: NoteLike, key: KeyLike): SpelledKey;
216
+ /**
217
+ * The subdominant key: the key a fifth below, in the mode this key's third
218
+ * names, and the exact inverse of {@link dominantKeyOf} on the tonic spelling.
219
+ *
220
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
221
+ * `Note`.
222
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`; its mask
223
+ * decides the mode of the result.
224
+ * @returns The key a fifth below, in the mode this key's third names.
225
+ * @throws If the tonic or the mask is malformed, or if the resulting signature
226
+ * falls outside [-12, 12] fifths — the subdominant of a key already at -12.
227
+ * @example
228
+ * ```ts
229
+ * import { formatNote, majorKey, parseNote, subdominantKeyOf } from '@libraz/libcantus';
230
+ * formatNote(subdominantKeyOf(parseNote('C'), majorKey(0)).tonic); // 'F'
231
+ * ```
232
+ * @category Scales
233
+ */
234
+ declare function subdominantKeyOf(tonic: NoteLike, key: KeyLike): SpelledKey;
235
+ /**
236
+ * The same sounding key written the other way round the circle of fifths, or
237
+ * null when it has no second spelling.
238
+ *
239
+ * Twelve fifths is one enharmonic turn of the circle, so a tonic's alternative
240
+ * spelling sits at its own position ±12: Db (-5) is also C# (+7). It is offered
241
+ * only when the key is actually written there, by the same test
242
+ * {@link spelledKeyOf} spells with. That is why C major is alone while Db major
243
+ * and F# major each answer with their twin: Eb major's twin would be D# major
244
+ * and its nine sharps, and pitch class 3 altered is written D# but never Eb,
245
+ * which would need two double flats to say the same thing.
246
+ *
247
+ * The answer is therefore always a spelling the key is written on, which makes
248
+ * the relation its own inverse for such a key. A key spelled some other way —
249
+ * a tonic a transposition drove out to Ebb, say — still names its written twin,
250
+ * so this is also the way back from a spelling no one writes.
251
+ *
252
+ * The relation respells rather than moves, so the mask is kept: the other
253
+ * spelling of C# lydian is Db lydian, and its root pitch class is the one it
254
+ * was handed.
255
+ *
256
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
257
+ * `Note`.
258
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`; its mask
259
+ * decides the mode the tonic is read in, and is carried into the result.
260
+ * @returns The other spelling of the key, or null when it is not written.
261
+ * @throws If the tonic or the mask is malformed.
262
+ * @example
263
+ * ```ts
264
+ * import { enharmonicKeyOf, formatNote, majorKey, parseNote } from '@libraz/libcantus';
265
+ * const other = enharmonicKeyOf(parseNote('Db'), majorKey(1));
266
+ * other === null ? 'none' : formatNote(other.tonic); // 'C#'
267
+ * enharmonicKeyOf('C', majorKey(0)); // null
268
+ * ```
269
+ * @category Scales
270
+ */
271
+ declare function enharmonicKeyOf(tonic: NoteLike, key: KeyLike): SpelledKey | null;
272
+ /**
273
+ * The six closely related keys of a key, each tagged with its relation.
274
+ *
275
+ * These are the keys the German and Japanese teaching tradition counts as a
276
+ * key's near relations: the relative and parallel keys, the dominant and the
277
+ * subdominant, and the relatives of those two. For C major they are A minor,
278
+ * C minor, G major, F major, E minor and D minor, in that order. Five of them
279
+ * are written within one accidental of the key's own signature — the relative
280
+ * shares it exactly and the other four stand one away; the parallel key does
281
+ * not — C minor is three flats away from C major — and belongs to the set for
282
+ * the tonic it shares rather than for the signature it carries.
283
+ *
284
+ * @param tonic The spelled tonic of the key, as a note name, note data, or a
285
+ * `Note`.
286
+ * @param key The key/scale, as a key name, a key/scale, or a `Key`.
287
+ * @returns The six related keys, in relation order, each with its tonic
288
+ * spelling and its `relation` tag.
289
+ * @throws If the tonic or the mask is malformed, or if a neighbouring signature
290
+ * falls outside [-12, 12] fifths.
291
+ * @example
292
+ * ```ts
293
+ * import { majorKey, parseNote, relatedKeysOf } from '@libraz/libcantus';
294
+ * relatedKeysOf(parseNote('C'), majorKey(0)).map((related) => related.relation);
295
+ * // ['relative', 'parallel', 'dominant', 'subdominant', 'relativeOfDominant', 'relativeOfSubdominant']
296
+ * ```
297
+ * @category Scales
298
+ */
299
+ declare function relatedKeysOf(tonic: NoteLike, key: KeyLike): (SpelledKey & {
300
+ relation: KeyRelation;
301
+ })[];
302
+ /**
303
+ * How the second key stands to the first, or null when they are not related.
304
+ *
305
+ * The relations are tested in a fixed order — identity, enharmonic spelling,
306
+ * then the six closely related keys in the order {@link relatedKeysOf} lists
307
+ * them — and the first match is reported. Only the identity test looks at the
308
+ * tonic spelling; every other test compares root pitch class and mode, so
309
+ * C# minor and Db minor both read as the relative of E major.
310
+ *
311
+ * Both keys are read through the mode their third names, exactly as
312
+ * {@link relatedKeysOf} reads the key it is given, so A harmonic minor stands
313
+ * to C major as A minor does whichever of the two is asked about. That is what
314
+ * makes the answer symmetric: if one key's related keys name the other, the
315
+ * relation between them is reported from either side.
316
+ *
317
+ * @param a The key the relation is measured from.
318
+ * @param b The key the relation is measured to.
319
+ * @returns The relation, or null when `b` is none of `a`'s related keys.
320
+ * @throws If either key is malformed, or if a neighbouring signature of `a`
321
+ * falls outside [-12, 12] fifths.
322
+ * @example
323
+ * ```ts
324
+ * import { keyRelationBetween, majorKey, minorKey, parseNote } from '@libraz/libcantus';
325
+ * const cMajor = { tonic: parseNote('C'), key: majorKey(0) };
326
+ * keyRelationBetween(cMajor, { tonic: parseNote('A'), key: minorKey(9) }); // 'relative'
327
+ * keyRelationBetween(cMajor, { tonic: parseNote('Eb'), key: minorKey(3) }); // null
328
+ * ```
329
+ * @category Scales
330
+ */
331
+ declare function keyRelationBetween(a: SpelledKey, b: SpelledKey): KeyRelation | null;
332
+
333
+ /**
334
+ * The structured reading of a chord: what it is built from, not what it is
335
+ * called.
336
+ *
337
+ * A quality name is a closed vocabulary and a lead sheet's harmony is not. A
338
+ * chart writes a *set* of alterations over a base — `maj7#11`, `7b9#11`,
339
+ * `sus4(add9)` — so an enumeration of names can never be complete, and every
340
+ * name added to one is a name missing from its neighbours. A {@link ChordSpec}
341
+ * names the parts instead: a base triad, an optional seventh, altered, added
342
+ * and omitted degrees. A combination nothing names still has exact intervals,
343
+ * an exact pitch-class set, and a symbol that reads back as itself.
344
+ *
345
+ * Each {@link ChordQuality} is an alias for one spec, so the two directions
346
+ * cannot drift: a named chord's interval template is derived from its spec
347
+ * rather than listed beside it.
348
+ */
349
+ /**
350
+ * Chord quality identifiers understood by the chord builder.
351
+ *
352
+ * Each name is an alias for one {@link ChordSpec}. The union is closed, so it
353
+ * names the chords a chart writes most often rather than every chord that can
354
+ * be written; build the rest from a spec.
355
+ *
356
+ * @category Chords
357
+ */
358
+ type ChordQuality = 'maj' | 'min' | 'dim' | 'aug' | 'maj7' | 'min7' | 'dom7' | 'dim7' | 'm7b5' | 'minMaj7' | 'minMaj9' | 'minMaj11' | 'minMaj13' | 'aug7' | 'augMaj7' | 'majb5' | '6' | 'min6' | '6/9' | 'sus2' | 'sus4' | 'add9' | 'add11' | 'maj9' | 'min9' | 'dom9' | '7b9' | '7#9' | '7#11' | '7b13' | '11' | '13' | '5' | '7sus4' | '7b5' | '7alt' | '13b9' | 'maj13' | 'maj7#11' | 'min11' | 'min13' | 'minAdd9' | 'min6/9';
359
+ /**
360
+ * The triad (or dyad) a chord is built on, before any seventh or tension.
361
+ *
362
+ * `sus2` and `sus4` replace the third rather than sitting beside it, and
363
+ * `power` is the bare root and fifth, so the base says which tones the chord
364
+ * has before anything is added to them.
365
+ *
366
+ * @category Chords
367
+ */
368
+ type ChordBase = 'maj' | 'min' | 'dim' | 'aug' | 'sus2' | 'sus4' | 'power';
369
+ /**
370
+ * The seventh stacked over a base: major, minor, or diminished.
371
+ *
372
+ * @category Chords
373
+ */
374
+ type ChordSeventh = 'maj7' | 'min7' | 'dim7';
375
+ /**
376
+ * A chord degree that can be raised or lowered: the fifth and the tensions.
377
+ *
378
+ * @category Chords
379
+ */
380
+ type AlteredDegree = 5 | 9 | 11 | 13;
381
+ /**
382
+ * One altered degree: which one, and by how much.
383
+ *
384
+ * `alter: 0` is not redundant — it says the degree is *present* and unaltered,
385
+ * which is what the natural ninth of a thirteenth chord is.
386
+ *
387
+ * @category Chords
388
+ */
389
+ type Alteration = {
390
+ degree: AlteredDegree;
391
+ alter: -1 | 0 | 1;
392
+ };
393
+ /**
394
+ * A chord as its parts: base, seventh, alterations, additions and omissions.
395
+ *
396
+ * The library's structural chord model. `alterations` are tensions over a
397
+ * seventh chord; `additions` are degrees added without one (`add9`, and the
398
+ * sixth of a sixth chord); `omissions` are degrees the chord leaves out (the
399
+ * third of an eleventh chord, the fifth of a shell voicing) named by chord
400
+ * degree, so `omissions: [5]` is a fifth-less chord.
401
+ *
402
+ * @category Chords
403
+ */
404
+ type ChordSpec = {
405
+ rootPc: number;
406
+ base: ChordBase;
407
+ seventh?: ChordSeventh;
408
+ alterations: Alteration[];
409
+ additions: number[];
410
+ omissions: number[];
411
+ bassPc?: number;
412
+ };
413
+ /**
414
+ * The semitone offsets above the root a spec sounds, ascending.
415
+ *
416
+ * The library's single derivation of chord tones: a name contributes nothing
417
+ * here, so a combination of alterations no name covers yields its intervals the
418
+ * same way a `maj7` does.
419
+ *
420
+ * @param spec The chord spec.
421
+ * @returns Semitone offsets above the root, ascending and deduplicated.
422
+ * @throws If any part of the spec is not one the model defines
423
+ * ({@link InvalidInputError}), exactly as {@link chordFromSpec} rejects it.
424
+ *
425
+ * @example
426
+ * ```ts
427
+ * import { chordSpecIntervals } from '@libraz/libcantus';
428
+ * chordSpecIntervals({
429
+ * rootPc: 0,
430
+ * base: 'maj',
431
+ * seventh: 'min7',
432
+ * alterations: [{ degree: 9, alter: -1 }, { degree: 11, alter: 1 }],
433
+ * additions: [],
434
+ * omissions: [],
435
+ * });
436
+ * // [0, 4, 7, 10, 13, 18] — the C7(b9,#11) no quality name covers
437
+ * ```
438
+ *
439
+ * @category Chords
440
+ */
441
+ declare function chordSpecIntervals(spec: ChordSpec): number[];
442
+ /**
443
+ * The quality name a spec is reported under.
444
+ *
445
+ * A spec no name covers still has to answer, because `quality` is a required
446
+ * field of every {@link Chord} and of the records that travel with one. The
447
+ * answer is the *nearest* name: the largest named chord whose every tone this
448
+ * spec also sounds, and failing that the name of its base. Nothing is lost by
449
+ * it — the spec and the interval template still carry the alterations, and a
450
+ * symbol is written from those rather than from this name.
451
+ *
452
+ * @param spec The chord spec.
453
+ * @returns The name that fits the spec exactly, or the nearest one that fits
454
+ * inside it.
455
+ * @throws If any part of the spec is not one the model defines
456
+ * ({@link InvalidInputError}), exactly as {@link chordFromSpec} rejects it.
457
+ *
458
+ * @example
459
+ * ```ts
460
+ * import { chordSpecQuality, parseChordSymbol } from '@libraz/libcantus';
461
+ * parseChordSymbol('C7(b9,#11)').quality; // '7b9' — the nearest name
462
+ * chordSpecQuality({ rootPc: 0, base: 'maj', seventh: 'min7', alterations: [],
463
+ * additions: [], omissions: [] }); // 'dom7'
464
+ * ```
465
+ *
466
+ * @category Chords
467
+ */
468
+ declare function chordSpecQuality(spec: ChordSpec): ChordQuality;
469
+
470
+ /**
471
+ * The basic role a chord tone plays: the degrees a chord's own template names.
472
+ *
473
+ * The shared vocabulary behind {@link chordToneRole}, the harmony layer's
474
+ * `HarmonyRole`, and the voice analyser's labels, so the three cannot drift.
475
+ *
476
+ * @category Chords
477
+ */
478
+ type ChordToneRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh';
479
+ /**
480
+ * A bare spelled pitch used as an enharmonic hint: a diatonic letter
481
+ * (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).
482
+ * Mirrors the letter/alter half of the pitch module's `Note` without an octave.
483
+ *
484
+ * @category Chords
485
+ */
486
+ type PitchSpelling = {
487
+ letter: number;
488
+ alter: number;
489
+ };
490
+ /**
491
+ * A chord expressed as a root pitch class plus semitone offsets.
492
+ *
493
+ * `intervals` is what the chord sounds and `quality` is what it is called. The
494
+ * two are not equally expressive: a chart writes any set of alterations over a
495
+ * base, while {@link ChordQuality} is a closed list of names, so `quality` is a
496
+ * *derived* label — the name that fits the chord exactly, or else the nearest
497
+ * name inside it (see {@link chordSpecQuality}). Read the structure with
498
+ * {@link chordSpecOf} rather than the name when the alterations matter; that is
499
+ * also what {@link formatChordSymbol} does, so a chord no name covers still
500
+ * writes itself out in full.
501
+ *
502
+ * `rootSpelling`/`bassSpelling` are optional enharmonic hints recorded by
503
+ * parsers (e.g. `parseChordSymbol('Bb7')`) so formatters can reproduce the
504
+ * original spelling instead of defaulting to sharps. Consumers may ignore
505
+ * them; a hint is only trusted when its pitch class still matches the
506
+ * corresponding `rootPc`/`bassPc`.
507
+ *
508
+ * `toneSpellings` is the same kind of hint for the tones themselves, one
509
+ * spelling per entry in `intervals`. It exists for the chords whose letters do
510
+ * not follow from stacking thirds: an augmented sixth is ten semitones like a
511
+ * minor seventh but is five letters above its root rather than six, and no
512
+ * {@link ChordQuality} can say so. Builders that know better attach it, and
513
+ * {@link spellChordFromRoot} reads the letter distances back out of it; a hint
514
+ * is trusted as a whole or not at all, and only while every spelling still
515
+ * names the pitch class its interval names.
516
+ *
517
+ * @category Chords
518
+ */
519
+ type Chord = {
520
+ rootPc: number;
521
+ quality: ChordQuality;
522
+ intervals: number[];
523
+ bassPc?: number;
524
+ rootSpelling?: PitchSpelling;
525
+ bassSpelling?: PitchSpelling;
526
+ toneSpellings?: PitchSpelling[];
527
+ };
528
+ /**
529
+ * A chord positioned in time: a root pitch class and quality placed at a beat,
530
+ * with optional harmonic-analysis hints. Serves as the neutral exchange record
531
+ * between progression generators and timeline analysers.
532
+ *
533
+ * @category Composition
534
+ */
535
+ type ChordSpan = {
536
+ rootPc: number;
537
+ quality: ChordQuality;
538
+ startBeat: number;
539
+ bassPc?: number;
540
+ /**
541
+ * Semitone offsets from the root, for a chord the {@link ChordQuality} union
542
+ * cannot name exactly. Omitted for a standard chord: the template is then
543
+ * derived from `quality`, which is what every producer and consumer did
544
+ * before the field existed. Read a span with {@link chordFromSpan} so either
545
+ * case yields the same chord.
546
+ */
547
+ intervals?: number[];
548
+ /** 1-based scale degree of the chord root, when known. */
549
+ degree?: number;
550
+ /** True when the chord is a secondary dominant tonicizing another degree. */
551
+ secondaryDominant?: boolean;
552
+ };
553
+ /**
554
+ * A chord occupying a half-open beat span `[startBeat, endBeat)`.
555
+ *
556
+ * The exchange record between anything that lays chords out in time — a
557
+ * timeline analysis, a bass-line plan, an accompaniment generator — so those
558
+ * surfaces share one definition instead of agreeing by coincidence.
559
+ *
560
+ * @category Composition
561
+ */
562
+ type ChordSegment = {
563
+ startBeat: number;
564
+ endBeat: number;
565
+ chord: Chord;
566
+ };
567
+ /**
568
+ * All chord qualities the builder understands, in declaration order.
569
+ *
570
+ * The order is stable but carries no meaning: it is neither alphabetical nor
571
+ * sorted by template size. {@link detectChord} uses it as its final tie-break,
572
+ * so it is part of the observable behaviour and does not get reshuffled
573
+ * casually — but do not read it as a ranking.
574
+ *
575
+ * @category Chords
576
+ */
577
+ declare function chordQualities(): ChordQuality[];
578
+ /**
579
+ * Build a chord rooted on a diatonic scale degree.
580
+ *
581
+ * The root pitch class is the degree's diatonic pitch class in `key`; the
582
+ * quality's interval template is attached unchanged. Degrees beyond the scale
583
+ * length wrap around, so degree 8 of a heptatonic scale is its degree 1.
584
+ *
585
+ * @param degree 1-based scale degree of the chord root: 1 is the tonic.
586
+ * @param ext Chord quality to apply.
587
+ * @param key Key context supplying the diatonic root, as a key name, a
588
+ * key/scale, or a `Key`.
589
+ * @returns The constructed chord.
590
+ * @throws If `degree` is not a positive integer, or `ext` is not a known
591
+ * quality.
592
+ *
593
+ * @category Chords
594
+ */
595
+ declare function chordFromDegree(degree: number, ext: ChordQuality, key: KeyLike): Chord;
596
+ /**
597
+ * Build a chord from an explicit root pitch class and quality.
598
+ *
599
+ * @param rootPc Root pitch class (0..11).
600
+ * @param quality Chord quality supplying the interval template.
601
+ * @param bassPc Optional slash-chord bass pitch class.
602
+ * @returns The constructed chord.
603
+ *
604
+ * @example
605
+ * ```ts
606
+ * import { makeChord } from '@libraz/libcantus';
607
+ * const cmaj7 = makeChord(0, 'maj7');
608
+ * // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }
609
+ * ```
610
+ *
611
+ * @category Chords
612
+ */
613
+ declare function makeChord(rootPc: number, quality: ChordQuality, bassPc?: number): Chord;
614
+ /**
615
+ * Build a chord from a {@link ChordSpec}.
616
+ *
617
+ * The structural way in, for the chords a quality name cannot reach: the tones
618
+ * come from the spec, and `quality` is the name that fits it, or the nearest
619
+ * name when none does. A chord built this way is an ordinary {@link Chord} —
620
+ * every consumer reads its `intervals` as before, and
621
+ * {@link formatChordSymbol} writes the alterations back out.
622
+ *
623
+ * @param spec The chord spec; its `rootPc`/`bassPc` become the chord's.
624
+ * @returns The constructed chord.
625
+ * @throws If any part of the spec is not one the model defines.
626
+ *
627
+ * @example
628
+ * ```ts
629
+ * import { chordFromSpec } from '@libraz/libcantus';
630
+ * chordFromSpec({
631
+ * rootPc: 0,
632
+ * base: 'maj',
633
+ * seventh: 'maj7',
634
+ * alterations: [{ degree: 11, alter: 1 }],
635
+ * additions: [],
636
+ * omissions: [],
637
+ * });
638
+ * // { rootPc: 0, quality: 'maj7#11', intervals: [0, 4, 7, 11, 18] }
639
+ * ```
640
+ *
641
+ * @category Chords
642
+ */
643
+ declare function chordFromSpec(spec: ChordSpec): Chord;
644
+ /**
645
+ * Read a chord structurally: which base, seventh, alterations and omissions it
646
+ * is made of.
647
+ *
648
+ * The reading comes from the tones themselves, so it describes a chord whatever
649
+ * built it — a parsed symbol, a detected pitch set, a span carrying a template
650
+ * no name covers. Only a template with no structural reading at all falls back
651
+ * to the one its `quality` names.
652
+ *
653
+ * @param chord The chord to read.
654
+ * @returns The spec, carrying the chord's own root and slash bass.
655
+ * @throws If the chord's template has no reading and its quality is unknown.
656
+ *
657
+ * @example
658
+ * ```ts
659
+ * import { chordSpecOf, parseChordSymbol } from '@libraz/libcantus';
660
+ * chordSpecOf(parseChordSymbol('C7(b9,#11)')).alterations;
661
+ * // [{ degree: 9, alter: -1 }, { degree: 11, alter: 1 }]
662
+ * ```
663
+ *
664
+ * @category Chords
665
+ */
666
+ declare function chordSpecOf(chord: Chord): ChordSpec;
667
+ /**
668
+ * Read a {@link ChordSpan} as a chord.
669
+ *
670
+ * The canonical way to cross from a span to a chord. A span carrying no
671
+ * `intervals` yields exactly the chord {@link makeChord} builds from its root,
672
+ * quality and bass; a span carrying an explicit template keeps it, so a color
673
+ * tone the {@link ChordQuality} union cannot name survives the trip through a
674
+ * progression, a timeline, or a generator. The template is copied, so the
675
+ * chord and the span never share an array.
676
+ *
677
+ * @param span The span to read.
678
+ * @returns The chord the span describes.
679
+ * @throws If the span's root, bass or quality is invalid, or its `intervals`
680
+ * are not a non-empty array of integer semitone offsets.
681
+ *
682
+ * @example
683
+ * ```ts
684
+ * import { chordFromSpan } from '@libraz/libcantus';
685
+ * chordFromSpan({ rootPc: 0, quality: 'maj7', startBeat: 0 });
686
+ * // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }
687
+ * chordFromSpan({ rootPc: 0, quality: 'maj7', startBeat: 0, intervals: [0, 4, 11, 18] });
688
+ * // the same span with a fifth-less, #11 voicing the quality cannot name
689
+ * ```
690
+ *
691
+ * @category Composition
692
+ */
693
+ declare function chordFromSpan(span: ChordSpan): Chord;
694
+ /**
695
+ * Place a chord at a beat as a {@link ChordSpan}.
696
+ *
697
+ * The interval template is recorded only when it departs from the one the
698
+ * chord's quality names, so a span built from a standard chord carries the
699
+ * same fields it always did while a custom template is not lost.
700
+ *
701
+ * @param chord The chord to place.
702
+ * @param startBeat Beat the chord starts on.
703
+ * @returns The span describing that chord at that beat.
704
+ * @throws If `startBeat` is not finite, or the chord's quality is unknown.
705
+ *
706
+ * @example
707
+ * ```ts
708
+ * import { makeChord, spanFromChord } from '@libraz/libcantus';
709
+ * spanFromChord(makeChord(0, 'maj7'), 4);
710
+ * // { rootPc: 0, quality: 'maj7', startBeat: 4 } — no intervals for a standard chord
711
+ * ```
712
+ *
713
+ * @category Composition
714
+ */
715
+ declare function spanFromChord(chord: Chord, startBeat: number): ChordSpan;
716
+ /**
717
+ * Transpose a chord by a number of semitones.
718
+ *
719
+ * The interval template is carried over untouched, so a chord whose intervals
720
+ * were customised keeps them, and a slash bass moves with the root. Enharmonic
721
+ * spelling hints are dropped rather than shifted: the letter a transposed root
722
+ * should take depends on the destination key, which a semitone count does not
723
+ * carry. Pass the result through {@link spellChord} to respell it.
724
+ *
725
+ * @param chord The chord to transpose.
726
+ * @param semitones The signed semitone offset.
727
+ * @returns The transposed chord.
728
+ * @throws If `semitones` is not finite.
729
+ *
730
+ * @example
731
+ * ```ts
732
+ * import { formatChordSymbol, parseChordSymbol, transposeChord } from '@libraz/libcantus';
733
+ * formatChordSymbol(transposeChord(parseChordSymbol('C/G'), 2)); // 'D/A'
734
+ * ```
735
+ *
736
+ * @category Chords
737
+ */
738
+ declare function transposeChord(chord: Chord, semitones: number): Chord;
739
+ /**
740
+ * Get the sorted, deduplicated pitch classes of a chord.
741
+ *
742
+ * A slash bass is one of them: `F/G` sounds a G, the voicers put it in the
743
+ * bass, and a set that omitted it would not re-detect as the chord it came
744
+ * from. Pass `includeBass: false` to enumerate the interval template alone.
745
+ *
746
+ * @param chord The chord to enumerate.
747
+ * @param opts Set `includeBass: false` to omit a slash bass.
748
+ * @returns The chord's pitch classes, sorted ascending in [0, 11].
749
+ *
750
+ * @example
751
+ * ```ts
752
+ * import { makeChord, chordPitchClasses } from '@libraz/libcantus';
753
+ * chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]
754
+ * chordPitchClasses(makeChord(5, 'maj', 7)); // [0, 5, 7, 9] — F/G, G included
755
+ * ```
756
+ *
757
+ * @category Chords
758
+ */
759
+ declare function chordPitchClasses(chord: Chord, opts?: {
760
+ includeBass?: boolean;
761
+ }): number[];
762
+ /**
763
+ * A pitch's interval class above the chord root, in [0, 11].
764
+ *
765
+ * The shared reading of "where does this pitch sit in the chord", used by the
766
+ * safety evaluator and the voice analyser alike so they cannot disagree.
767
+ *
768
+ * @param pitch MIDI pitch or bare pitch class.
769
+ * @param chord The chord providing the root reference.
770
+ * @returns The interval class above the root.
771
+ * @category Chords
772
+ */
773
+ declare function intervalAboveRoot(pitch: number, chord: Chord): number;
774
+ /**
775
+ * Whether a pitch is one of a chord's tones, ignoring octave.
776
+ *
777
+ * @param pitch MIDI pitch or bare pitch class.
778
+ * @param chord The chord, or null for no sounding harmony.
779
+ * @returns True when the pitch class belongs to the chord.
780
+ * @category Chords
781
+ */
782
+ declare function isChordMember(pitch: number, chord: Chord | null): boolean;
783
+ /**
784
+ * Determine a pitch's harmonic role within a chord.
785
+ *
786
+ * The role is derived from the pitch's interval above the chord root, reduced
787
+ * modulo 12. A major sixth (9) reads as a `sixth` for sixth chords but as a
788
+ * `seventh` for a diminished-seventh chord; ninths and other tensions have no
789
+ * basic role and return null.
790
+ *
791
+ * @param pitch MIDI pitch or bare pitch class.
792
+ * @param chord The chord providing the root reference.
793
+ * @returns The chord-tone role, or null if the pitch has no basic role.
794
+ *
795
+ * @category Chords
796
+ */
797
+ declare function chordToneRole(pitch: number, chord: Chord): ChordToneRole | null;
798
+ /**
799
+ * Build the diatonic triad rooted on a scale degree by stacking scale thirds.
800
+ *
801
+ * Unlike {@link chordFromDegree}, the chord quality is derived from the scale
802
+ * rather than supplied, so degrees yield their scale-correct triads (e.g. a
803
+ * diminished triad on the leading tone of a major key).
804
+ *
805
+ * @param degree 1-based scale degree of the chord root: 1 is the tonic.
806
+ * @param key Key/scale context, as a key name, a key/scale, or a `Key`.
807
+ * @returns The diatonic triad.
808
+ * @throws If the scale is not heptatonic. Stacking thirds means skipping every
809
+ * other degree, which only lands on a triad when there are seven of them, so
810
+ * the pentatonic, blues, whole-tone, octatonic and chromatic scales have no
811
+ * diatonic triad; use {@link chordFromDegree} with an explicit quality there.
812
+ *
813
+ * @example
814
+ * ```ts
815
+ * import { majorKey, diatonicTriad } from '@libraz/libcantus';
816
+ * const tonic = diatonicTriad(1, majorKey(0)); // C major triad (degree 1 of C major)
817
+ * ```
818
+ *
819
+ * @category Chords
820
+ */
821
+ declare function diatonicTriad(degree: number, key: KeyLike): Chord;
822
+ /**
823
+ * Build the diatonic seventh chord rooted on a scale degree.
824
+ *
825
+ * @param degree 1-based scale degree of the chord root: 1 is the tonic.
826
+ * @param key Key/scale context, as a key name, a key/scale, or a `Key`.
827
+ * @returns The diatonic seventh chord.
828
+ * @throws If the scale is not heptatonic, for the reason given on
829
+ * {@link diatonicTriad}.
830
+ *
831
+ * @category Chords
832
+ */
833
+ declare function diatonicSeventh(degree: number, key: KeyLike): Chord;
834
+
835
+ /**
836
+ * Style policy: `strict` counterpoint vs. `pop` voice leading.
837
+ *
838
+ * A profile says two things. It sets the severity of each reason
839
+ * {@link evaluateSafety} finds, which decides what is rejected outright, and it
840
+ * carries the {@link ProfileWeights} that rank whatever survives — because most
841
+ * of what separates the two styles is preference rather than prohibition.
842
+ *
843
+ * @category Arrangement & Analysis
844
+ */
845
+ type SafetyProfile = 'strict' | 'pop';
846
+ /**
847
+ * How a profile ranks the candidates its severity table has let through.
848
+ *
849
+ * Each field is a score contribution, added when the situation it names occurs;
850
+ * a negative value is a penalty. The scale is arbitrary but shared, so only the
851
+ * relative sizes matter. Nothing here can make an unsafe pitch usable: rejection
852
+ * is the severity table's business, and these weights only order what is left.
853
+ *
854
+ * @category Arrangement & Analysis
855
+ */
856
+ type ProfileWeights = {
857
+ /** A third or a sixth against the other voice. */
858
+ imperfectConsonance: number;
859
+ /** A unison, fifth or octave against the other voice. */
860
+ perfectConsonance: number;
861
+ /** A second, seventh or tritone against the other voice. */
862
+ dissonance: number;
863
+ /** The candidate belongs to the sounding chord. */
864
+ chordTone: number;
865
+ /** The two voices move in opposite directions. */
866
+ contraryMotion: number;
867
+ /** One voice holds while the other moves. */
868
+ obliqueMotion: number;
869
+ /** Both voices move the same way into a different interval. */
870
+ similarMotion: number;
871
+ /** Both voices move the same way, keeping the same imperfect consonance. */
872
+ parallelImperfect: number;
873
+ /** The candidate is a step from the previous note of its own line. */
874
+ stepwise: number;
875
+ /** Per semitone of melodic movement, so a leap costs more than a step. */
876
+ melodicDistance: number;
877
+ /** The move is a leap strict counterpoint forbids outright. */
878
+ forbiddenLeap: number;
879
+ /** Per semitone away from the centre of the line's register. */
880
+ registerDrift: number;
881
+ };
882
+ /**
883
+ * The weight table each profile ranks candidates by.
884
+ *
885
+ * `strict` states the sixteenth-century preferences: contrary motion is worth
886
+ * seeking, similar motion is worth avoiding, imperfect consonances carry the
887
+ * line, and a run of parallel thirds earns nothing. `pop` inverts two of those.
888
+ * Parallel thirds and sixths are the harmony line an arranger writes on purpose,
889
+ * a pedal or a held unison under a moving lead is a texture rather than a fault,
890
+ * and similar motion is simply how two parts often move together — while a bass
891
+ * moving against the lead is still worth preferring where it is available.
892
+ *
893
+ * @category Arrangement & Analysis
894
+ */
895
+ declare const PROFILE_WEIGHTS: Readonly<Record<SafetyProfile, Readonly<ProfileWeights>>>;
896
+ /**
897
+ * Resolve a profile to the weights that rank its candidates, with per-field
898
+ * overrides applied on top.
899
+ *
900
+ * @param profile The profile whose table to start from.
901
+ * @param overrides Fields to replace; anything absent keeps the profile's value.
902
+ * @returns The complete weight table to score with.
903
+ * @throws If `profile` is not one of the profile names
904
+ * ({@link InvalidInputError}). A misspelled profile scored under a default
905
+ * table would rank candidates by a style the caller did not ask for.
906
+ * @example
907
+ * ```ts
908
+ * import { profileWeights } from '@libraz/libcantus';
909
+ * profileWeights('pop', { parallelImperfect: 4 }).contraryMotion; // 1.5 — the rest is untouched
910
+ * ```
911
+ * @category Arrangement & Analysis
912
+ */
913
+ declare function profileWeights(profile: SafetyProfile, overrides?: Partial<ProfileWeights>): ProfileWeights;
914
+ /**
915
+ * Overall placeability verdict for a candidate pitch.
916
+ *
917
+ * @category Arrangement & Analysis
918
+ */
919
+ declare enum NoteSafety {
920
+ Safe = 0,
921
+ Warning = 1,
922
+ Dissonant = 2
923
+ }
924
+ /**
925
+ * Bit flags describing why a pitch received its verdict.
926
+ *
927
+ * @category Arrangement & Analysis
928
+ */
929
+ declare enum ReasonFlag {
930
+ ChordTone = 1,
931
+ Tension = 2,
932
+ AvoidNote = 4,
933
+ ScaleTone = 8,
934
+ NonScale = 16,
935
+ OutOfRange = 32,
936
+ Tritone = 64,
937
+ LargeLeap = 128,
938
+ MinorSecond = 256,
939
+ MajorSeventh = 512,
940
+ VerticalDissonance = 1024,
941
+ ParallelPerfect = 2048,
942
+ HiddenParallel = 4096,
943
+ VoiceCrossing = 8192,
944
+ Suspension = 16384,
945
+ NeedsResolution = 32768,
946
+ MelodicTritone = 65536
947
+ }
948
+ /**
949
+ * A neighbouring voice's current and previous pitch.
950
+ *
951
+ * @category Arrangement & Analysis
952
+ */
953
+ type VoiceSnapshot = {
954
+ pitch: number;
955
+ prevPitch?: number;
956
+ };
957
+ /**
958
+ * Everything needed to evaluate one candidate pitch.
959
+ *
960
+ * @category Arrangement & Analysis
961
+ */
962
+ type SafetyQuery = {
963
+ profile: SafetyProfile;
964
+ candidatePitch: number;
965
+ prevPitch?: number;
966
+ chord: Chord | null;
967
+ key: KeyScale;
968
+ otherVoices: VoiceSnapshot[];
969
+ strongBeat: boolean;
970
+ vocalLow?: number;
971
+ vocalHigh?: number;
972
+ };
973
+ /**
974
+ * The verdict, reason flags, and optional resolution guidance.
975
+ *
976
+ * @category Arrangement & Analysis
977
+ */
978
+ type SafetyResult = {
979
+ safety: NoteSafety;
980
+ reasons: number;
981
+ resolveTo?: number;
982
+ suggestions?: number[];
983
+ rationale?: string;
984
+ };
985
+ /**
986
+ * Evaluate the safety of placing a candidate pitch in a voice.
987
+ *
988
+ * Reasons are merged from harmonic context (chord tone / tension / avoid / scale)
989
+ * and counterpoint (vertical dissonance, parallels, voice crossing). The `strict`
990
+ * profile treats avoid notes and parallels as dissonant; `pop` treats them as
991
+ * warnings. The final verdict is the worst severity among the reasons.
992
+ *
993
+ * @param q The candidate and its harmonic/voice-leading context.
994
+ * @returns The verdict, reason bitmask, and optional resolution guidance.
995
+ * @throws If the profile is not one of the profile names, or if any pitch in
996
+ * the query is not a MIDI pitch in 0..127 ({@link InvalidInputError}).
997
+ * @example
998
+ * ```ts
999
+ * import { evaluateSafety, makeChord, majorKey, NoteSafety } from '@libraz/libcantus';
1000
+ * const result = evaluateSafety({
1001
+ * profile: 'pop',
1002
+ * candidatePitch: 60, // C over a C major chord
1003
+ * chord: makeChord(0, 'maj'),
1004
+ * key: majorKey(0),
1005
+ * otherVoices: [],
1006
+ * strongBeat: true,
1007
+ * });
1008
+ * result.safety === NoteSafety.Safe; // true — C is a chord tone
1009
+ * ```
1010
+ * @category Arrangement & Analysis
1011
+ */
1012
+ declare function evaluateSafety(q: SafetyQuery, opts?: EvaluateSafetyOptions): SafetyResult;
1013
+ /**
1014
+ * Options for {@link evaluateSafety}.
1015
+ *
1016
+ * @category Arrangement & Analysis
1017
+ */
1018
+ type EvaluateSafetyOptions = {
1019
+ /**
1020
+ * Whether to search for safe replacement pitches when the verdict is not
1021
+ * safe. Turning it off skips up to two dozen extra evaluations per rejected
1022
+ * pitch, which is worth doing when only the verdict is wanted.
1023
+ *
1024
+ * @defaultValue true
1025
+ */
1026
+ suggestions?: boolean;
1027
+ };
1028
+ /**
1029
+ * Enumerate placeable pitches in a range, chord tones first, descending.
1030
+ *
1031
+ * @param q The safety context minus the candidate pitch.
1032
+ * @param pitchLow Lowest MIDI pitch to consider (inclusive).
1033
+ * @param pitchHigh Highest MIDI pitch to consider (inclusive).
1034
+ * @returns Placeable pitches (non-dissonant), chord tones before others, each group descending.
1035
+ * @throws If either bound is not a MIDI pitch in 0..127, reversed, or exceeds
1036
+ * the generation budget, or if the context names an unknown profile.
1037
+ * @example
1038
+ * ```ts
1039
+ * import { enumerateSafePitches, makeChord, majorKey } from '@libraz/libcantus';
1040
+ * const pitches = enumerateSafePitches(
1041
+ * { profile: 'pop', chord: makeChord(0, 'maj'), key: majorKey(0), otherVoices: [], strongBeat: true },
1042
+ * 60,
1043
+ * 72,
1044
+ * );
1045
+ * pitches; // placeable pitches in [60, 72], chord tones first, each group descending
1046
+ * ```
1047
+ * @category Arrangement & Analysis
1048
+ */
1049
+ declare function enumerateSafePitches(q: Omit<SafetyQuery, 'candidatePitch'>, pitchLow: number, pitchHigh: number): number[];
1050
+
1051
+ /**
1052
+ * Lead-sheet chord symbol parsing and formatting.
1053
+ *
1054
+ * Bridges the informal `<root><quality>[/<bass>]` notation musicians write
1055
+ * (`Cmaj7`, `F#m7b5`, `Bb7`, `C/G`) and the library's structured {@link Chord}
1056
+ * type, so callers can accept/emit plain text at the edges of the API.
1057
+ *
1058
+ * The root and the slash bass are note names, so they are read and written in
1059
+ * whichever notation system the caller names — a German chart's `H7`, `As7` and
1060
+ * `Ges/B` included. Unlike a note name, a chord symbol is never attributed to a
1061
+ * system on its own: German `B` is a B flat and English `B` a B natural, and a
1062
+ * symbol carries no `dur`/`moll` word to break the tie, so the most common
1063
+ * symbol in the vocabulary would otherwise change chord with the source it came
1064
+ * from. With no system given a symbol is English.
1065
+ */
1066
+
1067
+ /**
1068
+ * Parse a lead-sheet chord symbol into a {@link Chord}.
1069
+ *
1070
+ * Accepts `<root><quality>[/<bass>]`, e.g. `Cmaj7`, `F#m7b5`, `Bb7`, `C/G`,
1071
+ * `C6/9`, `C6/9/E`. Root and bass letters are case-insensitive, matching
1072
+ * {@link parseNote}. A `/` is ambiguous between a slash bass and the `6/9`
1073
+ * quality; the text splits at the last `/` whose right-hand side is a valid
1074
+ * bare note preceded by a recognized quality, so `6/9` (with or without a
1075
+ * further slash bass) parses as a quality.
1076
+ *
1077
+ * The root and bass are read in `system`, so a German chart's `H7`, `As7` and
1078
+ * `Ges/B` are read by asking for `'german'`. The system is never inferred: with
1079
+ * none given the symbol is English, where `B` is the B natural and `H` no note
1080
+ * at all. Case carries nothing in a chord symbol — unlike a German key name,
1081
+ * where the case of the tonic is the mode — so the quality suffix alone says
1082
+ * major or minor. Where a German root's flat suffix could equally open the
1083
+ * quality, the longest root that leaves a known quality behind wins: `Asus4` is
1084
+ * an A suspended chord and `Assus4` the A flat one.
1085
+ *
1086
+ * The quality suffix is read structurally when no name covers it, so a chart's
1087
+ * bracketed tensions parse as readily as the names do: `Cmaj7(#11)`,
1088
+ * `C7(b9,#11)`, `C7(13)`, `Csus4(add9)`, `C-Δ9`, `C6/9(#11)`. A `/` between two
1089
+ * figures separates them as it does inside brackets, which is what the sixth
1090
+ * and ninth of a `6/9` are. Such a chord carries the tones it names and reports
1091
+ * the nearest quality name (see {@link chordSpecQuality}); read
1092
+ * {@link chordSpecOf} for its structure.
1093
+ *
1094
+ * The parsed chord carries the root/bass spellings as enharmonic hints
1095
+ * (`rootSpelling`/`bassSpelling`) so {@link formatChordSymbol} can reproduce
1096
+ * flat spellings such as `Bbmaj7` instead of respelling them with sharps.
1097
+ *
1098
+ * @param text The chord symbol text.
1099
+ * @param opts `system` reads the root and bass in that notation system instead
1100
+ * of English.
1101
+ * @returns The parsed chord.
1102
+ * @throws If the root or quality is not recognized in that system. Use
1103
+ * {@link tryParseChordSymbol} where failure is ordinary, such as a chord
1104
+ * field read on every keystroke.
1105
+ * @example
1106
+ * ```ts
1107
+ * import { parseChordSymbol, formatChordSymbol } from '@libraz/libcantus';
1108
+ * const c = parseChordSymbol('Bbmaj7');
1109
+ * formatChordSymbol(c); // 'Bbmaj7' — flat spelling is preserved on round-trip
1110
+ * parseChordSymbol('H7', { system: 'german' }).rootPc; // 11 — the B natural
1111
+ * parseChordSymbol('B', { system: 'german' }).rootPc; // 10 — the German B flat
1112
+ * ```
1113
+ * @category Chords
1114
+ */
1115
+ declare function parseChordSymbol(text: string, opts?: NoteNameOptions): Chord;
1116
+ /**
1117
+ * Parse a lead-sheet chord symbol, reporting failure instead of throwing it.
1118
+ *
1119
+ * The same reading as {@link parseChordSymbol} — that function is this one with
1120
+ * its error thrown — for the callers where a symbol that does not parse yet is
1121
+ * the normal state of the input rather than a fault: a chord field says what is
1122
+ * wrong with what has been typed so far, and does not need a `try` around every
1123
+ * keystroke to do it.
1124
+ *
1125
+ * @param text The chord symbol text.
1126
+ * @param opts `system` reads the root and bass in that notation system instead
1127
+ * of English.
1128
+ * @returns The chord, or the error explaining why the text is not one.
1129
+ * @example
1130
+ * ```ts
1131
+ * import { tryParseChordSymbol } from '@libraz/libcantus';
1132
+ * const result = tryParseChordSymbol('Cmaj7(#11)');
1133
+ * result.ok ? result.value.intervals : result.error.message;
1134
+ * ```
1135
+ * @category Chords
1136
+ */
1137
+ declare function tryParseChordSymbol(text: string, opts?: NoteNameOptions): ParseResult<Chord>;
1138
+ /**
1139
+ * Anything that names a chord: a chord symbol, plain chord data, or a value
1140
+ * that serializes to chord data such as the `Chord` class.
1141
+ *
1142
+ * @category Chords
1143
+ */
1144
+ type ChordLike = string | Chord | {
1145
+ /** The chord data this value stands for. */
1146
+ toJSON(): Chord;
1147
+ };
1148
+ /**
1149
+ * Resolve any chord-shaped value to plain {@link Chord} data.
1150
+ *
1151
+ * The counterpart of {@link toSpelledInterval} for chords: an entry point takes
1152
+ * whatever form the caller has — the symbol a chart holds, the data the chord
1153
+ * module returns, or a `Chord` instance — and gets one shape back. An instance
1154
+ * is accepted through its `toJSON` method rather than by its type, so the
1155
+ * layers below the model can read a class without importing it.
1156
+ *
1157
+ * @param value A chord symbol, plain chord data, or a value whose `toJSON`
1158
+ * returns chord data.
1159
+ * @returns The validated chord data, with root and bass reduced to pitch
1160
+ * classes and any spelling hint carried through.
1161
+ * @throws If the value names no chord, or an interval, root, or bass is not a
1162
+ * finite number.
1163
+ * @example
1164
+ * ```ts
1165
+ * import { toChordData } from '@libraz/libcantus';
1166
+ * toChordData('Cmaj7').intervals; // [0, 4, 7, 11]
1167
+ * toChordData({ rootPc: 0, quality: 'maj', intervals: [0, 4, 7] }).rootPc; // 0
1168
+ * ```
1169
+ * @category Chords
1170
+ */
1171
+ declare function toChordData(value: ChordLike): Chord;
1172
+ /**
1173
+ * How a chord symbol is written: in which notation system, and on which side of
1174
+ * the enharmonic fence.
1175
+ *
1176
+ * @category Chords
1177
+ */
1178
+ type ChordSymbolOptions = NoteNameOptions & {
1179
+ /**
1180
+ * Prefer flat spellings over sharps for an altered root or bass; passing
1181
+ * either `true` or `false` overrides any spelling hint the chord carries.
1182
+ */
1183
+ flats?: boolean;
1184
+ };
1185
+ /**
1186
+ * Format a {@link Chord} as a lead-sheet chord symbol.
1187
+ *
1188
+ * The inverse of {@link parseChordSymbol} in every notation system: each
1189
+ * quality maps to one canonical suffix spelling, the root and bass are written
1190
+ * in `system`, and a slash bass is appended only when it differs from the root.
1191
+ * Every symbol written here reads back through {@link parseChordSymbol} as the
1192
+ * same root, sounding bass and tones — whatever combination of tensions the
1193
+ * chord carries, and whether or not a quality name covers it.
1194
+ * When the chord carries `rootSpelling`/`bassSpelling` hints (as chords from
1195
+ * {@link parseChordSymbol} do) and no explicit `flats` preference is given, the
1196
+ * hints are reused so flat symbols round-trip unchanged.
1197
+ *
1198
+ * The suffix is written from the chord's own tones (see {@link chordSpecOf}),
1199
+ * not from its quality name, so a chord carrying alterations no name covers is
1200
+ * written out in full — `C7(b9,#11)` — rather than under the nearest name. A
1201
+ * tone the chord leaves out is not written: the symbol names the harmony, so a
1202
+ * fifth-less dominant is still `C7`.
1203
+ *
1204
+ * @param chord The chord to format, as a chord symbol, chord data, or a
1205
+ * `Chord`.
1206
+ * @param opts `system` writes the root and bass in that notation system instead
1207
+ * of English; `flats` overrides the spelling hints, as
1208
+ * {@link ChordSymbolOptions} describes.
1209
+ * @returns The chord symbol text.
1210
+ * @example
1211
+ * ```ts
1212
+ * import { makeChord, formatChordSymbol, parseChordSymbol } from '@libraz/libcantus';
1213
+ * formatChordSymbol(makeChord(0, 'min7')); // 'Cm7'
1214
+ * formatChordSymbol(parseChordSymbol('Bb7'), { system: 'german' }); // 'B7'
1215
+ * formatChordSymbol(parseChordSymbol('B7'), { system: 'german' }); // 'H7'
1216
+ * ```
1217
+ * @category Chords
1218
+ */
1219
+ declare function formatChordSymbol(chord: ChordLike, opts?: ChordSymbolOptions): string;
1220
+ /**
1221
+ * Transpose a chord symbol by a number of semitones.
1222
+ *
1223
+ * The symbol is read in the same system it is written back in, so a German
1224
+ * chart stays German across the transposition.
1225
+ *
1226
+ * @param text The chord symbol text.
1227
+ * @param semitones Signed semitone offset to apply to the root and bass.
1228
+ * @param opts Options for reading and writing the symbol; see
1229
+ * {@link ChordSymbolOptions}.
1230
+ * @returns The transposed chord symbol text.
1231
+ * @throws If `text` does not parse as a chord symbol.
1232
+ * @example
1233
+ * ```ts
1234
+ * import { transposeChordSymbol } from '@libraz/libcantus';
1235
+ * transposeChordSymbol('C/G', 2); // 'D/A'
1236
+ * transposeChordSymbol('H7', 1, { system: 'german' }); // 'C7'
1237
+ * ```
1238
+ * @category Chords
1239
+ */
1240
+ declare function transposeChordSymbol(text: string, semitones: number, opts?: ChordSymbolOptions): string;
1241
+
1242
+ export { toChordData as $, type Alteration as A, diatonicTriad as B, type ChordBase as C, dominantKeyOf as D, type EvaluateSafetyOptions as E, enharmonicKeyOf as F, enumerateSafePitches as G, evaluateSafety as H, formatChordSymbol as I, intervalAboveRoot as J, type KeyLike as K, isChordMember as L, keyRelationBetween as M, NoteSafety as N, makeChord as O, PROFILE_WEIGHTS as P, parallelKeyOf as Q, ReasonFlag as R, type SafetyProfile as S, parseChordSymbol as T, profileWeights as U, type VoiceSnapshot as V, relatedKeysOf as W, relativeKeyOf as X, spanFromChord as Y, spelledKeyOf as Z, subdominantKeyOf as _, type AlteredDegree as a, toKeyScale as a0, transposeChord as a1, transposeChordSymbol as a2, tryParseChordSymbol as a3, type Chord as b, type ChordLike as c, type ChordQuality as d, type ChordSegment as e, type ChordSeventh as f, type ChordSpan as g, type ChordSpec as h, type ChordSymbolOptions as i, type ChordToneRole as j, type KeyRelation as k, type PitchSpelling as l, type ProfileWeights as m, type SafetyQuery as n, type SafetyResult as o, type SpelledKey as p, chordFromDegree as q, chordFromSpan as r, chordFromSpec as s, chordPitchClasses as t, chordQualities as u, chordSpecIntervals as v, chordSpecOf as w, chordSpecQuality as x, chordToneRole as y, diatonicSeventh as z };