@libraz/libcantus 0.9.5 → 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 (185) hide show
  1. package/README.md +61 -270
  2. package/README_ja.md +61 -214
  3. package/dist/analyze/index.cjs +54 -7
  4. package/dist/analyze/index.cjs.map +1 -1
  5. package/dist/analyze/index.d.cts +200 -353
  6. package/dist/analyze/index.d.ts +200 -353
  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-2PTFGVD7.js → chunk-ELCTZUJJ.js} +250 -132
  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 +93 -6
  64. package/dist/core/index.cjs.map +1 -1
  65. package/dist/core/index.d.cts +87 -346
  66. package/dist/core/index.d.ts +87 -346
  67. package/dist/core/index.js +94 -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 +436 -1094
  71. package/dist/generate/index.d.ts +436 -1094
  72. package/dist/generate/index.js +94 -15
  73. package/dist/index-9wcMhG73.d.ts +1095 -0
  74. package/dist/{index-Cfx8xgH0.d.ts → 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-x2vcsduE.d.cts → 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 +348 -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 +397 -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 +4659 -249
  103. package/dist/model/index.d.ts +4659 -249
  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 +511 -171
  110. package/dist/theory/index.d.ts +511 -171
  111. package/dist/theory/index.js +118 -24
  112. package/package.json +6 -4
  113. package/dist/chunk-2A2QMA74.cjs +0 -261
  114. package/dist/chunk-2A2QMA74.cjs.map +0 -1
  115. package/dist/chunk-2PTFGVD7.js.map +0 -1
  116. package/dist/chunk-357ZDPVU.cjs +0 -162
  117. package/dist/chunk-357ZDPVU.cjs.map +0 -1
  118. package/dist/chunk-3KX76RLG.js +0 -1548
  119. package/dist/chunk-3KX76RLG.js.map +0 -1
  120. package/dist/chunk-4VZ5MZAM.cjs +0 -889
  121. package/dist/chunk-4VZ5MZAM.cjs.map +0 -1
  122. package/dist/chunk-7EONYVI5.js +0 -1204
  123. package/dist/chunk-7EONYVI5.js.map +0 -1
  124. package/dist/chunk-7JEP3MFY.js +0 -162
  125. package/dist/chunk-7JEP3MFY.js.map +0 -1
  126. package/dist/chunk-AID75RN3.js +0 -3176
  127. package/dist/chunk-AID75RN3.js.map +0 -1
  128. package/dist/chunk-BSLTLGM3.cjs +0 -497
  129. package/dist/chunk-BSLTLGM3.cjs.map +0 -1
  130. package/dist/chunk-CU6VG2YM.cjs +0 -109
  131. package/dist/chunk-CU6VG2YM.cjs.map +0 -1
  132. package/dist/chunk-DZMHIGI4.js +0 -337
  133. package/dist/chunk-DZMHIGI4.js.map +0 -1
  134. package/dist/chunk-EDOTEABK.js +0 -109
  135. package/dist/chunk-EDOTEABK.js.map +0 -1
  136. package/dist/chunk-HN2OEUN2.js +0 -33
  137. package/dist/chunk-HN2OEUN2.js.map +0 -1
  138. package/dist/chunk-KBTTEX7Q.js +0 -497
  139. package/dist/chunk-KBTTEX7Q.js.map +0 -1
  140. package/dist/chunk-KQN2ZYND.cjs +0 -724
  141. package/dist/chunk-KQN2ZYND.cjs.map +0 -1
  142. package/dist/chunk-MPTVJIVG.cjs +0 -3176
  143. package/dist/chunk-MPTVJIVG.cjs.map +0 -1
  144. package/dist/chunk-MTMZTMWM.cjs +0 -53
  145. package/dist/chunk-MTMZTMWM.cjs.map +0 -1
  146. package/dist/chunk-N6IHQUOX.js +0 -1
  147. package/dist/chunk-NNB67XA2.js +0 -724
  148. package/dist/chunk-NNB67XA2.js.map +0 -1
  149. package/dist/chunk-OL3IHHSJ.cjs +0 -1204
  150. package/dist/chunk-OL3IHHSJ.cjs.map +0 -1
  151. package/dist/chunk-PI3UXRWK.cjs +0 -528
  152. package/dist/chunk-PI3UXRWK.cjs.map +0 -1
  153. package/dist/chunk-R2VVFAIN.js +0 -528
  154. package/dist/chunk-R2VVFAIN.js.map +0 -1
  155. package/dist/chunk-T64C7ZD7.cjs +0 -1
  156. package/dist/chunk-T64C7ZD7.cjs.map +0 -1
  157. package/dist/chunk-WFDXOLUB.cjs +0 -337
  158. package/dist/chunk-WFDXOLUB.cjs.map +0 -1
  159. package/dist/chunk-WTAN4ACG.cjs +0 -1548
  160. package/dist/chunk-WTAN4ACG.cjs.map +0 -1
  161. package/dist/chunk-YFJXS3AU.cjs +0 -33
  162. package/dist/chunk-YFJXS3AU.cjs.map +0 -1
  163. package/dist/chunk-YUE6TJ4M.js +0 -889
  164. package/dist/chunk-YUE6TJ4M.js.map +0 -1
  165. package/dist/chunk-ZGLJM4A4.js +0 -53
  166. package/dist/chunk-ZGLJM4A4.js.map +0 -1
  167. package/dist/function-CxixTB02.d.cts +0 -299
  168. package/dist/function-DTCt675z.d.ts +0 -299
  169. package/dist/index-B2Ulxxpo.d.cts +0 -144
  170. package/dist/index-BkYJ0xMq.d.cts +0 -152
  171. package/dist/index-BuaB-ypt.d.ts +0 -144
  172. package/dist/index-CAN7v-kw.d.ts +0 -199
  173. package/dist/index-COw1Ky9g.d.ts +0 -242
  174. package/dist/index-DRtIhlJj.d.ts +0 -152
  175. package/dist/index-DXd9JikN.d.cts +0 -246
  176. package/dist/index-DXd9JikN.d.ts +0 -246
  177. package/dist/index-alrRninU.d.cts +0 -199
  178. package/dist/index-oTQbYYIs.d.cts +0 -242
  179. package/dist/index-tR9jTn26.d.cts +0 -275
  180. package/dist/index-tR9jTn26.d.ts +0 -275
  181. package/dist/styled-Bl0ZK28h.d.ts +0 -543
  182. package/dist/styled-Crv6SA4S.d.cts +0 -543
  183. package/dist/types-BN6_Q9Kl.d.cts +0 -39
  184. package/dist/types-BN6_Q9Kl.d.ts +0 -39
  185. /package/dist/{chunk-N6IHQUOX.js.map → chunk-HFPS7JFD.js.map} +0 -0
@@ -1,152 +0,0 @@
1
- import { T as TimeSignature } from './index-DXd9JikN.js';
2
- import { K as KeyScale, N as NoteEvent } from './types-BN6_Q9Kl.js';
3
- import { C as Chord, b as ChordSegment, c as ChordSpan } from './index-COw1Ky9g.js';
4
- import { C as Cadence } from './function-DTCt675z.js';
5
-
6
- /**
7
- * A beat-indexed sequence of chord segments.
8
- *
9
- * @category Arrangement & Analysis
10
- */
11
- type ChordTimeline = {
12
- /** The chord sounding at a beat, or null when no segment covers it. */
13
- at: (beat: number) => Chord | null;
14
- segments: ChordSegment[];
15
- };
16
- /**
17
- * Build a chord timeline from placed chords.
18
- *
19
- * Each chord spans from its `startBeat` to the next chord's `startBeat`; the last
20
- * chord runs to `totalBeats`. Segments with no positive length (from duplicate
21
- * onsets or a last chord at or past `totalBeats`) are dropped. `at(beat)` returns
22
- * the covering segment's chord, or null when the beat lies outside every segment.
23
- *
24
- * @param chords Placed chords in time order.
25
- * @param totalBeats End of the timeline in beats.
26
- * @returns A queryable chord timeline.
27
- * @category Arrangement & Analysis
28
- */
29
- declare function chordTimelineFromChords(chords: readonly ChordSpan[], totalBeats: number): ChordTimeline;
30
- /**
31
- * Options controlling {@link chordTimelineFromNotes}.
32
- *
33
- * @category Arrangement & Analysis
34
- */
35
- type ChordTimelineOptions = {
36
- /** Key context; inferred from the notes with {@link detectKeyFromNotes} when omitted. */
37
- key?: KeyScale;
38
- /**
39
- * Time signature used for metric accents; defaults to 4/4.
40
- *
41
- * @defaultValue `4/4`
42
- */
43
- ts?: TimeSignature;
44
- /**
45
- * Window length in beats per chord slot; defaults to one bar of `ts`.
46
- *
47
- * @defaultValue one bar of `ts`
48
- */
49
- harmonicRhythm?: number;
50
- /**
51
- * End of the analyzed span in beats; defaults to the end of the last note.
52
- *
53
- * @defaultValue the end of the last note
54
- */
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;
67
- };
68
- /**
69
- * The result of {@link chordTimelineFromNotes}.
70
- *
71
- * @category Arrangement & Analysis
72
- */
73
- type ChordTimelineResult = {
74
- /** The inferred timeline, with adjacent identical chords merged. */
75
- timeline: ChordTimeline;
76
- /** The key used for the analysis (given or inferred). */
77
- key: KeyScale;
78
- /** One confidence value in [0, 1] per segment, in segment order. */
79
- segmentConfidence: number[];
80
- };
81
- /**
82
- * Infer a chord timeline from raw multi-track notes.
83
- *
84
- * The span `[0, totalBeats)` is sliced into `harmonicRhythm`-beat windows; each
85
- * window's chord is inferred from a pitch-class weight histogram of the notes
86
- * overlapping it (weight = overlap duration x velocity x metric-accent bonus
87
- * for onsets in the window). Adjacent windows carrying the identical chord are
88
- * merged into one segment; windows with no notes produce no segment, so
89
- * `at(beat)` returns null there. Each segment carries a confidence in [0, 1]:
90
- * the fraction of the window weight explained by chord tones, reduced when the
91
- * match is inexact, and duration-weighted across merged windows.
92
- *
93
- * Notes with a zero or negative duration never sound, so they are dropped at
94
- * ingest: they contribute to neither the key inference, the span, nor any
95
- * window's histogram.
96
- *
97
- * @param notes The notes to analyze (any number of tracks, flattened).
98
- * @param opts Analysis options; see {@link ChordTimelineOptions}.
99
- * @returns The inferred timeline, the key used, and per-segment confidences.
100
- * @throws If `harmonicRhythm` is not positive.
101
- * @example
102
- * ```ts
103
- * import { chordTimelineFromNotes } from '@libraz/libcantus';
104
- * const notes = [
105
- * { pitch: 60, startBeat: 0, durationBeat: 2 }, // C
106
- * { pitch: 64, startBeat: 0, durationBeat: 2 }, // E
107
- * { pitch: 67, startBeat: 0, durationBeat: 2 }, // G
108
- * ];
109
- * const { timeline, key } = chordTimelineFromNotes(notes);
110
- * timeline.at(0); // the chord inferred over beat 0, or null
111
- * ```
112
- * @category Arrangement & Analysis
113
- */
114
- declare function chordTimelineFromNotes(notes: NoteEvent[], opts?: ChordTimelineOptions): ChordTimelineResult;
115
- /**
116
- * A cadence found between two consecutive timeline segments.
117
- *
118
- * @category Arrangement & Analysis
119
- */
120
- type CadenceHit = {
121
- /** The beat where the cadence arrives (the second chord's onset). */
122
- atBeat: number;
123
- type: Exclude<Cadence, null>;
124
- from: Chord;
125
- to: Chord;
126
- };
127
- /**
128
- * Find cadences between consecutive segments of a chord timeline.
129
- *
130
- * Each temporally adjacent segment pair is classified with
131
- * {@link detectCadence}; pairs forming no cadence are skipped. Segments
132
- * separated by a gap (a rest in the timeline) are not a chord-to-chord
133
- * progression, so they are never paired.
134
- *
135
- * @param timeline The chord timeline to scan.
136
- * @param key The prevailing key.
137
- * @returns The cadences found, in time order.
138
- * @example
139
- * ```ts
140
- * import { chordTimelineFromNotes, detectCadences } from '@libraz/libcantus';
141
- * const notes = [
142
- * { pitch: 67, startBeat: 0, durationBeat: 4 }, // G, a dominant
143
- * { pitch: 60, startBeat: 4, durationBeat: 4 }, // C, the tonic
144
- * ];
145
- * const { timeline, key } = chordTimelineFromNotes(notes);
146
- * const cadences = detectCadences(timeline, key);
147
- * ```
148
- * @category Arrangement & Analysis
149
- */
150
- declare function detectCadences(timeline: ChordTimeline, key: KeyScale): CadenceHit[];
151
-
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,246 +0,0 @@
1
- /**
2
- * Meter and time signatures: bar/beat arithmetic, simple vs. compound meters,
3
- * metric-accent hierarchy, and tuplet subdivision.
4
- *
5
- * Positions and durations are measured in quarter-note beats, matching the rest
6
- * of the library's beat convention (four quarter-note beats per bar in 4/4).
7
- */
8
- /**
9
- * A time signature as a numerator over a note-value denominator.
10
- *
11
- * @category Rhythm & Meter
12
- */
13
- type TimeSignature = {
14
- numerator: number;
15
- denominator: number;
16
- /**
17
- * Optional additive grouping of the bar's main pulses, as the felt-beat
18
- * lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or
19
- * `[3, 2]` for 5/8. The entries must be positive integers summing to the
20
- * numerator.
21
- *
22
- * A compound numerator accepts both readings. 9/8 groups its three dotted
23
- * pulses as `[1, 1, 1]`, or reads additively as `[2, 2, 2, 3]` quavers; a
24
- * grouping that sums to the numerator selects the additive reading, so
25
- * aksak and other additive metres are expressible. {@link pulsesPerBar}
26
- * and {@link isCompound} follow whichever reading the grouping selects.
27
- *
28
- * When present, the head pulse of each group (other than the downbeat) is
29
- * treated as a secondary strong pulse by
30
- * {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses
31
- * are weighted equally as flat, evenly divided pulses.
32
- */
33
- grouping?: number[];
34
- };
35
- /**
36
- * A position expressed as a bar index and a quarter-note offset within the bar.
37
- *
38
- * @category Rhythm & Meter
39
- */
40
- type BarPosition = {
41
- /** 0-based bar index. {@link formatBarPosition} renders it 1-based. */
42
- bar: number;
43
- /**
44
- * Quarter-note offset from the start of the bar — not the felt beat. In 6/8
45
- * the second felt beat is at `beat: 1.5`; {@link barPositionToPulse} converts
46
- * to felt-beat numbering.
47
- */
48
- beat: number;
49
- };
50
- /**
51
- * Parse a time signature such as `"4/4"` or `"6/8"`.
52
- *
53
- * @param text The signature text.
54
- * @returns The parsed time signature.
55
- * @throws If the text is not `n/d` with positive integers.
56
- * @example
57
- * ```ts
58
- * import { parseTimeSignature } from '@libraz/libcantus';
59
- * parseTimeSignature('6/8'); // { numerator: 6, denominator: 8 }
60
- * ```
61
- * @category Rhythm & Meter
62
- */
63
- declare function parseTimeSignature(text: string): TimeSignature;
64
- /**
65
- * Render a time signature as `"n/d"`, or as `"a+b+c/d"` when it carries an
66
- * additive grouping and `grouping` is requested.
67
- *
68
- * The plain form drops the grouping, so a round trip through it reads 7/8 as
69
- * flat rather than as 2+2+3; ask for the additive form to keep it.
70
- *
71
- * @param ts The time signature.
72
- * @param opts Set `grouping: true` to render an additive grouping.
73
- * @returns The formatted signature.
74
- * @example
75
- * ```ts
76
- * import { formatTimeSignature } from '@libraz/libcantus';
77
- * const aksak = { numerator: 7, denominator: 8, grouping: [2, 2, 3] };
78
- * formatTimeSignature(aksak); // '7/8'
79
- * formatTimeSignature(aksak, { grouping: true }); // '2+2+3/8'
80
- * ```
81
- * @category Rhythm & Meter
82
- */
83
- declare function formatTimeSignature(ts: TimeSignature, opts?: {
84
- grouping?: boolean;
85
- }): string;
86
- /**
87
- * Whether a meter is compound: its main pulses each divide into three, as in
88
- * 6/8, 9/8, 12/8, or 6/4. Compound meters are those whose numerator is a
89
- * multiple of three greater than three, independent of the denominator. Meters
90
- * like 3/8 and 3/4 (simple triples, numerator 3) are not compound, and neither
91
- * is a signature whose {@link TimeSignature.grouping} selects the additive
92
- * reading (9/8 as 2+2+2+3).
93
- *
94
- * @param ts The time signature.
95
- * @returns True for compound meters.
96
- * @category Rhythm & Meter
97
- */
98
- declare function isCompound(ts: TimeSignature): boolean;
99
- /**
100
- * Length of a bar in quarter-note beats.
101
- *
102
- * @param ts The time signature.
103
- * @returns The bar length in quarter notes.
104
- * @category Rhythm & Meter
105
- */
106
- declare function beatsPerBar(ts: TimeSignature): number;
107
- /**
108
- * Number of main pulses (felt beats) per bar: the numerator for simple meters,
109
- * a third of it for compound meters.
110
- *
111
- * For additive/irregular meters such as 7/8 or 5/8 this counts the raw pulses
112
- * (7 and 5 respectively), which are otherwise felt as flat, evenly divided and
113
- * equally accented pulses. To recover a 2+2+3 or 3+2 felt-beat grouping, set
114
- * {@link TimeSignature.grouping}; {@link metricWeight} then accents each
115
- * group's head pulse.
116
- *
117
- * @param ts The time signature.
118
- * @returns The pulse count per bar.
119
- * @category Rhythm & Meter
120
- */
121
- declare function pulsesPerBar(ts: TimeSignature): number;
122
- /**
123
- * Convert an absolute quarter-note position to a bar index and in-bar offset.
124
- *
125
- * @param beatInQuarters Absolute position in quarter-note beats.
126
- * @param ts The time signature.
127
- * @returns The bar and in-bar quarter-note offset.
128
- * @example
129
- * ```ts
130
- * import { parseTimeSignature, beatToBarPosition } from '@libraz/libcantus';
131
- * const ts = parseTimeSignature('4/4');
132
- * beatToBarPosition(5, ts); // { bar: 1, beat: 1 }
133
- * ```
134
- * @category Rhythm & Meter
135
- */
136
- declare function beatToBarPosition(beatInQuarters: number, ts: TimeSignature): BarPosition;
137
- /**
138
- * Length of one felt beat (main pulse) in quarter-note beats.
139
- *
140
- * A quarter note in simple meters, a dotted quarter in compound ones, and one
141
- * denominator unit in an additive metre. Position displays, click tracks, and
142
- * score export are all written against this length.
143
- *
144
- * @param ts The time signature.
145
- * @returns The pulse length in quarter-note beats.
146
- * @example
147
- * ```ts
148
- * import { parseTimeSignature, pulseBeats } from '@libraz/libcantus';
149
- * pulseBeats(parseTimeSignature('6/8')); // 1.5
150
- * ```
151
- * @category Rhythm & Meter
152
- */
153
- declare function pulseBeats(ts: TimeSignature): number;
154
- /**
155
- * The felt-beat number of a bar position, 1-based.
156
- *
157
- * {@link BarPosition.beat} is a quarter-note offset, so in 6/8 the second felt
158
- * beat reads as 1.5. This is the number a musician says and a position display
159
- * shows.
160
- *
161
- * @param pos The bar position.
162
- * @param ts The time signature.
163
- * @returns The 1-based felt-beat number, fractional between pulses.
164
- * @example
165
- * ```ts
166
- * import { barPositionToPulse, parseTimeSignature } from '@libraz/libcantus';
167
- * barPositionToPulse({ bar: 0, beat: 1.5 }, parseTimeSignature('6/8')); // 2
168
- * ```
169
- * @category Rhythm & Meter
170
- */
171
- declare function barPositionToPulse(pos: BarPosition, ts: TimeSignature): number;
172
- /**
173
- * Render an absolute position as the `bar.beat` a DAW or a score shows:
174
- * 1-based bar, 1-based felt beat.
175
- *
176
- * @param beatInQuarters Absolute position in quarter-note beats.
177
- * @param ts The time signature.
178
- * @param decimals Digits of the fractional beat to keep.
179
- * @returns The formatted position, e.g. `'3.2'` for bar 3, felt beat 2.
180
- * @example
181
- * ```ts
182
- * import { formatBarPosition, parseTimeSignature } from '@libraz/libcantus';
183
- * formatBarPosition(7.5, parseTimeSignature('6/8')); // '3.2'
184
- * ```
185
- * @category Rhythm & Meter
186
- */
187
- declare function formatBarPosition(beatInQuarters: number, ts: TimeSignature, decimals?: number): string;
188
- /**
189
- * Convert a bar index and in-bar offset back to an absolute quarter-note
190
- * position.
191
- *
192
- * @param pos The bar position.
193
- * @param ts The time signature.
194
- * @returns The absolute position in quarter-note beats.
195
- * @category Rhythm & Meter
196
- */
197
- declare function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number;
198
- /**
199
- * Metric weight of a position within its bar, on a 0–3 scale:
200
- * 3 the downbeat, 2 a secondary strong pulse, 1 any other main pulse, and 0 an
201
- * off-pulse subdivision.
202
- *
203
- * The secondary strong pulse is the bar's midpoint in even simple/compound
204
- * meters. For an additive/irregular meter with {@link TimeSignature.grouping}
205
- * set (e.g. `[2, 2, 3]` for 7/8), each group's head pulse other than the
206
- * downbeat is the secondary strong pulse instead; without a grouping every
207
- * non-downbeat main pulse of such a meter weighs 1 (flat, evenly divided
208
- * pulses).
209
- *
210
- * @param beatInQuarters Absolute or in-bar quarter-note position.
211
- * @param ts The time signature.
212
- * @returns The metric weight (0–3).
213
- * @throws If the time signature is malformed, including a grouping that is not
214
- * a positive-integer list summing to the pulse count or the numerator.
215
- * @example
216
- * ```ts
217
- * import { parseTimeSignature, metricWeight } from '@libraz/libcantus';
218
- * const ts = parseTimeSignature('4/4');
219
- * metricWeight(0, ts); // 3 (the downbeat)
220
- * ```
221
- * @category Rhythm & Meter
222
- */
223
- declare function metricWeight(beatInQuarters: number, ts: TimeSignature): number;
224
- /**
225
- * Whether a position is metrically accented (weight 2 or more — a downbeat or a
226
- * secondary strong pulse).
227
- *
228
- * @param beatInQuarters Absolute or in-bar quarter-note position.
229
- * @param ts The time signature.
230
- * @returns True on strong beats.
231
- * @category Rhythm & Meter
232
- */
233
- declare function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolean;
234
- /**
235
- * Subdivide a span into `count` equal tuplet durations (e.g. an eighth-note
236
- * triplet is `tuplet(1, 3)`).
237
- *
238
- * @param totalBeats Total span in quarter-note beats.
239
- * @param count Number of equal parts.
240
- * @returns `count` equal durations summing to `totalBeats`.
241
- * @throws If `count` is not a positive integer.
242
- * @category Rhythm & Meter
243
- */
244
- declare function tuplet(totalBeats: number, count: number): number[];
245
-
246
- export { type BarPosition as B, type TimeSignature as T, barPositionToPulse as a, barPositionToBeat as b, beatToBarPosition as c, beatsPerBar as d, formatTimeSignature as e, formatBarPosition as f, isStrongBeat as g, pulseBeats as h, isCompound as i, pulsesPerBar as j, metricWeight as m, parseTimeSignature as p, tuplet as t };
@@ -1,246 +0,0 @@
1
- /**
2
- * Meter and time signatures: bar/beat arithmetic, simple vs. compound meters,
3
- * metric-accent hierarchy, and tuplet subdivision.
4
- *
5
- * Positions and durations are measured in quarter-note beats, matching the rest
6
- * of the library's beat convention (four quarter-note beats per bar in 4/4).
7
- */
8
- /**
9
- * A time signature as a numerator over a note-value denominator.
10
- *
11
- * @category Rhythm & Meter
12
- */
13
- type TimeSignature = {
14
- numerator: number;
15
- denominator: number;
16
- /**
17
- * Optional additive grouping of the bar's main pulses, as the felt-beat
18
- * lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or
19
- * `[3, 2]` for 5/8. The entries must be positive integers summing to the
20
- * numerator.
21
- *
22
- * A compound numerator accepts both readings. 9/8 groups its three dotted
23
- * pulses as `[1, 1, 1]`, or reads additively as `[2, 2, 2, 3]` quavers; a
24
- * grouping that sums to the numerator selects the additive reading, so
25
- * aksak and other additive metres are expressible. {@link pulsesPerBar}
26
- * and {@link isCompound} follow whichever reading the grouping selects.
27
- *
28
- * When present, the head pulse of each group (other than the downbeat) is
29
- * treated as a secondary strong pulse by
30
- * {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses
31
- * are weighted equally as flat, evenly divided pulses.
32
- */
33
- grouping?: number[];
34
- };
35
- /**
36
- * A position expressed as a bar index and a quarter-note offset within the bar.
37
- *
38
- * @category Rhythm & Meter
39
- */
40
- type BarPosition = {
41
- /** 0-based bar index. {@link formatBarPosition} renders it 1-based. */
42
- bar: number;
43
- /**
44
- * Quarter-note offset from the start of the bar — not the felt beat. In 6/8
45
- * the second felt beat is at `beat: 1.5`; {@link barPositionToPulse} converts
46
- * to felt-beat numbering.
47
- */
48
- beat: number;
49
- };
50
- /**
51
- * Parse a time signature such as `"4/4"` or `"6/8"`.
52
- *
53
- * @param text The signature text.
54
- * @returns The parsed time signature.
55
- * @throws If the text is not `n/d` with positive integers.
56
- * @example
57
- * ```ts
58
- * import { parseTimeSignature } from '@libraz/libcantus';
59
- * parseTimeSignature('6/8'); // { numerator: 6, denominator: 8 }
60
- * ```
61
- * @category Rhythm & Meter
62
- */
63
- declare function parseTimeSignature(text: string): TimeSignature;
64
- /**
65
- * Render a time signature as `"n/d"`, or as `"a+b+c/d"` when it carries an
66
- * additive grouping and `grouping` is requested.
67
- *
68
- * The plain form drops the grouping, so a round trip through it reads 7/8 as
69
- * flat rather than as 2+2+3; ask for the additive form to keep it.
70
- *
71
- * @param ts The time signature.
72
- * @param opts Set `grouping: true` to render an additive grouping.
73
- * @returns The formatted signature.
74
- * @example
75
- * ```ts
76
- * import { formatTimeSignature } from '@libraz/libcantus';
77
- * const aksak = { numerator: 7, denominator: 8, grouping: [2, 2, 3] };
78
- * formatTimeSignature(aksak); // '7/8'
79
- * formatTimeSignature(aksak, { grouping: true }); // '2+2+3/8'
80
- * ```
81
- * @category Rhythm & Meter
82
- */
83
- declare function formatTimeSignature(ts: TimeSignature, opts?: {
84
- grouping?: boolean;
85
- }): string;
86
- /**
87
- * Whether a meter is compound: its main pulses each divide into three, as in
88
- * 6/8, 9/8, 12/8, or 6/4. Compound meters are those whose numerator is a
89
- * multiple of three greater than three, independent of the denominator. Meters
90
- * like 3/8 and 3/4 (simple triples, numerator 3) are not compound, and neither
91
- * is a signature whose {@link TimeSignature.grouping} selects the additive
92
- * reading (9/8 as 2+2+2+3).
93
- *
94
- * @param ts The time signature.
95
- * @returns True for compound meters.
96
- * @category Rhythm & Meter
97
- */
98
- declare function isCompound(ts: TimeSignature): boolean;
99
- /**
100
- * Length of a bar in quarter-note beats.
101
- *
102
- * @param ts The time signature.
103
- * @returns The bar length in quarter notes.
104
- * @category Rhythm & Meter
105
- */
106
- declare function beatsPerBar(ts: TimeSignature): number;
107
- /**
108
- * Number of main pulses (felt beats) per bar: the numerator for simple meters,
109
- * a third of it for compound meters.
110
- *
111
- * For additive/irregular meters such as 7/8 or 5/8 this counts the raw pulses
112
- * (7 and 5 respectively), which are otherwise felt as flat, evenly divided and
113
- * equally accented pulses. To recover a 2+2+3 or 3+2 felt-beat grouping, set
114
- * {@link TimeSignature.grouping}; {@link metricWeight} then accents each
115
- * group's head pulse.
116
- *
117
- * @param ts The time signature.
118
- * @returns The pulse count per bar.
119
- * @category Rhythm & Meter
120
- */
121
- declare function pulsesPerBar(ts: TimeSignature): number;
122
- /**
123
- * Convert an absolute quarter-note position to a bar index and in-bar offset.
124
- *
125
- * @param beatInQuarters Absolute position in quarter-note beats.
126
- * @param ts The time signature.
127
- * @returns The bar and in-bar quarter-note offset.
128
- * @example
129
- * ```ts
130
- * import { parseTimeSignature, beatToBarPosition } from '@libraz/libcantus';
131
- * const ts = parseTimeSignature('4/4');
132
- * beatToBarPosition(5, ts); // { bar: 1, beat: 1 }
133
- * ```
134
- * @category Rhythm & Meter
135
- */
136
- declare function beatToBarPosition(beatInQuarters: number, ts: TimeSignature): BarPosition;
137
- /**
138
- * Length of one felt beat (main pulse) in quarter-note beats.
139
- *
140
- * A quarter note in simple meters, a dotted quarter in compound ones, and one
141
- * denominator unit in an additive metre. Position displays, click tracks, and
142
- * score export are all written against this length.
143
- *
144
- * @param ts The time signature.
145
- * @returns The pulse length in quarter-note beats.
146
- * @example
147
- * ```ts
148
- * import { parseTimeSignature, pulseBeats } from '@libraz/libcantus';
149
- * pulseBeats(parseTimeSignature('6/8')); // 1.5
150
- * ```
151
- * @category Rhythm & Meter
152
- */
153
- declare function pulseBeats(ts: TimeSignature): number;
154
- /**
155
- * The felt-beat number of a bar position, 1-based.
156
- *
157
- * {@link BarPosition.beat} is a quarter-note offset, so in 6/8 the second felt
158
- * beat reads as 1.5. This is the number a musician says and a position display
159
- * shows.
160
- *
161
- * @param pos The bar position.
162
- * @param ts The time signature.
163
- * @returns The 1-based felt-beat number, fractional between pulses.
164
- * @example
165
- * ```ts
166
- * import { barPositionToPulse, parseTimeSignature } from '@libraz/libcantus';
167
- * barPositionToPulse({ bar: 0, beat: 1.5 }, parseTimeSignature('6/8')); // 2
168
- * ```
169
- * @category Rhythm & Meter
170
- */
171
- declare function barPositionToPulse(pos: BarPosition, ts: TimeSignature): number;
172
- /**
173
- * Render an absolute position as the `bar.beat` a DAW or a score shows:
174
- * 1-based bar, 1-based felt beat.
175
- *
176
- * @param beatInQuarters Absolute position in quarter-note beats.
177
- * @param ts The time signature.
178
- * @param decimals Digits of the fractional beat to keep.
179
- * @returns The formatted position, e.g. `'3.2'` for bar 3, felt beat 2.
180
- * @example
181
- * ```ts
182
- * import { formatBarPosition, parseTimeSignature } from '@libraz/libcantus';
183
- * formatBarPosition(7.5, parseTimeSignature('6/8')); // '3.2'
184
- * ```
185
- * @category Rhythm & Meter
186
- */
187
- declare function formatBarPosition(beatInQuarters: number, ts: TimeSignature, decimals?: number): string;
188
- /**
189
- * Convert a bar index and in-bar offset back to an absolute quarter-note
190
- * position.
191
- *
192
- * @param pos The bar position.
193
- * @param ts The time signature.
194
- * @returns The absolute position in quarter-note beats.
195
- * @category Rhythm & Meter
196
- */
197
- declare function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number;
198
- /**
199
- * Metric weight of a position within its bar, on a 0–3 scale:
200
- * 3 the downbeat, 2 a secondary strong pulse, 1 any other main pulse, and 0 an
201
- * off-pulse subdivision.
202
- *
203
- * The secondary strong pulse is the bar's midpoint in even simple/compound
204
- * meters. For an additive/irregular meter with {@link TimeSignature.grouping}
205
- * set (e.g. `[2, 2, 3]` for 7/8), each group's head pulse other than the
206
- * downbeat is the secondary strong pulse instead; without a grouping every
207
- * non-downbeat main pulse of such a meter weighs 1 (flat, evenly divided
208
- * pulses).
209
- *
210
- * @param beatInQuarters Absolute or in-bar quarter-note position.
211
- * @param ts The time signature.
212
- * @returns The metric weight (0–3).
213
- * @throws If the time signature is malformed, including a grouping that is not
214
- * a positive-integer list summing to the pulse count or the numerator.
215
- * @example
216
- * ```ts
217
- * import { parseTimeSignature, metricWeight } from '@libraz/libcantus';
218
- * const ts = parseTimeSignature('4/4');
219
- * metricWeight(0, ts); // 3 (the downbeat)
220
- * ```
221
- * @category Rhythm & Meter
222
- */
223
- declare function metricWeight(beatInQuarters: number, ts: TimeSignature): number;
224
- /**
225
- * Whether a position is metrically accented (weight 2 or more — a downbeat or a
226
- * secondary strong pulse).
227
- *
228
- * @param beatInQuarters Absolute or in-bar quarter-note position.
229
- * @param ts The time signature.
230
- * @returns True on strong beats.
231
- * @category Rhythm & Meter
232
- */
233
- declare function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolean;
234
- /**
235
- * Subdivide a span into `count` equal tuplet durations (e.g. an eighth-note
236
- * triplet is `tuplet(1, 3)`).
237
- *
238
- * @param totalBeats Total span in quarter-note beats.
239
- * @param count Number of equal parts.
240
- * @returns `count` equal durations summing to `totalBeats`.
241
- * @throws If `count` is not a positive integer.
242
- * @category Rhythm & Meter
243
- */
244
- declare function tuplet(totalBeats: number, count: number): number[];
245
-
246
- export { type BarPosition as B, type TimeSignature as T, barPositionToPulse as a, barPositionToBeat as b, beatToBarPosition as c, beatsPerBar as d, formatTimeSignature as e, formatBarPosition as f, isStrongBeat as g, pulseBeats as h, isCompound as i, pulsesPerBar as j, metricWeight as m, parseTimeSignature as p, tuplet as t };