@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,6 +1,10 @@
1
1
  import {
2
+ BASS_STYLES,
3
+ BORROWED_DEGREES,
4
+ DRUM_NOTES,
2
5
  applyGrooveTemplate,
3
6
  developMotif,
7
+ drumVoiceOf,
4
8
  extractGrooveTemplate,
5
9
  generateBassLine,
6
10
  generateCounterMelody,
@@ -10,27 +14,34 @@ import {
10
14
  generateRhythm,
11
15
  harmonizeMelody,
12
16
  humanize,
17
+ motifToNoteEvents,
13
18
  onsetWeightCurve,
19
+ pickProgressionPreset,
14
20
  progressions,
15
21
  progressionsByStyle,
16
22
  rhythmDensity,
23
+ rhythmToNoteEvents,
17
24
  transformMotif
18
- } from "../chunk-4MHA432G.js";
19
- import "../chunk-62QZKCJQ.js";
20
- import "../chunk-I5R7ZBJS.js";
25
+ } from "../chunk-AID75RN3.js";
26
+ import "../chunk-ZGLJM4A4.js";
27
+ import "../chunk-2PTFGVD7.js";
21
28
  import {
22
29
  modalInterchangePalette,
23
30
  negativeHarmonyMirror,
24
31
  substituteChord
25
- } from "../chunk-IT2O4XFE.js";
26
- import "../chunk-CHMXELDS.js";
27
- import "../chunk-2ZWMSJH6.js";
28
- import "../chunk-EH6EM37U.js";
29
- import "../chunk-MIWO425M.js";
30
- import "../chunk-FBQK3ZQN.js";
32
+ } from "../chunk-7JEP3MFY.js";
33
+ import "../chunk-NNB67XA2.js";
34
+ import "../chunk-HN2OEUN2.js";
35
+ import "../chunk-DZMHIGI4.js";
36
+ import "../chunk-KBTTEX7Q.js";
37
+ import "../chunk-R2VVFAIN.js";
31
38
  export {
39
+ BASS_STYLES,
40
+ BORROWED_DEGREES,
41
+ DRUM_NOTES,
32
42
  applyGrooveTemplate,
33
43
  developMotif,
44
+ drumVoiceOf,
34
45
  extractGrooveTemplate,
35
46
  generateBassLine,
36
47
  generateCounterMelody,
@@ -41,11 +52,14 @@ export {
41
52
  harmonizeMelody,
42
53
  humanize,
43
54
  modalInterchangePalette,
55
+ motifToNoteEvents,
44
56
  negativeHarmonyMirror,
45
57
  onsetWeightCurve,
58
+ pickProgressionPreset,
46
59
  progressions,
47
60
  progressionsByStyle,
48
61
  rhythmDensity,
62
+ rhythmToNoteEvents,
49
63
  substituteChord,
50
64
  transformMotif
51
65
  };
@@ -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
  * Severity policy: `strict` counterpoint vs. lenient `pop` voice-leading.
@@ -38,7 +38,8 @@ declare enum ReasonFlag {
38
38
  HiddenParallel = 4096,
39
39
  VoiceCrossing = 8192,
40
40
  Suspension = 16384,
41
- NeedsResolution = 32768
41
+ NeedsResolution = 32768,
42
+ MelodicTritone = 65536
42
43
  }
43
44
  /**
44
45
  * A neighbouring voice's current and previous pitch.
@@ -102,7 +103,22 @@ type SafetyResult = {
102
103
  * ```
103
104
  * @category Arrangement & Analysis
104
105
  */
105
- declare function evaluateSafety(q: SafetyQuery): SafetyResult;
106
+ declare function evaluateSafety(q: SafetyQuery, opts?: EvaluateSafetyOptions): SafetyResult;
107
+ /**
108
+ * Options for {@link evaluateSafety}.
109
+ *
110
+ * @category Arrangement & Analysis
111
+ */
112
+ type EvaluateSafetyOptions = {
113
+ /**
114
+ * Whether to search for safe replacement pitches when the verdict is not
115
+ * safe. Turning it off skips up to two dozen extra evaluations per rejected
116
+ * pitch, which is worth doing when only the verdict is wanted.
117
+ *
118
+ * @defaultValue true
119
+ */
120
+ suggestions?: boolean;
121
+ };
106
122
  /**
107
123
  * Enumerate placeable pitches in a range, chord tones first, descending.
108
124
  *
@@ -125,4 +141,4 @@ declare function evaluateSafety(q: SafetyQuery): SafetyResult;
125
141
  */
126
142
  declare function enumerateSafePitches(q: Omit<SafetyQuery, 'candidatePitch'>, pitchLow: number, pitchHigh: number): number[];
127
143
 
128
- export { 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 };
144
+ 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,18 +1,8 @@
1
- import { T as TimeSignature } from './index-Cl7mhOFM.cjs';
2
- import { K as KeyScale, N as NoteEvent } from './types-MGP29r3t.cjs';
3
- import { C as Chord, b as ChordSpan } from './index-BNlGP86A.cjs';
4
- import { C as Cadence } from './function-DYt4iKsn.cjs';
1
+ import { T as TimeSignature } from './index-DXd9JikN.cjs';
2
+ import { K as KeyScale, N as NoteEvent } from './types-BN6_Q9Kl.cjs';
3
+ import { C as Chord, b as ChordSegment, c as ChordSpan } from './index-oTQbYYIs.cjs';
4
+ import { C as Cadence } from './function-CxixTB02.cjs';
5
5
 
6
- /**
7
- * A chord occupying a half-open beat span.
8
- *
9
- * @category Arrangement & Analysis
10
- */
11
- type ChordSegment = {
12
- startBeat: number;
13
- endBeat: number;
14
- chord: Chord;
15
- };
16
6
  /**
17
7
  * A beat-indexed sequence of chord segments.
18
8
  *
@@ -36,14 +26,14 @@ type ChordTimeline = {
36
26
  * @returns A queryable chord timeline.
37
27
  * @category Arrangement & Analysis
38
28
  */
39
- declare function chordTimelineFromChords(chords: ChordSpan[], totalBeats: number): ChordTimeline;
29
+ declare function chordTimelineFromChords(chords: readonly ChordSpan[], totalBeats: number): ChordTimeline;
40
30
  /**
41
31
  * Options controlling {@link chordTimelineFromNotes}.
42
32
  *
43
33
  * @category Arrangement & Analysis
44
34
  */
45
35
  type ChordTimelineOptions = {
46
- /** Key context; inferred from the notes with {@link detectKey} when omitted. */
36
+ /** Key context; inferred from the notes with {@link detectKeyFromNotes} when omitted. */
47
37
  key?: KeyScale;
48
38
  /**
49
39
  * Time signature used for metric accents; defaults to 4/4.
@@ -63,6 +53,17 @@ type ChordTimelineOptions = {
63
53
  * @defaultValue the end of the last note
64
54
  */
65
55
  totalBeats?: number;
56
+ /**
57
+ * Upper bound on the work this call may do — note counts, windows, and
58
+ * candidate counts are each checked against it before anything is allocated.
59
+ *
60
+ * Raise it to analyse a piece larger than the default allows; the default is
61
+ * {@link DEFAULT_GENERATION_BUDGET}, chosen so a runaway input fails fast
62
+ * rather than blocking the thread.
63
+ *
64
+ * @defaultValue {@link DEFAULT_GENERATION_BUDGET}
65
+ */
66
+ budget?: number;
66
67
  };
67
68
  /**
68
69
  * The result of {@link chordTimelineFromNotes}.
@@ -148,4 +149,4 @@ type CadenceHit = {
148
149
  */
149
150
  declare function detectCadences(timeline: ChordTimeline, key: KeyScale): CadenceHit[];
150
151
 
151
- export { type CadenceHit as C, type ChordSegment as a, type ChordTimeline as b, type ChordTimelineOptions as c, type ChordTimelineResult as d, chordTimelineFromChords as e, chordTimelineFromNotes as f, detectCadences as g };
152
+ export { type CadenceHit as C, type ChordTimeline as a, type ChordTimelineOptions as b, type ChordTimelineResult as c, chordTimelineFromChords as d, chordTimelineFromNotes as e, detectCadences as f };
@@ -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
  * Severity policy: `strict` counterpoint vs. lenient `pop` voice-leading.
@@ -38,7 +38,8 @@ declare enum ReasonFlag {
38
38
  HiddenParallel = 4096,
39
39
  VoiceCrossing = 8192,
40
40
  Suspension = 16384,
41
- NeedsResolution = 32768
41
+ NeedsResolution = 32768,
42
+ MelodicTritone = 65536
42
43
  }
43
44
  /**
44
45
  * A neighbouring voice's current and previous pitch.
@@ -102,7 +103,22 @@ type SafetyResult = {
102
103
  * ```
103
104
  * @category Arrangement & Analysis
104
105
  */
105
- declare function evaluateSafety(q: SafetyQuery): SafetyResult;
106
+ declare function evaluateSafety(q: SafetyQuery, opts?: EvaluateSafetyOptions): SafetyResult;
107
+ /**
108
+ * Options for {@link evaluateSafety}.
109
+ *
110
+ * @category Arrangement & Analysis
111
+ */
112
+ type EvaluateSafetyOptions = {
113
+ /**
114
+ * Whether to search for safe replacement pitches when the verdict is not
115
+ * safe. Turning it off skips up to two dozen extra evaluations per rejected
116
+ * pitch, which is worth doing when only the verdict is wanted.
117
+ *
118
+ * @defaultValue true
119
+ */
120
+ suggestions?: boolean;
121
+ };
106
122
  /**
107
123
  * Enumerate placeable pitches in a range, chord tones first, descending.
108
124
  *
@@ -125,4 +141,4 @@ declare function evaluateSafety(q: SafetyQuery): SafetyResult;
125
141
  */
126
142
  declare function enumerateSafePitches(q: Omit<SafetyQuery, 'candidatePitch'>, pitchLow: number, pitchHigh: number): number[];
127
143
 
128
- export { 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 };
144
+ 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 };
@@ -0,0 +1,199 @@
1
+ import { K as KeyScale, N as NoteEvent } from './types-BN6_Q9Kl.js';
2
+ import { a as ChordQuality, C as Chord } from './index-COw1Ky9g.js';
3
+
4
+ /**
5
+ * Recognition: infer a chord name from a set of pitches, or a key from a set of
6
+ * pitch classes. This is the inverse direction of the chord/scale builders,
7
+ * which only go name -> notes.
8
+ */
9
+
10
+ /**
11
+ * A candidate chord interpretation of a pitch set.
12
+ *
13
+ * @category Recognition
14
+ */
15
+ type ChordMatch = {
16
+ rootPc: number;
17
+ quality: ChordQuality;
18
+ /** Chord tones absent from the input (an incomplete voicing). */
19
+ missingPcs: number[];
20
+ /** Input pitch classes not belonging to the chord. */
21
+ extraPcs: number[];
22
+ /** True when the input pitch-class set equals the chord exactly. */
23
+ exact: boolean;
24
+ /**
25
+ * Inversion implied by a known bass: 0 for root position, 1..n for an
26
+ * inversion. Null when no inversion can be named — either the input is an
27
+ * unordered pitch-class set with no bass, or the bass is not a chord tone (a
28
+ * pedal or passing bass), in which case `bassPc` still reports it.
29
+ */
30
+ inversion: number | null;
31
+ /** Bass pitch class when the lowest note is not the root. */
32
+ bassPc?: number;
33
+ };
34
+ /**
35
+ * Input interpretation for {@link detectChord} and {@link detectChordBest}.
36
+ *
37
+ * @category Recognition
38
+ */
39
+ type DetectChordOptions = {
40
+ /**
41
+ * `midi` uses the numerically lowest pitch as bass; `pitchClass` treats the
42
+ * input as unordered. `auto` (default) selects pitch-class mode only when all
43
+ * values lie in 0..11.
44
+ */
45
+ input?: 'auto' | 'midi' | 'pitchClass';
46
+ /** Explicit bass pitch class, including for an unordered pitch-class set. */
47
+ bassPc?: number;
48
+ };
49
+ /**
50
+ * A candidate key interpretation of a pitch-class set.
51
+ *
52
+ * @category Recognition
53
+ */
54
+ type KeyMatch = {
55
+ /** The scale that scored best for this tonic and mode, `variant` included. */
56
+ key: KeyScale;
57
+ mode: 'major' | 'minor';
58
+ /** Which scale form `key` uses; minor keys pick the best-scoring of the three. */
59
+ variant: KeyVariant;
60
+ /**
61
+ * Fraction of the distinct input pitch classes that belong to `key`, in
62
+ * [0, 1]. Measured against the returned scale, so it always agrees with
63
+ * `isScaleTone(pc, match.key)`. This is a coverage figure, not the ranking:
64
+ * see `score`.
65
+ */
66
+ fit: number;
67
+ /**
68
+ * The value the results are ranked by, in [0, 1.5]. Unlike `fit` it counts
69
+ * every occurrence rather than every distinct pitch class, so a repeated tone
70
+ * weighs more, and it adds half a count per sounding of the tonic itself to
71
+ * break ties between keys that contain the same notes.
72
+ */
73
+ score: number;
74
+ };
75
+ /**
76
+ * Which form of a scale a {@link KeyMatch} settled on.
77
+ *
78
+ * @category Recognition
79
+ */
80
+ type KeyVariant = 'major' | 'natural' | 'harmonic' | 'melodic';
81
+ /**
82
+ * Input weighting for {@link detectKey}.
83
+ *
84
+ * @category Recognition
85
+ */
86
+ type DetectKeyOptions = {
87
+ /**
88
+ * How much each pitch counts toward the histogram, one entry per pitch.
89
+ * Defaults to one per pitch, which weighs a thirty-second-note ornament as
90
+ * heavily as the whole note under it. {@link detectKeyFromNotes} supplies
91
+ * duration times velocity, matching how chord inference weighs its own
92
+ * histogram.
93
+ */
94
+ weights?: readonly number[];
95
+ /**
96
+ * Upper bound on the input pitches processed by this detection call.
97
+ *
98
+ * @defaultValue {@link DEFAULT_GENERATION_BUDGET}
99
+ */
100
+ budget?: number;
101
+ };
102
+ /**
103
+ * Identify chords matching a set of pitches.
104
+ *
105
+ * Every input pitch class is tried as a root against every known chord quality.
106
+ * A match is reported when all of the chord's tones are present in the input, or
107
+ * when the only absent tone is the perfect fifth (a common omission in shell
108
+ * voicings); matches are ranked best-first by fewest extra notes, then fewest
109
+ * missing notes, then most specific (largest) chord. An exact match (no extras,
110
+ * no missing) is flagged and ranked first.
111
+ *
112
+ * @param pitches MIDI pitches or bare pitch classes (octave-agnostic).
113
+ * @returns Ranked chord interpretations (may be empty).
114
+ * @example
115
+ * ```ts
116
+ * import { detectChord } from '@libraz/libcantus';
117
+ * const matches = detectChord([60, 64, 67]); // C E G
118
+ * matches[0]; // { rootPc: 0, quality: 'maj', exact: true, ... }
119
+ * ```
120
+ * @category Recognition
121
+ */
122
+ declare function detectChord(pitches: readonly number[], opts?: DetectChordOptions): ChordMatch[];
123
+ /**
124
+ * The single best chord interpretation of a pitch set, or null if none.
125
+ *
126
+ * @param pitches MIDI pitches or bare pitch classes.
127
+ * @returns The top-ranked chord, or null when nothing matches.
128
+ * @example
129
+ * ```ts
130
+ * import { detectChordBest } from '@libraz/libcantus';
131
+ * detectChordBest([60, 64, 67]); // C major triad: { rootPc: 0, quality: 'maj', ... }
132
+ * ```
133
+ * @category Recognition
134
+ */
135
+ declare function detectChordBest(pitches: readonly number[], opts?: DetectChordOptions): Chord | null;
136
+ /**
137
+ * Rank major and minor keys by how well they contain a set of pitch classes.
138
+ *
139
+ * Ranking is by `score`, which counts repetitions and adds a tonic weight so
140
+ * that, among equally-fitting keys, the one whose root is actually sounded is
141
+ * preferred. Minor candidates are scored against the natural, harmonic, and
142
+ * melodic minor variants and keep the best of the three, so a minor cadence
143
+ * containing the leading tone still resolves to its own tonic; the winning
144
+ * variant is what `key` and `variant` report, so `fit` describes the scale the
145
+ * caller receives. Returns all 24 keys ranked best-first, or an empty array for
146
+ * an empty input (mirroring {@link detectChord}).
147
+ *
148
+ * @param pitches MIDI pitches or bare pitch classes.
149
+ * @returns Ranked key interpretations (empty for an empty input).
150
+ * @example
151
+ * ```ts
152
+ * import { detectKey } from '@libraz/libcantus';
153
+ * const keys = detectKey([60, 62, 64, 65, 67, 69, 71]); // C major scale
154
+ * keys[0].mode; // 'major', with keys[0].key.rootPc === 0
155
+ * ```
156
+ * @category Recognition
157
+ */
158
+ declare function detectKey(pitches: readonly number[], opts?: DetectKeyOptions): KeyMatch[];
159
+ /**
160
+ * Rank keys by how well they contain a set of note events, weighting each note
161
+ * by how much of the music it actually occupies.
162
+ *
163
+ * {@link detectKey} counts every pitch once, which lets a run of fast ornamental
164
+ * notes outvote the sustained harmony that establishes the key. This weighs
165
+ * each note by duration times velocity, the same measure chord inference uses,
166
+ * so the two agree on what the music emphasises. Notes that never sound (zero
167
+ * or negative duration) are ignored.
168
+ *
169
+ * @param notes The note events to weigh.
170
+ * @param opts Budget for processing imported note events.
171
+ * @returns Ranked key interpretations (empty when nothing sounds).
172
+ * @example
173
+ * ```ts
174
+ * import { detectKeyFromNotes } from '@libraz/libcantus';
175
+ * detectKeyFromNotes([{ pitch: 60, startBeat: 0, durationBeat: 4 }])[0]?.key.rootPc; // 0
176
+ * ```
177
+ * @category Recognition
178
+ */
179
+ declare function detectKeyFromNotes(notes: readonly NoteEvent[], opts?: Omit<DetectKeyOptions, 'weights'>): KeyMatch[];
180
+ /**
181
+ * The single best key interpretation of a pitch set.
182
+ *
183
+ * The counterpart of {@link detectChordBest}: the ranked list is the general
184
+ * answer, but a caller that just wants "what key is this" should not have to
185
+ * index into it and assert the result is there.
186
+ *
187
+ * @param pitches MIDI pitches or bare pitch classes.
188
+ * @param opts How to weigh the input; see {@link DetectKeyOptions}.
189
+ * @returns The top-ranked key, or null when nothing sounds.
190
+ * @example
191
+ * ```ts
192
+ * import { detectKeyBest } from '@libraz/libcantus';
193
+ * detectKeyBest([0, 2, 4, 5, 7, 9, 11])?.mode; // 'major'
194
+ * ```
195
+ * @category Recognition
196
+ */
197
+ declare function detectKeyBest(pitches: readonly number[], opts?: DetectKeyOptions): KeyMatch | null;
198
+
199
+ export { type ChordMatch as C, type DetectChordOptions as D, type KeyMatch as K, type DetectKeyOptions as a, type KeyVariant as b, detectChordBest as c, detectChord as d, detectKey as e, detectKeyBest as f, detectKeyFromNotes as g };
@@ -1,11 +1,20 @@
1
- import { K as KeyScale } from './types-MGP29r3t.js';
1
+ import { K as KeyScale } from './types-BN6_Q9Kl.js';
2
2
 
