@libraz/libcantus 0.9.3 → 0.9.5

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 (201) hide show
  1. package/README.md +29 -20
  2. package/README_ja.md +268 -0
  3. package/dist/analyze/index.cjs +39 -1947
  4. package/dist/analyze/index.cjs.map +1 -1
  5. package/dist/analyze/index.d.cts +161 -91
  6. package/dist/analyze/index.d.ts +161 -91
  7. package/dist/analyze/index.js +19 -8
  8. package/dist/chunk-2A2QMA74.cjs +261 -0
  9. package/dist/chunk-2A2QMA74.cjs.map +1 -0
  10. package/dist/chunk-2PTFGVD7.js +261 -0
  11. package/dist/chunk-2PTFGVD7.js.map +1 -0
  12. package/dist/chunk-357ZDPVU.cjs +162 -0
  13. package/dist/chunk-357ZDPVU.cjs.map +1 -0
  14. package/dist/chunk-3KX76RLG.js +1548 -0
  15. package/dist/chunk-3KX76RLG.js.map +1 -0
  16. package/dist/chunk-4VZ5MZAM.cjs +889 -0
  17. package/dist/chunk-4VZ5MZAM.cjs.map +1 -0
  18. package/dist/{chunk-C5XYKUVG.js → chunk-7EONYVI5.js} +471 -171
  19. package/dist/chunk-7EONYVI5.js.map +1 -0
  20. package/dist/{chunk-IT2O4XFE.js → chunk-7JEP3MFY.js} +42 -34
  21. package/dist/chunk-7JEP3MFY.js.map +1 -0
  22. package/dist/{chunk-4MHA432G.js → chunk-AID75RN3.js} +572 -250
  23. package/dist/chunk-AID75RN3.js.map +1 -0
  24. package/dist/chunk-BSLTLGM3.cjs +497 -0
  25. package/dist/chunk-BSLTLGM3.cjs.map +1 -0
  26. package/dist/chunk-CU6VG2YM.cjs +109 -0
  27. package/dist/chunk-CU6VG2YM.cjs.map +1 -0
  28. package/dist/{chunk-EH6EM37U.js → chunk-DZMHIGI4.js} +81 -59
  29. package/dist/chunk-DZMHIGI4.js.map +1 -0
  30. package/dist/{chunk-AKLYPWIN.js → chunk-EDOTEABK.js} +45 -19
  31. package/dist/chunk-EDOTEABK.js.map +1 -0
  32. package/dist/{chunk-2ZWMSJH6.js → chunk-HN2OEUN2.js} +7 -4
  33. package/dist/chunk-HN2OEUN2.js.map +1 -0
  34. package/dist/{chunk-MIWO425M.js → chunk-KBTTEX7Q.js} +128 -43
  35. package/dist/chunk-KBTTEX7Q.js.map +1 -0
  36. package/dist/chunk-KQN2ZYND.cjs +724 -0
  37. package/dist/chunk-KQN2ZYND.cjs.map +1 -0
  38. package/dist/chunk-MPTVJIVG.cjs +3176 -0
  39. package/dist/chunk-MPTVJIVG.cjs.map +1 -0
  40. package/dist/chunk-MTMZTMWM.cjs +53 -0
  41. package/dist/chunk-MTMZTMWM.cjs.map +1 -0
  42. package/dist/{chunk-CHMXELDS.js → chunk-NNB67XA2.js} +372 -197
  43. package/dist/chunk-NNB67XA2.js.map +1 -0
  44. package/dist/chunk-OL3IHHSJ.cjs +1204 -0
  45. package/dist/chunk-OL3IHHSJ.cjs.map +1 -0
  46. package/dist/chunk-PI3UXRWK.cjs +528 -0
  47. package/dist/chunk-PI3UXRWK.cjs.map +1 -0
  48. package/dist/chunk-R2VVFAIN.js +528 -0
  49. package/dist/chunk-R2VVFAIN.js.map +1 -0
  50. package/dist/chunk-T64C7ZD7.cjs +1 -0
  51. package/dist/chunk-T64C7ZD7.cjs.map +1 -0
  52. package/dist/chunk-WFDXOLUB.cjs +337 -0
  53. package/dist/chunk-WFDXOLUB.cjs.map +1 -0
  54. package/dist/chunk-WTAN4ACG.cjs +1548 -0
  55. package/dist/chunk-WTAN4ACG.cjs.map +1 -0
  56. package/dist/chunk-YFJXS3AU.cjs +33 -0
  57. package/dist/chunk-YFJXS3AU.cjs.map +1 -0
  58. package/dist/{chunk-GOAW4VYL.js → chunk-YUE6TJ4M.js} +315 -145
  59. package/dist/chunk-YUE6TJ4M.js.map +1 -0
  60. package/dist/{chunk-62QZKCJQ.js → chunk-ZGLJM4A4.js} +10 -6
  61. package/dist/chunk-ZGLJM4A4.js.map +1 -0
  62. package/dist/core/index.cjs +140 -647
  63. package/dist/core/index.cjs.map +1 -1
  64. package/dist/core/index.d.cts +313 -41
  65. package/dist/core/index.d.ts +313 -41
  66. package/dist/core/index.js +64 -16
  67. package/dist/{function-DVH4Eusr.d.ts → function-CxixTB02.d.cts} +122 -10
  68. package/dist/{function-DYt4iKsn.d.cts → function-DTCt675z.d.ts} +122 -10
  69. package/dist/generate/index.cjs +28 -4085
  70. package/dist/generate/index.cjs.map +1 -1
  71. package/dist/generate/index.d.cts +374 -66
  72. package/dist/generate/index.d.ts +374 -66
  73. package/dist/generate/index.js +23 -9
  74. package/dist/{index-Jc0Ryi79.d.ts → index-B2Ulxxpo.d.cts} +21 -5
  75. package/dist/{index-CpOsP1y9.d.cts → index-BkYJ0xMq.d.cts} +18 -17
  76. package/dist/{index-CxqBQtH1.d.cts → index-BuaB-ypt.d.ts} +21 -5
  77. package/dist/index-CAN7v-kw.d.ts +199 -0
  78. package/dist/{index-Bt4tOUD9.d.ts → index-COw1Ky9g.d.ts} +93 -8
  79. package/dist/{index-Dikst44v.d.cts → index-Cfx8xgH0.d.ts} +14 -11
  80. package/dist/{index-DxvARIP2.d.ts → index-DRtIhlJj.d.ts} +18 -17
  81. package/dist/{index-Cl7mhOFM.d.cts → index-DXd9JikN.d.cts} +92 -10
  82. package/dist/{index-Cl7mhOFM.d.ts → index-DXd9JikN.d.ts} +92 -10
  83. package/dist/index-alrRninU.d.cts +199 -0
  84. package/dist/{index-BNlGP86A.d.cts → index-oTQbYYIs.d.cts} +93 -8
  85. package/dist/index-tR9jTn26.d.cts +275 -0
  86. package/dist/index-tR9jTn26.d.ts +275 -0
  87. package/dist/{index-Bg5dYMmZ.d.ts → index-x2vcsduE.d.cts} +14 -11
  88. package/dist/index.cjs +429 -7383
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.d.cts +15 -15
  91. package/dist/index.d.ts +15 -15
  92. package/dist/index.js +121 -27
  93. package/dist/model/index.cjs +8 -2562
  94. package/dist/model/index.cjs.map +1 -1
  95. package/dist/model/index.d.cts +471 -81
  96. package/dist/model/index.d.ts +471 -81
  97. package/dist/model/index.js +6 -7
  98. package/dist/styled-Bl0ZK28h.d.ts +543 -0
  99. package/dist/styled-Crv6SA4S.d.cts +543 -0
  100. package/dist/theory/index.cjs +172 -1822
  101. package/dist/theory/index.cjs.map +1 -1
  102. package/dist/theory/index.d.cts +151 -233
  103. package/dist/theory/index.d.ts +151 -233
  104. package/dist/theory/index.js +30 -7
  105. package/dist/{types-MGP29r3t.d.cts → types-BN6_Q9Kl.d.cts} +11 -2
  106. package/dist/{types-MGP29r3t.d.ts → types-BN6_Q9Kl.d.ts} +11 -2
  107. package/package.json +34 -13
  108. package/dist/chunk-2ZWMSJH6.js.map +0 -1
  109. package/dist/chunk-4MHA432G.js.map +0 -1
  110. package/dist/chunk-62QZKCJQ.js.map +0 -1
  111. package/dist/chunk-AKLYPWIN.js.map +0 -1
  112. package/dist/chunk-C5XYKUVG.js.map +0 -1
  113. package/dist/chunk-CHMXELDS.js.map +0 -1
  114. package/dist/chunk-DYWFNC4A.js +0 -152
  115. package/dist/chunk-DYWFNC4A.js.map +0 -1
  116. package/dist/chunk-EH6EM37U.js.map +0 -1
  117. package/dist/chunk-FBQK3ZQN.js +0 -131
  118. package/dist/chunk-FBQK3ZQN.js.map +0 -1
  119. package/dist/chunk-GOAW4VYL.js.map +0 -1
  120. package/dist/chunk-I5R7ZBJS.js +0 -202
  121. package/dist/chunk-I5R7ZBJS.js.map +0 -1
  122. package/dist/chunk-IT2O4XFE.js.map +0 -1
  123. package/dist/chunk-MIWO425M.js.map +0 -1
  124. package/dist/chunk-SGU7SPLK.js +0 -924
  125. package/dist/chunk-SGU7SPLK.js.map +0 -1
  126. package/dist/index-CGMZNCx6.d.cts +0 -140
  127. package/dist/index-CGMZNCx6.d.ts +0 -140
  128. package/dist/index-CnZCo29u.d.cts +0 -108
  129. package/dist/index-JnF4v9bx.d.ts +0 -108
  130. package/dist/styled-DZ7GjShb.d.ts +0 -282
  131. package/dist/styled-ZTbdaVFM.d.cts +0 -282
  132. package/src/analyze/arrange/index.ts +0 -21
  133. package/src/analyze/arrange/internal.ts +0 -127
  134. package/src/analyze/arrange/tension.ts +0 -199
  135. package/src/analyze/arrange/tracks.ts +0 -312
  136. package/src/analyze/detect/index.ts +0 -272
  137. package/src/analyze/functional/borrowed.ts +0 -84
  138. package/src/analyze/functional/cadence.ts +0 -66
  139. package/src/analyze/functional/function.ts +0 -184
  140. package/src/analyze/functional/index.ts +0 -23
  141. package/src/analyze/functional/internal.ts +0 -29
  142. package/src/analyze/functional/roman.ts +0 -402
  143. package/src/analyze/index.ts +0 -49
  144. package/src/analyze/timeline/index.ts +0 -451
  145. package/src/analyze/voice/index.ts +0 -339
  146. package/src/core/event-index/index.ts +0 -104
  147. package/src/core/index.ts +0 -61
  148. package/src/core/interval/index.ts +0 -81
  149. package/src/core/meter/index.ts +0 -302
  150. package/src/core/pitch/index.ts +0 -311
  151. package/src/core/random/index.ts +0 -76
  152. package/src/core/tuning/index.ts +0 -186
  153. package/src/core/types.ts +0 -29
  154. package/src/core/validation/index.ts +0 -119
  155. package/src/generate/bass/index.ts +0 -373
  156. package/src/generate/countermelody/index.ts +0 -470
  157. package/src/generate/drums/beat.ts +0 -266
  158. package/src/generate/drums/euclid.ts +0 -65
  159. package/src/generate/drums/fills.ts +0 -356
  160. package/src/generate/drums/ghost.ts +0 -119
  161. package/src/generate/drums/hihat.ts +0 -285
  162. package/src/generate/drums/hit.ts +0 -31
  163. package/src/generate/drums/index.ts +0 -361
  164. package/src/generate/drums/internal.ts +0 -257
  165. package/src/generate/drums/kick.ts +0 -160
  166. package/src/generate/drums/percussion.ts +0 -121
  167. package/src/generate/drums/rng.ts +0 -7
  168. package/src/generate/drums/swing.ts +0 -71
  169. package/src/generate/groove/index.ts +0 -351
  170. package/src/generate/harmonize/index.ts +0 -451
  171. package/src/generate/index.ts +0 -58
  172. package/src/generate/motif/index.ts +0 -422
  173. package/src/generate/progression/index.ts +0 -362
  174. package/src/generate/reharmony/index.ts +0 -323
  175. package/src/generate/rhythm/index.ts +0 -175
  176. package/src/index.ts +0 -13
  177. package/src/model/chord.ts +0 -442
  178. package/src/model/index.ts +0 -15
  179. package/src/model/interval.ts +0 -82
  180. package/src/model/key.ts +0 -266
  181. package/src/model/note.ts +0 -176
  182. package/src/model/progression.ts +0 -161
  183. package/src/model/shared.ts +0 -12
  184. package/src/theory/chord/index.ts +0 -375
  185. package/src/theory/chordscale/index.ts +0 -374
  186. package/src/theory/counterpoint/index.ts +0 -230
  187. package/src/theory/harmony/index.ts +0 -77
  188. package/src/theory/index.ts +0 -112
  189. package/src/theory/safety/index.ts +0 -488
  190. package/src/theory/scale/degrees.ts +0 -123
  191. package/src/theory/scale/index.ts +0 -28
  192. package/src/theory/scale/key.ts +0 -56
  193. package/src/theory/scale/masks.ts +0 -153
  194. package/src/theory/spelling/index.ts +0 -249
  195. package/src/theory/symbol/index.ts +0 -268
  196. package/src/theory/voicing/index.ts +0 -5
  197. package/src/theory/voicing/internal.ts +0 -168
  198. package/src/theory/voicing/leading.ts +0 -112
  199. package/src/theory/voicing/satb.ts +0 -216
  200. package/src/theory/voicing/styled.ts +0 -199
  201. package/tsconfig.json +0 -23
