@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
@@ -1,272 +0,0 @@
1
- /**
2
- * Pitch spelling: letter-name notes, enharmonic-aware conversion, and spelled
3
- * intervals.
4
- *
5
- * The rest of the library works in pitch classes (0..11), which cannot tell a
6
- * G# from an Ab or an augmented fourth from a diminished fifth. This module adds
7
- * an explicit spelling layer — a note is a diatonic letter plus a chromatic
8
- * alteration — so interval quality (P/M/m/A/d) and enharmonic identity are
9
- * preserved.
10
- */
11
- /**
12
- * A spelled note: a diatonic letter, a chromatic alteration, and an optional
13
- * octave.
14
- *
15
- * - `letter` is 0..6 for C..B.
16
- * - `alter` is the number of semitones of alteration: -2 double-flat, -1 flat,
17
- * 0 natural, +1 sharp, +2 double-sharp.
18
- * - `octave` follows scientific pitch notation (middle C = C4 = MIDI 60). When
19
- * absent, the note denotes a bare pitch class.
20
- *
21
- * @category Pitch & Intervals
22
- */
23
- type Note = {
24
- letter: number;
25
- alter: number;
26
- octave?: number;
27
- };
28
- /**
29
- * The quality label of a spelled interval: perfect, major, minor, or one or
30
- * more augmentations or diminutions.
31
- *
32
- * This names how an interval is *spelled*. It is a different notion from
33
- * {@link ConsonanceClass}, which classifies how an interval *sounds* against
34
- * another voice.
35
- *
36
- * @see {@link ConsonanceClass}
37
- * @category Pitch & Intervals
38
- */
39
- type IntervalQualityLabel = 'P' | 'M' | 'm' | `A${string}` | `d${string}`;
40
- /**
41
- * A spelled interval: a diatonic number, a quality label, and its semitone span.
42
- *
43
- * @category Pitch & Intervals
44
- */
45
- type SpelledInterval = {
46
- /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */
47
- number: number;
48
- /** Quality label: 'P', 'M', 'm', or repeated 'A'/'d' for (multiply) aug/dim. */
49
- quality: IntervalQualityLabel;
50
- /** Signed semitone distance from the first note to the second. */
51
- semitones: number;
52
- };
53
- /**
54
- * Reduce a MIDI pitch, a bare pitch class, or any signed offset to a pitch
55
- * class in [0, 11].
56
- *
57
- * This is the library's single definition of pitch-class arithmetic: every
58
- * layer routes through it so a fractional pitch reduces the same way
59
- * everywhere. A non-integral input is rounded to the nearest semitone first, so
60
- * a microtonal 60.6 reads as C# rather than C.
61
- *
62
- * @param value A MIDI pitch, pitch class, or signed semitone offset.
63
- * @returns The pitch class in [0, 11].
64
- * @example
65
- * ```ts
66
- * import { pitchClassOf } from '@libraz/libcantus';
67
- * pitchClassOf(61); // 1
68
- * pitchClassOf(-1); // 11
69
- * pitchClassOf(60.6); // 1
70
- * ```
71
- * @category Pitch & Intervals
72
- */
73
- declare function pitchClassOf(value: number): number;
74
- /**
75
- * Reduce a letter number or letter offset to a diatonic letter in [0, 6]
76
- * (0 = C .. 6 = B).
77
- *
78
- * @param value A letter number or signed letter offset.
79
- * @returns The diatonic letter in [0, 6].
80
- * @category Pitch & Intervals
81
- */
82
- declare function diatonicLetterOf(value: number): number;
83
- /**
84
- * The pitch class of a diatonic letter with no accidental (C = 0, D = 2, ...).
85
- *
86
- * @param letter A letter number or signed letter offset; reduced to [0, 6].
87
- * @returns The natural pitch class of that letter.
88
- * @category Pitch & Intervals
89
- */
90
- declare function naturalPitchClassOf(letter: number): number;
91
- /**
92
- * Parse scientific pitch notation into a {@link Note}.
93
- *
94
- * Accepts a letter (case-insensitive) followed by any number of same-direction
95
- * accidentals and an optional octave, e.g. `"C"`, `"C#4"`, `"Bb"`, `"F##3"`,
96
- * `"Ebb2"`. Both `#` and `x` (double-sharp) are accepted for sharps; `b` for
97
- * flats. Mixing sharps and flats (e.g. `"C#b"`) is rejected.
98
- *
99
- * @param text The note text.
100
- * @returns The parsed note.
101
- * @throws If the text is not a valid note.
102
- * @example
103
- * ```ts
104
- * import { parseNote, noteToMidi } from '@libraz/libcantus';
105
- * const n = parseNote('C#4');
106
- * noteToMidi(n); // 61
107
- * ```
108
- * @category Pitch & Intervals
109
- */
110
- declare function parseNote(text: string): Note;
111
- /**
112
- * Render a {@link Note} as scientific pitch notation.
113
- *
114
- * @param note The note to format.
115
- * @returns The note text, including the octave when present.
116
- * @example
117
- * ```ts
118
- * import { formatNote, parseNote } from '@libraz/libcantus';
119
- * formatNote(parseNote('C#4')); // 'C#4'
120
- * ```
121
- * @category Pitch & Intervals
122
- */
123
- declare function formatNote(note: Note): string;
124
- /**
125
- * Pitch class (0..11) of a note, ignoring octave.
126
- *
127
- * @param note The note.
128
- * @returns The pitch class.
129
- * @example
130
- * ```ts
131
- * import { noteToPitchClass, parseNote } from '@libraz/libcantus';
132
- * noteToPitchClass(parseNote('Db')); // 1
133
- * ```
134
- * @category Pitch & Intervals
135
- */
136
- declare function noteToPitchClass(note: Note): number;
137
- /**
138
- * MIDI number of a note (middle C = C4 = 60).
139
- *
140
- * @param note The note; must carry an octave.
141
- * @returns The MIDI number.
142
- * @throws If the note has no octave.
143
- * @example
144
- * ```ts
145
- * import { noteToMidi, parseNote } from '@libraz/libcantus';
146
- * noteToMidi(parseNote('A4')); // 69
147
- * ```
148
- * @category Pitch & Intervals
149
- */
150
- declare function noteToMidi(note: Note): number;
151
- /**
152
- * Name a MIDI number as a {@link Note}, choosing sharp or flat spelling.
153
- *
154
- * The input is rounded to the nearest integer but is not clamped to the MIDI
155
- * range 0..127: out-of-range values extrapolate linearly (e.g. `-1` -> `B-2`,
156
- * `128` -> `G#9`) and remain an exact inverse of {@link noteToMidi}.
157
- *
158
- * @param midi The MIDI number.
159
- * @param spelling Whether to prefer sharps or flats for black keys.
160
- * @returns The spelled note, with octave.
161
- * @example
162
- * ```ts
163
- * import { midiToNote, formatNote } from '@libraz/libcantus';
164
- * formatNote(midiToNote(61)); // 'C#4'
165
- * formatNote(midiToNote(61, 'flat')); // 'Db4'
166
- * ```
167
- * @category Pitch & Intervals
168
- */
169
- declare function midiToNote(midi: number, spelling?: 'sharp' | 'flat'): Note;
170
- /**
171
- * Transpose a note by a signed number of semitones, keeping its spelling.
172
- *
173
- * The letter moves by the diatonic distance of the conventional interval for
174
- * that many semitones and the accidental is recomputed for the new letter, so
175
- * enharmonic identity survives: `Ab4` up a major second is `Bb4`, not `A#4`, and
176
- * the operation is an exact inverse of itself. An octave-less note stays
177
- * octave-less.
178
- *
179
- * A bare semitone count cannot distinguish an augmented fourth from a diminished
180
- * fifth; pass `spelling` to override the letter distance when the enharmonic
181
- * choice matters.
182
- *
183
- * @param note The note to transpose.
184
- * @param semitones The signed semitone offset.
185
- * @param opts `spelling` forces the result onto the sharp or flat side instead
186
- * of following the source note's letter.
187
- * @returns The transposed note.
188
- * @example
189
- * ```ts
190
- * import { transposeNote, formatNote, parseNote } from '@libraz/libcantus';
191
- * formatNote(transposeNote(parseNote('Ab4'), 2)); // 'Bb4'
192
- * formatNote(transposeNote(parseNote('Ab4'), 2, { spelling: 'sharp' })); // 'A#4'
193
- * ```
194
- * @category Pitch & Intervals
195
- */
196
- declare function transposeNote(note: Note, semitones: number, opts?: {
197
- spelling?: 'sharp' | 'flat';
198
- }): Note;
199
- /**
200
- * The semitone span of the interval named by a diatonic number and a quality.
201
- *
202
- * The inverse of the quality derivation in {@link spelledInterval}: it turns a
203
- * name back into a distance, which is what transposing by a named interval or
204
- * parsing one from text needs.
205
- *
206
- * @param numberValue Diatonic size: 1 = unison, 2 = second, ... 8 = octave.
207
- * @param quality Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`.
208
- * @returns The unsigned semitone span.
209
- * @throws If the quality cannot apply to the number, such as a major fifth.
210
- * @example
211
- * ```ts
212
- * import { intervalSemitones } from '@libraz/libcantus';
213
- * intervalSemitones(5, 'P'); // 7
214
- * ```
215
- * @category Pitch & Intervals
216
- */
217
- declare function intervalSemitones(numberValue: number, quality: IntervalQualityLabel): number;
218
- /**
219
- * Parse an interval name such as `'P5'`, `'m3'`, or `'AA4'`.
220
- *
221
- * @param name The interval name: a quality label followed by a diatonic number.
222
- * @returns The spelled interval, with an ascending (positive) span.
223
- * @throws If the name is not a quality label followed by a number, or the two
224
- * cannot describe the same interval.
225
- * @example
226
- * ```ts
227
- * import { parseInterval } from '@libraz/libcantus';
228
- * parseInterval('m3'); // { number: 3, quality: 'm', semitones: 3 }
229
- * ```
230
- * @category Pitch & Intervals
231
- */
232
- declare function parseInterval(name: string): SpelledInterval;
233
- /**
234
- * Transpose a note by a spelled interval, keeping the spelling the interval
235
- * names.
236
- *
237
- * Unlike {@link transposeNote}, which picks a letter from the semitone count,
238
- * the diatonic number decides the letter here: transposing C by an augmented
239
- * second gives D#, not Eb.
240
- *
241
- * @param note The note to transpose.
242
- * @param interval The interval to apply; a negative span transposes downward.
243
- * @returns The transposed note, octave-less if the source was.
244
- * @example
245
- * ```ts
246
- * import { formatNote, parseInterval, parseNote, transposeByInterval } from '@libraz/libcantus';
247
- * formatNote(transposeByInterval(parseNote('C4'), parseInterval('A2'))); // 'D#4'
248
- * ```
249
- * @category Pitch & Intervals
250
- */
251
- declare function transposeByInterval(note: Note, interval: SpelledInterval): Note;
252
- /**
253
- * The spelled interval from one note to another.
254
- *
255
- * When both notes carry octaves, the interval reflects their full signed
256
- * distance (so `C4 -> C5` is a perfect octave). When either lacks an octave the
257
- * interval is measured within a single ascending octave from `a` to `b`.
258
- *
259
- * @param a The lower/first note.
260
- * @param b The upper/second note.
261
- * @returns The diatonic number, quality, and semitone span.
262
- * @example
263
- * ```ts
264
- * import { spelledInterval, parseNote } from '@libraz/libcantus';
265
- * spelledInterval(parseNote('C4'), parseNote('G4'));
266
- * // { number: 5, quality: 'P', semitones: 7 }
267
- * ```
268
- * @category Pitch & Intervals
269
- */
270
- declare function spelledInterval(a: Note, b: Note): SpelledInterval;
271
-
272
- export { type IntervalQualityLabel as I, type Note as N, type SpelledInterval as S, noteToMidi as a, noteToPitchClass as b, parseNote as c, diatonicLetterOf as d, pitchClassOf as e, formatNote as f, transposeNote as g, intervalSemitones as i, midiToNote as m, naturalPitchClassOf as n, parseInterval as p, spelledInterval as s, transposeByInterval as t };
@@ -1,143 +0,0 @@
1
- import { K as KeyScale } from './types-BN6_Q9Kl.cjs';
2
- import { C as Chord } from './index-y_ak9_Hi.cjs';
3
-
4
- /**
5
- * Severity policy: `strict` counterpoint vs. lenient `pop` voice-leading.
6
- *
7
- * @category Arrangement & Analysis
8
- */
9
- type SafetyProfile = 'strict' | 'pop';
10
- /**
11
- * Overall placeability verdict for a candidate pitch.
12
- *
13
- * @category Arrangement & Analysis
14
- */
15
- declare enum NoteSafety {
16
- Safe = 0,
17
- Warning = 1,
18
- Dissonant = 2
19
- }
20
- /**
21
- * Bit flags describing why a pitch received its verdict.
22
- *
23
- * @category Arrangement & Analysis
24
- */
25
- declare enum ReasonFlag {
26
- ChordTone = 1,
27
- Tension = 2,
28
- AvoidNote = 4,
29
- ScaleTone = 8,
30
- NonScale = 16,
31
- OutOfRange = 32,
32
- Tritone = 64,
33
- LargeLeap = 128,
34
- MinorSecond = 256,
35
- MajorSeventh = 512,
36
- VerticalDissonance = 1024,
37
- ParallelPerfect = 2048,
38
- HiddenParallel = 4096,
39
- VoiceCrossing = 8192,
40
- Suspension = 16384,
41
- NeedsResolution = 32768
42
- }
43
- /**
44
- * A neighbouring voice's current and previous pitch.
45
- *
46
- * @category Arrangement & Analysis
47
- */
48
- type VoiceSnapshot = {
49
- pitch: number;
50
- prevPitch?: number;
51
- };
52
- /**
53
- * Everything needed to evaluate one candidate pitch.
54
- *
55
- * @category Arrangement & Analysis
56
- */
57
- type SafetyQuery = {
58
- profile: SafetyProfile;
59
- candidatePitch: number;
60
- prevPitch?: number;
61
- chord: Chord | null;
62
- key: KeyScale;
63
- otherVoices: VoiceSnapshot[];
64
- strongBeat: boolean;
65
- vocalLow?: number;
66
- vocalHigh?: number;
67
- };
68
- /**
69
- * The verdict, reason flags, and optional resolution guidance.
70
- *
71
- * @category Arrangement & Analysis
72
- */
73
- type SafetyResult = {
74
- safety: NoteSafety;
75
- reasons: number;
76
- resolveTo?: number;
77
- suggestions?: number[];
78
- rationale?: string;
79
- };
80
- /**
81
- * Evaluate the safety of placing a candidate pitch in a voice.
82
- *
83
- * Reasons are merged from harmonic context (chord tone / tension / avoid / scale)
84
- * and counterpoint (vertical dissonance, parallels, voice crossing). The `strict`
85
- * profile treats avoid notes and parallels as dissonant; `pop` treats them as
86
- * warnings. The final verdict is the worst severity among the reasons.
87
- *
88
- * @param q The candidate and its harmonic/voice-leading context.
89
- * @returns The verdict, reason bitmask, and optional resolution guidance.
90
- * @example
91
- * ```ts
92
- * import { evaluateSafety, makeChord, majorKey, NoteSafety } from '@libraz/libcantus';
93
- * const result = evaluateSafety({
94
- * profile: 'pop',
95
- * candidatePitch: 60, // C over a C major chord
96
- * chord: makeChord(0, 'maj'),
97
- * key: majorKey(0),
98
- * otherVoices: [],
99
- * strongBeat: true,
100
- * });
101
- * result.safety === NoteSafety.Safe; // true — C is a chord tone
102
- * ```
103
- * @category Arrangement & Analysis
104
- */
105
- declare function evaluateSafety(q: SafetyQuery, opts?: EvaluateSafetyOptions): SafetyResult;
106
- /**
107
- * Options for {@link evaluateSafety}.
108
- *
109
- * @category Arrangement & Analysis
110
- */
111
- type EvaluateSafetyOptions = {
112
- /**
113
- * Whether to search for safe replacement pitches when the verdict is not
114
- * safe. Turning it off skips up to two dozen extra evaluations per rejected
115
- * pitch, which is worth doing when only the verdict is wanted.
116
- *
117
- * @defaultValue true
118
- */
119
- suggestions?: boolean;
120
- };
121
- /**
122
- * Enumerate placeable pitches in a range, chord tones first, descending.
123
- *
124
- * @param q The safety context minus the candidate pitch.
125
- * @param pitchLow Lowest MIDI pitch to consider (inclusive).
126
- * @param pitchHigh Highest MIDI pitch to consider (inclusive).
127
- * @returns Placeable pitches (non-dissonant), chord tones before others, each group descending.
128
- * @throws If either bound is non-finite/non-integral, reversed, or exceeds the generation budget.
129
- * @example
130
- * ```ts
131
- * import { enumerateSafePitches, makeChord, majorKey } from '@libraz/libcantus';
132
- * const pitches = enumerateSafePitches(
133
- * { profile: 'pop', chord: makeChord(0, 'maj'), key: majorKey(0), otherVoices: [], strongBeat: true },
134
- * 60,
135
- * 72,
136
- * );
137
- * pitches; // placeable pitches in [60, 72], chord tones first, each group descending
138
- * ```
139
- * @category Arrangement & Analysis
140
- */
141
- declare function enumerateSafePitches(q: Omit<SafetyQuery, 'candidatePitch'>, pitchLow: number, pitchHigh: number): number[];
142
-
143
- export { type EvaluateSafetyOptions as E, NoteSafety as N, ReasonFlag as R, type SafetyProfile as S, type VoiceSnapshot as V, type SafetyQuery as a, type SafetyResult as b, evaluateSafety as c, enumerateSafePitches as e };
@@ -1,242 +0,0 @@
1
- import { K as KeyScale } from './types-BN6_Q9Kl.cjs';
2
-
3
- /**
4
- * Chord quality identifiers understood by the chord builder.
5
- *
6
- * @category Chords
7
- */
8
- type ChordQuality = 'maj' | 'min' | 'dim' | 'aug' | 'maj7' | 'min7' | 'dom7' | 'dim7' | 'm7b5' | 'minMaj7' | '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';
9
- /**
10
- * The basic role a chord tone plays: the degrees a chord's own template names.
11
- *
12
- * The shared vocabulary behind {@link chordToneRole}, the harmony layer's
13
- * `HarmonyRole`, and the voice analyser's labels, so the three cannot drift.
14
- *
15
- * @category Chords
16
- */
17
- type ChordToneRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh';
18
- /**
19
- * A bare spelled pitch used as an enharmonic hint: a diatonic letter
20
- * (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).
21
- * Mirrors the letter/alter half of the pitch module's `Note` without an octave.
22
- *
23
- * @category Chords
24
- */
25
- type PitchSpelling = {
26
- letter: number;
27
- alter: number;
28
- };
29
- /**
30
- * A chord expressed as a root pitch class plus semitone offsets.
31
- *
32
- * `rootSpelling`/`bassSpelling` are optional enharmonic hints recorded by
33
- * parsers (e.g. `parseChordSymbol('Bb7')`) so formatters can reproduce the
34
- * original spelling instead of defaulting to sharps. Consumers may ignore
35
- * them; a hint is only trusted when its pitch class still matches the
36
- * corresponding `rootPc`/`bassPc`.
37
- *
38
- * @category Chords
39
- */
40
- type Chord = {
41
- rootPc: number;
42
- quality: ChordQuality;
43
- intervals: number[];
44
- bassPc?: number;
45
- rootSpelling?: PitchSpelling;
46
- bassSpelling?: PitchSpelling;
47
- };
48
- /**
49
- * A chord positioned in time: a root pitch class and quality placed at a beat,
50
- * with optional harmonic-analysis hints. Serves as the neutral exchange record
51
- * between progression generators and timeline analysers.
52
- *
53
- * @category Composition
54
- */
55
- type ChordSpan = {
56
- rootPc: number;
57
- quality: ChordQuality;
58
- startBeat: number;
59
- bassPc?: number;
60
- /** 0-based scale degree of the chord root, when known. */
61
- degree?: number;
62
- /** True when the chord is a secondary dominant tonicizing another degree. */
63
- secondaryDominant?: boolean;
64
- };
65
- /**
66
- * A chord occupying a half-open beat span `[startBeat, endBeat)`.
67
- *
68
- * The exchange record between anything that lays chords out in time — a
69
- * timeline analysis, a bass-line plan, an accompaniment generator — so those
70
- * surfaces share one definition instead of agreeing by coincidence.
71
- *
72
- * @category Composition
73
- */
74
- type ChordSegment = {
75
- startBeat: number;
76
- endBeat: number;
77
- chord: Chord;
78
- };
79
- /**
80
- * All chord qualities the builder understands, in declaration order.
81
- *
82
- * The order is stable but carries no meaning: it is neither alphabetical nor
83
- * sorted by template size. {@link detectChord} uses it as its final tie-break,
84
- * so it is part of the observable behaviour and does not get reshuffled
85
- * casually — but do not read it as a ranking.
86
- *
87
- * @category Chords
88
- */
89
- declare function chordQualities(): ChordQuality[];
90
- /**
91
- * Build a chord rooted on a diatonic scale degree.
92
- *
93
- * The root pitch class is the degree's diatonic pitch class in `key`; the
94
- * quality's interval template is attached unchanged. Degrees beyond the scale
95
- * length wrap around.
96
- *
97
- * @param degree 0-based scale degree of the chord root.
98
- * @param ext Chord quality to apply.
99
- * @param key Key context supplying the diatonic root.
100
- * @returns The constructed chord.
101
- *
102
- * @category Chords
103
- */
104
- declare function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScale): Chord;
105
- /**
106
- * Build a chord from an explicit root pitch class and quality.
107
- *
108
- * @param rootPc Root pitch class (0..11).
109
- * @param quality Chord quality supplying the interval template.
110
- * @param bassPc Optional slash-chord bass pitch class.
111
- * @returns The constructed chord.
112
- *
113
- * @example
114
- * ```ts
115
- * import { makeChord } from '@libraz/libcantus';
116
- * const cmaj7 = makeChord(0, 'maj7');
117
- * // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }
118
- * ```
119
- *
120
- * @category Chords
121
- */
122
- declare function makeChord(rootPc: number, quality: ChordQuality, bassPc?: number): Chord;
123
- /**
124
- * Transpose a chord by a number of semitones.
125
- *
126
- * The interval template is carried over untouched, so a chord whose intervals
127
- * were customised keeps them, and a slash bass moves with the root. Enharmonic
128
- * spelling hints are dropped rather than shifted: the letter a transposed root
129
- * should take depends on the destination key, which a semitone count does not
130
- * carry. Pass the result through {@link spellChord} to respell it.
131
- *
132
- * @param chord The chord to transpose.
133
- * @param semitones The signed semitone offset.
134
- * @returns The transposed chord.
135
- * @throws If `semitones` is not finite.
136
- *
137
- * @example
138
- * ```ts
139
- * import { formatChordSymbol, parseChordSymbol, transposeChord } from '@libraz/libcantus';
140
- * formatChordSymbol(transposeChord(parseChordSymbol('C/G'), 2)); // 'D/A'
141
- * ```
142
- *
143
- * @category Chords
144
- */
145
- declare function transposeChord(chord: Chord, semitones: number): Chord;
146
- /**
147
- * Get the sorted, deduplicated pitch classes of a chord.
148
- *
149
- * A slash bass is one of them: `F/G` sounds a G, the voicers put it in the
150
- * bass, and a set that omitted it would not re-detect as the chord it came
151
- * from. Pass `includeBass: false` to enumerate the interval template alone.
152
- *
153
- * @param chord The chord to enumerate.
154
- * @param opts Set `includeBass: false` to omit a slash bass.
155
- * @returns The chord's pitch classes, sorted ascending in [0, 11].
156
- *
157
- * @example
158
- * ```ts
159
- * import { makeChord, chordPitchClasses } from '@libraz/libcantus';
160
- * chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]
161
- * chordPitchClasses(makeChord(5, 'maj', 7)); // [0, 5, 7, 9] — F/G, G included
162
- * ```
163
- *
164
- * @category Chords
165
- */
166
- declare function chordPitchClasses(chord: Chord, opts?: {
167
- includeBass?: boolean;
168
- }): number[];
169
- /**
170
- * A pitch's interval class above the chord root, in [0, 11].
171
- *
172
- * The shared reading of "where does this pitch sit in the chord", used by the
173
- * safety evaluator and the voice analyser alike so they cannot disagree.
174
- *
175
- * @param pitch MIDI pitch or bare pitch class.
176
- * @param chord The chord providing the root reference.
177
- * @returns The interval class above the root.
178
- * @category Chords
179
- */
180
- declare function intervalAboveRoot(pitch: number, chord: Chord): number;
181
- /**
182
- * Whether a pitch is one of a chord's tones, ignoring octave.
183
- *
184
- * @param pitch MIDI pitch or bare pitch class.
185
- * @param chord The chord, or null for no sounding harmony.
186
- * @returns True when the pitch class belongs to the chord.
187
- * @category Chords
188
- */
189
- declare function isChordMember(pitch: number, chord: Chord | null): boolean;
190
- /**
191
- * Determine a pitch's harmonic role within a chord.
192
- *
193
- * The role is derived from the pitch's interval above the chord root, reduced
194
- * modulo 12. A major sixth (9) reads as a `sixth` for sixth chords but as a
195
- * `seventh` for a diminished-seventh chord; ninths and other tensions have no
196
- * basic role and return null.
197
- *
198
- * @param pitch MIDI pitch or bare pitch class.
199
- * @param chord The chord providing the root reference.
200
- * @returns The chord-tone role, or null if the pitch has no basic role.
201
- *
202
- * @category Chords
203
- */
204
- declare function chordToneRole(pitch: number, chord: Chord): ChordToneRole | null;
205
- /**
206
- * Build the diatonic triad rooted on a scale degree by stacking scale thirds.
207
- *
208
- * Unlike {@link chordFromDegree}, the chord quality is derived from the scale
209
- * rather than supplied, so degrees yield their scale-correct triads (e.g. a
210
- * diminished triad on the leading tone of a major key).
211
- *
212
- * @param degree 0-based scale degree of the chord root.
213
- * @param key Key/scale context.
214
- * @returns The diatonic triad.
215
- * @throws If the scale is not heptatonic. Stacking thirds means skipping every
216
- * other degree, which only lands on a triad when there are seven of them, so
217
- * the pentatonic, blues, whole-tone, octatonic and chromatic scales have no
218
- * diatonic triad; use {@link chordFromDegree} with an explicit quality there.
219
- *
220
- * @example
221
- * ```ts
222
- * import { majorKey, diatonicTriad } from '@libraz/libcantus';
223
- * const tonic = diatonicTriad(0, majorKey(0)); // C major triad (degree 0 of C major)
224
- * ```
225
- *
226
- * @category Chords
227
- */
228
- declare function diatonicTriad(degree: number, key: KeyScale): Chord;
229
- /**
230
- * Build the diatonic seventh chord rooted on a scale degree.
231
- *
232
- * @param degree 0-based scale degree of the chord root.
233
- * @param key Key/scale context.
234
- * @returns The diatonic seventh chord.
235
- * @throws If the scale is not heptatonic, for the reason given on
236
- * {@link diatonicTriad}.
237
- *
238
- * @category Chords
239
- */
240
- declare function diatonicSeventh(degree: number, key: KeyScale): Chord;
241
-
242
- export { type Chord as C, type PitchSpelling as P, type ChordQuality as a, type ChordSegment as b, type ChordSpan as c, type ChordToneRole as d, chordFromDegree as e, chordPitchClasses as f, chordQualities as g, chordToneRole as h, diatonicSeventh as i, diatonicTriad as j, intervalAboveRoot as k, isChordMember as l, makeChord as m, transposeChord as t };