3
3
  /**
4
4
  * Chord quality identifiers understood by the chord builder.
5
5
  *
6
6
  * @category Chords
7
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';
8
+ 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';
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';
9
18
  /**
10
19
  * A bare spelled pitch used as an enharmonic hint: a diatonic letter
11
20
  * (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).
@@ -54,7 +63,26 @@ type ChordSpan = {
54
63
  secondaryDominant?: boolean;
55
64
  };
56
65
  /**
57
- * All chord qualities the builder understands, longest templates last.
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.
58
86
  *
59
87
  * @category Chords
60
88
  */
@@ -92,21 +120,73 @@ declare function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScal
92
120
  * @category Chords
93
121
  */
94
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;
95
146
  /**
96
147
  * Get the sorted, deduplicated pitch classes of a chord.
97
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
+ *
98
153
  * @param chord The chord to enumerate.
154
+ * @param opts Set `includeBass: false` to omit a slash bass.
99
155
  * @returns The chord's pitch classes, sorted ascending in [0, 11].
100
156
  *
101
157
  * @example
102
158
  * ```ts
103
159
  * import { makeChord, chordPitchClasses } from '@libraz/libcantus';
104
160
  * chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]
161
+ * chordPitchClasses(makeChord(5, 'maj', 7)); // [0, 5, 7, 9] — F/G, G included
105
162
  * ```
106
163
  *
107
164
  * @category Chords
108
165
  */