@@ -1,5 +1,5 @@
1
- import { K as KeyScale } from './types-MGP29r3t.js';
2
- import { C as Chord } from './index-Bt4tOUD9.js';
1
+ import { K as KeyScale } from './types-BN6_Q9Kl.cjs';
2
+ import { C as Chord } from './index-oTQbYYIs.cjs';
3
3
 
4
4
  /**
5
5
  * Borrowed chords (modal interchange) and the Neapolitan.
@@ -14,7 +14,7 @@ import { C as Chord } from './index-Bt4tOUD9.js';
14
14
  *
15
15
  * @category Functional Harmony
16
16
  */
17
- type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;
17
+ type BorrowedSource = 'parallelMinor' | 'parallelMajor' | 'neapolitan' | null;
18
18
  /**
19
19
  * Whether a chord is borrowed from the parallel mode (modal interchange).
20
20
  *
@@ -22,7 +22,7 @@ type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;
22
22
  * {@link parallelKey} — e.g. iv, bVI, or bVII in a major key, or the Picardy
23
23
  * tonic and major IV in a minor key. Two non-diatonic families are excluded:
24
24
  * chords diatonic to neither mode (they are chromatic, not borrowed), and, in
25
- * a minor key, chords explained by the harmonic minor scale (the major
25
+ * a minor key, chords explained by the altered minor forms (the major
26
26
  * dominant and raised-leading-tone chords), which are in-key alterations
27
27
  * rather than interchange even though they happen to fit the parallel major.
28
28
  *
@@ -37,7 +37,7 @@ declare function isBorrowedChord(chord: Chord, key: KeyScale): boolean;
37
37
  *
38
38
  * The Neapolitan (major triad on b2) is recognized first, since it sits
39
39
  * outside both parallel modes; parallel-mode borrowing follows the
40
- * {@link isBorrowedChord} rules. Diatonic chords, harmonic-minor alterations,
40
+ * {@link isBorrowedChord} rules. Diatonic chords and altered-minor chords,
41
41
  * and unrecognized chromatic chords all yield null.
42
42
  *
43
43
  * @param chord The chord to classify.
@@ -85,6 +85,96 @@ type Cadence = 'authentic' | 'plagal' | 'half' | 'deceptive' | null;
85
85
  */
