@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/event-index/index.ts","../src/core/meter/index.ts"],"sourcesContent":["import type { NoteEvent } from '../types.js';\nimport { assertFiniteNumber, assertNoteEvents } from '../validation/index.js';\n\n/**\n * A validated note retaining its position in the caller's original array.\n *\n * @category Core\n */\nexport type IndexedNoteEvent = {\n note: Readonly<NoteEvent>;\n originalIndex: number;\n endBeat: number;\n};\n\n/**\n * Which note wins when several sound from the same onset.\n *\n * `'highest'` and `'lowest'` name a voice, so the answer does not depend on the\n * order the caller happened to store the chord in; `'last'` takes the one\n * latest in the input array.\n *\n * @category Core\n */\nexport type OnsetTieBreak = 'highest' | 'lowest' | 'last';\n\n/**\n * Binary-searchable, stable-sorted index over note onsets and active spans.\n *\n * @category Core\n */\nexport type NoteEventIndex = {\n notes: readonly IndexedNoteEvent[];\n /**\n * Latest-onset note sounding at `beat`. Simultaneous onsets are resolved by\n * the index's {@link OnsetTieBreak}.\n *\n * @throws If `beat` is not finite.\n */\n at: (beat: number) => IndexedNoteEvent | undefined;\n /**\n * Whether one or more sounding notes attack at `beat`.\n *\n * @throws If `beat` is not finite.\n */\n attacksAt: (beat: number) => boolean;\n /**\n * Unique sounding-note attack beats strictly inside `(startBeat, endBeat)`.\n *\n * @throws If either bound is not finite.\n */\n onsetsBetween: (startBeat: number, endBeat: number) => number[];\n};\n\nconst EPS = 1e-9;\n\nfunction upperBound(values: readonly IndexedNoteEvent[], beat: number): number {\n let low = 0;\n let high = values.length;\n while (low < high) {\n const middle = Math.floor((low + high) / 2);\n if ((values[middle]?.note.startBeat ?? Number.POSITIVE_INFINITY) <= beat) {\n low = middle + 1;\n } else {\n high = middle;\n }\n }\n return low;\n}\n\n/**\n * How an index reads the events it is built from.\n *\n * @category Core\n */\nexport type NoteEventIndexOptions = {\n allowNonPositiveDuration?: boolean;\n tieBreak?: OnsetTieBreak;\n budget?: number;\n /** What the events are, for the validation error message. */\n name?: string;\n};\n\n/**\n * Validate and stable-sort note events once, then expose logarithmic onset and\n * active-note lookups. Non-positive-duration notes may be retained for callers\n * that intentionally filter them later, but never count as sounding.\n *\n * @category Core\n */\nexport function createNoteEventIndex(\n events: readonly NoteEvent[],\n options: NoteEventIndexOptions = {},\n): NoteEventIndex {\n assertNoteEvents(events, options.name ?? 'note events', options);\n const tieBreak = options.tieBreak ?? 'highest';\n const notes = Object.freeze(\n events\n .map((note, originalIndex) => ({\n note: Object.freeze({ ...note }),\n originalIndex,\n endBeat: note.startBeat + note.durationBeat,\n }))\n .sort((a, b) => a.note.startBeat - b.note.startBeat || a.originalIndex - b.originalIndex),\n );\n // Segment-tree maxima find the latest active onset in logarithmic time even\n // when an early, very long note would defeat a prefix-max backwards scan.\n let treeSize = 1;\n while (treeSize < notes.length) treeSize *= 2;\n const maxEndTree = new Array<number>(treeSize * 2).fill(Number.NEGATIVE_INFINITY);\n for (let index = 0; index < notes.length; index += 1) {\n maxEndTree[treeSize + index] = notes[index]?.endBeat ?? Number.NEGATIVE_INFINITY;\n }\n for (let index = treeSize - 1; index > 0; index -= 1) {\n maxEndTree[index] = Math.max(\n maxEndTree[index * 2] ?? Number.NEGATIVE_INFINITY,\n maxEndTree[index * 2 + 1] ?? Number.NEGATIVE_INFINITY,\n );\n }\n const latestActiveIndex = (exclusive: number, beat: number): number => {\n const find = (node: number, start: number, end: number): number => {\n if (start >= exclusive || (maxEndTree[node] ?? Number.NEGATIVE_INFINITY) <= beat + EPS) {\n return -1;\n }\n if (end - start === 1) return start < notes.length ? start : -1;\n const mid = Math.floor((start + end) / 2);\n const right = find(node * 2 + 1, mid, end);\n return right >= 0 ? right : find(node * 2, start, mid);\n };\n return find(1, 0, treeSize);\n };\n\n return {\n notes,\n at(beat) {\n // A query beat comes from wherever the host got it — a scrub position, a\n // parsed field — so it is checked like any other entry argument. `NaN`\n // compares false against every bound, which would read as an open window\n // rather than as the missing value it is.\n assertFiniteNumber(beat, 'beat');\n const index = latestActiveIndex(upperBound(notes, beat + EPS), beat);\n if (index < 0) return undefined;\n const onset = notes[index]?.note.startBeat;\n let best: IndexedNoteEvent | undefined;\n for (let candidateIndex = index; candidateIndex >= 0; candidateIndex -= 1) {\n const indexed = notes[candidateIndex];\n if (indexed !== undefined && indexed.note.startBeat !== onset) break;\n if (\n indexed === undefined ||\n indexed.note.durationBeat <= 0 ||\n indexed.note.startBeat - EPS > beat ||\n beat >= indexed.endBeat - EPS\n ) {\n continue;\n }\n if (best === undefined) {\n best = indexed;\n continue;\n }\n if (tieBreak === 'last') continue;\n const higher = indexed.note.pitch > best.note.pitch;\n if (tieBreak === 'highest' ? higher : !higher) {\n best = indexed;\n }\n }\n return best;\n },\n attacksAt(beat) {\n assertFiniteNumber(beat, 'beat');\n // Only a sounding note attacks: a zero-length artefact must not make\n // `attacksAt(b)` true on a beat where `at(b)` finds nothing.\n let index = upperBound(notes, beat + EPS) - 1;\n while (index >= 0) {\n const candidate = notes[index];\n if (candidate === undefined || Math.abs(candidate.note.startBeat - beat) >= EPS) {\n return false;\n }\n if (candidate.note.durationBeat > 0) {\n return true;\n }\n index -= 1;\n }\n return false;\n },\n onsetsBetween(startBeat, endBeat) {\n assertFiniteNumber(startBeat, 'startBeat');\n assertFiniteNumber(endBeat, 'endBeat');\n const result: number[] = [];\n let index = upperBound(notes, startBeat + EPS);\n while (index < notes.length) {\n const indexed = notes[index];\n const onset = indexed?.note.startBeat;\n if (indexed === undefined || onset === undefined || onset >= endBeat - EPS) {\n break;\n }\n index += 1;\n if (indexed.note.durationBeat <= 0) {\n continue;\n }\n const previous = result[result.length - 1];\n if (previous === undefined || Math.abs(previous - onset) >= EPS) {\n result.push(onset);\n }\n }\n return result;\n },\n };\n}\n","/**\n * Meter and time signatures: bar/beat arithmetic, simple vs. compound meters,\n * metric-accent hierarchy, and tuplet subdivision.\n *\n * Positions and durations are measured in quarter-note beats, matching the rest\n * of the library's beat convention (four quarter-note beats per bar in 4/4).\n * Beat 0 is the first downbeat, so a pickup sounds at negative beats, and a\n * piece that changes meter is described by a {@link MeterMap} rather than by\n * one signature.\n */\n\nimport { InvalidInputError, type ParseResult, parseFailure, unwrapParse } from '../errors/index.js';\nimport {\n assertFiniteNumber,\n assertInteger,\n assertMeterMap,\n assertPositiveInt,\n assertRange,\n assertTimeSignature,\n} from '../validation/index.js';\nimport type { MeterData } from './internal.js';\nimport {\n barBeatsOf,\n barIndexOf,\n barLengthOf,\n barStartOf,\n beatOfBarIndex,\n entryIndexOf,\n groupingSumOf,\n isAdditiveReading,\n isCompoundNumerator,\n isMeterMap,\n pulseBeatsOf,\n pulseCountOf,\n pulseGroupingOf,\n} from './internal.js';\n\n/**\n * A time signature as a numerator over a note-value denominator.\n *\n * @category Rhythm & Meter\n */\nexport type TimeSignature = {\n numerator: number;\n denominator: number;\n /**\n * Optional grouping of the bar into felt beats, as positive integers. The\n * entries are group lengths, written either in the meter's main pulses —\n * `[2, 2, 3]` for a 2+2+3 reading of 7/8, `[3, 2]` for 5/8 — or, for a\n * compound numerator, in denominator units. They must sum to\n * {@link pulsesPerBar} in the first spelling and to the numerator in the\n * second; a pulse is one unit outside compound meters, where the two\n * spellings coincide.\n *\n * A compound numerator accepts both readings, and the shape of the grouping\n * says which is meant. Groups of nothing but threes spell the compound\n * division itself, so 9/8 as `[3, 3, 3]` (equivalently `[1, 1, 1]`) is the\n * ordinary three dotted-quarter pulses; any other grouping summing to the\n * numerator reads additively, so 9/8 as `[2, 2, 2, 3]` is nine quaver pulses\n * grouped aksak-fashion. {@link pulsesPerBar}, {@link pulseBeats} and\n * {@link isCompound} follow whichever reading the grouping selects.\n *\n * The head pulse of each group other than the downbeat is a secondary strong\n * pulse to {@link metricWeight}/{@link isStrongBeat}. A grouping whose groups\n * are all the same length states no accent the meter does not already have,\n * so it weighs exactly as an ungrouped bar does.\n */\n grouping?: number[];\n};\n\n/**\n * One time signature and the beat at which it takes effect.\n *\n * @category Rhythm & Meter\n */\nexport type MeterChange = {\n /** Absolute quarter-note beat the signature takes effect at. */\n startBeat: number;\n /** The signature in force from that beat until the next change. */\n ts: TimeSignature;\n};\n\n/**\n * A piece's meter over time: the signatures in force, in beat order.\n *\n * A meter change starts a new bar, so a span that does not divide evenly into\n * its own bars ends with a short bar rather than spilling across the change.\n * The first entry also governs everything before it, which is what reads a\n * pickup written at negative beats in the signature the piece opens in.\n *\n * @category Rhythm & Meter\n */\nexport type MeterMap = MeterChange[];\n\nexport type { MeterData } from './internal.js';\n\n/**\n * Anything that names a meter: a signature text such as `'6/8'`, a plain\n * {@link TimeSignature}, a full {@link MeterMap}, or a value that serializes to\n * one of those such as the `Meter` class.\n *\n * Every meter-aware function takes this, so a piece in one meter reads as\n * `'4/4'` and a piece that changes meter reads as the map, without the caller\n * choosing a different function for each. Only a signature has a text form — a\n * meter map is a run of changes and is given as the data it is.\n *\n * @category Rhythm & Meter\n */\nexport type MeterLike =\n | string\n | TimeSignature\n | MeterMap\n | {\n /** The meter data this value stands for. */\n toJSON(): TimeSignature | MeterMap;\n };\n\n/**\n * Resolve any meter-shaped value to the plain meter data the library reads.\n *\n * The counterpart of {@link toNoteData} for meters: an entry point takes\n * whatever form the caller has — the signature a meter field holds, the data\n * the meter module returns, the map of a piece that changes meter, or a `Meter`\n * instance — and gets one of two shapes back. An instance is accepted through\n * its `toJSON` method rather than by its type, so the core layer can read a\n * class it cannot import.\n *\n * Text is read by {@link parseTimeSignature} and nothing else, so every entry\n * point that takes a meter accepts exactly the signatures that parser accepts,\n * the additive `'2+2+3/8'` included and nothing besides. A meter map has no text\n * form — it is a run of changes, each with the beat it starts at — so text\n * always names a single signature.\n *\n * @param value A signature text, a plain time signature, a meter map, or a\n * value whose `toJSON` returns one of those.\n * @param name What the meter is called in an error message, so a caller that\n * holds several of them hears which one was malformed.\n * @returns The validated signature, or the validated map.\n * @throws If the value names no meter, or the meter it names is malformed.\n */\nexport function toMeterData(value: MeterLike, name = 'meter'): MeterData {\n if (typeof value === 'string') {\n return parseTimeSignature(value);\n }\n if (typeof value === 'object' && value !== null) {\n const data =\n !Array.isArray(value) && 'toJSON' in value && typeof value.toJSON === 'function'\n ? value.toJSON()\n : (value as MeterData);\n return isMeterMap(data) ? assertMeterMap(data, name) : assertTimeSignature(data, name);\n }\n throw new InvalidInputError(\n `${name} must be a time signature, a meter map, or a signature name; received ${typeof value}`,\n );\n}\n\n/**\n * A position expressed as a bar index and a quarter-note offset within the bar.\n *\n * @category Rhythm & Meter\n */\nexport type BarPosition = {\n /**\n * 0-based bar index, counting the first full bar as 0.\n * {@link formatBarPosition} renders it 1-based. A pickup sounds before that\n * bar, so its notes report bar -1.\n */\n bar: number;\n /**\n * Quarter-note offset from the start of the bar — not the felt beat. In 6/8\n * the second felt beat is at `beat: 1.5`; {@link barPositionToPulse} converts\n * to felt-beat numbering.\n */\n beat: number;\n};\n\nconst EPS = 1e-9;\n\n/** The meter assumed when a caller names none. */\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\n\n/** Whether `value` is an integer multiple of `unit` (within a float tolerance). */\nfunction isMultiple(value: number, unit: number): boolean {\n if (unit === 0) {\n return false;\n }\n const ratio = value / unit;\n return Math.abs(ratio - Math.round(ratio)) < EPS;\n}\n\n/**\n * Parse a time signature such as `\"4/4\"` or `\"6/8\"`, or the additive `\"2+2+3/8\"`.\n *\n * @param text The signature text.\n * @returns The parsed time signature.\n * @throws If the text is not `n/d` with positive integers, or names a signature\n * the library rejects. Use {@link tryParseTimeSignature} where failure is\n * ordinary, such as a meter field read on every keystroke.\n * @example\n * ```ts\n * import { parseTimeSignature } from '@libraz/libcantus';\n * parseTimeSignature('6/8'); // { numerator: 6, denominator: 8 }\n * ```\n * @category Rhythm & Meter\n */\nexport function parseTimeSignature(text: string): TimeSignature {\n return unwrapParse(tryParseTimeSignature(text));\n}\n\n/**\n * Parse a time signature, reporting failure instead of throwing it.\n *\n * The same reading as {@link parseTimeSignature} — that function is this one\n * with its error thrown — for the callers where text that does not parse yet is\n * the normal state of the input rather than a fault.\n *\n * @param text The signature text.\n * @returns The signature, or the error explaining why the text is not one.\n * @example\n * ```ts\n * import { tryParseTimeSignature } from '@libraz/libcantus';\n * const result = tryParseTimeSignature('7/8');\n * result.ok ? result.value.numerator : result.error.message;\n * ```\n * @category Rhythm & Meter\n */\nexport function tryParseTimeSignature(text: string): ParseResult<TimeSignature> {\n try {\n if (typeof text !== 'string') {\n throw new InvalidInputError(`time signature must be a string; received ${typeof text}`);\n }\n return { ok: true, value: readTimeSignature(text) };\n } catch (error) {\n return parseFailure(error);\n }\n}\n\n/** The reading both parsers share, throwing on anything it cannot read. */\nfunction readTimeSignature(text: string): TimeSignature {\n const match = /^\\s*((?:\\d+\\s*\\+\\s*)*\\d+)\\s*\\/\\s*(\\d+)\\s*$/.exec(text);\n if (!match) {\n throw new InvalidInputError(`Invalid time signature: ${text}`);\n }\n const groupTokens = (match[1] ?? '').split('+').map((token) => Number.parseInt(token.trim(), 10));\n const numerator = groupTokens.reduce((sum, value) => sum + value, 0);\n const denominator = Number.parseInt(match[2] ?? '', 10);\n if (\n !Number.isSafeInteger(numerator) ||\n !Number.isSafeInteger(denominator) ||\n numerator <= 0 ||\n denominator <= 0\n ) {\n throw new InvalidInputError(`Invalid time signature: ${text}`);\n }\n // The same signature every consumer validates, validated here too: parsing\n // a signature the rest of the library rejects only moves the failure.\n const grouping = groupTokens.length > 1 ? groupTokens : undefined;\n return assertTimeSignature({ numerator, denominator, grouping }, `time signature ${text}`);\n}\n\n/**\n * Render a time signature as `\"n/d\"`, or as `\"a+b+c/d\"` when it carries an\n * additive grouping and `grouping` is requested.\n *\n * The additive form is what {@link parseTimeSignature} reads back, and it adds\n * its terms to get the numerator — so only a grouping written in denominator\n * units can be rendered that way. A grouping counted in main pulses (9/8 as\n * `[1, 1, 1]`, 12/8 as `[2, 2]`) would come back as a different bar, so it\n * falls back to the plain form, which those groupings cost nothing: they select\n * the same reading the bare signature does.\n *\n * The plain form drops the grouping, so a round trip through it reads 7/8 as\n * flat rather than as 2+2+3; ask for the additive form to keep it.\n *\n * @param ts The time signature.\n * @param opts Set `grouping: true` to render an additive grouping.\n * @returns The formatted signature.\n * @example\n * ```ts\n * import { formatTimeSignature } from '@libraz/libcantus';\n * const aksak = { numerator: 7, denominator: 8, grouping: [2, 2, 3] };\n * formatTimeSignature(aksak); // '7/8'\n * formatTimeSignature(aksak, { grouping: true }); // '2+2+3/8'\n * ```\n * @category Rhythm & Meter\n */\nexport function formatTimeSignature(ts: TimeSignature, opts: { grouping?: boolean } = {}): string {\n assertTimeSignature(ts);\n if (opts.grouping === true && ts.grouping !== undefined && groupingSumOf(ts) === ts.numerator) {\n return `${ts.grouping.join('+')}/${ts.denominator}`;\n }\n return `${ts.numerator}/${ts.denominator}`;\n}\n\n/**\n * Whether a meter is compound: its main pulses each divide into three, as in\n * 6/8, 9/8, 12/8, or 6/4. Compound meters are those whose numerator is a\n * multiple of three greater than three, independent of the denominator. Meters\n * like 3/8 and 3/4 (simple triples, numerator 3) are not compound, and neither\n * is a signature whose {@link TimeSignature.grouping} selects the additive\n * reading (9/8 as 2+2+2+3).\n *\n * @param ts The time signature.\n * @returns True for compound meters.\n * @category Rhythm & Meter\n */\nexport function isCompound(ts: TimeSignature): boolean {\n assertTimeSignature(ts);\n return isCompoundNumerator(ts.numerator) && !isAdditiveReading(ts);\n}\n\n/**\n * Length of a bar in quarter-note beats.\n *\n * @param ts The time signature.\n * @returns The bar length in quarter notes.\n * @category Rhythm & Meter\n */\nexport function beatsPerBar(ts: TimeSignature): number {\n assertTimeSignature(ts);\n return barBeatsOf(ts);\n}\n\n/**\n * The time signature in force at a beat.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @returns The signature governing that beat.\n * @example\n * ```ts\n * import { meterAt, parseTimeSignature } from '@libraz/libcantus';\n * const meters = [\n * { startBeat: 0, ts: parseTimeSignature('4/4') },\n * { startBeat: 8, ts: parseTimeSignature('3/4') },\n * ];\n * meterAt(9, meters); // { numerator: 3, denominator: 4 }\n * ```\n * @category Rhythm & Meter\n */\nexport function meterAt(beatInQuarters: number, meter: MeterLike): TimeSignature {\n assertFiniteNumber(beatInQuarters, 'beat');\n return meterAtChecked(beatInQuarters, toMeterData(meter));\n}\n\n/** {@link meterAt} without re-reading an already resolved meter. */\nfunction meterAtChecked(beatInQuarters: number, meter: MeterData): TimeSignature {\n if (!isMeterMap(meter)) {\n return meter;\n }\n return meter[entryIndexOf(meter, beatInQuarters)]?.ts ?? DEFAULT_TS;\n}\n\n/**\n * Absolute beat at which the bar containing `beatInQuarters` begins.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @returns The bar's first beat, negative inside a pickup.\n * @category Rhythm & Meter\n */\nexport function barStartBeat(beatInQuarters: number, meter: MeterLike): number {\n assertFiniteNumber(beatInQuarters, 'beat');\n return barStartChecked(beatInQuarters, toMeterData(meter));\n}\n\n/** {@link barStartBeat} without re-reading an already resolved meter. */\nfunction barStartChecked(beatInQuarters: number, meter: MeterData): number {\n if (isMeterMap(meter)) {\n return barStartOf(meter, beatInQuarters);\n }\n const barLen = barBeatsOf(meter);\n return Math.floor(beatInQuarters / barLen + EPS) * barLen;\n}\n\n/**\n * Bar index of a beat: 0 for the first full bar, negative inside a pickup.\n *\n * Bars accumulate across meter changes, so the bar after a 4/4-to-3/4 change is\n * the next bar and not the first bar of a new count.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @returns The 0-based bar index.\n * @example\n * ```ts\n * import { barIndexAt, parseTimeSignature } from '@libraz/libcantus';\n * const meters = [\n * { startBeat: 0, ts: parseTimeSignature('4/4') },\n * { startBeat: 8, ts: parseTimeSignature('3/4') },\n * ];\n * barIndexAt(11, meters); // 3\n * ```\n * @category Rhythm & Meter\n */\nexport function barIndexAt(beatInQuarters: number, meter: MeterLike): number {\n assertFiniteNumber(beatInQuarters, 'beat');\n return barIndexChecked(beatInQuarters, toMeterData(meter));\n}\n\n/** {@link barIndexAt} without re-reading an already resolved meter. */\nfunction barIndexChecked(beatInQuarters: number, meter: MeterData): number {\n if (isMeterMap(meter)) {\n return barIndexOf(meter, beatInQuarters);\n }\n return Math.floor(beatInQuarters / barBeatsOf(meter) + EPS);\n}\n\n/**\n * Length in quarter-note beats of the bar containing a beat.\n *\n * The meter-map counterpart of {@link beatsPerBar}, which answers for one\n * signature and so cannot be asked about a piece that changes meter.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @returns The bar length in quarter notes.\n * @category Rhythm & Meter\n */\nexport function beatsPerBarAt(beatInQuarters: number, meter: MeterLike): number {\n return barBeatsOf(meterAt(beatInQuarters, meter));\n}\n\n/**\n * Read the meter out of a pair of options that accept either form.\n *\n * Entry points take `meters` for a piece that changes meter and keep `ts` as\n * sugar for a piece that does not, so this is the one place that resolves the\n * pair — including the rule that naming both is an input error rather than one\n * of them silently winning.\n *\n * @param opts The options carrying `ts`, `meters`, or neither.\n * @param name What the options belong to, for the error message.\n * @returns The meter map to analyse against; 4/4 throughout when neither is given.\n * @throws If both `ts` and `meters` are given, or the map is malformed.\n * @example\n * ```ts\n * import { parseTimeSignature, resolveMeters } from '@libraz/libcantus';\n * resolveMeters({ ts: parseTimeSignature('3/4') });\n * // [{ startBeat: 0, ts: { numerator: 3, denominator: 4 } }]\n * ```\n * @category Rhythm & Meter\n */\nexport function resolveMeters(\n opts: { ts?: TimeSignature; meters?: MeterMap },\n name = 'meters',\n): MeterMap {\n if (opts.ts !== undefined && opts.meters !== undefined) {\n throw new InvalidInputError(\n `${name} and ts name the same thing; give one or the other, not both`,\n );\n }\n if (opts.meters !== undefined) {\n return assertMeterMap(opts.meters, name);\n }\n const ts = opts.ts ?? DEFAULT_TS;\n assertTimeSignature(ts);\n return [{ startBeat: 0, ts }];\n}\n\n/**\n * Number of main pulses (felt beats) per bar: the numerator for simple meters,\n * a third of it for compound meters.\n *\n * For additive/irregular meters such as 7/8 or 5/8 this counts the raw pulses\n * (7 and 5 respectively), which are otherwise felt as flat, evenly divided and\n * equally accented pulses. To recover a 2+2+3 or 3+2 felt-beat grouping, set\n * {@link TimeSignature.grouping}; {@link metricWeight} then accents each\n * group's head pulse.\n *\n * @param ts The time signature.\n * @returns The pulse count per bar.\n * @category Rhythm & Meter\n */\nexport function pulsesPerBar(ts: TimeSignature): number {\n assertTimeSignature(ts);\n return pulseCountOf(ts);\n}\n\n/** Whether `pulseIndex` is the head pulse of one of the groups, counted in pulses. */\nfunction isGroupHead(grouping: number[], pulseIndex: number): boolean {\n let acc = 0;\n for (const g of grouping) {\n if (acc === pulseIndex) {\n return true;\n }\n acc += g;\n }\n return false;\n}\n\n/**\n * Whether every group is the same length.\n *\n * Such a grouping divides the bar the way its own meter already divides it, so\n * it names no accent structure: 9/8 as `[1, 1, 1]` is the plain compound bar,\n * not three pulses of equal strength.\n */\nfunction isUniformGrouping(grouping: number[]): boolean {\n return grouping.every((entry) => entry === grouping[0]);\n}\n\n/**\n * Convert an absolute quarter-note position to a bar index and in-bar offset.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @returns The bar and in-bar quarter-note offset.\n * @example\n * ```ts\n * import { parseTimeSignature, beatToBarPosition } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * beatToBarPosition(5, ts); // { bar: 1, beat: 1 }\n * ```\n * @category Rhythm & Meter\n */\nexport function beatToBarPosition(beatInQuarters: number, meter: MeterLike): BarPosition {\n assertFiniteNumber(beatInQuarters, 'beat');\n return barPositionChecked(beatInQuarters, toMeterData(meter));\n}\n\n/** {@link beatToBarPosition} without re-reading an already resolved meter. */\nfunction barPositionChecked(beatInQuarters: number, meter: MeterData): BarPosition {\n return {\n bar: barIndexChecked(beatInQuarters, meter),\n beat: beatInQuarters - barStartChecked(beatInQuarters, meter),\n };\n}\n\n/**\n * Length of one felt beat (main pulse) in quarter-note beats.\n *\n * A quarter note in simple meters, a dotted quarter in compound ones, and one\n * denominator unit in an additive metre. Position displays, click tracks, and\n * score export are all written against this length.\n *\n * @param ts The time signature.\n * @returns The pulse length in quarter-note beats.\n * @example\n * ```ts\n * import { parseTimeSignature, pulseBeats } from '@libraz/libcantus';\n * pulseBeats(parseTimeSignature('6/8')); // 1.5\n * ```\n * @category Rhythm & Meter\n */\nexport function pulseBeats(ts: TimeSignature): number {\n assertTimeSignature(ts);\n return pulseBeatsOf(ts);\n}\n\n/**\n * The felt-beat number of a bar position, 1-based.\n *\n * {@link BarPosition.beat} is a quarter-note offset, so in 6/8 the second felt\n * beat reads as 1.5. This is the number a musician says and a position display\n * shows.\n *\n * @param pos The bar position.\n * @param meter A single signature, or the piece's meter map.\n * @returns The 1-based felt-beat number, fractional between pulses.\n * @example\n * ```ts\n * import { barPositionToPulse, parseTimeSignature } from '@libraz/libcantus';\n * barPositionToPulse({ bar: 0, beat: 1.5 }, parseTimeSignature('6/8')); // 2\n * ```\n * @category Rhythm & Meter\n */\nexport function barPositionToPulse(pos: BarPosition, meter: MeterLike): number {\n assertFiniteNumber(pos.beat, 'position.beat');\n return pulseChecked(pos, toMeterData(meter));\n}\n\n/** {@link barPositionToPulse} without re-reading an already resolved meter. */\nfunction pulseChecked(pos: BarPosition, meter: MeterData): number {\n return pos.beat / pulseBeatsOf(meterAtBarChecked(pos.bar, meter)) + 1;\n}\n\n/** The signature governing a bar index, on an already resolved meter. */\nfunction meterAtBarChecked(bar: number, meter: MeterData): TimeSignature {\n if (!isMeterMap(meter)) {\n return meter;\n }\n assertFiniteNumber(bar, 'position.bar');\n return meterAtChecked(beatOfBarIndex(meter, bar), meter);\n}\n\n/**\n * Render an absolute position as the `bar.beat` a DAW or a score shows:\n * 1-based bar, 1-based felt beat.\n *\n * The felt beats counted are the ones the bar actually has. A meter change\n * starts a new bar, so the bar it interrupts is short, and a position that\n * rounds past the end of a short bar reads as the downbeat of the next one\n * rather than as a beat the bar never reached.\n *\n * @param beatInQuarters Absolute position in quarter-note beats.\n * @param meter A single signature, or the piece's meter map.\n * @param decimals Digits of the fractional beat to keep.\n * @returns The formatted position, e.g. `'3.2'` for bar 3, felt beat 2.\n * @example\n * ```ts\n * import { formatBarPosition, parseTimeSignature } from '@libraz/libcantus';\n * formatBarPosition(7.5, parseTimeSignature('6/8')); // '3.2'\n * ```\n * @category Rhythm & Meter\n */\nexport function formatBarPosition(beatInQuarters: number, meter: MeterLike, decimals = 2): string {\n assertInteger(decimals, 'decimals', 0, 100);\n assertFiniteNumber(beatInQuarters, 'beat');\n const resolved = toMeterData(meter);\n const position = barPositionChecked(beatInQuarters, resolved);\n const ts = meterAtChecked(beatInQuarters, resolved);\n const pulse = pulseChecked(position, ts);\n const rounded = Number(pulse.toFixed(decimals));\n const barLength = isMeterMap(resolved)\n ? barLengthOf(resolved, beatInQuarters)\n : barBeatsOf(resolved);\n // A short bar has a whole final pulse only in the sense that the pulse it\n // started is cut off, so the count rounds up: 2 beats of 4/4 hold felt beats\n // 1 and 2, and anything past those belongs to the next bar.\n const pulsesInBar = Math.ceil(barLength / pulseBeatsOf(ts) - EPS);\n if (rounded >= pulsesInBar + 1) {\n return `${barIndexChecked(barStartChecked(beatInQuarters, resolved) + barLength, resolved) + 1}.1`;\n }\n const wholePulse = Math.floor(rounded);\n const fraction = Number((rounded - wholePulse).toFixed(decimals));\n return fraction === 0\n ? `${position.bar + 1}.${wholePulse}`\n : `${position.bar + 1}.${wholePulse}+${fraction}`;\n}\n\n/**\n * Convert a bar index and in-bar offset back to an absolute quarter-note\n * position.\n *\n * @param pos The bar position.\n * @param meter A single signature, or the piece's meter map.\n * @returns The absolute position in quarter-note beats.\n * @category Rhythm & Meter\n */\nexport function barPositionToBeat(pos: BarPosition, meter: MeterLike): number {\n assertInteger(pos.bar, 'bar position bar');\n assertFiniteNumber(pos.beat, 'bar position beat');\n const resolved = toMeterData(meter);\n if (isMeterMap(resolved)) {\n return beatOfBarIndex(resolved, pos.bar) + pos.beat;\n }\n return pos.bar * barBeatsOf(resolved) + pos.beat;\n}\n\n/**\n * Metric weight of a position within its bar, on a 0–3 scale:\n * 3 the downbeat, 2 a secondary strong pulse, 1 any other main pulse, and 0 an\n * off-pulse subdivision.\n *\n * The secondary strong pulse is the bar's midpoint in even simple/compound\n * meters. For an additive/irregular meter with {@link TimeSignature.grouping}\n * set (e.g. `[2, 2, 3]` for 7/8), each group's head pulse other than the\n * downbeat is the secondary strong pulse instead; without a grouping every\n * non-downbeat main pulse of such a meter weighs 1 (flat, evenly divided\n * pulses). A grouping of equal-length groups (9/8 as `[1, 1, 1]`, 4/4 as\n * `[1, 1, 1, 1]`) states the division the meter already has, so it weighs as\n * an ungrouped bar rather than accenting every group head.\n *\n * Given a meter map, the weight follows the signature in force at that beat, so\n * beat 5 of a piece is a mid-bar accent in 4/4 and a plain main pulse in 3/4.\n * The downbeat is beat 0 however much pickup precedes it, so a note in the\n * pickup weighs as the upbeat it is rather than as a downbeat.\n *\n * @param beatInQuarters Absolute quarter-note position, or an in-bar offset\n * when the meter is a single signature.\n * @param meter A single signature, or the piece's meter map.\n * @returns The metric weight (0–3).\n * @throws If the meter is malformed, including a grouping that is not a\n * positive-integer list summing to the pulse count or the numerator.\n * @example\n * ```ts\n * import { parseTimeSignature, metricWeight } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * metricWeight(0, ts); // 3 (the downbeat)\n * ```\n * @category Rhythm & Meter\n */\nexport function metricWeight(beatInQuarters: number, meter: MeterLike): number {\n assertFiniteNumber(beatInQuarters, 'beat');\n const resolved = toMeterData(meter);\n const ts = meterAtChecked(beatInQuarters, resolved);\n const beat = beatInQuarters - barStartChecked(beatInQuarters, resolved);\n const pulse = pulseBeatsOf(ts);\n if (!isMultiple(beat, pulse)) {\n return 0;\n }\n const pulses = pulseCountOf(ts);\n const pulseIndex = Math.round(beat / pulse) % pulses;\n if (pulseIndex === 0) {\n return 3;\n }\n const grouping = pulseGroupingOf(ts);\n if (grouping !== undefined && !isUniformGrouping(grouping)) {\n return isGroupHead(grouping, pulseIndex) ? 2 : 1;\n }\n if (pulses % 2 === 0 && pulseIndex === pulses / 2) {\n return 2;\n }\n return 1;\n}\n\n/**\n * Whether a position is metrically accented (weight 2 or more — a downbeat or a\n * secondary strong pulse).\n *\n * @param beatInQuarters Absolute quarter-note position, or an in-bar offset\n * when the meter is a single signature.\n * @param meter A single signature, or the piece's meter map.\n * @returns True on strong beats.\n * @category Rhythm & Meter\n */\nexport function isStrongBeat(beatInQuarters: number, meter: MeterLike): boolean {\n return metricWeight(beatInQuarters, meter) >= 2;\n}\n\n/**\n * Subdivide a span into `count` equal tuplet durations (e.g. an eighth-note\n * triplet is `tuplet(1, 3)`).\n *\n * @param totalBeats Total span in quarter-note beats.\n * @param count Number of equal parts.\n * @returns `count` equal durations summing to `totalBeats`.\n * @throws If `count` is not a positive integer.\n * @category Rhythm & Meter\n */\nexport function tuplet(totalBeats: number, count: number): number[] {\n assertRange(totalBeats, 0, Number.MAX_SAFE_INTEGER, 'tuplet total beats');\n assertPositiveInt(count, 'tuplet count');\n return new Array<number>(count).fill(totalBeats / count);\n}\n"],"mappings":"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","names":["EPS"]}