109
- declare function chordPitchClasses(chord: Chord): number[];
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;
110
190
  /**
111
191
  * Determine a pitch's harmonic role within a chord.
112
192
  *
@@ -121,18 +201,21 @@ declare function chordPitchClasses(chord: Chord): number[];
121
201
  *
122
202
  * @category Chords
123
203
  */
124
- declare function chordToneRole(pitch: number, chord: Chord): 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | null;
204
+ declare function chordToneRole(pitch: number, chord: Chord): ChordToneRole | null;
125
205
  /**
126
206
  * Build the diatonic triad rooted on a scale degree by stacking scale thirds.
127
207
  *
128
208
  * Unlike {@link chordFromDegree}, the chord quality is derived from the scale
129
209
  * rather than supplied, so degrees yield their scale-correct triads (e.g. a
130
- * diminished triad on the leading tone of a major key). Intended for heptatonic
131
- * scales; other scales stack by scale step regardless.
210
+ * diminished triad on the leading tone of a major key).
132
211
  *
133
212
  * @param degree 0-based scale degree of the chord root.
134
213
  * @param key Key/scale context.
135
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.
136
219
  *
137
220
  * @example
138
221
  * ```ts
@@ -149,9 +232,11 @@ declare function diatonicTriad(degree: number, key: KeyScale): Chord;
149
232
  * @param degree 0-based scale degree of the chord root.
150
233
  * @param key Key/scale context.
151
234
  * @returns The diatonic seventh chord.
235
+ * @throws If the scale is not heptatonic, for the reason given on
236
+ * {@link diatonicTriad}.
152
237
  *
153
238
  * @category Chords
154
239
  */