86
86
  declare function detectCadence(from: Chord, to: Chord, key: KeyScale): Cadence;
87
87
 
88
+ /**
89
+ * Roman-numeral parsing and formatting.
90
+ *
91
+ * The {@link ROMAN_STYLE} table is the single source of truth for both
92
+ * directions, so {@link chordToRoman} and {@link romanToChord} stay mutual
93
+ * inverses by construction.
94
+ */
95
+
96
+ /**
97
+ * Build the chord denoted by a Roman numeral in a key.
98
+ *
99
+ * Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`
100
+ * suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions
101
+ * (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash
102
+ * (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree
103
+ * whose root becomes a local major tonic for the applied chord. Inverted chords
104
+ * carry a `bassPc`.
105
+ *
106
+ * The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==
107
+ * `m7b5`), since no half-diminished triad exists. Extension and added-tone
108
+ * suffixes are the canonical case-sensitive forms emitted by
109
+ * {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->
110
+ * `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->
111
+ * `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->
112
+ * `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.
113
+ * A figure string that is neither a recognized inversion nor a supported
114
+ * quality suffix throws rather than silently degrading to a triad.
115
+ *
116
+ * @param text The Roman numeral.
117
+ * @param key The prevailing key.
118
+ * @returns The chord.
119
+ * @example
120
+ * ```ts
121
+ * import { romanToChord, majorKey } from '@libraz/libcantus';
122
+ * romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }
123
+ * ```
124
+ * @category Functional Harmony
125
+ */
126
+ declare function romanToChord(text: string, key: KeyScale): Chord;
127
+ /**
128
+ * Options for {@link chordToRoman}.
129
+ *
130
+ * @category Functional Harmony
131
+ */
132
+ type ChordToRomanOptions = {
133
+ /**
134
+ * Render a tonicizing chord as an applied numeral (`V7/V`, `viio7/ii`)
135
+ * instead of naming its root against the home key (`II7`, `#ivo7`).
136
+ *
137
+ * Off by default: naming the root is always a correct spelling, whereas
138
+ * whether a chromatic dominant is genuinely applied is a reading only the
139
+ * caller can make. Turning it on makes {@link chordToRoman} the exact inverse
140
+ * of {@link romanToChord} for the chords {@link secondaryDominant} builds.
141
+ */
142
+ applied?: boolean;
143
+ };
144
+ /**
145
+ * Render a chord as a Roman numeral relative to a key.
146
+ *
147
+ * Diatonic roots take their scale-degree numeral directly, so numerals are
148
+ * correct in both major and minor keys (and any custom scale). The quality
149
+ * selects the case and suffix; chromatic roots receive a flat/sharp spelling by
150
+ * convention. A key that is not heptatonic has no numeral of its own for every
151
+ * degree, so its roots are named against its parallel major.
152
+ *
153
+ * When the chord carries a `bassPc` on a chord tone, a figured-bass inversion
154
+ * (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true seventh
155
+ * chords; added-tone and extended qualities have no lossless figure and render
156
+ * in root position instead (the bass is dropped, pitch classes are preserved).
157
+ *
158
+ * A `bassPc` that is *not* a chord tone — a pedal or passing bass such as
159
+ * `C/D` — is likewise dropped, and the numeral names the upper chord alone.
160
+ * Roman-numeral notation spends its slash on applied chords (`V7/V`), so there
161
+ * is no unambiguous way to write such a bass; a caller that must keep it should
162
+ * read `chord.bassPc` alongside the numeral.
163
+ *
164
+ * @param chord The chord to name.
165
+ * @param key The prevailing key.
166
+ * @param opts `applied` renders tonicizing chords as `V7/V`-style numerals.
167
+ * @returns The Roman numeral string.
168
+ * @example
169
+ * ```ts
170
+ * import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';
171
+ * chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)
172
+ * chordToRoman(makeChord(2, 'dom7'), majorKey(0), { applied: true }); // => 'V7/V'
173
+ * ```
174
+ * @category Functional Harmony
175
+ */
176
+ declare function chordToRoman(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): string;
177
+
88
178
  /**
89
179
  * Harmonic function (tonic / subdominant / dominant), diatonicity, parallel-key
90
180
  * mirroring, and full chord analysis.
@@ -107,13 +197,33 @@ type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';
107
197
  */
108
198
  declare function isMinorKey(key: KeyScale): boolean;
109
199
  /**
110
- * The harmonic function of a chord in a key, from its root's offset above the
111
- * tonic. The mapping follows common-practice major-key function and is a useful
112
- * approximation in minor and for borrowed chords.
200
+ * The harmonic function of a chord in a key.
201
+ *
202
+ * The root's offset above the tonic gives the baseline mapping, which follows
203
+ * common-practice major-key function and is a useful approximation in minor and
204
+ * for borrowed chords. Chord quality then refines it where the sonority settles
205
+ * an ambiguity the root offset cannot:
206
+ *
207
+ * - A chord that *sounds* like a dominant — a major third with a minor seventh,
208
+ * or a diminished-family chord — and is not diatonic to the key has dominant
209
+ * function when its root resolves down a fifth or by a semitone onto a
210
+ * diatonic degree. This is what makes an applied dominant (`A7` in C, which
211
+ * tonicizes ii) and its tritone substitute (`Db7`) read as dominant rather
212
+ * than inheriting the function of the degree they happen to sit on.
213
+ * - The Neapolitan is subdominant.
214
+ * - A major triad on bVI or bVII of a major key is subdominant — the borrowed
215
+ * pop cadence chord, distinct from the bVII7 above, which has a seventh and
216
+ * is a dominant sonority.
113
217
  *
114
218
  * @param chord The chord.
115
219
  * @param key The prevailing key.
116
220
  * @returns The harmonic function.
221
+ * @example
222
+ * ```ts
223
+ * import { functionOf, makeChord, majorKey } from '@libraz/libcantus';
224
+ * functionOf(makeChord(9, 'dom7'), majorKey(0)); // 'dominant' — A7 tonicizes ii
225
+ * functionOf(makeChord(10, 'maj'), majorKey(0)); // 'subdominant' — borrowed bVII
226
+ * ```
117
227
  * @category Functional Harmony
118
228
  */