155
240
  declare function diatonicSeventh(degree: number, key: KeyScale): Chord;
156
241
 
157
- export { type Chord as C, type PitchSpelling as P, type ChordQuality as a, type ChordSpan as b, chordFromDegree as c, chordPitchClasses as d, chordQualities as e, chordToneRole as f, diatonicSeventh as g, diatonicTriad as h, makeChord as m };
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 };
@@ -1,11 +1,11 @@
1
- import { C as Chord } from './index-BNlGP86A.cjs';
1
+ import { d as ChordToneRole, C as Chord } from './index-COw1Ky9g.js';
2
2
 
3
3
  /**
4
4
  * Harmonic role a pitch plays within a chord.
5
5
  *
6
6
  * @category Functional Harmony
7
7
  */
8
- type HarmonyRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | 'tension' | 'doubling';
8
+ type HarmonyRole = ChordToneRole | 'tension' | 'doubling';
9
9
  /**
10
10
  * How firmly a pitch is locked to the chord's identity.
11
11
  *
@@ -29,15 +29,18 @@ type VoicedRole = {
29
29
  /**
30
30
  * Classify a pitch's harmonic role and lock level within a chord.
31
31
  *
32
- * The role comes from the pitch's interval class above the chord root: root (0),
33
- * third (3/4), fifth (6/7/8), seventh (10/11), and 9/11/13 tensions (2/5/9, and
34
- * the flat ninth 1). The root locks the chord identity, the third locks its
35
- * quality, and everything else is free voicing. In a suspended chord (a chord
36
- * whose intervals include a 4th (5) or 2nd (2) but no third), the suspended tone
37
- * takes the third's place as the quality-defining tone and is locked to
38
- * `quality`, since moving it changes the chord. Detecting an octave doubling
39
- * requires the surrounding voicing, which this single-pitch query does not carry,
40
- * so `doubling` is part of the type but not returned here.
32
+ * The role comes from the pitch's interval class above the chord root, read
33
+ * against the chord's own template: root (0), third (3/4), fifth (6/7/8),
34
+ * sixth or seventh (9/10/11). Every pitch the template does not claim is
35
+ * `'tension'` — including one that is simply foreign to the chord, which this
36
+ * single-pitch query cannot tell from a colour tone. The root locks the chord
37
+ * identity, the third locks its quality, and everything else is free voicing.
38
+ * In a suspended chord (a chord whose intervals include a 4th (5) or 2nd (2)
39
+ * but no third), the suspended tone takes the third's place as the
40
+ * quality-defining tone and is locked to `quality`, since moving it changes the
41
+ * chord. Detecting an octave doubling requires the surrounding voicing, which
42
+ * this query does not carry, so `'doubling'` is part of the type — the shared
43
+ * vocabulary of harmonic roles — but is never returned here.
41
44
  *
42
45
  * @param pitch MIDI pitch or bare pitch class.
43
46
  * @param chord The chord providing the root reference.