119
229
  declare function functionOf(chord: Chord, key: KeyScale): HarmonicFunction;
@@ -164,6 +274,7 @@ declare function parallelKey(key: KeyScale): KeyScale;
164
274
  *
165
275
  * @param chord The chord to analyze.
166
276
  * @param key The prevailing key.
277
+ * @param opts Options used when rendering the Roman numeral.
167
278
  * @returns The chord analysis.
168
279
  * @example
169
280
  * ```ts
@@ -173,15 +284,16 @@ declare function parallelKey(key: KeyScale): KeyScale;
173
284
  * ```
174
285
  * @category Functional Harmony
175
286
  */
176
- declare function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis;
287
+ declare function analyzeChord(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): ChordAnalysis;
177
288
  /**
178
289
  * The secondary dominant (V7) that tonicizes a scale degree.
179
290
  *
180
291
  * @param targetDegree 0-based scale degree to tonicize.
181
292
  * @param key The prevailing key.
182
293
  * @returns A dominant-seventh chord a fifth above the target's root.
294
+ * @throws If `targetDegree` is not an integer naming a degree in `key`.
183
295
  * @category Functional Harmony
184
296
  */
185
297
  declare function secondaryDominant(targetDegree: number, key: KeyScale): Chord;
186
298
 
187
- export { type BorrowedSource as B, type Cadence as C, type HarmonicFunction as H, type ChordAnalysis as a, analyzeChord as b, borrowedSource as c, detectCadence as d, isDiatonic as e, functionOf as f, isMinorKey as g, isBorrowedChord as i, parallelKey as p, secondaryDominant as s };
299
+ export { type BorrowedSource as B, type Cadence as C, type HarmonicFunction as H, type ChordAnalysis as a, type ChordToRomanOptions as b, analyzeChord as c, borrowedSource as d, chordToRoman as e, detectCadence as f, functionOf as g, isDiatonic as h, isBorrowedChord as i, isMinorKey as j, parallelKey as p, romanToChord as r, secondaryDominant as s };
@@ -1,5 +1,5 @@
1
- import { K as KeyScale } from './types-MGP29r3t.cjs';
2
- import { C as Chord } from './index-BNlGP86A.cjs';
1
+ import { K as KeyScale } from './types-BN6_Q9Kl.js';
2
+ import { C as Chord } from './index-COw1Ky9g.js';
3
3
 
4
4
  /**
5
5
  * Borrowed chords (modal interchange) and the Neapolitan.
@@ -14,7 +14,7 @@ import { C as Chord } from './index-BNlGP86A.cjs';
14
14
  *
15
15
  * @category Functional Harmony
16
16
  */
17
- type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;
17
+ type BorrowedSource = 'parallelMinor' | 'parallelMajor' | 'neapolitan' | null;
18
18
  /**
19
19
  * Whether a chord is borrowed from the parallel mode (modal interchange).
20
20
  *
@@ -22,7 +22,7 @@ type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;
22
22
  * {@link parallelKey} — e.g. iv, bVI, or bVII in a major key, or the Picardy
23
23
  * tonic and major IV in a minor key. Two non-diatonic families are excluded:
24
24
  * chords diatonic to neither mode (they are chromatic, not borrowed), and, in
25
- * a minor key, chords explained by the harmonic minor scale (the major
25
+ * a minor key, chords explained by the altered minor forms (the major
26
26
  * dominant and raised-leading-tone chords), which are in-key alterations
27
27
  * rather than interchange even though they happen to fit the parallel major.
28
28
  *
@@ -37,7 +37,7 @@ declare function isBorrowedChord(chord: Chord, key: KeyScale): boolean;
37
37
  *
38
38
  * The Neapolitan (major triad on b2) is recognized first, since it sits
39
39
  * outside both parallel modes; parallel-mode borrowing follows the
40
- * {@link isBorrowedChord} rules. Diatonic chords, harmonic-minor alterations,
40
+ * {@link isBorrowedChord} rules. Diatonic chords and altered-minor chords,
41
41
  * and unrecognized chromatic chords all yield null.
42
42
  *
43
43
  * @param chord The chord to classify.
@@ -85,6 +85,96 @@ type Cadence = 'authentic' | 'plagal' | 'half' | 'deceptive' | null;
85
85
  */
86
86
  declare function detectCadence(from: Chord, to: Chord, key: KeyScale): Cadence;
87
87
 
88
+ /**
89
+ * Roman-numeral parsing and formatting.
90
+ *
91
+ * The {@link ROMAN_STYLE} table is the single source of truth for both
92
+ * directions, so {@link chordToRoman} and {@link romanToChord} stay mutual
93
+ * inverses by construction.
94
+ */
95
+
96
+ /**
97
+ * Build the chord denoted by a Roman numeral in a key.
98
+ *
99
+ * Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`
100
+ * suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions
101
+ * (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash
102
+ * (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree
103
+ * whose root becomes a local major tonic for the applied chord. Inverted chords
104
+ * carry a `bassPc`.
105
+ *
106
+ * The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==
107
+ * `m7b5`), since no half-diminished triad exists. Extension and added-tone
108
+ * suffixes are the canonical case-sensitive forms emitted by
109
+ * {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->
110
+ * `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->
111
+ * `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->
112
+ * `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.
113
+ * A figure string that is neither a recognized inversion nor a supported
114
+ * quality suffix throws rather than silently degrading to a triad.
115
+ *
116
+ * @param text The Roman numeral.
117
+ * @param key The prevailing key.
118
+ * @returns The chord.
119
+ * @example
120
+ * ```ts
121
+ * import { romanToChord, majorKey } from '@libraz/libcantus';
122
+ * romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }
123
+ * ```
124
+ * @category Functional Harmony
125
+ */
126
+ declare function romanToChord(text: string, key: KeyScale): Chord;
127
+ /**
128
+ * Options for {@link chordToRoman}.
129
+ *
130
+ * @category Functional Harmony
131
+ */
132
+ type ChordToRomanOptions = {
133
+ /**
134
+ * Render a tonicizing chord as an applied numeral (`V7/V`, `viio7/ii`)
135
+ * instead of naming its root against the home key (`II7`, `#ivo7`).
136
+ *
137
+ * Off by default: naming the root is always a correct spelling, whereas
138
+ * whether a chromatic dominant is genuinely applied is a reading only the
139
+ * caller can make. Turning it on makes {@link chordToRoman} the exact inverse
140
+ * of {@link romanToChord} for the chords {@link secondaryDominant} builds.
141
+ */
142
+ applied?: boolean;
143
+ };
144
+ /**
145
+ * Render a chord as a Roman numeral relative to a key.
146
+ *
147
+ * Diatonic roots take their scale-degree numeral directly, so numerals are
148
+ * correct in both major and minor keys (and any custom scale). The quality
149
+ * selects the case and suffix; chromatic roots receive a flat/sharp spelling by
150
+ * convention. A key that is not heptatonic has no numeral of its own for every
151
+ * degree, so its roots are named against its parallel major.
152
+ *
153
+ * When the chord carries a `bassPc` on a chord tone, a figured-bass inversion
154
+ * (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true seventh
155
+ * chords; added-tone and extended qualities have no lossless figure and render
156
+ * in root position instead (the bass is dropped, pitch classes are preserved).
157
+ *
158
+ * A `bassPc` that is *not* a chord tone — a pedal or passing bass such as
159
+ * `C/D` — is likewise dropped, and the numeral names the upper chord alone.
160
+ * Roman-numeral notation spends its slash on applied chords (`V7/V`), so there
161
+ * is no unambiguous way to write such a bass; a caller that must keep it should
162
+ * read `chord.bassPc` alongside the numeral.
163
+ *
164
+ * @param chord The chord to name.
165
+ * @param key The prevailing key.
166
+ * @param opts `applied` renders tonicizing chords as `V7/V`-style numerals.
167
+ * @returns The Roman numeral string.
168
+ * @example
169
+ * ```ts
170
+ * import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';
171
+ * chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)
172
+ * chordToRoman(makeChord(2, 'dom7'), majorKey(0), { applied: true }); // => 'V7/V'
173
+ * ```
174
+ * @category Functional Harmony
175
+ */
176
+ declare function chordToRoman(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): string;
177
+
88
178
  /**
89
179
  * Harmonic function (tonic / subdominant / dominant), diatonicity, parallel-key
90
180
  * mirroring, and full chord analysis.
@@ -107,13 +197,33 @@ type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';
107
197
  */
108
198
  declare function isMinorKey(key: KeyScale): boolean;
109
199
  /**
110
- * The harmonic function of a chord in a key, from its root's offset above the
111
- * tonic. The mapping follows common-practice major-key function and is a useful
112
- * approximation in minor and for borrowed chords.
200
+ * The harmonic function of a chord in a key.
201
+ *
202
+ * The root's offset above the tonic gives the baseline mapping, which follows
203
+ * common-practice major-key function and is a useful approximation in minor and
204
+ * for borrowed chords. Chord quality then refines it where the sonority settles
205
+ * an ambiguity the root offset cannot:
206
+ *
207
+ * - A chord that *sounds* like a dominant — a major third with a minor seventh,
208
+ * or a diminished-family chord — and is not diatonic to the key has dominant
209
+ * function when its root resolves down a fifth or by a semitone onto a
210
+ * diatonic degree. This is what makes an applied dominant (`A7` in C, which
211
+ * tonicizes ii) and its tritone substitute (`Db7`) read as dominant rather
212
+ * than inheriting the function of the degree they happen to sit on.
213
+ * - The Neapolitan is subdominant.
214
+ * - A major triad on bVI or bVII of a major key is subdominant — the borrowed
215
+ * pop cadence chord, distinct from the bVII7 above, which has a seventh and
216
+ * is a dominant sonority.
113
217
  *
114
218
  * @param chord The chord.
115
219
  * @param key The prevailing key.
116
220
  * @returns The harmonic function.
221
+ * @example
222
+ * ```ts
223
+ * import { functionOf, makeChord, majorKey } from '@libraz/libcantus';
224
+ * functionOf(makeChord(9, 'dom7'), majorKey(0)); // 'dominant' — A7 tonicizes ii
225
+ * functionOf(makeChord(10, 'maj'), majorKey(0)); // 'subdominant' — borrowed bVII
226
+ * ```
117
227
  * @category Functional Harmony
118
228
  */
119
229
  declare function functionOf(chord: Chord, key: KeyScale): HarmonicFunction;
@@ -164,6 +274,7 @@ declare function parallelKey(key: KeyScale): KeyScale;
164
274
  *
165
275
  * @param chord The chord to analyze.
166
276
  * @param key The prevailing key.
277
+ * @param opts Options used when rendering the Roman numeral.
167
278
  * @returns The chord analysis.
168
279
  * @example
169
280
  * ```ts
@@ -173,15 +284,16 @@ declare function parallelKey(key: KeyScale): KeyScale;
173
284
  * ```
174
285
  * @category Functional Harmony
175
286
  */
176
- declare function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis;
287
+ declare function analyzeChord(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): ChordAnalysis;
177
288
  /**
178
289
  * The secondary dominant (V7) that tonicizes a scale degree.
179
290
  *
180
291
  * @param targetDegree 0-based scale degree to tonicize.
181
292
  * @param key The prevailing key.
182
293
  * @returns A dominant-seventh chord a fifth above the target's root.
294
+ * @throws If `targetDegree` is not an integer naming a degree in `key`.
183
295
  * @category Functional Harmony
184
296
  */
185
297
  declare function secondaryDominant(targetDegree: number, key: KeyScale): Chord;
186
298
 
187
- export { type BorrowedSource as B, type Cadence as C, type HarmonicFunction as H, type ChordAnalysis as a, analyzeChord as b, borrowedSource as c, detectCadence as d, isDiatonic as e, functionOf as f, isMinorKey as g, isBorrowedChord as i, parallelKey as p, secondaryDominant as s };
299
+ export { type BorrowedSource as B, type Cadence as C, type HarmonicFunction as H, type ChordAnalysis as a, type ChordToRomanOptions as b, analyzeChord as c, borrowedSource as d, chordToRoman as e, detectCadence as f, functionOf as g, isDiatonic as h, isBorrowedChord as i, isMinorKey as j, parallelKey as p, romanToChord as r, secondaryDominant as s };