@libraz/libcantus 0.9.1 → 0.9.2

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 (154) hide show
  1. package/README.md +15 -0
  2. package/dist/analyze/index.cjs +1697 -0
  3. package/dist/analyze/index.cjs.map +1 -0
  4. package/dist/analyze/index.d.cts +429 -0
  5. package/dist/analyze/index.d.ts +429 -0
  6. package/dist/analyze/index.js +51 -0
  7. package/dist/analyze/index.js.map +1 -0
  8. package/dist/chunk-5HTNMQW4.js +653 -0
  9. package/dist/chunk-5HTNMQW4.js.map +1 -0
  10. package/dist/chunk-7Y7WF64D.js +410 -0
  11. package/dist/chunk-7Y7WF64D.js.map +1 -0
  12. package/dist/chunk-A4532ZFR.js +259 -0
  13. package/dist/chunk-A4532ZFR.js.map +1 -0
  14. package/dist/chunk-BHUT2S5G.js +22 -0
  15. package/dist/chunk-BHUT2S5G.js.map +1 -0
  16. package/dist/chunk-CCBLVAPK.js +42 -0
  17. package/dist/chunk-CCBLVAPK.js.map +1 -0
  18. package/dist/chunk-COKTX2G5.js +907 -0
  19. package/dist/chunk-COKTX2G5.js.map +1 -0
  20. package/dist/chunk-DYWFNC4A.js +152 -0
  21. package/dist/chunk-DYWFNC4A.js.map +1 -0
  22. package/dist/chunk-GQKN5KDT.js +159 -0
  23. package/dist/chunk-GQKN5KDT.js.map +1 -0
  24. package/dist/chunk-LN7ZZMD2.js +530 -0
  25. package/dist/chunk-LN7ZZMD2.js.map +1 -0
  26. package/dist/chunk-MSWFZF7J.js +118 -0
  27. package/dist/chunk-MSWFZF7J.js.map +1 -0
  28. package/dist/chunk-R3S2LUBH.js +2722 -0
  29. package/dist/chunk-R3S2LUBH.js.map +1 -0
  30. package/dist/chunk-SDM3VJJ5.js +41 -0
  31. package/dist/chunk-SDM3VJJ5.js.map +1 -0
  32. package/dist/chunk-XTC3X6MS.js +816 -0
  33. package/dist/chunk-XTC3X6MS.js.map +1 -0
  34. package/dist/chunk-ZXW5YIWK.js +55 -0
  35. package/dist/chunk-ZXW5YIWK.js.map +1 -0
  36. package/dist/core/index.cjs +432 -0
  37. package/dist/core/index.cjs.map +1 -0
  38. package/dist/core/index.d.cts +210 -0
  39. package/dist/core/index.d.ts +210 -0
  40. package/dist/core/index.js +73 -0
  41. package/dist/core/index.js.map +1 -0
  42. package/dist/function-2bJW1Zp_.d.ts +187 -0
  43. package/dist/function-r2sh-jOO.d.cts +187 -0
  44. package/dist/generate/index.cjs +3787 -0
  45. package/dist/generate/index.cjs.map +1 -0
  46. package/dist/generate/index.d.cts +980 -0
  47. package/dist/generate/index.d.ts +980 -0
  48. package/dist/generate/index.js +52 -0
  49. package/dist/generate/index.js.map +1 -0
  50. package/dist/index-BMPxwjwV.d.ts +151 -0
  51. package/dist/index-BOBXBNwP.d.cts +157 -0
  52. package/dist/index-BdeQ1r_p.d.cts +56 -0
  53. package/dist/index-BreoJRw0.d.ts +127 -0
  54. package/dist/index-CGMZNCx6.d.cts +140 -0
  55. package/dist/index-CGMZNCx6.d.ts +140 -0
  56. package/dist/index-CM5W4rcm.d.ts +157 -0
  57. package/dist/index-CP3wAfEH.d.ts +56 -0
  58. package/dist/index-Cl7mhOFM.d.cts +164 -0
  59. package/dist/index-Cl7mhOFM.d.ts +164 -0
  60. package/dist/index-DZ1M21do.d.cts +127 -0
  61. package/dist/index-D_ZTUNKp.d.cts +151 -0
  62. package/dist/index.cjs +3016 -2984
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +14 -3982
  65. package/dist/index.d.ts +14 -3982
  66. package/dist/index.js +170 -6504
  67. package/dist/index.js.map +1 -1
  68. package/dist/model/index.cjs +2435 -0
  69. package/dist/model/index.cjs.map +1 -0
  70. package/dist/model/index.d.cts +630 -0
  71. package/dist/model/index.d.ts +630 -0
  72. package/dist/model/index.js +21 -0
  73. package/dist/model/index.js.map +1 -0
  74. package/dist/styled-BjXtOFNk.d.cts +282 -0
  75. package/dist/styled-D7BAx3S3.d.ts +282 -0
  76. package/dist/theory/index.cjs +1677 -0
  77. package/dist/theory/index.cjs.map +1 -0
  78. package/dist/theory/index.d.cts +535 -0
  79. package/dist/theory/index.d.ts +535 -0
  80. package/dist/theory/index.js +149 -0
  81. package/dist/theory/index.js.map +1 -0
  82. package/dist/types-MGP29r3t.d.cts +30 -0
  83. package/dist/types-MGP29r3t.d.ts +30 -0
  84. package/package.json +27 -2
  85. package/src/analyze/arrange/index.ts +21 -0
  86. package/src/analyze/arrange/internal.ts +125 -0
  87. package/src/analyze/arrange/tension.ts +187 -0
  88. package/src/analyze/arrange/tracks.ts +279 -0
  89. package/src/{detect → analyze/detect}/index.ts +4 -4
  90. package/src/analyze/functional/borrowed.ts +84 -0
  91. package/src/analyze/functional/cadence.ts +66 -0
  92. package/src/analyze/functional/function.ts +184 -0
  93. package/src/analyze/functional/index.ts +23 -0
  94. package/src/analyze/functional/internal.ts +29 -0
  95. package/src/{functional/index.ts → analyze/functional/roman.ts} +9 -327
  96. package/src/analyze/index.ts +49 -0
  97. package/src/{timeline → analyze/timeline}/index.ts +7 -11
  98. package/src/{analysis → analyze/voice}/index.ts +8 -5
  99. package/src/core/index.ts +47 -0
  100. package/src/{bass → generate/bass}/index.ts +5 -5
  101. package/src/{countermelody → generate/countermelody}/index.ts +11 -11
  102. package/src/{drums → generate/drums}/index.ts +2 -2
  103. package/src/{drums → generate/drums}/rng.ts +2 -2
  104. package/src/{groove → generate/groove}/index.ts +3 -3
  105. package/src/{harmonize → generate/harmonize}/index.ts +13 -13
  106. package/src/generate/index.ts +59 -0
  107. package/src/{motif → generate/motif}/index.ts +7 -7
  108. package/src/{progression → generate/progression}/index.ts +11 -25
  109. package/src/{reharmony → generate/reharmony}/index.ts +11 -11
  110. package/src/{rhythm → generate/rhythm}/index.ts +2 -2
  111. package/src/index.ts +130 -117
  112. package/src/model/chord.ts +423 -0
  113. package/src/model/index.ts +5 -1096
  114. package/src/model/interval.ts +82 -0
  115. package/src/model/key.ts +266 -0
  116. package/src/model/note.ts +176 -0
  117. package/src/model/progression.ts +161 -0
  118. package/src/model/shared.ts +12 -0
  119. package/src/{chord → theory/chord}/index.ts +19 -1
  120. package/src/{counterpoint → theory/counterpoint}/index.ts +2 -2
  121. package/src/theory/index.ts +107 -0
  122. package/src/{safety → theory/safety}/index.ts +1 -1
  123. package/src/theory/scale/degrees.ts +123 -0
  124. package/src/theory/scale/index.ts +28 -0
  125. package/src/theory/scale/key.ts +56 -0
  126. package/src/theory/scale/masks.ts +153 -0
  127. package/src/{spelling → theory/spelling}/index.ts +3 -3
  128. package/src/{symbol → theory/symbol}/index.ts +8 -1
  129. package/src/theory/voicing/index.ts +5 -0
  130. package/src/theory/voicing/internal.ts +168 -0
  131. package/src/theory/voicing/leading.ts +112 -0
  132. package/src/theory/voicing/satb.ts +195 -0
  133. package/src/theory/voicing/styled.ts +176 -0
  134. package/src/arrange/index.ts +0 -571
  135. package/src/scale/index.ts +0 -331
  136. package/src/voicing/index.ts +0 -623
  137. /package/src/{interval → core/interval}/index.ts +0 -0
  138. /package/src/{meter → core/meter}/index.ts +0 -0
  139. /package/src/{pitch → core/pitch}/index.ts +0 -0
  140. /package/src/{random → core/random}/index.ts +0 -0
  141. /package/src/{tuning → core/tuning}/index.ts +0 -0
  142. /package/src/{types.ts → core/types.ts} +0 -0
  143. /package/src/{drums → generate/drums}/beat.ts +0 -0
  144. /package/src/{drums → generate/drums}/euclid.ts +0 -0
  145. /package/src/{drums → generate/drums}/fills.ts +0 -0
  146. /package/src/{drums → generate/drums}/ghost.ts +0 -0
  147. /package/src/{drums → generate/drums}/hihat.ts +0 -0
  148. /package/src/{drums → generate/drums}/hit.ts +0 -0
  149. /package/src/{drums → generate/drums}/internal.ts +0 -0
  150. /package/src/{drums → generate/drums}/kick.ts +0 -0
  151. /package/src/{drums → generate/drums}/percussion.ts +0 -0
  152. /package/src/{drums → generate/drums}/swing.ts +0 -0
  153. /package/src/{chordscale → theory/chordscale}/index.ts +0 -0
  154. /package/src/{harmony → theory/harmony}/index.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/scale/index.ts","../src/chord/index.ts","../src/interval/index.ts","../src/counterpoint/index.ts","../src/analysis/index.ts","../src/functional/index.ts","../src/meter/index.ts","../src/safety/index.ts","../src/detect/index.ts","../src/timeline/index.ts","../src/arrange/index.ts","../src/random/index.ts","../src/bass/index.ts","../src/chordscale/index.ts","../src/countermelody/index.ts","../src/drums/internal.ts","../src/drums/ghost.ts","../src/drums/hihat.ts","../src/drums/swing.ts","../src/drums/beat.ts","../src/drums/euclid.ts","../src/drums/fills.ts","../src/drums/hit.ts","../src/drums/kick.ts","../src/drums/percussion.ts","../src/drums/index.ts","../src/groove/index.ts","../src/harmony/index.ts","../src/harmonize/index.ts","../src/pitch/index.ts","../src/reharmony/index.ts","../src/spelling/index.ts","../src/symbol/index.ts","../src/voicing/index.ts","../src/model/index.ts","../src/motif/index.ts","../src/progression/index.ts","../src/rhythm/index.ts","../src/tuning/index.ts"],"sourcesContent":["export type { AnalyzedNote, TheoryLabel, VoiceNote } from './analysis/index.js';\nexport { analyzeVoice } from './analysis/index.js';\nexport type {\n ArrangementAnalysis,\n ArrangementOptions,\n ArrangementTrack,\n Conflict,\n TensionPoint,\n TrackAnalysis,\n TrackRole,\n} from './arrange/index.js';\nexport { analyzeArrangement, tensionCurve } from './arrange/index.js';\nexport type { BassLineOptions, BassSegment, BassStyle } from './bass/index.js';\nexport { generateBassLine } from './bass/index.js';\nexport type { Chord as ChordData, ChordQuality } from './chord/index.js';\nexport {\n chordFromDegree,\n chordPitchClasses,\n chordQualities,\n chordToneRole,\n diatonicSeventh,\n diatonicTriad,\n makeChord,\n} from './chord/index.js';\nexport type { ChordScaleMatch, ChordScaleReportEntry, ScaleChoice } from './chordscale/index.js';\nexport {\n availableTensions,\n avoidNotes,\n chordScaleReport,\n chordScales,\n scaleMatchesChord,\n scalesForChanges,\n} from './chordscale/index.js';\nexport type { CounterMelodyOptions } from './countermelody/index.js';\nexport { generateCounterMelody } from './countermelody/index.js';\nexport {\n createsHiddenParallelPerfect,\n createsParallelOctave,\n createsParallelPerfect,\n createsParallelUnison,\n createsVerticalDissonance,\n createsVoiceCrossing,\n createsVoiceOverlap,\n exceedsSpacing,\n isForbiddenMelodicLeap,\n isLeadingToneResolution,\n} from './counterpoint/index.js';\nexport type { ChordMatch, KeyMatch } from './detect/index.js';\nexport { detectChord, detectChordBest, detectKey } from './detect/index.js';\nexport type {\n DrumGenOptions,\n DrumHit,\n DrumRole,\n EuclideanKick,\n GrooveFeel,\n GrooveStyle,\n Section,\n} from './drums/index.js';\nexport { generateDrums } from './drums/index.js';\nexport type {\n BorrowedSource,\n Cadence,\n ChordAnalysis,\n HarmonicFunction,\n} from './functional/index.js';\nexport {\n analyzeChord,\n borrowedSource,\n chordToRoman,\n detectCadence,\n functionOf,\n isBorrowedChord,\n isDiatonic,\n isMinorKey,\n parallelKey,\n romanToChord,\n secondaryDominant,\n} from './functional/index.js';\nexport type { GrooveSlot, GrooveTemplate, HumanizeOptions } from './groove/index.js';\nexport { applyGrooveTemplate, extractGrooveTemplate, humanize } from './groove/index.js';\nexport type {\n HarmonizeOptions,\n HarmonizeResult,\n MelodyNote,\n} from './harmonize/index.js';\nexport { harmonizeMelody } from './harmonize/index.js';\nexport type { HarmonyRole, LockLevel, VoicedRole } from './harmony/index.js';\nexport { roleOf } from './harmony/index.js';\nexport {\n classifyInterval,\n IntervalQuality,\n isConsonantInterval,\n isPerfectInterval,\n} from './interval/index.js';\nexport type { BarPosition, TimeSignature } from './meter/index.js';\nexport {\n barPositionToBeat,\n beatsPerBar,\n beatToBarPosition,\n formatTimeSignature,\n isCompound,\n isStrongBeat,\n metricWeight,\n parseTimeSignature,\n pulsesPerBar,\n tuplet,\n} from './meter/index.js';\nexport { Chord, Interval, Key, Note, Progression } from './model/index.js';\nexport type {\n GenerateMotifOptions,\n MotifCell,\n MotifContour,\n MotifNote,\n MotifTransform,\n} from './motif/index.js';\nexport { developMotif, generateMotif, transformMotif } from './motif/index.js';\nexport type { Note as NoteData, SpelledInterval } from './pitch/index.js';\nexport {\n formatNote,\n midiToNote,\n noteToMidi,\n noteToPitchClass,\n parseNote,\n spelledInterval,\n} from './pitch/index.js';\nexport type {\n GeneratedChord,\n GenerateProgressionOptions,\n ProgFunction,\n ProgressionPreset,\n ProgStyle,\n} from './progression/index.js';\nexport {\n generateProgression,\n progressions,\n progressionsByStyle,\n} from './progression/index.js';\nexport type { Rng } from './random/index.js';\nexport { createRng } from './random/index.js';\nexport type {\n BorrowedChord,\n SubstituteOptions,\n Substitution,\n SubstitutionType,\n} from './reharmony/index.js';\nexport {\n modalInterchangePalette,\n negativeHarmonyMirror,\n substituteChord,\n} from './reharmony/index.js';\nexport type { RhythmEvent, RhythmOptions } from './rhythm/index.js';\nexport { generateRhythm, onsetWeightCurve, rhythmDensity } from './rhythm/index.js';\nexport type {\n SafetyProfile,\n SafetyQuery,\n SafetyResult,\n VoiceSnapshot,\n} from './safety/index.js';\nexport { enumerateSafePitches, evaluateSafety, NoteSafety, ReasonFlag } from './safety/index.js';\nexport {\n BLUES_MASK,\n CHROMATIC_MASK,\n DORIAN_MASK,\n diatonicPitchClasses,\n HARMONIC_MINOR_MASK,\n isScaleTone,\n LOCRIAN_MASK,\n LYDIAN_MASK,\n MAJOR_MASK,\n MAJOR_PENTATONIC_MASK,\n MELODIC_MINOR_MASK,\n MINOR_PENTATONIC_MASK,\n MIXOLYDIAN_MASK,\n majorKey,\n maskFromOffsets,\n minorKey,\n NAMED_SCALES,\n NATURAL_MINOR_MASK,\n nearestScaleTone,\n OCTATONIC_HALF_WHOLE_MASK,\n OCTATONIC_WHOLE_HALF_MASK,\n PHRYGIAN_MASK,\n pitchToScaleDegree,\n scaleByName,\n scaleTonesInDegreeOrder,\n WHOLE_TONE_MASK,\n} from './scale/index.js';\nexport {\n noteNames,\n spellChord,\n spellPitchClass,\n spellPitchClasses,\n spellScale,\n} from './spelling/index.js';\nexport { formatChordSymbol, parseChordSymbol, transposeChordSymbol } from './symbol/index.js';\nexport type {\n CadenceHit,\n ChordSegment,\n ChordTimeline,\n ChordTimelineOptions,\n ChordTimelineResult,\n} from './timeline/index.js';\nexport {\n chordTimelineFromChords,\n chordTimelineFromNotes,\n detectCadences,\n} from './timeline/index.js';\nexport type { Tuning } from './tuning/index.js';\nexport {\n centsBetweenFreq,\n centsOfSteps,\n edo,\n frequencyOf,\n JUST_RATIOS,\n justDeviationCents,\n nearestStep,\n ratioToCents,\n TWELVE_TET,\n} from './tuning/index.js';\nexport type { KeyScale, NoteEvent } from './types.js';\nexport type {\n StyledVoicingOptions,\n VoiceRange,\n VoicingOptions,\n VoicingStyle,\n} from './voicing/index.js';\nexport {\n nextVoicing,\n SATB_RANGES,\n voiceChord,\n voiceChordStyled,\n voiceLeadingCost,\n voiceProgression,\n} from './voicing/index.js';\n","import type { KeyScale } from '../types.js';\n\n/**\n * Build a 12-bit mode mask from a list of semitone offsets above the root.\n *\n * Bit 0 (the root) is always set, enforcing the `KeyScale` invariant that the\n * root is a scale tone even when the offset list omits 0.\n *\n * @category Scales\n */\nexport function maskFromOffsets(offsets: readonly number[]): number {\n let mask = 1;\n for (const offset of offsets) {\n mask |= 1 << (((offset % 12) + 12) % 12);\n }\n return mask;\n}\n\n/**\n * Mode mask for the major (Ionian) scale: offsets {0, 2, 4, 5, 7, 9, 11}.\n *\n * @category Scales\n */\nexport const MAJOR_MASK = 0b101010110101;\n\n/**\n * Mode mask for the natural minor (Aeolian) scale: offsets {0, 2, 3, 5, 7, 8, 10}.\n *\n * @category Scales\n */\nexport const NATURAL_MINOR_MASK = 0b010110101101;\n\n/**\n * Harmonic minor: natural minor with a raised seventh — offsets {0,2,3,5,7,8,11}.\n *\n * @category Scales\n */\nexport const HARMONIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 8, 11]);\n\n/**\n * Ascending melodic minor: offsets {0,2,3,5,7,9,11}.\n *\n * @category Scales\n */\nexport const MELODIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 11]);\n\n/**\n * Dorian mode: offsets {0,2,3,5,7,9,10}.\n *\n * @category Scales\n */\nexport const DORIAN_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 10]);\n\n/**\n * Phrygian mode: offsets {0,1,3,5,7,8,10}.\n *\n * @category Scales\n */\nexport const PHRYGIAN_MASK = maskFromOffsets([0, 1, 3, 5, 7, 8, 10]);\n\n/**\n * Lydian mode: offsets {0,2,4,6,7,9,11}.\n *\n * @category Scales\n */\nexport const LYDIAN_MASK = maskFromOffsets([0, 2, 4, 6, 7, 9, 11]);\n\n/**\n * Mixolydian mode: offsets {0,2,4,5,7,9,10}.\n *\n * @category Scales\n */\nexport const MIXOLYDIAN_MASK = maskFromOffsets([0, 2, 4, 5, 7, 9, 10]);\n\n/**\n * Locrian mode: offsets {0,1,3,5,6,8,10}.\n *\n * @category Scales\n */\nexport const LOCRIAN_MASK = maskFromOffsets([0, 1, 3, 5, 6, 8, 10]);\n\n/**\n * Major pentatonic: offsets {0,2,4,7,9}.\n *\n * @category Scales\n */\nexport const MAJOR_PENTATONIC_MASK = maskFromOffsets([0, 2, 4, 7, 9]);\n\n/**\n * Minor pentatonic: offsets {0,3,5,7,10}.\n *\n * @category Scales\n */\nexport const MINOR_PENTATONIC_MASK = maskFromOffsets([0, 3, 5, 7, 10]);\n\n/**\n * Hexatonic blues scale: minor pentatonic plus the flat-fifth — {0,3,5,6,7,10}.\n *\n * @category Scales\n */\nexport const BLUES_MASK = maskFromOffsets([0, 3, 5, 6, 7, 10]);\n\n/**\n * Whole-tone scale: offsets {0,2,4,6,8,10}.\n *\n * @category Scales\n */\nexport const WHOLE_TONE_MASK = maskFromOffsets([0, 2, 4, 6, 8, 10]);\n\n/**\n * Octatonic (half-step first): offsets {0,1,3,4,6,7,9,10}.\n *\n * @category Scales\n */\nexport const OCTATONIC_HALF_WHOLE_MASK = maskFromOffsets([0, 1, 3, 4, 6, 7, 9, 10]);\n\n/**\n * Octatonic (whole-step first): offsets {0,2,3,5,6,8,9,11}.\n *\n * @category Scales\n */\nexport const OCTATONIC_WHOLE_HALF_MASK = maskFromOffsets([0, 2, 3, 5, 6, 8, 9, 11]);\n\n/**\n * Chromatic scale: all twelve pitch classes.\n *\n * @category Scales\n */\nexport const CHROMATIC_MASK = 0b111111111111;\n\n/**\n * Named scale masks addressable by {@link scaleByName}.\n *\n * @category Scales\n */\nexport const NAMED_SCALES: Record<string, number> = {\n major: MAJOR_MASK,\n ionian: MAJOR_MASK,\n naturalMinor: NATURAL_MINOR_MASK,\n aeolian: NATURAL_MINOR_MASK,\n harmonicMinor: HARMONIC_MINOR_MASK,\n melodicMinor: MELODIC_MINOR_MASK,\n dorian: DORIAN_MASK,\n phrygian: PHRYGIAN_MASK,\n lydian: LYDIAN_MASK,\n mixolydian: MIXOLYDIAN_MASK,\n locrian: LOCRIAN_MASK,\n majorPentatonic: MAJOR_PENTATONIC_MASK,\n minorPentatonic: MINOR_PENTATONIC_MASK,\n blues: BLUES_MASK,\n wholeTone: WHOLE_TONE_MASK,\n octatonicHalfWhole: OCTATONIC_HALF_WHOLE_MASK,\n octatonicWholeHalf: OCTATONIC_WHOLE_HALF_MASK,\n chromatic: CHROMATIC_MASK,\n};\n\n/**\n * Build a `KeyScale` for a major key on the given root pitch class.\n *\n * @example\n * ```ts\n * import { majorKey } from '@libraz/libcantus';\n * const cMajor = majorKey(0); // C major: { rootPc: 0, modeMask12: MAJOR_MASK }\n * ```\n *\n * @category Scales\n */\nexport function majorKey(rootPc: number): KeyScale {\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: MAJOR_MASK };\n}\n\n/**\n * Build a `KeyScale` for a natural-minor key on the given root pitch class.\n *\n * @example\n * ```ts\n * import { minorKey } from '@libraz/libcantus';\n * const aMinor = minorKey(9); // A natural minor: { rootPc: 9, modeMask12: NATURAL_MINOR_MASK }\n * ```\n *\n * @category Scales\n */\nexport function minorKey(rootPc: number): KeyScale {\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: NATURAL_MINOR_MASK };\n}\n\n/**\n * Build a `KeyScale` from a named scale (see {@link NAMED_SCALES}).\n *\n * @param name The scale name, e.g. `'dorian'` or `'harmonicMinor'`.\n * @param rootPc The root pitch class.\n * @returns The key/scale.\n * @throws If the name is not a known scale.\n *\n * @example\n * ```ts\n * import { scaleByName } from '@libraz/libcantus';\n * const dDorian = scaleByName('dorian', 2); // D Dorian, rootPc 2\n * ```\n *\n * @category Scales\n */\nexport function scaleByName(name: string, rootPc: number): KeyScale {\n const mask = NAMED_SCALES[name];\n if (mask === undefined) {\n throw new Error(`Unknown scale: ${name}`);\n }\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: mask };\n}\n\n/** Reduce a pitch (or pitch class) to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/** Scale offset of a pitch relative to the key root, in [0, 11]. */\nfunction scaleOffset(pitch: number, key: KeyScale): number {\n return (pitchClass(pitch) - pitchClass(key.rootPc) + 12) % 12;\n}\n\n/**\n * Test whether a pitch belongs to the scale.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param key The key/scale to test against.\n * @returns True if the pitch class is a member of the scale.\n *\n * @example\n * ```ts\n * import { majorKey, isScaleTone } from '@libraz/libcantus';\n * const key = majorKey(0); // C major\n * isScaleTone(64, key); // true — E is in C major\n * isScaleTone(61, key); // false — C# is not\n * ```\n *\n * @category Scales\n */\nexport function isScaleTone(pitch: number, key: KeyScale): boolean {\n return ((key.modeMask12 >> scaleOffset(pitch, key)) & 1) === 1;\n}\n\n/**\n * Find the nearest MIDI pitch whose pitch class is in the scale.\n *\n * The search expands symmetrically outward from `pitch`. On a tie (equal\n * distance above and below) the lower pitch is returned.\n *\n * @param pitch MIDI pitch to snap.\n * @param key The key/scale to snap to.\n * @returns The nearest in-scale MIDI pitch.\n *\n * @category Scales\n */\nexport function nearestScaleTone(pitch: number, key: KeyScale): number {\n const base = Math.round(pitch);\n for (let distance = 0; distance < 12; distance += 1) {\n const lower = base - distance;\n if (isScaleTone(lower, key)) {\n return lower;\n }\n const higher = base + distance;\n if (isScaleTone(higher, key)) {\n return higher;\n }\n }\n return base;\n}\n\n/**\n * Get the 0-based scale degree of a pitch.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param key The key/scale to measure against.\n * @returns The 0-based degree, or -1 if the pitch is not in the scale.\n *\n * @category Scales\n */\nexport function pitchToScaleDegree(pitch: number, key: KeyScale): number {\n const offset = scaleOffset(pitch, key);\n if (((key.modeMask12 >> offset) & 1) === 0) {\n return -1;\n }\n let degree = 0;\n for (let n = 0; n < offset; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n degree += 1;\n }\n }\n return degree;\n}\n\n/**\n * List the pitch classes of a key's scale.\n *\n * @param key The key/scale to enumerate.\n * @returns The member pitch classes, sorted ascending in [0, 11].\n *\n * @category Scales\n */\nexport function diatonicPitchClasses(key: KeyScale): number[] {\n const root = pitchClass(key.rootPc);\n const pcs: number[] = [];\n for (let n = 0; n < 12; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n pcs.push((root + n) % 12);\n }\n }\n return pcs.sort((a, b) => a - b);\n}\n\n/**\n * List the pitch classes of a key's scale in ascending scale-degree order.\n *\n * Degree 0 is the root; degrees follow the mask bits in offset order rather\n * than sorted pitch-class order.\n *\n * @param key The key/scale to enumerate.\n * @returns The member pitch classes ordered by scale degree.\n *\n * @category Scales\n */\nexport function scaleTonesInDegreeOrder(key: KeyScale): number[] {\n const root = pitchClass(key.rootPc);\n const pcs: number[] = [];\n for (let n = 0; n < 12; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n pcs.push((root + n) % 12);\n }\n }\n return pcs;\n}\n","import { scaleTonesInDegreeOrder } from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * Chord quality identifiers understood by the chord builder.\n *\n * @category Chords\n */\nexport type ChordQuality =\n | 'maj'\n | 'min'\n | 'dim'\n | 'aug'\n | 'maj7'\n | 'min7'\n | 'dom7'\n | 'dim7'\n | 'm7b5'\n | 'minMaj7'\n | 'aug7'\n | 'augMaj7'\n | 'majb5'\n | '6'\n | 'min6'\n | '6/9'\n | 'sus2'\n | 'sus4'\n | 'add9'\n | 'add11'\n | 'maj9'\n | 'min9'\n | 'dom9'\n | '7b9'\n | '7#9'\n | '7#11'\n | '7b13'\n | '11'\n | '13'\n | '5';\n\n/**\n * A bare spelled pitch used as an enharmonic hint: a diatonic letter\n * (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).\n * Mirrors the letter/alter half of the pitch module's `Note` without an octave.\n *\n * @category Chords\n */\nexport type PitchSpelling = {\n letter: number;\n alter: number;\n};\n\n/**\n * A chord expressed as a root pitch class plus semitone offsets.\n *\n * `rootSpelling`/`bassSpelling` are optional enharmonic hints recorded by\n * parsers (e.g. `parseChordSymbol('Bb7')`) so formatters can reproduce the\n * original spelling instead of defaulting to sharps. Consumers may ignore\n * them; a hint is only trusted when its pitch class still matches the\n * corresponding `rootPc`/`bassPc`.\n *\n * @category Chords\n */\nexport type Chord = {\n rootPc: number;\n quality: ChordQuality;\n intervals: number[];\n bassPc?: number;\n rootSpelling?: PitchSpelling;\n bassSpelling?: PitchSpelling;\n};\n\n/** Semitone offsets from the root for each supported chord quality. */\nconst QUALITY_INTERVALS: Record<ChordQuality, number[]> = {\n maj: [0, 4, 7],\n min: [0, 3, 7],\n dim: [0, 3, 6],\n aug: [0, 4, 8],\n majb5: [0, 4, 6],\n maj7: [0, 4, 7, 11],\n min7: [0, 3, 7, 10],\n dom7: [0, 4, 7, 10],\n dim7: [0, 3, 6, 9],\n m7b5: [0, 3, 6, 10],\n minMaj7: [0, 3, 7, 11],\n aug7: [0, 4, 8, 10],\n augMaj7: [0, 4, 8, 11],\n '6': [0, 4, 7, 9],\n min6: [0, 3, 7, 9],\n '6/9': [0, 4, 7, 9, 14],\n sus2: [0, 2, 7],\n sus4: [0, 5, 7],\n add9: [0, 4, 7, 14],\n add11: [0, 4, 7, 17],\n maj9: [0, 4, 7, 11, 14],\n min9: [0, 3, 7, 10, 14],\n dom9: [0, 4, 7, 10, 14],\n '7b9': [0, 4, 7, 10, 13],\n '7#9': [0, 4, 7, 10, 15],\n '7#11': [0, 4, 7, 10, 18],\n '7b13': [0, 4, 7, 10, 20],\n '11': [0, 7, 10, 14, 17],\n '13': [0, 4, 7, 10, 14, 21],\n '5': [0, 7],\n};\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * All chord qualities the builder understands, longest templates last.\n *\n * @category Chords\n */\nexport function chordQualities(): ChordQuality[] {\n return Object.keys(QUALITY_INTERVALS) as ChordQuality[];\n}\n\n/**\n * Build a chord rooted on a diatonic scale degree.\n *\n * The root pitch class is the degree's diatonic pitch class in `key`; the\n * quality's interval template is attached unchanged. Degrees beyond the scale\n * length wrap around.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param ext Chord quality to apply.\n * @param key Key context supplying the diatonic root.\n * @returns The constructed chord.\n *\n * @category Chords\n */\nexport function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScale): Chord {\n const tones = scaleTonesInDegreeOrder(key);\n const length = tones.length;\n const index = length > 0 ? ((degree % length) + length) % length : 0;\n const rootPc = tones[index] ?? pitchClass(key.rootPc);\n return { rootPc, quality: ext, intervals: [...QUALITY_INTERVALS[ext]] };\n}\n\n/**\n * Build a chord from an explicit root pitch class and quality.\n *\n * @param rootPc Root pitch class (0..11).\n * @param quality Chord quality supplying the interval template.\n * @param bassPc Optional slash-chord bass pitch class.\n * @returns The constructed chord.\n *\n * @example\n * ```ts\n * import { makeChord } from '@libraz/libcantus';\n * const cmaj7 = makeChord(0, 'maj7');\n * // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }\n * ```\n *\n * @category Chords\n */\nexport function makeChord(rootPc: number, quality: ChordQuality, bassPc?: number): Chord {\n const chord: Chord = {\n rootPc: pitchClass(rootPc),\n quality,\n intervals: [...QUALITY_INTERVALS[quality]],\n };\n if (bassPc !== undefined) {\n chord.bassPc = pitchClass(bassPc);\n }\n return chord;\n}\n\n/**\n * Get the sorted, deduplicated pitch classes of a chord.\n *\n * @param chord The chord to enumerate.\n * @returns The chord's pitch classes, sorted ascending in [0, 11].\n *\n * @example\n * ```ts\n * import { makeChord, chordPitchClasses } from '@libraz/libcantus';\n * chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]\n * ```\n *\n * @category Chords\n */\nexport function chordPitchClasses(chord: Chord): number[] {\n const set = new Set<number>();\n for (const interval of chord.intervals) {\n set.add(pitchClass(chord.rootPc + interval));\n }\n return [...set].sort((a, b) => a - b);\n}\n\n/** The chord-tone offsets present in a chord, reduced to pitch-class space. */\nfunction chordToneOffsets(chord: Chord): Set<number> {\n return new Set(chord.intervals.map((i) => ((i % 12) + 12) % 12));\n}\n\n/**\n * Determine a pitch's harmonic role within a chord.\n *\n * The role is derived from the pitch's interval above the chord root, reduced\n * modulo 12. A major sixth (9) reads as a `sixth` for sixth chords but as a\n * `seventh` for a diminished-seventh chord; ninths and other tensions have no\n * basic role and return null.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param chord The chord providing the root reference.\n * @returns The chord-tone role, or null if the pitch has no basic role.\n *\n * @category Chords\n */\nexport function chordToneRole(\n pitch: number,\n chord: Chord,\n): 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | null {\n const interval = (pitchClass(pitch) - pitchClass(chord.rootPc) + 12) % 12;\n const tones = chordToneOffsets(chord);\n if (interval === 0) {\n return 'root';\n }\n if (interval === 3 || interval === 4) {\n return tones.has(interval) ? 'third' : null;\n }\n if (interval === 7) {\n return tones.has(7) ? 'fifth' : null;\n }\n if (interval === 6) {\n // A diminished fifth is the chord's fifth only when no perfect fifth is\n // present; alongside a perfect fifth it is a #11 tension, not a fifth.\n return tones.has(6) && !tones.has(7) ? 'fifth' : null;\n }\n if (interval === 8) {\n // An augmented fifth is the chord's fifth only without a perfect fifth;\n // alongside a perfect fifth it is a b13 tension, not a fifth.\n return tones.has(8) && !tones.has(7) ? 'fifth' : null;\n }\n if (interval === 9) {\n const hasHigherSeventh = tones.has(10) || tones.has(11);\n const isDiminishedSeventh = tones.has(3) && tones.has(6) && !hasHigherSeventh;\n if (isDiminishedSeventh) {\n return 'seventh';\n }\n if (tones.has(9) && !hasHigherSeventh) {\n return 'sixth';\n }\n return null;\n }\n if (interval === 10 || interval === 11) {\n return tones.has(interval) ? 'seventh' : null;\n }\n return null;\n}\n\n/** Classify a stacked-thirds triad into a chord quality from its interval set. */\nfunction classifyTriad(thirdIc: number, fifthIc: number): ChordQuality {\n if (thirdIc === 4 && fifthIc === 8) {\n return 'aug';\n }\n if (thirdIc === 4 && fifthIc === 6) {\n return 'majb5';\n }\n if (thirdIc === 3 && fifthIc === 6) {\n return 'dim';\n }\n if (thirdIc === 3) {\n return 'min';\n }\n return 'maj';\n}\n\n/** Classify a stacked-thirds seventh chord into a chord quality. */\nfunction classifySeventh(thirdIc: number, fifthIc: number, seventhIc: number): ChordQuality {\n if (thirdIc === 3 && fifthIc === 6 && seventhIc === 9) {\n return 'dim7';\n }\n if (thirdIc === 3 && fifthIc === 6 && seventhIc === 10) {\n return 'm7b5';\n }\n if (thirdIc === 3 && seventhIc === 11) {\n return 'minMaj7';\n }\n if (thirdIc === 3) {\n return 'min7';\n }\n if (fifthIc === 8 && seventhIc === 10) {\n return 'aug7';\n }\n if (fifthIc === 8 && seventhIc === 11) {\n return 'augMaj7';\n }\n if (seventhIc === 11) {\n return 'maj7';\n }\n return 'dom7';\n}\n\n/** Stack scale thirds from a scale degree into a chord of `size` notes. */\nfunction stackThirds(degree: number, key: KeyScale, size: 3 | 4): Chord {\n const tones = scaleTonesInDegreeOrder(key);\n const length = tones.length;\n if (length === 0) {\n return { rootPc: pitchClass(key.rootPc), quality: 'maj', intervals: [0, 4, 7] };\n }\n const idx = (step: number) => (((degree + step) % length) + length) % length;\n const rootPc = tones[idx(0)] ?? pitchClass(key.rootPc);\n const offsets = [0, 2, 4, 6].slice(0, size).map((step) => {\n const pc = tones[idx(step)] ?? rootPc;\n return (((pc - rootPc) % 12) + 12) % 12;\n });\n const thirdIc = offsets[1] ?? 4;\n const fifthIc = offsets[2] ?? 7;\n const quality =\n size === 3\n ? classifyTriad(thirdIc, fifthIc)\n : classifySeventh(thirdIc, fifthIc, offsets[3] ?? 11);\n return { rootPc, quality, intervals: offsets };\n}\n\n/**\n * Build the diatonic triad rooted on a scale degree by stacking scale thirds.\n *\n * Unlike {@link chordFromDegree}, the chord quality is derived from the scale\n * rather than supplied, so degrees yield their scale-correct triads (e.g. a\n * diminished triad on the leading tone of a major key). Intended for heptatonic\n * scales; other scales stack by scale step regardless.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param key Key/scale context.\n * @returns The diatonic triad.\n *\n * @example\n * ```ts\n * import { majorKey, diatonicTriad } from '@libraz/libcantus';\n * const tonic = diatonicTriad(0, majorKey(0)); // C major triad (degree 0 of C major)\n * ```\n *\n * @category Chords\n */\nexport function diatonicTriad(degree: number, key: KeyScale): Chord {\n return stackThirds(degree, key, 3);\n}\n\n/**\n * Build the diatonic seventh chord rooted on a scale degree.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param key Key/scale context.\n * @returns The diatonic seventh chord.\n *\n * @category Chords\n */\nexport function diatonicSeventh(degree: number, key: KeyScale): Chord {\n return stackThirds(degree, key, 4);\n}\n","/**\n * Counterpoint classification of a harmonic interval.\n *\n * @category Pitch & Intervals\n */\nexport enum IntervalQuality {\n PerfectConsonance = 0,\n ImperfectConsonance = 1,\n Dissonance = 2,\n}\n\n/** Reduce an interval to a simple interval class in the range [0, 11]. */\nfunction simpleInterval(semitones: number): number {\n return Math.abs(semitones) % 12;\n}\n\n/**\n * Classify an interval for counterpoint evaluation.\n *\n * The interval is reduced modulo 12, so compound intervals classify as their\n * simple equivalents. The perfect fourth (5) is context-dependent: with\n * `twoVoice` (the default) it classifies as a dissonance, matching\n * {@link isConsonantInterval}; otherwise it is an imperfect consonance.\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @param twoVoice When true, the perfect fourth is treated as dissonant.\n * @returns The counterpoint quality of the interval.\n * @example\n * ```ts\n * import { classifyInterval, IntervalQuality } from '@libraz/libcantus';\n * classifyInterval(7); // IntervalQuality.PerfectConsonance\n * classifyInterval(5); // IntervalQuality.Dissonance (two-voice)\n * classifyInterval(5, false); // IntervalQuality.ImperfectConsonance\n * ```\n * @category Pitch & Intervals\n */\nexport function classifyInterval(semitones: number, twoVoice = true): IntervalQuality {\n const pc = simpleInterval(semitones);\n if (pc === 0 || pc === 7) {\n return IntervalQuality.PerfectConsonance;\n }\n if (pc === 3 || pc === 4 || pc === 8 || pc === 9) {\n return IntervalQuality.ImperfectConsonance;\n }\n if (pc === 5) {\n return twoVoice ? IntervalQuality.Dissonance : IntervalQuality.ImperfectConsonance;\n }\n return IntervalQuality.Dissonance;\n}\n\n/**\n * Test whether an interval is a perfect interval (unison/octave or fifth).\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @returns True for the unison/octave (0) and the perfect fifth (7) mod 12.\n * @category Pitch & Intervals\n */\nexport function isPerfectInterval(semitones: number): boolean {\n const pc = simpleInterval(semitones);\n return pc === 0 || pc === 7;\n}\n\n/**\n * Test whether an interval is consonant.\n *\n * The consonant set is {0, 3, 4, 5, 7, 8, 9} mod 12. In two-voice counterpoint\n * the perfect fourth (5) is treated as a dissonance, so `twoVoice` set to true\n * excludes it.\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @param twoVoice When true, the perfect fourth is treated as dissonant.\n * @returns True if the interval is consonant in the given context.\n * @category Pitch & Intervals\n */\nexport function isConsonantInterval(semitones: number, twoVoice = true): boolean {\n const pc = simpleInterval(semitones);\n if (pc === 5) {\n return !twoVoice;\n }\n return pc === 0 || pc === 3 || pc === 4 || pc === 7 || pc === 8 || pc === 9;\n}\n","import { isConsonantInterval } from '../interval/index.js';\nimport type { KeyScale } from '../types.js';\n\n/** Reduce a MIDI pitch (or pitch class) to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/**\n * Whether an upper voice has crossed below a lower voice.\n *\n * @param upperPitch Pitch of the nominally higher voice.\n * @param lowerPitch Pitch of the nominally lower voice.\n * @returns True when the upper voice sits below the lower voice.\n * @category Voicing & Counterpoint\n */\nexport function createsVoiceCrossing(upperPitch: number, lowerPitch: number): boolean {\n return upperPitch < lowerPitch;\n}\n\n/**\n * Whether two simultaneous pitches form a dissonance.\n *\n * @param a First pitch.\n * @param b Second pitch.\n * @param twoVoice When true, the perfect fourth counts as dissonant.\n * @returns True when the vertical interval is dissonant.\n * @category Voicing & Counterpoint\n */\nexport function createsVerticalDissonance(a: number, b: number, twoVoice: boolean): boolean {\n return !isConsonantInterval(a - b, twoVoice);\n}\n\n/**\n * Whether a melodic move is a forbidden leap: a tritone, either seventh (minor\n * or major), or any leap wider than an octave.\n *\n * Operates on the raw absolute distance, so compound leaps are not reduced to\n * their simple class before the octave check.\n *\n * @param prev Starting pitch.\n * @param cur Ending pitch.\n * @returns True when the leap is forbidden in strict counterpoint.\n * @category Voicing & Counterpoint\n */\nexport function isForbiddenMelodicLeap(prev: number, cur: number): boolean {\n const semis = Math.abs(cur - prev);\n return semis === 6 || semis === 10 || semis === 11 || semis > 12;\n}\n\n/** Reduce an interval to its simple class in [0, 11]. */\nfunction simpleClass(semitones: number): number {\n return Math.abs(semitones) % 12;\n}\n\n/** Whether a simple interval class is a perfect kind (unison/octave or fifth). */\nfunction isPerfectClass(cls: number): boolean {\n return cls === 0 || cls === 7;\n}\n\n/** Whether two voices move in the same direction (similar or parallel motion). */\nfunction similarMotion(aMove: number, bMove: number): boolean {\n return aMove !== 0 && bMove !== 0 && aMove > 0 === bMove > 0;\n}\n\n/** Whether both voices actually move (neither is stationary — excludes oblique motion). */\nfunction bothVoicesMove(aMove: number, bMove: number): boolean {\n return aMove !== 0 && bMove !== 0;\n}\n\n/**\n * Whether two voices move into consecutive perfect intervals of the same kind\n * (fifth-to-fifth, octave-to-octave, unison-to-unison).\n *\n * Both true parallels (similar motion) and anti-parallels — the same perfect\n * class reached by contrary motion, e.g. octave to octave with the voices moving\n * in opposite directions — are flagged, as both are forbidden in strict two-voice\n * counterpoint. The rule requires that both voices actually move: oblique motion\n * (either voice stationary) and the no-change case (identical pitches) are excluded.\n *\n * A fifth expanding to a twelfth counts (same perfect class); a fifth moving to\n * an octave does not (different perfect kinds — the direct/hidden case owned by\n * {@link createsHiddenParallelPerfect}).\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelPerfect(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (!bothVoicesMove(aCur - aPrev, bCur - bPrev)) {\n return false;\n }\n const nowClass = simpleClass(aCur - bCur);\n const prevClass = simpleClass(aPrev - bPrev);\n return isPerfectClass(nowClass) && nowClass === prevClass;\n}\n\n/**\n * Whether two voices move in consecutive parallel octaves (or unisons) by\n * similar motion.\n *\n * This is a strict subset of {@link createsParallelPerfect}: a similar-motion\n * octave-to-octave is the perfect-class-zero case that predicate already flags\n * (and it additionally catches the contrary-motion anti-parallel). Callers that\n * tally parallel violations should therefore use {@link createsParallelPerfect}\n * alone to avoid double counting; this predicate remains for callers wanting a\n * dedicated similar-motion octave test.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelOctave(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (!similarMotion(aCur - aPrev, bCur - bPrev)) {\n return false;\n }\n return simpleClass(aCur - bCur) === 0 && simpleClass(aPrev - bPrev) === 0;\n}\n\n/**\n * Whether two voices move in consecutive parallel unisons — both landing on the\n * same pitch, having shared a pitch on the previous move.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelUnison(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (aCur === aPrev || bCur === bPrev) {\n return false;\n }\n return aCur === bCur && aPrev === bPrev;\n}\n\n/**\n * Whether two voices reach a perfect interval by similar motion from an\n * imperfect one (a hidden/direct fifth or octave).\n *\n * The traditional step exception is applied: the approach is allowed when the\n * upper of the two voices moves by step, so only leaps into the perfect\n * interval are flagged.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsHiddenParallelPerfect(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n const aMove = aCur - aPrev;\n const bMove = bCur - bPrev;\n if (!similarMotion(aMove, bMove)) {\n return false;\n }\n const nowClass = simpleClass(aCur - bCur);\n const prevClass = simpleClass(aPrev - bPrev);\n // Approaching the same perfect class (e.g. fifth to fifth) is a true parallel\n // owned by createsParallelPerfect; approaching a different perfect interval\n // (fifth to octave, or vice versa) is the hidden/direct case flagged here.\n if (!isPerfectClass(nowClass) || prevClass === nowClass) {\n return false;\n }\n const upperMove = aCur >= bCur ? aMove : bMove;\n if (Math.abs(upperMove) <= 2) {\n return false; // upper voice moves by step — direct interval is acceptable\n }\n return true;\n}\n\n/**\n * Whether two voices overlap: the upper voice descends below where the lower\n * voice just was, or the lower voice rises above where the upper voice just was.\n * Distinct from a simultaneous voice crossing.\n *\n * @param upperPrev Previous pitch of the upper voice.\n * @param upperCur Current pitch of the upper voice.\n * @param lowerPrev Previous pitch of the lower voice.\n * @param lowerCur Current pitch of the lower voice.\n * @category Voicing & Counterpoint\n */\nexport function createsVoiceOverlap(\n upperPrev: number,\n upperCur: number,\n lowerPrev: number,\n lowerCur: number,\n): boolean {\n return upperCur < lowerPrev || lowerCur > upperPrev;\n}\n\n/**\n * Whether two adjacent upper voices are spaced more than a maximum apart\n * (commonly an octave). Bass-to-tenor spacing is conventionally exempt, so this\n * is meant for the upper voice pairs.\n *\n * @param upperPitch Pitch of the higher voice.\n * @param lowerPitch Pitch of the lower voice.\n * @param maxSemitones Maximum allowed spacing in semitones (default an octave).\n * @category Voicing & Counterpoint\n */\nexport function exceedsSpacing(upperPitch: number, lowerPitch: number, maxSemitones = 12): boolean {\n return Math.abs(upperPitch - lowerPitch) > maxSemitones;\n}\n\n/**\n * Whether a leading tone resolves correctly upward to the tonic.\n *\n * @param prev The leading-tone pitch.\n * @param cur The following pitch.\n * @param key Key context supplying the tonic.\n * @returns True when `prev` is the leading tone and `cur` is the tonic a step above.\n * @category Voicing & Counterpoint\n */\nexport function isLeadingToneResolution(prev: number, cur: number, key: KeyScale): boolean {\n const tonic = pitchClass(key.rootPc);\n const leading = (tonic + 11) % 12;\n if (pitchClass(prev) !== leading || pitchClass(cur) !== tonic) {\n return false;\n }\n return cur > prev && cur - prev <= 2;\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses, chordToneRole } from '../chord/index.js';\nimport { createsVerticalDissonance, isLeadingToneResolution } from '../counterpoint/index.js';\nimport type { VoiceSnapshot } from '../safety/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/**\n * A theory annotation attached to a note.\n *\n * @category Arrangement & Analysis\n */\nexport type TheoryLabel =\n | { kind: 'chordTone'; role: 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' }\n | { kind: 'tension'; degree: 9 | 11 | 13 }\n | { kind: 'avoid' }\n | { kind: 'passing' }\n | { kind: 'neighbor' }\n | { kind: 'suspension'; type: 'sus4-3' | 'sus7-6' | 'sus9-8' | 'sus2-3'; resolveTo: number }\n | { kind: 'anticipation' }\n | { kind: 'escape' }\n | { kind: 'needsResolution'; resolveTo: number }\n | { kind: 'leadingTone'; resolveTo: number };\n\n/**\n * A note with its theory labels and a short rationale.\n *\n * @category Arrangement & Analysis\n */\nexport type AnalyzedNote = {\n noteId: number;\n labels: TheoryLabel[];\n rationale?: string;\n};\n\n/**\n * A single note in a monophonic voice: a {@link NoteEvent} with a stable id.\n *\n * @category Arrangement & Analysis\n */\nexport type VoiceNote = NoteEvent & { id: number };\n\n/** Float tolerance for beat comparisons. */\nconst EPS = 1e-9;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction intervalAboveRoot(pitch: number, chord: Chord): number {\n return (((pitchClass(pitch) - pitchClass(chord.rootPc)) % 12) + 12) % 12;\n}\n\n/**\n * Interval class of a pitch above the actual sounding bass.\n *\n * Suspension figures (4-3, 7-6, 9-8) are named for the interval above the bass,\n * not the chord root, so this prefers the lowest pitch among the other sounding\n * voices when one lies below the note. Without a lower sounding voice it falls\n * back to the chord's bass pitch class (or root in root position).\n */\nfunction intervalAboveBass(pitch: number, others: VoiceSnapshot[], chord: Chord): number {\n let bass = Number.POSITIVE_INFINITY;\n for (const ov of others) {\n bass = Math.min(bass, ov.pitch);\n }\n if (Number.isFinite(bass) && bass < pitch) {\n return (((pitch - bass) % 12) + 12) % 12;\n }\n const ref = chord.bassPc ?? chord.rootPc;\n return (((pitchClass(pitch) - pitchClass(ref)) % 12) + 12) % 12;\n}\n\n/**\n * Map an interval class above the root to its extended-tension scale degree:\n * a flat/natural ninth (1 or 2) to 9, an eleventh (5 or 6) to 11, and a\n * thirteenth (8 or 9) to 13.\n */\nfunction tensionDegree(ic: number): 9 | 11 | 13 {\n if (ic === 1 || ic === 2) {\n return 9;\n }\n if (ic === 5 || ic === 6) {\n return 11;\n }\n return 13;\n}\n\nfunction isChordMember(pitch: number, chord: Chord | null): boolean {\n return chord ? chordPitchClasses(chord).includes(pitchClass(pitch)) : false;\n}\n\nfunction isStep(a: number, b: number): boolean {\n const d = Math.abs(a - b);\n return d === 1 || d === 2;\n}\n\n/**\n * Classify a suspension figure from the interval class above the sounding bass\n * (`ic`) and the resolution direction (`delta`, positive when resolving upward).\n */\nfunction suspensionType(ic: number, delta: number): TheoryLabel & { kind: 'suspension' } {\n let type: 'sus4-3' | 'sus7-6' | 'sus9-8' | 'sus2-3';\n if (delta > 0) {\n type = 'sus2-3';\n } else if (ic === 2) {\n type = 'sus9-8';\n } else if (ic === 10 || ic === 11) {\n type = 'sus7-6';\n } else {\n type = 'sus4-3';\n }\n return { kind: 'suspension', type, resolveTo: 0 };\n}\n\nfunction stepResolution(pitch: number, chord: Chord): number | undefined {\n for (let delta = 1; delta <= 2; delta += 1) {\n if (isChordMember(pitch - delta, chord)) {\n return pitch - delta;\n }\n }\n return undefined;\n}\n\n/**\n * Label every note of a voice with its theory roles.\n *\n * Each note is classified against the chord sounding at its beat. Chord tones\n * get a role label; non-chord tones are matched, in order, as suspensions\n * (prepared by an identical consonant pitch and resolving by step), passing\n * tones, neighbors, anticipations, and escape tones, then fall back to tension,\n * avoid, or an unresolved-dissonance label. Leading-tone resolutions are noted\n * additionally.\n *\n * The voice is expected to be monophonic (one note at a time). Notes sharing an\n * onset are treated as simultaneous cluster members, not melodic neighbors, so\n * they receive no melodic labels (suspension, passing, neighbor, anticipation,\n * escape) — only harmonic ones. Callers with truly polyphonic material should\n * split it into monophonic sub-voices first, as `analyzeArrangement` does.\n *\n * @param voice The monophonic voice, in time order.\n * @param chordAtBeat Chord sounding at a given beat, or null.\n * @param key Key context for leading-tone detection.\n * @param otherVoicesAtBeat Other sounding voices at a given beat.\n * @returns One annotation per input note.\n * @example\n * ```ts\n * import { analyzeVoice, makeChord, majorKey } from '@libraz/libcantus';\n * const voice = [\n * { id: 0, pitch: 60, startBeat: 0, durationBeat: 1 },\n * { id: 1, pitch: 62, startBeat: 1, durationBeat: 1 },\n * { id: 2, pitch: 64, startBeat: 2, durationBeat: 1 },\n * ];\n * const cMajor = makeChord(0, 'maj');\n * const labels = analyzeVoice(voice, () => cMajor, majorKey(0), () => []);\n * labels; // one AnalyzedNote per input note, in the same order\n * ```\n * @category Arrangement & Analysis\n */\nexport function analyzeVoice(\n voice: VoiceNote[],\n chordAtBeat: (beat: number) => Chord | null,\n key: KeyScale,\n otherVoicesAtBeat: (beat: number) => VoiceSnapshot[],\n): AnalyzedNote[] {\n const result: AnalyzedNote[] = [];\n\n for (let i = 0; i < voice.length; i += 1) {\n const note = voice[i];\n if (!note) {\n continue;\n }\n const prevNote = i > 0 ? voice[i - 1] : undefined;\n const nextNote = i + 1 < voice.length ? voice[i + 1] : undefined;\n // A neighboring note sharing this note's onset is a simultaneous cluster\n // member, not a melodic predecessor/successor; treating it as one would\n // fabricate passing/suspension figures, so it is dropped here.\n const prev =\n prevNote !== undefined && prevNote.startBeat < note.startBeat - EPS ? prevNote : undefined;\n const next =\n nextNote !== undefined && nextNote.startBeat > note.startBeat + EPS ? nextNote : undefined;\n const chord = chordAtBeat(note.startBeat);\n const labels: TheoryLabel[] = [];\n const member = isChordMember(note.pitch, chord);\n let handled = false;\n\n if (chord && member) {\n const role = chordToneRole(note.pitch, chord);\n if (role) {\n labels.push({ kind: 'chordTone', role });\n } else {\n const ic = intervalAboveRoot(note.pitch, chord);\n labels.push({ kind: 'tension', degree: tensionDegree(ic) });\n }\n handled = true;\n }\n\n if (!handled && chord && prev && next) {\n const prevChord = chordAtBeat(prev.startBeat);\n const prepared = prev.pitch === note.pitch && isChordMember(prev.pitch, prevChord);\n const resolves = isStep(next.pitch, note.pitch);\n const others = otherVoicesAtBeat(note.startBeat);\n const verticallyDissonant = others.some((ov) =>\n createsVerticalDissonance(note.pitch, ov.pitch, true),\n );\n if (prepared && verticallyDissonant && resolves) {\n const ic = intervalAboveBass(note.pitch, others, chord);\n const sus = suspensionType(ic, next.pitch - note.pitch);\n sus.resolveTo = next.pitch;\n labels.push(sus);\n handled = true;\n }\n }\n\n if (!handled && chord && prev && next) {\n const prevMember = isChordMember(prev.pitch, chordAtBeat(prev.startBeat));\n const nextMember = isChordMember(next.pitch, chordAtBeat(next.startBeat));\n const up = note.pitch - prev.pitch > 0;\n const contInto = next.pitch - note.pitch > 0;\n const sameDir = note.pitch !== prev.pitch && next.pitch !== note.pitch && up === contInto;\n if (\n prevMember &&\n nextMember &&\n !member &&\n isStep(note.pitch, prev.pitch) &&\n isStep(next.pitch, note.pitch) &&\n sameDir\n ) {\n labels.push({ kind: 'passing' });\n handled = true;\n }\n }\n\n if (\n !handled &&\n chord &&\n prev &&\n next &&\n !member &&\n prev.pitch === next.pitch &&\n isChordMember(prev.pitch, chordAtBeat(prev.startBeat)) &&\n isStep(note.pitch, prev.pitch)\n ) {\n labels.push({ kind: 'neighbor' });\n handled = true;\n }\n\n if (!handled && chord && next && !member && note.pitch === next.pitch) {\n const nextChord = chordAtBeat(next.startBeat);\n if (isChordMember(next.pitch, nextChord)) {\n labels.push({ kind: 'anticipation' });\n handled = true;\n }\n }\n\n if (!handled && chord && prev && next && !member) {\n const prevMember = isChordMember(prev.pitch, chordAtBeat(prev.startBeat));\n const nextMember = isChordMember(next.pitch, chordAtBeat(next.startBeat));\n const stepFromPrev = isStep(note.pitch, prev.pitch);\n const leapToNext = Math.abs(next.pitch - note.pitch) >= 3;\n const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;\n if (prevMember && nextMember && stepFromPrev && leapToNext && opposite) {\n labels.push({ kind: 'escape' });\n handled = true;\n }\n }\n\n if (!handled && chord && !member) {\n const ic = intervalAboveRoot(note.pitch, chord);\n const isTension = ic === 2 || ic === 5 || ic === 9;\n const avoid =\n (ic === 5 && chord.intervals.includes(4) && !chord.intervals.includes(5)) ||\n (ic === 11 && chord.intervals.includes(4) && chord.intervals.includes(10));\n if (avoid) {\n labels.push({ kind: 'avoid' });\n const resolveTo = stepResolution(note.pitch, chord);\n if (resolveTo !== undefined) {\n labels.push({ kind: 'needsResolution', resolveTo });\n }\n } else if (isTension) {\n labels.push({ kind: 'tension', degree: tensionDegree(ic) });\n } else {\n const resolveTo = stepResolution(note.pitch, chord);\n if (resolveTo !== undefined) {\n labels.push({ kind: 'needsResolution', resolveTo });\n }\n }\n }\n\n if (next && isLeadingToneResolution(note.pitch, next.pitch, key)) {\n labels.push({ kind: 'leadingTone', resolveTo: next.pitch });\n }\n\n result.push({ noteId: note.id, labels, rationale: describe(labels) });\n }\n\n return result;\n}\n\n/** Build a short rationale from a note's primary label. */\nfunction describe(labels: TheoryLabel[]): string {\n const primary = labels[0];\n if (!primary) {\n return 'Unclassified note';\n }\n switch (primary.kind) {\n case 'chordTone':\n return `Chord ${primary.role}`;\n case 'tension':\n return `${primary.degree}th tension`;\n case 'avoid':\n return 'Avoid note';\n case 'passing':\n return 'Passing tone between chord tones';\n case 'neighbor':\n return 'Neighbor tone';\n case 'suspension':\n return `Suspension (${primary.type})`;\n case 'anticipation':\n return 'Anticipation of the next chord';\n case 'escape':\n return 'Escape tone';\n case 'needsResolution':\n return 'Unresolved dissonance';\n case 'leadingTone':\n return 'Leading tone resolving to the tonic';\n }\n}\n","/**\n * Functional harmony: Roman-numeral parsing and formatting, harmonic function\n * (tonic / subdominant / dominant), and cadence detection.\n *\n * Roots are pitch classes measured against the key tonic, so borrowed and\n * chromatic chords are handled by their semitone offset rather than requiring a\n * spelled key signature.\n */\n\nimport type { Chord, ChordQuality } from '../chord/index.js';\nimport { chordPitchClasses, makeChord } from '../chord/index.js';\nimport {\n HARMONIC_MINOR_MASK,\n isScaleTone,\n MAJOR_MASK,\n majorKey,\n NATURAL_MINOR_MASK,\n scaleTonesInDegreeOrder,\n} from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * The three broad harmonic functions of tonal music.\n *\n * @category Functional Harmony\n */\nexport type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';\n\n/**\n * A recognized cadence type, or null when a chord pair forms none.\n *\n * @category Functional Harmony\n */\nexport type Cadence = 'authentic' | 'plagal' | 'half' | 'deceptive' | null;\n\n/** Roman numeral glyphs indexed by degree number - 1. */\nconst ROMAN = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] as const;\n\n/** Roman glyph -> degree number (1..7). */\nconst ROMAN_TO_DEGREE: Record<string, number> = {\n I: 1,\n II: 2,\n III: 3,\n IV: 4,\n V: 5,\n VI: 6,\n VII: 7,\n};\n\n/** Major-key Roman spelling for each semitone offset above the tonic. */\nconst OFFSET_SPELLING: readonly [number, string][] = [\n [1, ''],\n [2, 'b'],\n [2, ''],\n [3, 'b'],\n [3, ''],\n [4, ''],\n [4, '#'],\n [5, ''],\n [6, 'b'],\n [6, ''],\n [7, 'b'],\n [7, ''],\n];\n\n/** Harmonic function of each semitone offset above the tonic (major context). */\nconst FUNCTION_BY_OFFSET: readonly HarmonicFunction[] = [\n 'tonic', // 0 I\n 'subdominant', // 1 bII (Neapolitan)\n 'subdominant', // 2 ii\n 'tonic', // 3 bIII\n 'tonic', // 4 iii\n 'subdominant', // 5 IV\n 'dominant', // 6 #IV / bV\n 'dominant', // 7 V\n 'subdominant', // 8 bVI\n 'tonic', // 9 vi\n 'subdominant', // 10 bVII\n 'dominant', // 11 vii\n];\n\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/**\n * Whether a key's scale has a minor third and no major third (a minor key).\n *\n * @category Functional Harmony\n */\nexport function isMinorKey(key: KeyScale): boolean {\n const hasMinorThird = (key.modeMask12 >> 3) & 1;\n const hasMajorThird = (key.modeMask12 >> 4) & 1;\n return Boolean(hasMinorThird) && !hasMajorThird;\n}\n\n/** Diatonic pitch class of a 1-based scale degree in a key. */\nfunction degreeRootPc(degreeNumber: number, key: KeyScale): number {\n const tones = scaleTonesInDegreeOrder(key);\n if (tones.length === 0) {\n return mod12(key.rootPc);\n }\n return tones[(degreeNumber - 1) % tones.length] ?? mod12(key.rootPc);\n}\n\n/** Choose a seventh-chord quality from a triad label and the numeral case. */\nfunction seventhQuality(base: 'maj' | 'min' | 'dim' | 'aug', halfDim: boolean): ChordQuality {\n if (halfDim) {\n return 'm7b5';\n }\n if (base === 'dim') {\n return 'dim7';\n }\n if (base === 'aug') {\n return 'aug7';\n }\n return base === 'maj' ? 'dom7' : 'min7';\n}\n\n/** Figure strings that denote a recognized figured-bass inversion. */\nconst INVERSION_FIGURES = new Set(['6', '64', '65', '43', '42', '2', '7']);\n\n/**\n * Canonical Roman-numeral rendering (numeral case and quality suffix) for every\n * supported chord quality. The table is the single source of truth for both\n * directions: {@link chordToRoman} renders from it and {@link romanToChord}\n * recognizes its exact case-sensitive suffixes, so the two stay mutual\n * inverses by construction. Suffixes are chosen to never collide with\n * figured-bass inversion digits (`6`, `64`, `65`, `43`, `42`, `2`) — the added\n * sixth is `add6`, the six-nine chord is `69` — and each (case, suffix) pair is\n * unique.\n */\nconst ROMAN_STYLE: Record<ChordQuality, { lower: boolean; suffix: string }> = {\n maj: { lower: false, suffix: '' },\n min: { lower: true, suffix: '' },\n dim: { lower: true, suffix: 'o' },\n aug: { lower: false, suffix: '+' },\n maj7: { lower: false, suffix: 'maj7' },\n min7: { lower: true, suffix: '7' },\n dom7: { lower: false, suffix: '7' },\n dim7: { lower: true, suffix: 'o7' },\n m7b5: { lower: true, suffix: 'ø7' },\n minMaj7: { lower: true, suffix: 'maj7' },\n aug7: { lower: false, suffix: '+7' },\n augMaj7: { lower: false, suffix: '+maj7' },\n majb5: { lower: false, suffix: 'b5' },\n '6': { lower: false, suffix: 'add6' },\n min6: { lower: true, suffix: 'add6' },\n '6/9': { lower: false, suffix: '69' },\n sus2: { lower: false, suffix: 'sus2' },\n sus4: { lower: false, suffix: 'sus4' },\n add9: { lower: false, suffix: 'add9' },\n add11: { lower: false, suffix: 'add11' },\n maj9: { lower: false, suffix: 'maj9' },\n min9: { lower: true, suffix: '9' },\n dom9: { lower: false, suffix: '9' },\n '7b9': { lower: false, suffix: '7b9' },\n '7#9': { lower: false, suffix: '7#9' },\n '7#11': { lower: false, suffix: '7#11' },\n '7b13': { lower: false, suffix: '7b13' },\n '11': { lower: false, suffix: '11' },\n '13': { lower: false, suffix: '13' },\n '5': { lower: false, suffix: '5' },\n};\n\n/** Reverse lookup of {@link ROMAN_STYLE}: `(case, exact suffix) -> quality`. */\nconst SUFFIX_QUALITY: ReadonlyMap<string, ChordQuality> = new Map(\n (Object.entries(ROMAN_STYLE) as [ChordQuality, { lower: boolean; suffix: string }][]).map(\n ([quality, style]) => [`${style.lower ? 'l' : 'u'}:${style.suffix}`, quality],\n ),\n);\n\n/** Read figured-bass digits into a chord inversion and whether a seventh is implied. */\nfunction parseInversion(figures: string): { inversion: number; seventh: boolean } {\n if (figures === '65') {\n return { inversion: 1, seventh: true };\n }\n if (figures === '43') {\n return { inversion: 2, seventh: true };\n }\n if (figures === '42' || figures === '2') {\n return { inversion: 3, seventh: true };\n }\n if (figures === '7') {\n return { inversion: 0, seventh: true };\n }\n if (figures === '64') {\n return { inversion: 2, seventh: false };\n }\n if (figures === '6') {\n return { inversion: 1, seventh: false };\n }\n return { inversion: 0, seventh: false };\n}\n\n/** Parse a Roman numeral (no secondary '/') into a root, quality, and inversion. */\nfunction parseSimpleRoman(\n text: string,\n key: KeyScale,\n): { rootPc: number; quality: ChordQuality; inversion: number } {\n const match = /^([b#]?)([iIvV]+)(.*)$/.exec(text.trim());\n if (!match) {\n throw new Error(`Invalid Roman numeral: ${text}`);\n }\n const accidental = match[1] === 'b' ? -1 : match[1] === '#' ? 1 : 0;\n const glyph = (match[2] ?? '').toUpperCase();\n const degreeNumber = ROMAN_TO_DEGREE[glyph];\n if (degreeNumber === undefined) {\n throw new Error(`Invalid Roman numeral: ${text}`);\n }\n const isUpper = (match[2] ?? '')[0] === (match[2] ?? '')[0]?.toUpperCase();\n const suffix = match[3] ?? '';\n const rootPc = mod12(degreeRootPc(degreeNumber, key) + accidental);\n\n // Canonical quality suffixes (exact match, case-sensitive on the numeral)\n // come first so every chordToRoman rendering re-parses to the same quality:\n // `V9` -> dom9 but `ii9` -> min9 and `Imaj9` -> maj9, and added-tone suffixes\n // whose digits would otherwise be misread as figured bass (`Iadd6`, `I69`,\n // `Isus2`, `Iadd11`) resolve to their qualities in root position.\n const canonical = SUFFIX_QUALITY.get(`${isUpper ? 'u' : 'l'}:${suffix}`);\n if (canonical !== undefined) {\n return { rootPc, quality: canonical, inversion: 0 };\n }\n\n const isDim = /o|°|dim/.test(suffix);\n const isAug = /\\+|aug/.test(suffix);\n const isHalfDim = /ø/.test(suffix);\n const explicitMaj7 = /maj7|M7/.test(suffix);\n const figures = suffix.replace(/maj7|M7/g, '').replace(/[^0-9]/g, '');\n\n // Reject figure strings that are neither a known figured-bass inversion nor a\n // canonical quality suffix rather than silently degrading to a root triad.\n if (figures !== '' && !INVERSION_FIGURES.has(figures)) {\n throw new Error(`Unsupported figured-bass or extension \"${figures}\" in Roman numeral: ${text}`);\n }\n\n const { inversion, seventh } = parseInversion(figures);\n // The ø glyph is the half-diminished seventh by definition (there is no\n // half-diminished triad), so it always implies a seventh.\n const hasSeventh = explicitMaj7 || seventh || isHalfDim;\n\n let base: 'maj' | 'min' | 'dim' | 'aug';\n if (isDim || isHalfDim) {\n base = 'dim';\n } else if (isAug) {\n base = 'aug';\n } else {\n base = isUpper ? 'maj' : 'min';\n }\n\n let quality: ChordQuality;\n if (explicitMaj7) {\n quality = base === 'min' ? 'minMaj7' : base === 'aug' ? 'augMaj7' : 'maj7';\n } else if (hasSeventh) {\n quality = seventhQuality(base, isHalfDim);\n } else if (base === 'dim') {\n quality = 'dim';\n } else if (base === 'aug') {\n quality = 'aug';\n } else {\n quality = base;\n }\n return { rootPc, quality, inversion };\n}\n\n/** Build a chord from a parsed Roman numeral, attaching a bass for inversions. */\nfunction chordFromParsed(parsed: {\n rootPc: number;\n quality: ChordQuality;\n inversion: number;\n}): Chord {\n const chord = makeChord(parsed.rootPc, parsed.quality);\n if (parsed.inversion > 0 && parsed.inversion < chord.intervals.length) {\n chord.bassPc = mod12(parsed.rootPc + (chord.intervals[parsed.inversion] ?? 0));\n }\n return chord;\n}\n\n/**\n * Build the chord denoted by a Roman numeral in a key.\n *\n * Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`\n * suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions\n * (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash\n * (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree\n * whose root becomes a local major tonic for the applied chord. Inverted chords\n * carry a `bassPc`.\n *\n * The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==\n * `m7b5`), since no half-diminished triad exists. Extension and added-tone\n * suffixes are the canonical case-sensitive forms emitted by\n * {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->\n * `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->\n * `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->\n * `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.\n * A figure string that is neither a recognized inversion nor a supported\n * quality suffix throws rather than silently degrading to a triad.\n *\n * @param text The Roman numeral.\n * @param key The prevailing key.\n * @returns The chord.\n * @example\n * ```ts\n * import { romanToChord, majorKey } from '@libraz/libcantus';\n * romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }\n * ```\n * @category Functional Harmony\n */\nexport function romanToChord(text: string, key: KeyScale): Chord {\n const trimmed = text.trim();\n const slash = trimmed.indexOf('/');\n if (slash >= 0) {\n const applied = trimmed.slice(0, slash);\n const target = trimmed.slice(slash + 1);\n const targetRoot = parseSimpleRoman(target, key).rootPc;\n const localKey = majorKey(targetRoot);\n return chordFromParsed(parseSimpleRoman(applied, localKey));\n }\n return chordFromParsed(parseSimpleRoman(trimmed, key));\n}\n\n/** Case and suffix for rendering a chord quality as a Roman numeral. */\nfunction romanStyle(quality: ChordQuality): { lower: boolean; suffix: string } {\n return ROMAN_STYLE[quality];\n}\n\n/** Choose the degree number and accidental to spell a root as a Roman numeral. */\nfunction romanSpelling(\n rootPc: number,\n key: KeyScale,\n): { degreeNumber: number; accidental: string } {\n const tones = scaleTonesInDegreeOrder(key);\n const diatonic = tones.indexOf(mod12(rootPc));\n if (diatonic >= 0) {\n return { degreeNumber: diatonic + 1, accidental: '' };\n }\n // Chromatic root: prefer a flat of the diatonic degree a semitone above it,\n // then a sharp of the degree a semitone below. Degree 1 (the tonic) and\n // degree 5 (the dominant) are skipped in the flat pass, so a raised leading\n // tone spells as `#vii` rather than a flat tonic `bI`, and the tritone above\n // the tonic spells as `#iv` rather than a flat fifth `bV` (matching the\n // conventional `OFFSET_SPELLING` for offset 6).\n for (let i = 0; i < tones.length; i += 1) {\n const degreeNumber = i + 1;\n if (degreeNumber === 1 || degreeNumber === 5) {\n continue;\n }\n if (mod12((tones[i] ?? 0) - 1) === mod12(rootPc)) {\n return { degreeNumber, accidental: 'b' };\n }\n }\n for (let i = 0; i < tones.length; i += 1) {\n if (mod12((tones[i] ?? 0) + 1) === mod12(rootPc)) {\n return { degreeNumber: i + 1, accidental: '#' };\n }\n }\n const [degreeNumber, accidental] = OFFSET_SPELLING[mod12(rootPc - key.rootPc)] ?? [1, ''];\n return { degreeNumber, accidental };\n}\n\n/** Quality marker (without the seventh digit) used when a figure carries the 7. */\nfunction baseMarker(quality: ChordQuality): string {\n if (quality === 'dim' || quality === 'dim7') {\n return 'o';\n }\n if (quality === 'm7b5') {\n return 'ø';\n }\n if (quality === 'aug' || quality === 'aug7') {\n return '+';\n }\n if (quality === 'augMaj7') {\n return '+maj7';\n }\n if (quality === 'maj7' || quality === 'minMaj7') {\n return 'maj7';\n }\n return '';\n}\n\nconst TRIAD_FIGURES: Record<number, string> = { 1: '6', 2: '64' };\nconst SEVENTH_FIGURES: Record<number, string> = { 1: '65', 2: '43', 3: '42' };\n\n/** Qualities whose inversions render as lossless triad figures (6, 64). */\nconst TRIAD_FIGURE_QUALITIES: ReadonlySet<ChordQuality> = new Set(['maj', 'min', 'dim', 'aug']);\n\n/**\n * Qualities carrying a chordal seventh, whose inversions render as seventh\n * figures (65, 43, 42). Membership is decided by the quality itself — a 7th\n * above the root (10 or 11 semitones, or the diminished 7th of `dim7`) — never\n * by interval count, which would turn added-tone chords into false sevenths.\n */\nconst SEVENTH_FIGURE_QUALITIES: ReadonlySet<ChordQuality> = new Set([\n 'maj7',\n 'min7',\n 'dom7',\n 'dim7',\n 'm7b5',\n 'minMaj7',\n 'aug7',\n 'augMaj7',\n]);\n\n/**\n * Render a chord as a Roman numeral relative to a key.\n *\n * Diatonic roots take their scale-degree numeral directly, so numerals are\n * correct in both major and minor keys (and any custom scale). The quality\n * selects the case and suffix; chromatic roots receive a flat/sharp spelling by\n * convention. When the chord carries a `bassPc` on a chord tone, a figured-bass\n * inversion (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true\n * seventh chords; added-tone and extended qualities have no lossless figure and\n * render in root position instead (the bass is dropped, pitch classes are\n * preserved).\n *\n * @param chord The chord to name.\n * @param key The prevailing key.\n * @returns The Roman numeral string.\n * @example\n * ```ts\n * import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';\n * chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)\n * ```\n * @category Functional Harmony\n */\nexport function chordToRoman(chord: Chord, key: KeyScale): string {\n const { degreeNumber, accidental } = romanSpelling(chord.rootPc, key);\n const { lower, suffix } = romanStyle(chord.quality);\n const numeral: string = ROMAN[degreeNumber - 1] ?? 'I';\n const cased = lower ? numeral.toLowerCase() : numeral;\n\n let inversion = 0;\n if (chord.bassPc !== undefined) {\n const idx = chord.intervals.findIndex((iv) => mod12(chord.rootPc + iv) === chord.bassPc);\n if (idx > 0) {\n inversion = idx;\n }\n }\n if (inversion > 0) {\n const figure = SEVENTH_FIGURE_QUALITIES.has(chord.quality)\n ? SEVENTH_FIGURES[inversion]\n : TRIAD_FIGURE_QUALITIES.has(chord.quality)\n ? TRIAD_FIGURES[inversion]\n : undefined;\n if (figure !== undefined) {\n return `${accidental}${cased}${baseMarker(chord.quality)}${figure}`;\n }\n // No lossless figured-bass symbol exists — the quality is an added-tone or\n // extended chord, or the bass falls on a tension beyond the seventh — so\n // fall back to root-position rendering with the quality suffix rather than\n // emitting a figure that would re-parse as a different chord.\n }\n return `${accidental}${cased}${suffix}`;\n}\n\n/**\n * The harmonic function of a chord in a key, from its root's offset above the\n * tonic. The mapping follows common-practice major-key function and is a useful\n * approximation in minor and for borrowed chords.\n *\n * @param chord The chord.\n * @param key The prevailing key.\n * @returns The harmonic function.\n * @category Functional Harmony\n */\nexport function functionOf(chord: Chord, key: KeyScale): HarmonicFunction {\n return FUNCTION_BY_OFFSET[mod12(chord.rootPc - key.rootPc)] ?? 'tonic';\n}\n\n/**\n * The origin of a recognized non-diatonic chord, or null when none applies.\n *\n * @category Functional Harmony\n */\nexport type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;\n\n/**\n * The result of {@link analyzeChord}: function, borrowing, and Roman numeral.\n *\n * @category Functional Harmony\n */\nexport type ChordAnalysis = {\n function: HarmonicFunction;\n borrowed: boolean;\n source: BorrowedSource;\n roman: string;\n};\n\n/**\n * Whether every pitch class of a chord belongs to the key's scale.\n *\n * The test is strict against the key's own mode mask: in a natural-minor key\n * the harmonic-minor dominant (major V) is *not* diatonic, since the raised\n * leading tone lies outside the mask. Borrowing predicates treat that case as\n * an in-key alteration separately (see {@link isBorrowedChord}).\n *\n * @param chord The chord to test.\n * @param key The prevailing key.\n * @returns True if all chord pitch classes are scale tones.\n * @category Functional Harmony\n */\nexport function isDiatonic(chord: Chord, key: KeyScale): boolean {\n return chordPitchClasses(chord).every((pc) => isScaleTone(pc, key));\n}\n\n/**\n * The parallel key: same tonic, opposite mode.\n *\n * A key with a minor third (natural/harmonic/melodic minor, dorian, phrygian)\n * maps to the parallel major; any other key maps to the parallel natural minor.\n *\n * @param key The key to mirror.\n * @returns The parallel major or natural-minor key on the same tonic.\n * @category Functional Harmony\n */\nexport function parallelKey(key: KeyScale): KeyScale {\n return {\n rootPc: mod12(key.rootPc),\n modeMask12: isMinorKey(key) ? MAJOR_MASK : NATURAL_MINOR_MASK,\n };\n}\n\n/**\n * In a minor key, whether a non-diatonic chord is explained by the harmonic\n * minor scale on the same tonic (major V, V7, the raised-leading-tone viio).\n * Such chords are in-key chromatic alterations, not modal interchange.\n */\nfunction isHarmonicMinorAlteration(chord: Chord, key: KeyScale): boolean {\n return (\n isMinorKey(key) &&\n isDiatonic(chord, { rootPc: mod12(key.rootPc), modeMask12: HARMONIC_MINOR_MASK })\n );\n}\n\n/** Whether a chord is the Neapolitan: a major triad on the flat second degree. */\nfunction isNeapolitan(chord: Chord, key: KeyScale): boolean {\n return mod12(chord.rootPc - key.rootPc) === 1 && chord.quality === 'maj';\n}\n\n/**\n * Whether a chord is borrowed from the parallel mode (modal interchange).\n *\n * True when the chord is not diatonic to `key` but is diatonic to its\n * {@link parallelKey} — e.g. iv, bVI, or bVII in a major key, or the Picardy\n * tonic and major IV in a minor key. Two non-diatonic families are excluded:\n * chords diatonic to neither mode (they are chromatic, not borrowed), and, in\n * a minor key, chords explained by the harmonic minor scale (the major\n * dominant and raised-leading-tone chords), which are in-key alterations\n * rather than interchange even though they happen to fit the parallel major.\n *\n * @param chord The chord to test.\n * @param key The prevailing key.\n * @returns True if the chord is borrowed from the parallel mode.\n * @category Functional Harmony\n */\nexport function isBorrowedChord(chord: Chord, key: KeyScale): boolean {\n if (isDiatonic(chord, key)) {\n return false;\n }\n if (isHarmonicMinorAlteration(chord, key)) {\n return false;\n }\n return isDiatonic(chord, parallelKey(key));\n}\n\n/**\n * Identify where a non-diatonic chord comes from.\n *\n * The Neapolitan (major triad on b2) is recognized first, since it sits\n * outside both parallel modes; parallel-mode borrowing follows the\n * {@link isBorrowedChord} rules. Diatonic chords, harmonic-minor alterations,\n * and unrecognized chromatic chords all yield null.\n *\n * @param chord The chord to classify.\n * @param key The prevailing key.\n * @returns The borrowing source, or null.\n * @category Functional Harmony\n */\nexport function borrowedSource(chord: Chord, key: KeyScale): BorrowedSource {\n if (isDiatonic(chord, key)) {\n return null;\n }\n if (isNeapolitan(chord, key)) {\n return 'neapolitan';\n }\n if (isBorrowedChord(chord, key)) {\n return isMinorKey(key) ? 'parallel-major' : 'parallel-minor';\n }\n return null;\n}\n\n/** Diminished-family qualities: diminished triad, dim7, half-diminished. */\nfunction isDiminishedQuality(quality: ChordQuality): boolean {\n return quality === 'dim' || quality === 'dim7' || quality === 'm7b5';\n}\n\n/** Whether the chord's interval template carries a major third above the root. */\nfunction hasMajorThird(chord: Chord): boolean {\n return chord.intervals.some((interval) => mod12(interval) === 4);\n}\n\n/**\n * Quality-aware harmonic function, refining the offset table where chord\n * quality disambiguates: diminished chords on the leading tone or the raised\n * subdominant resolve by semitone and act as dominants; the Neapolitan and the\n * major-third chords on bVI/bVII borrowed from the parallel minor act as\n * subdominant (predominant) harmony. All other chords keep {@link functionOf}.\n */\nfunction qualityAwareFunction(chord: Chord, key: KeyScale): HarmonicFunction {\n const offset = mod12(chord.rootPc - key.rootPc);\n if (isDiminishedQuality(chord.quality) && (offset === 11 || offset === 6)) {\n return 'dominant';\n }\n if (isNeapolitan(chord, key)) {\n return 'subdominant';\n }\n if (!isMinorKey(key) && hasMajorThird(chord) && (offset === 8 || offset === 10)) {\n return 'subdominant';\n }\n return functionOf(chord, key);\n}\n\n/**\n * Analyze a chord in a key: harmonic function, borrowing, and Roman numeral.\n *\n * The function is quality-aware (see the predicates behind it), the source\n * follows {@link borrowedSource}, and the numeral comes from\n * {@link chordToRoman}. `borrowed` is true whenever a source is identified —\n * including the Neapolitan, which the stricter parallel-mode predicate\n * {@link isBorrowedChord} does not count.\n *\n * @param chord The chord to analyze.\n * @param key The prevailing key.\n * @returns The chord analysis.\n * @example\n * ```ts\n * import { analyzeChord, makeChord, majorKey } from '@libraz/libcantus';\n * analyzeChord(makeChord(7, 'dom7'), majorKey(0));\n * // { function: 'dominant', borrowed: false, source: null, roman: 'V7' }\n * ```\n * @category Functional Harmony\n */\nexport function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis {\n const source = borrowedSource(chord, key);\n return {\n function: qualityAwareFunction(chord, key),\n borrowed: source !== null,\n source,\n roman: chordToRoman(chord, key),\n };\n}\n\n/**\n * Classify the cadence formed by moving from one chord to the next.\n *\n * - authentic: V (dominant a fifth above the tonic) to I\n * - plagal: IV (a fourth above the tonic) to I\n * - deceptive: V to the submediant (diatonic vi or borrowed bVI in major, VI in\n * minor)\n * - half: any chord other than the dominant itself to V\n *\n * A static V-to-V repeat with no root motion is not a cadence and yields null.\n *\n * @param from The penultimate chord.\n * @param to The final chord.\n * @param key The prevailing key.\n * @returns The cadence type, or null.\n * @example\n * ```ts\n * import { detectCadence, makeChord, majorKey } from '@libraz/libcantus';\n * detectCadence(makeChord(7, 'maj'), makeChord(0, 'maj'), majorKey(0)); // => 'authentic'\n * ```\n * @category Functional Harmony\n */\nexport function detectCadence(from: Chord, to: Chord, key: KeyScale): Cadence {\n const tonic = mod12(key.rootPc);\n const fromOffset = mod12(from.rootPc - tonic);\n const toOffset = mod12(to.rootPc - tonic);\n // Deceptive targets: the diatonic submediant (vi at offset 9 in major, VI at\n // offset 8 in minor) plus, in a major key, the borrowed flat-submediant bVI\n // at offset 8.\n const deceptiveTargets = isMinorKey(key) ? [8] : [8, 9];\n if (fromOffset === 7 && toOffset === 0) {\n return 'authentic';\n }\n if (fromOffset === 5 && toOffset === 0) {\n return 'plagal';\n }\n if (fromOffset === 7 && deceptiveTargets.includes(toOffset)) {\n return 'deceptive';\n }\n // A move to the dominant is a half cadence, but a no-root-motion V-to-V repeat\n // is not a cadence at all.\n if (toOffset === 7 && fromOffset !== 7) {\n return 'half';\n }\n return null;\n}\n\n/**\n * The secondary dominant (V7) that tonicizes a scale degree.\n *\n * @param targetDegree 0-based scale degree to tonicize.\n * @param key The prevailing key.\n * @returns A dominant-seventh chord a fifth above the target's root.\n * @category Functional Harmony\n */\nexport function secondaryDominant(targetDegree: number, key: KeyScale): Chord {\n const targetRoot = degreeRootPc(targetDegree + 1, key);\n return makeChord(mod12(targetRoot + 7), 'dom7');\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 */\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 additive grouping of the bar's main pulses, as the felt-beat\n * lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or\n * `[3, 2]` for 5/8. The entries must be positive integers summing to\n * {@link pulsesPerBar}. When present, the head pulse of each group (other\n * than the downbeat) is treated as a secondary strong pulse by\n * {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses\n * are weighted equally as flat, evenly divided pulses.\n */\n grouping?: number[];\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 bar: number;\n /** Quarter-note offset from the start of the bar. */\n beat: number;\n};\n\nconst EPS = 1e-9;\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\"`.\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.\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 const match = /^\\s*(\\d+)\\s*\\/\\s*(\\d+)\\s*$/.exec(text);\n if (!match) {\n throw new Error(`Invalid time signature: ${text}`);\n }\n const numerator = Number.parseInt(match[1] ?? '', 10);\n const denominator = Number.parseInt(match[2] ?? '', 10);\n if (numerator <= 0 || denominator <= 0) {\n throw new Error(`Invalid time signature: ${text}`);\n }\n return { numerator, denominator };\n}\n\n/**\n * Render a time signature as `\"n/d\"`.\n *\n * @category Rhythm & Meter\n */\nexport function formatTimeSignature(ts: TimeSignature): string {\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.\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 return ts.numerator % 3 === 0 && ts.numerator > 3;\n}\n\n/** Length of one denominator unit in quarter-note beats. */\nfunction unitBeats(ts: TimeSignature): number {\n return 4 / ts.denominator;\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 return ts.numerator * unitBeats(ts);\n}\n\n/** Length of one main pulse (a dotted value in compound meters) in quarter notes. */\nfunction pulseBeats(ts: TimeSignature): number {\n return isCompound(ts) ? 3 * unitBeats(ts) : unitBeats(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 return beatsPerBar(ts) / pulseBeats(ts);\n}\n\n/**\n * Whether `grouping` is a valid additive grouping for a bar of `pulses` main\n * pulses: a non-empty list of positive integers summing to `pulses`.\n */\nfunction isValidGrouping(grouping: number[], pulses: number): boolean {\n if (grouping.length === 0) {\n return false;\n }\n let sum = 0;\n for (const g of grouping) {\n if (!Number.isInteger(g) || g <= 0) {\n return false;\n }\n sum += g;\n }\n return sum === pulses;\n}\n\n/** Whether `pulseIndex` is the head pulse of one of the additive groups. */\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 * 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 ts The time signature.\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, ts: TimeSignature): BarPosition {\n const barLen = beatsPerBar(ts);\n const bar = Math.floor(beatInQuarters / barLen);\n return { bar, beat: beatInQuarters - bar * barLen };\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 ts The time signature.\n * @returns The absolute position in quarter-note beats.\n * @category Rhythm & Meter\n */\nexport function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number {\n return pos.bar * beatsPerBar(ts) + 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).\n *\n * @param beatInQuarters Absolute or in-bar quarter-note position.\n * @param ts The time signature.\n * @returns The metric weight (0–3).\n * @throws If `ts.grouping` is present but is not a positive-integer list\n * summing to {@link pulsesPerBar}.\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, ts: TimeSignature): number {\n const { beat } = beatToBarPosition(beatInQuarters, ts);\n const pulse = pulseBeats(ts);\n if (!isMultiple(beat, pulse)) {\n return 0;\n }\n const pulses = pulsesPerBar(ts);\n const pulseIndex = Math.round(beat / pulse) % pulses;\n if (pulseIndex === 0) {\n return 3;\n }\n const grouping = ts.grouping;\n if (grouping !== undefined) {\n if (!isValidGrouping(grouping, pulses)) {\n throw new Error(\n `Invalid grouping [${grouping.join(', ')}] for ${formatTimeSignature(ts)}: ` +\n `entries must be positive integers summing to ${pulses}`,\n );\n }\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 or in-bar quarter-note position.\n * @param ts The time signature.\n * @returns True on strong beats.\n * @category Rhythm & Meter\n */\nexport function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolean {\n return metricWeight(beatInQuarters, ts) >= 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 if (!Number.isInteger(count) || count <= 0) {\n throw new Error(`Invalid tuplet count: ${count}`);\n }\n return new Array<number>(count).fill(totalBeats / count);\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport {\n createsHiddenParallelPerfect,\n createsParallelPerfect,\n createsVerticalDissonance,\n isForbiddenMelodicLeap,\n} from '../counterpoint/index.js';\nimport { isScaleTone } from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * Severity policy: `strict` counterpoint vs. lenient `pop` voice-leading.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyProfile = 'strict' | 'pop';\n\n/**\n * Overall placeability verdict for a candidate pitch.\n *\n * @category Arrangement & Analysis\n */\nexport enum NoteSafety {\n Safe = 0,\n Warning = 1,\n Dissonant = 2,\n}\n\n/**\n * Bit flags describing why a pitch received its verdict.\n *\n * @category Arrangement & Analysis\n */\nexport enum ReasonFlag {\n ChordTone = 1 << 0,\n Tension = 1 << 1,\n AvoidNote = 1 << 2,\n ScaleTone = 1 << 3,\n NonScale = 1 << 4,\n OutOfRange = 1 << 5,\n Tritone = 1 << 6,\n LargeLeap = 1 << 7,\n MinorSecond = 1 << 8,\n MajorSeventh = 1 << 9,\n VerticalDissonance = 1 << 10,\n ParallelPerfect = 1 << 11,\n HiddenParallel = 1 << 12,\n VoiceCrossing = 1 << 13,\n Suspension = 1 << 14,\n NeedsResolution = 1 << 15,\n}\n\n/**\n * A neighbouring voice's current and previous pitch.\n *\n * @category Arrangement & Analysis\n */\nexport type VoiceSnapshot = {\n pitch: number;\n prevPitch?: number;\n};\n\n/**\n * Everything needed to evaluate one candidate pitch.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyQuery = {\n profile: SafetyProfile;\n candidatePitch: number;\n prevPitch?: number;\n chord: Chord | null;\n key: KeyScale;\n otherVoices: VoiceSnapshot[];\n strongBeat: boolean;\n vocalLow?: number;\n vocalHigh?: number;\n};\n\n/**\n * The verdict, reason flags, and optional resolution guidance.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyResult = {\n safety: NoteSafety;\n reasons: number;\n resolveTo?: number;\n suggestions?: number[];\n rationale?: string;\n};\n\n/** Semitone radius searched around a rejected candidate for safe alternatives. */\nconst SUGGESTION_WINDOW = 12;\n/** Maximum number of alternative pitches returned in `SafetyResult.suggestions`. */\nconst MAX_SUGGESTIONS = 3;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction intervalAboveRoot(pitch: number, chord: Chord): number {\n return (((pitchClass(pitch) - pitchClass(chord.rootPc)) % 12) + 12) % 12;\n}\n\nfunction isChordMember(pitch: number, chord: Chord): boolean {\n return chordPitchClasses(chord).includes(pitchClass(pitch));\n}\n\n/** Whether the perfect fourth is an avoid note over this chord. */\nfunction avoidsFourth(chord: Chord): boolean {\n return chord.intervals.includes(4) && !chord.intervals.includes(5);\n}\n\n/** Whether the major seventh is an avoid note over this chord (dominant). */\nfunction avoidsMajorSeventh(chord: Chord): boolean {\n return chord.intervals.includes(4) && chord.intervals.includes(10);\n}\n\n/** Nearest chord tone at or below the candidate, within two semitones. */\nfunction stepResolution(pitch: number, chord: Chord): number | undefined {\n for (let delta = 1; delta <= 2; delta += 1) {\n if (isChordMember(pitch - delta, chord)) {\n return pitch - delta;\n }\n }\n return undefined;\n}\n\n/**\n * Evaluate the safety of placing a candidate pitch in a voice.\n *\n * Reasons are merged from harmonic context (chord tone / tension / avoid / scale)\n * and counterpoint (vertical dissonance, parallels, voice crossing). The `strict`\n * profile treats avoid notes and parallels as dissonant; `pop` treats them as\n * warnings. The final verdict is the worst severity among the reasons.\n *\n * @param q The candidate and its harmonic/voice-leading context.\n * @returns The verdict, reason bitmask, and optional resolution guidance.\n * @example\n * ```ts\n * import { evaluateSafety, makeChord, majorKey, NoteSafety } from '@libraz/libcantus';\n * const result = evaluateSafety({\n * profile: 'pop',\n * candidatePitch: 60, // C over a C major chord\n * chord: makeChord(0, 'maj'),\n * key: majorKey(0),\n * otherVoices: [],\n * strongBeat: true,\n * });\n * result.safety === NoteSafety.Safe; // true — C is a chord tone\n * ```\n * @category Arrangement & Analysis\n */\nexport function evaluateSafety(q: SafetyQuery): SafetyResult {\n return evaluateInternal(q, true);\n}\n\n/**\n * Core safety evaluation.\n *\n * @param q The candidate and its harmonic/voice-leading context.\n * @param collectSuggestions Whether to search for safe alternatives on a\n * non-Safe verdict. Set false during that search itself to bound recursion.\n * @returns The verdict, reason bitmask, and optional guidance.\n */\nfunction evaluateInternal(q: SafetyQuery, collectSuggestions: boolean): SafetyResult {\n let reasons = 0;\n let level = NoteSafety.Safe;\n let resolveTo: number | undefined;\n const raise = (l: NoteSafety) => {\n if (l > level) {\n level = l;\n }\n };\n const avoidSeverity = q.profile === 'strict' ? NoteSafety.Dissonant : NoteSafety.Warning;\n const parallelSeverity = avoidSeverity;\n const pitch = q.candidatePitch;\n\n if (\n (q.vocalLow !== undefined && pitch < q.vocalLow) ||\n (q.vocalHigh !== undefined && pitch > q.vocalHigh)\n ) {\n reasons |= ReasonFlag.OutOfRange;\n raise(NoteSafety.Warning);\n }\n\n const inScale = isScaleTone(pitch, q.key);\n const chord = q.chord;\n\n if (chord && isChordMember(pitch, chord)) {\n reasons |= ReasonFlag.ChordTone;\n } else if (chord) {\n const ic = intervalAboveRoot(pitch, chord);\n const isTension = ic === 2 || ic === 5 || ic === 9;\n const avoid = (ic === 5 && avoidsFourth(chord)) || (ic === 11 && avoidsMajorSeventh(chord));\n if (avoid) {\n reasons |= ReasonFlag.AvoidNote;\n if (isTension) {\n reasons |= ReasonFlag.Tension;\n }\n reasons |= ReasonFlag.NeedsResolution;\n resolveTo = stepResolution(pitch, chord);\n raise(avoidSeverity);\n } else if (isTension && inScale) {\n reasons |= ReasonFlag.Tension;\n raise(NoteSafety.Warning);\n } else if (inScale) {\n reasons |= ReasonFlag.ScaleTone;\n raise(NoteSafety.Warning);\n } else {\n reasons |= ReasonFlag.NonScale;\n raise(NoteSafety.Dissonant);\n }\n } else if (inScale) {\n reasons |= ReasonFlag.ScaleTone;\n raise(NoteSafety.Warning);\n } else {\n reasons |= ReasonFlag.NonScale;\n raise(NoteSafety.Dissonant);\n }\n\n // Harmonic tritone against a chord tone (except in dominant chords, where the\n // tritone is a defining, stable colour).\n if (chord && !(chord.intervals.includes(4) && chord.intervals.includes(10))) {\n const ic = intervalAboveRoot(pitch, chord);\n const toneOffsets = chord.intervals.map((i) => ((i % 12) + 12) % 12);\n if (toneOffsets.some((t) => Math.abs(ic - t) === 6)) {\n reasons |= ReasonFlag.Tritone;\n }\n }\n\n if (q.prevPitch !== undefined) {\n // Quality flags reduce the melodic interval to its pitch-class interval so\n // compound intervals are treated uniformly with their simple form. The\n // forbidden-leap flag defers to the counterpoint rule, which preserves the\n // octave boundary (an octave leap is allowed, wider leaps are not).\n const pc = Math.abs(pitch - q.prevPitch) % 12;\n if (pc === 6) {\n reasons |= ReasonFlag.Tritone;\n }\n if (isForbiddenMelodicLeap(q.prevPitch, pitch)) {\n reasons |= ReasonFlag.LargeLeap;\n }\n if (pc === 1) {\n reasons |= ReasonFlag.MinorSecond;\n }\n if (pc === 11) {\n reasons |= ReasonFlag.MajorSeventh;\n }\n }\n\n if (q.strongBeat) {\n const twoVoice = q.otherVoices.length === 1;\n const prev = q.prevPitch;\n for (const ov of q.otherVoices) {\n if (!createsVerticalDissonance(pitch, ov.pitch, twoVoice)) {\n continue;\n }\n reasons |= ReasonFlag.VerticalDissonance;\n raise(NoteSafety.Dissonant);\n // A held pitch that was consonant on the previous step and is now\n // dissonant against the same voice is a prepared suspension.\n if (\n prev !== undefined &&\n pitch === prev &&\n ov.prevPitch !== undefined &&\n !createsVerticalDissonance(prev, ov.prevPitch, twoVoice)\n ) {\n reasons |= ReasonFlag.Suspension;\n }\n }\n }\n\n if (q.prevPitch !== undefined) {\n const prev = q.prevPitch;\n for (const ov of q.otherVoices) {\n if (ov.prevPitch === undefined) {\n continue;\n }\n // createsParallelPerfect covers every perfect class (unison/octave and\n // fifth), so no separate octave check is needed.\n if (createsParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {\n reasons |= ReasonFlag.ParallelPerfect;\n raise(parallelSeverity);\n }\n if (createsHiddenParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {\n reasons |= ReasonFlag.HiddenParallel;\n raise(parallelSeverity);\n }\n const crossedNow = pitch - ov.pitch;\n const crossedPrev = prev - ov.prevPitch;\n if (crossedNow !== 0 && crossedPrev !== 0 && crossedNow > 0 !== crossedPrev > 0) {\n reasons |= ReasonFlag.VoiceCrossing;\n raise(parallelSeverity);\n }\n }\n }\n\n const result: SafetyResult = { safety: level, reasons, rationale: describe(reasons, q) };\n if (resolveTo !== undefined) {\n result.resolveTo = resolveTo;\n }\n if (collectSuggestions && level !== NoteSafety.Safe) {\n const suggestions = findSafeNearby(q, pitch);\n if (suggestions.length > 0) {\n result.suggestions = suggestions;\n }\n }\n return result;\n}\n\n/**\n * Find safe alternative pitches near a rejected candidate.\n *\n * Searches outward from the candidate within `SUGGESTION_WINDOW` semitones,\n * probing the pitch below before the one above at each distance so the result\n * is deterministic and ordered by nearness.\n *\n * @param q The safety context of the rejected candidate.\n * @param candidate The candidate pitch that was not Safe.\n * @returns Up to `MAX_SUGGESTIONS` safe pitches, nearest first.\n */\nfunction findSafeNearby(q: SafetyQuery, candidate: number): number[] {\n const out: number[] = [];\n for (let d = 1; d <= SUGGESTION_WINDOW; d += 1) {\n for (const p of [candidate - d, candidate + d]) {\n if (evaluateInternal({ ...q, candidatePitch: p }, false).safety === NoteSafety.Safe) {\n out.push(p);\n if (out.length >= MAX_SUGGESTIONS) {\n return out;\n }\n }\n }\n }\n return out;\n}\n\n/** Build a short human explanation from the reason flags. */\nfunction describe(reasons: number, q: SafetyQuery): string {\n if (reasons & ReasonFlag.OutOfRange) {\n return 'Outside the target vocal range';\n }\n if (reasons & ReasonFlag.Suspension) {\n return 'Prepared suspension — a held consonance now dissonant, awaiting resolution';\n }\n if (reasons & ReasonFlag.VerticalDissonance) {\n return 'Dissonant against a sounding voice on a strong beat';\n }\n if (reasons & ReasonFlag.AvoidNote) {\n return 'Avoid note — clashes with a chord tone a semitone away';\n }\n if (reasons & ReasonFlag.ParallelPerfect) {\n return 'Parallel perfect interval with another voice';\n }\n if (reasons & ReasonFlag.HiddenParallel) {\n return 'Hidden perfect interval by similar motion';\n }\n if (reasons & ReasonFlag.VoiceCrossing) {\n return 'Crosses another voice';\n }\n if (reasons & ReasonFlag.ChordTone) {\n return 'Chord tone';\n }\n if (reasons & ReasonFlag.Tension) {\n return 'Chord tension';\n }\n if (reasons & ReasonFlag.NonScale) {\n return 'Outside the key';\n }\n if (reasons & ReasonFlag.ScaleTone) {\n return 'Scale tone, not in the chord';\n }\n return q.chord ? 'Placeable' : 'No chord context';\n}\n\n/**\n * Enumerate placeable pitches in a range, chord tones first, descending.\n *\n * @param q The safety context minus the candidate pitch.\n * @param pitchLow Lowest MIDI pitch to consider (inclusive).\n * @param pitchHigh Highest MIDI pitch to consider (inclusive).\n * @returns Placeable pitches (non-dissonant), chord tones before others, each group descending.\n * @example\n * ```ts\n * import { enumerateSafePitches, makeChord, majorKey } from '@libraz/libcantus';\n * const pitches = enumerateSafePitches(\n * { profile: 'pop', chord: makeChord(0, 'maj'), key: majorKey(0), otherVoices: [], strongBeat: true },\n * 60,\n * 72,\n * );\n * pitches; // placeable pitches in [60, 72], chord tones first, each group descending\n * ```\n * @category Arrangement & Analysis\n */\nexport function enumerateSafePitches(\n q: Omit<SafetyQuery, 'candidatePitch'>,\n pitchLow: number,\n pitchHigh: number,\n): number[] {\n const chordTones: number[] = [];\n const others: number[] = [];\n if (!Number.isFinite(pitchLow) || !Number.isFinite(pitchHigh)) {\n return [];\n }\n for (let pitch = pitchHigh; pitch >= pitchLow; pitch -= 1) {\n const result = evaluateInternal({ ...q, candidatePitch: pitch }, false);\n if (result.safety === NoteSafety.Dissonant) {\n continue;\n }\n if (result.reasons & ReasonFlag.ChordTone) {\n chordTones.push(pitch);\n } else {\n others.push(pitch);\n }\n }\n return [...chordTones, ...others];\n}\n","/**\n * Recognition: infer a chord name from a set of pitches, or a key from a set of\n * pitch classes. This is the inverse direction of the chord/scale builders,\n * which only go name -> notes.\n */\n\nimport type { Chord, ChordQuality } from '../chord/index.js';\nimport { chordPitchClasses, chordQualities, makeChord } from '../chord/index.js';\nimport {\n HARMONIC_MINOR_MASK,\n MAJOR_MASK,\n MELODIC_MINOR_MASK,\n majorKey,\n minorKey,\n NATURAL_MINOR_MASK,\n} from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * A candidate chord interpretation of a pitch set.\n *\n * @category Recognition\n */\nexport type ChordMatch = {\n rootPc: number;\n quality: ChordQuality;\n /** Chord tones absent from the input (an incomplete voicing). */\n missingPcs: number[];\n /** Input pitch classes not belonging to the chord. */\n extraPcs: number[];\n /** True when the input pitch-class set equals the chord exactly. */\n exact: boolean;\n /** Inversion implied by the lowest note: 0 root position, 1 first, ... */\n inversion: number;\n /** Bass pitch class when inverted (the lowest note is not the root). */\n bassPc?: number;\n};\n\n/**\n * A candidate key interpretation of a pitch-class set.\n *\n * @category Recognition\n */\nexport type KeyMatch = {\n key: KeyScale;\n mode: 'major' | 'minor';\n /** Fraction of input pitch classes that are in the scale, in [0, 1]. */\n fit: number;\n};\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Unique pitch classes of the input, sorted ascending. */\nfunction uniquePitchClasses(pitches: number[]): number[] {\n return [...new Set(pitches.map(pitchClass))].sort((a, b) => a - b);\n}\n\n/**\n * Identify chords matching a set of pitches.\n *\n * Every input pitch class is tried as a root against every known chord quality.\n * A match is reported when all of the chord's tones are present in the input, or\n * when the only absent tone is the perfect fifth (a common omission in shell\n * voicings); matches are ranked best-first by fewest extra notes, then fewest\n * missing notes, then most specific (largest) chord. An exact match (no extras,\n * no missing) is flagged and ranked first.\n *\n * @param pitches MIDI pitches or bare pitch classes (octave-agnostic).\n * @returns Ranked chord interpretations (may be empty).\n * @example\n * ```ts\n * import { detectChord } from '@libraz/libcantus';\n * const matches = detectChord([60, 64, 67]); // C E G\n * matches[0]; // { rootPc: 0, quality: 'maj', exact: true, ... }\n * ```\n * @category Recognition\n */\nexport function detectChord(pitches: number[]): ChordMatch[] {\n const input = uniquePitchClasses(pitches);\n if (input.length === 0) {\n return [];\n }\n const bassPc = pitchClass(Math.min(...pitches));\n const inputSet = new Set(input);\n const matches: ChordMatch[] = [];\n const qualities = chordQualities();\n for (const rootPc of input) {\n for (const quality of qualities) {\n const chord = makeChord(rootPc, quality);\n const tones = chordPitchClasses(chord);\n const toneSet = new Set(tones);\n const missingPcs = tones.filter((pc) => !inputSet.has(pc));\n // Accept an exact-tone match, or one whose only absent tone is the perfect\n // fifth; any other missing tone (third, sus tone, seventh, ...) rejects.\n const fifthPc = pitchClass(rootPc + 7);\n if (missingPcs.length > 1 || (missingPcs.length === 1 && missingPcs[0] !== fifthPc)) {\n continue;\n }\n const extraPcs = input.filter((pc) => !toneSet.has(pc));\n const bassIndex = chord.intervals.findIndex((iv) => pitchClass(rootPc + iv) === bassPc);\n const inversion = bassIndex > 0 ? bassIndex : 0;\n const match: ChordMatch = {\n rootPc,\n quality,\n missingPcs,\n extraPcs,\n exact: extraPcs.length === 0 && missingPcs.length === 0,\n inversion,\n };\n if (inversion > 0) {\n match.bassPc = bassPc;\n }\n matches.push(match);\n }\n }\n matches.sort((a, b) => {\n if (a.extraPcs.length !== b.extraPcs.length) {\n return a.extraPcs.length - b.extraPcs.length;\n }\n if (a.missingPcs.length !== b.missingPcs.length) {\n return a.missingPcs.length - b.missingPcs.length;\n }\n // Prefer root position (the bass is the chord root) on a tie.\n if ((a.inversion === 0) !== (b.inversion === 0)) {\n return a.inversion === 0 ? -1 : 1;\n }\n const aSize = chordPitchClasses(makeChord(a.rootPc, a.quality)).length;\n const bSize = chordPitchClasses(makeChord(b.rootPc, b.quality)).length;\n return bSize - aSize;\n });\n return matches;\n}\n\n/**\n * The single best chord interpretation of a pitch set, or null if none.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns The top-ranked chord, or null when nothing matches.\n * @example\n * ```ts\n * import { detectChordBest } from '@libraz/libcantus';\n * detectChordBest([60, 64, 67]); // C major triad: { rootPc: 0, quality: 'maj', ... }\n * ```\n * @category Recognition\n */\nexport function detectChordBest(pitches: number[]): Chord | null {\n const best = detectChord(pitches)[0];\n if (!best) {\n return null;\n }\n return makeChord(best.rootPc, best.quality, best.bassPc);\n}\n\n/**\n * Minor-scale variants scored for each minor-key candidate. Scoring against all\n * three lets the raised sixth and seventh (e.g. the leading tone G# in A minor)\n * count toward their own tonic instead of only penalizing it.\n */\nconst MINOR_MASK_VARIANTS = [NATURAL_MINOR_MASK, HARMONIC_MINOR_MASK, MELODIC_MINOR_MASK];\n\n/**\n * Rank major and minor keys by how well they contain a set of pitch classes.\n *\n * The tonic is weighted so that, among equally-fitting keys, the one whose root\n * appears in the input is preferred. Minor candidates are scored against the\n * natural, harmonic, and melodic minor variants and keep the best of the three,\n * so a minor cadence containing the leading tone still resolves to its own\n * tonic; the returned key is always the natural-minor scale. Returns all 24\n * keys ranked best-first, or an empty array for an empty input (mirroring\n * {@link detectChord}).\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns Ranked key interpretations (empty for an empty input).\n * @example\n * ```ts\n * import { detectKey } from '@libraz/libcantus';\n * const keys = detectKey([60, 62, 64, 65, 67, 69, 71]); // C major scale\n * keys[0].mode; // 'major', with keys[0].key.rootPc === 0\n * ```\n * @category Recognition\n */\nexport function detectKey(pitches: number[]): KeyMatch[] {\n const input = uniquePitchClasses(pitches);\n if (input.length === 0) {\n return [];\n }\n const counts = new Map<number, number>();\n for (const pc of pitches.map(pitchClass)) {\n counts.set(pc, (counts.get(pc) ?? 0) + 1);\n }\n const total = pitches.length;\n const results: (KeyMatch & { score: number })[] = [];\n for (let tonic = 0; tonic < 12; tonic += 1) {\n for (const mode of ['major', 'minor'] as const) {\n const key = mode === 'major' ? majorKey(tonic) : minorKey(tonic);\n const masks = mode === 'major' ? [MAJOR_MASK] : MINOR_MASK_VARIANTS;\n // Score each scale variant and keep the best; ties keep the earlier\n // (more diatonic) variant.\n let inScale = 0;\n let weighted = Number.NEGATIVE_INFINITY;\n for (const mask of masks) {\n let variantInScale = 0;\n let variantWeighted = 0;\n for (const pc of input) {\n const offset = (pc - tonic + 12) % 12;\n if ((mask >> offset) & 1) {\n variantInScale += 1;\n }\n }\n for (const [pc, count] of counts) {\n const offset = (pc - tonic + 12) % 12;\n if ((mask >> offset) & 1) {\n variantWeighted += count;\n }\n }\n if (variantWeighted > weighted) {\n weighted = variantWeighted;\n inScale = variantInScale;\n }\n }\n weighted += (counts.get(tonic) ?? 0) * 0.5;\n results.push({\n key,\n mode,\n fit: inScale / input.length,\n score: weighted / total,\n });\n }\n }\n results.sort((a, b) => b.score - a.score);\n return results.map(({ key, mode, fit }) => ({ key, mode, fit }));\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses, makeChord } from '../chord/index.js';\nimport type { ChordMatch } from '../detect/index.js';\nimport { detectChord, detectChordBest, detectKey } from '../detect/index.js';\nimport type { Cadence } from '../functional/index.js';\nimport { detectCadence } from '../functional/index.js';\nimport type { TimeSignature } from '../meter/index.js';\nimport { beatsPerBar, metricWeight, parseTimeSignature } from '../meter/index.js';\nimport type { GeneratedChord } from '../progression/index.js';\nimport { isScaleTone, majorKey } from '../scale/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/**\n * A chord occupying a half-open beat span.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordSegment = {\n startBeat: number;\n endBeat: number;\n chord: Chord;\n};\n\n/**\n * A beat-indexed sequence of chord segments.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimeline = {\n /** The chord sounding at a beat, or null when no segment covers it. */\n at: (beat: number) => Chord | null;\n segments: ChordSegment[];\n};\n\n/**\n * Build a chord timeline from placed chords.\n *\n * Each chord spans from its `startBeat` to the next chord's `startBeat`; the last\n * chord runs to `totalBeats`. Segments with no positive length (from duplicate\n * onsets or a last chord at or past `totalBeats`) are dropped. `at(beat)` returns\n * the covering segment's chord, or null when the beat lies outside every segment.\n *\n * @param chords Placed chords in time order.\n * @param totalBeats End of the timeline in beats.\n * @returns A queryable chord timeline.\n * @category Arrangement & Analysis\n */\nexport function chordTimelineFromChords(\n chords: GeneratedChord[],\n totalBeats: number,\n): ChordTimeline {\n const sorted = [...chords].sort((a, b) => a.startBeat - b.startBeat);\n const segments: ChordSegment[] = sorted\n .map((gc, i) => {\n const next = sorted[i + 1];\n const endBeat = Math.max(gc.startBeat, next ? next.startBeat : totalBeats);\n return {\n startBeat: gc.startBeat,\n endBeat,\n chord: makeChord(gc.rootPc, gc.quality, gc.bassPc),\n };\n })\n .filter((seg) => seg.endBeat > seg.startBeat);\n\n return { at: segmentLookup(segments), segments };\n}\n\n/** Build the `at(beat)` lookup over a segment list. */\nfunction segmentLookup(segments: ChordSegment[]): (beat: number) => Chord | null {\n return (beat) => {\n for (const seg of segments) {\n if (beat >= seg.startBeat && beat < seg.endBeat) {\n return seg.chord;\n }\n }\n return null;\n };\n}\n\nconst EPS = 1e-9;\n\n/** Fraction of the strongest pitch-class weight below which a pc is noise. */\nconst NOISE_THRESHOLD_RATIO = 0.2;\n\n/** Maximum number of pitch classes fed to chord detection per window. */\nconst MAX_DETECTION_PCS = 6;\n\n/** Number of top-weighted pitch classes tried in the detection fallback. */\nconst FALLBACK_PCS = 3;\n\n/** Confidence multiplier applied when the chosen chord match is inexact. */\nconst INEXACT_CONFIDENCE_FACTOR = 0.85;\n\n/** Score bonus for a match whose tones are all in the key. */\nconst DIATONIC_BONUS = 0.5;\n\n/** Score bonus for an exact match (no extra and no missing tones). */\nconst EXACT_BONUS = 0.5;\n\n/** Score penalty per extra or missing tone in a match. */\nconst MISMATCH_PENALTY = 0.3;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * Options controlling {@link chordTimelineFromNotes}.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimelineOptions = {\n /** Key context; inferred from the notes with {@link detectKey} when omitted. */\n key?: KeyScale;\n /**\n * Time signature used for metric accents; defaults to 4/4.\n *\n * @defaultValue `4/4`\n */\n ts?: TimeSignature;\n /**\n * Window length in beats per chord slot; defaults to one bar of `ts`.\n *\n * @defaultValue one bar of `ts`\n */\n harmonicRhythm?: number;\n /**\n * End of the analyzed span in beats; defaults to the end of the last note.\n *\n * @defaultValue the end of the last note\n */\n totalBeats?: number;\n};\n\n/**\n * The result of {@link chordTimelineFromNotes}.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimelineResult = {\n /** The inferred timeline, with adjacent identical chords merged. */\n timeline: ChordTimeline;\n /** The key used for the analysis (given or inferred). */\n key: KeyScale;\n /** One confidence value in [0, 1] per segment, in segment order. */\n segmentConfidence: number[];\n};\n\n/** A window's inferred chord and its confidence, or null for an empty window. */\ntype WindowChord = {\n chord: Chord;\n confidence: number;\n};\n\n/**\n * Score a chord match against a window's pitch-class weights: a heavily\n * weighted root, in-key tones, and exactness all raise the score; extra or\n * missing tones lower it.\n */\nfunction scoreMatch(\n match: ChordMatch,\n weights: number[],\n maxWeight: number,\n key: KeyScale,\n): number {\n const rootWeight = maxWeight > 0 ? (weights[match.rootPc] ?? 0) / maxWeight : 0;\n const tones = chordPitchClasses(makeChord(match.rootPc, match.quality));\n let score = rootWeight;\n if (tones.every((pc) => isScaleTone(pc, key))) {\n score += DIATONIC_BONUS;\n }\n if (match.exact) {\n score += EXACT_BONUS;\n }\n score -= MISMATCH_PENALTY * (match.extraPcs.length + match.missingPcs.length);\n return score;\n}\n\n/** Confidence of a chord for a window: chord-tone weight over total weight. */\nfunction chordConfidence(\n chord: Chord,\n weights: number[],\n totalWeight: number,\n exact: boolean,\n): number {\n const tones = new Set(chordPitchClasses(chord));\n let chordWeight = 0;\n for (let pc = 0; pc < 12; pc += 1) {\n if (tones.has(pc)) {\n chordWeight += weights[pc] ?? 0;\n }\n }\n const raw = totalWeight > 0 ? chordWeight / totalWeight : 0;\n const confidence = Math.min(1, Math.max(0, raw));\n return exact ? confidence : confidence * INEXACT_CONFIDENCE_FACTOR;\n}\n\n/**\n * Infer the chord sounding in one window from the notes overlapping it.\n *\n * Builds a pitch-class weight histogram (overlap duration x velocity x\n * metric-accent bonus for onsets inside the window), keeps the significantly\n * weighted pitch classes, and picks the best {@link detectChord} match by\n * root weight, key membership, and exactness.\n */\nfunction analyzeWindow(\n notes: NoteEvent[],\n windowStart: number,\n windowEnd: number,\n ts: TimeSignature,\n key: KeyScale,\n): WindowChord | null {\n const weights = new Array<number>(12).fill(0);\n let lowestPitch = Number.POSITIVE_INFINITY;\n for (const note of notes) {\n const noteEnd = note.startBeat + note.durationBeat;\n const overlap = Math.min(noteEnd, windowEnd) - Math.max(note.startBeat, windowStart);\n if (overlap <= EPS) {\n continue;\n }\n const velocityFactor = note.velocity !== undefined ? note.velocity / 127 : 1;\n const onsetInWindow = note.startBeat >= windowStart - EPS && note.startBeat < windowEnd - EPS;\n const accent = onsetInWindow ? 1 + metricWeight(note.startBeat, ts) / 3 : 1;\n const pc = pitchClass(note.pitch);\n weights[pc] = (weights[pc] ?? 0) + overlap * velocityFactor * accent;\n if (note.pitch < lowestPitch) {\n lowestPitch = note.pitch;\n }\n }\n let totalWeight = 0;\n let maxWeight = 0;\n for (const w of weights) {\n totalWeight += w;\n maxWeight = Math.max(maxWeight, w);\n }\n if (totalWeight <= EPS) {\n return null;\n }\n\n // Keep pitch classes with meaningful weight, strongest first.\n const ranked = weights\n .map((weight, pc) => ({ pc, weight }))\n .filter(({ weight }) => weight > 0)\n .sort((a, b) => b.weight - a.weight || a.pc - b.pc);\n const selected = ranked\n .filter(({ weight }) => weight >= maxWeight * NOISE_THRESHOLD_RATIO)\n .slice(0, MAX_DETECTION_PCS)\n .map(({ pc }) => pc);\n\n // Feed detection with the window's true bass as the lowest pitch so inversion\n // detection works; when the bass pc was filtered out as noise, anchor on the\n // heaviest pc instead so no spurious inversion is reported.\n const bassPc = pitchClass(lowestPitch);\n const anchorPc = selected.includes(bassPc) ? bassPc : (selected[0] ?? bassPc);\n const detectionPitches = selected.map((pc) => (pc === anchorPc ? pc : pc + 12));\n\n const matches = detectChord(detectionPitches);\n let bestMatch: ChordMatch | null = null;\n let bestScore = Number.NEGATIVE_INFINITY;\n for (const match of matches) {\n const score = scoreMatch(match, weights, maxWeight, key);\n if (score > bestScore) {\n bestScore = score;\n bestMatch = match;\n }\n }\n if (bestMatch) {\n const chord = makeChord(bestMatch.rootPc, bestMatch.quality, bestMatch.bassPc);\n return { chord, confidence: chordConfidence(chord, weights, totalWeight, bestMatch.exact) };\n }\n\n // Fallback: retry on only the top-weighted pitch classes.\n const fallback = detectChordBest(selected.slice(0, FALLBACK_PCS));\n if (fallback) {\n return { chord: fallback, confidence: chordConfidence(fallback, weights, totalWeight, false) };\n }\n return null;\n}\n\n/** Whether two chords are the same root, quality, and bass. */\nfunction sameChord(a: Chord, b: Chord): boolean {\n return a.rootPc === b.rootPc && a.quality === b.quality && a.bassPc === b.bassPc;\n}\n\n/**\n * Infer a chord timeline from raw multi-track notes.\n *\n * The span `[0, totalBeats)` is sliced into `harmonicRhythm`-beat windows; each\n * window's chord is inferred from a pitch-class weight histogram of the notes\n * overlapping it (weight = overlap duration x velocity x metric-accent bonus\n * for onsets in the window). Adjacent windows carrying the identical chord are\n * merged into one segment; windows with no notes produce no segment, so\n * `at(beat)` returns null there. Each segment carries a confidence in [0, 1]:\n * the fraction of the window weight explained by chord tones, reduced when the\n * match is inexact, and duration-weighted across merged windows.\n *\n * Notes with a zero or negative duration never sound, so they are dropped at\n * ingest: they contribute to neither the key inference, the span, nor any\n * window's histogram.\n *\n * @param notes The notes to analyze (any number of tracks, flattened).\n * @param opts Analysis options; see {@link ChordTimelineOptions}.\n * @returns The inferred timeline, the key used, and per-segment confidences.\n * @throws If `harmonicRhythm` is not positive.\n * @example\n * ```ts\n * import { chordTimelineFromNotes } from '@libraz/libcantus';\n * const notes = [\n * { pitch: 60, startBeat: 0, durationBeat: 2 }, // C\n * { pitch: 64, startBeat: 0, durationBeat: 2 }, // E\n * { pitch: 67, startBeat: 0, durationBeat: 2 }, // G\n * ];\n * const { timeline, key } = chordTimelineFromNotes(notes);\n * timeline.at(0); // the chord inferred over beat 0, or null\n * ```\n * @category Arrangement & Analysis\n */\nexport function chordTimelineFromNotes(\n notes: NoteEvent[],\n opts: ChordTimelineOptions = {},\n): ChordTimelineResult {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const harmonicRhythm = opts.harmonicRhythm ?? beatsPerBar(ts);\n if (!(harmonicRhythm > 0)) {\n throw new Error(`Invalid harmonic rhythm: ${harmonicRhythm}`);\n }\n // Zero/negative-length notes never sound; drop them before any inference.\n const sounding = notes.filter((note) => note.durationBeat > 0);\n const lastNoteEnd = sounding.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);\n const totalBeats = opts.totalBeats ?? lastNoteEnd;\n const key = opts.key ?? detectKey(sounding.map((n) => n.pitch))[0]?.key ?? majorKey(0);\n\n const segments: ChordSegment[] = [];\n const segmentConfidence: number[] = [];\n const windowCount = Math.max(0, Math.ceil(totalBeats / harmonicRhythm - EPS));\n for (let i = 0; i < windowCount; i += 1) {\n const start = i * harmonicRhythm;\n const end = Math.min(start + harmonicRhythm, totalBeats);\n const inferred = analyzeWindow(sounding, start, end, ts, key);\n if (!inferred) {\n continue;\n }\n const last = segments[segments.length - 1];\n if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) < EPS) {\n // Merge into the previous segment, blending confidence by duration.\n const lastLength = last.endBeat - last.startBeat;\n const length = end - start;\n const lastConfidence = segmentConfidence[segmentConfidence.length - 1] ?? 0;\n segmentConfidence[segmentConfidence.length - 1] =\n (lastConfidence * lastLength + inferred.confidence * length) / (lastLength + length);\n last.endBeat = end;\n } else {\n segments.push({ startBeat: start, endBeat: end, chord: inferred.chord });\n segmentConfidence.push(inferred.confidence);\n }\n }\n\n return {\n timeline: { at: segmentLookup(segments), segments },\n key,\n segmentConfidence,\n };\n}\n\n/**\n * A cadence found between two consecutive timeline segments.\n *\n * @category Arrangement & Analysis\n */\nexport type CadenceHit = {\n /** The beat where the cadence arrives (the second chord's onset). */\n atBeat: number;\n type: Exclude<Cadence, null>;\n from: Chord;\n to: Chord;\n};\n\n/**\n * Find cadences between consecutive segments of a chord timeline.\n *\n * Each temporally adjacent segment pair is classified with\n * {@link detectCadence}; pairs forming no cadence are skipped. Segments\n * separated by a gap (a rest in the timeline) are not a chord-to-chord\n * progression, so they are never paired.\n *\n * @param timeline The chord timeline to scan.\n * @param key The prevailing key.\n * @returns The cadences found, in time order.\n * @example\n * ```ts\n * import { chordTimelineFromNotes, detectCadences } from '@libraz/libcantus';\n * const notes = [\n * { pitch: 67, startBeat: 0, durationBeat: 4 }, // G, a dominant\n * { pitch: 60, startBeat: 4, durationBeat: 4 }, // C, the tonic\n * ];\n * const { timeline, key } = chordTimelineFromNotes(notes);\n * const cadences = detectCadences(timeline, key);\n * ```\n * @category Arrangement & Analysis\n */\nexport function detectCadences(timeline: ChordTimeline, key: KeyScale): CadenceHit[] {\n const hits: CadenceHit[] = [];\n for (let i = 1; i < timeline.segments.length; i += 1) {\n const prev = timeline.segments[i - 1];\n const cur = timeline.segments[i];\n if (!prev || !cur) {\n continue;\n }\n if (Math.abs(cur.startBeat - prev.endBeat) > EPS) {\n continue; // A rest separates the chords; no cadential motion across it.\n }\n const type = detectCadence(prev.chord, cur.chord, key);\n if (type !== null) {\n hits.push({ atBeat: cur.startBeat, type, from: prev.chord, to: cur.chord });\n }\n }\n return hits;\n}\n","/**\n * Arrangement analysis: the capstone that ties the timeline, per-voice analysis,\n * functional harmony, and safety modules together for a whole multi-track piece.\n *\n * A chord timeline and key are inferred once from every track's notes pooled\n * together; each track is then analysed against that shared harmony, notes that\n * clash with the sounding chord are collected as conflicts, and a coarse tension\n * curve is sampled across the piece.\n */\n\nimport { type AnalyzedNote, analyzeVoice, type VoiceNote } from '../analysis/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport { functionOf } from '../functional/index.js';\nimport { isStrongBeat, parseTimeSignature, type TimeSignature } from '../meter/index.js';\nimport {\n evaluateSafety,\n NoteSafety,\n type SafetyProfile,\n type VoiceSnapshot,\n} from '../safety/index.js';\nimport {\n type CadenceHit,\n type ChordTimeline,\n chordTimelineFromNotes,\n detectCadences,\n} from '../timeline/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/** Float tolerance for beat boundary comparisons. */\nconst EPS = 1e-9;\n\n/**\n * The musical role a track plays in the arrangement.\n *\n * @category Arrangement & Analysis\n */\nexport type TrackRole = 'melody' | 'harmony' | 'bass' | 'other';\n\n/**\n * One input track: its notes plus optional name and role.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementTrack = {\n name?: string;\n role?: TrackRole;\n notes: NoteEvent[];\n};\n\n/**\n * A track after analysis: its resolved name, role, and per-note annotations.\n *\n * @category Arrangement & Analysis\n */\nexport type TrackAnalysis = {\n name: string;\n role: TrackRole;\n /** One {@link AnalyzedNote} per note, labelled against the inferred chords. */\n notes: AnalyzedNote[];\n};\n\n/**\n * A note that clashes with the harmony sounding beneath it.\n *\n * @category Arrangement & Analysis\n */\nexport type Conflict = {\n beat: number;\n trackName: string;\n pitch: number;\n /** The clash severity: {@link NoteSafety.Warning} or {@link NoteSafety.Dissonant}. */\n safety: NoteSafety;\n /** {@link import('../safety/index.js').SafetyResult.reasons} bitmask. */\n reasons: number;\n rationale?: string;\n};\n\n/**\n * The full result of {@link analyzeArrangement}.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementAnalysis = {\n key: KeyScale;\n timeline: ChordTimeline;\n segmentConfidence: number[];\n cadences: CadenceHit[];\n tracks: TrackAnalysis[];\n /** Notes clashing with the sounding harmony, worst severity first. */\n conflicts: Conflict[];\n};\n\n/**\n * Options controlling {@link analyzeArrangement} and {@link tensionCurve}.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementOptions = {\n /** Key context; inferred from the pooled notes when omitted. */\n key?: KeyScale;\n /**\n * Time signature; defaults to 4/4.\n *\n * @defaultValue `4/4`\n */\n ts?: TimeSignature;\n /**\n * Chord-slot length in beats; defaults to one bar of `ts`.\n *\n * @defaultValue one bar of `ts`\n */\n harmonicRhythm?: number;\n /**\n * Safety profile used for conflict detection; defaults to `pop`.\n *\n * @defaultValue `'pop'`\n */\n profile?: SafetyProfile;\n};\n\n/** A note with the pitch that immediately preceded it in the same sub-voice. */\ntype PreparedNote = {\n pitch: number;\n prevPitch?: number;\n startBeat: number;\n endBeat: number;\n};\n\n/** One monophonic sub-voice of a track: ordered notes plus sounding spans. */\ntype PreparedVoice = {\n /** The sub-voice's notes in time order, each with a stable id. */\n voice: VoiceNote[];\n /** The same notes as sounding spans, each carrying its predecessor's pitch. */\n sounding: PreparedNote[];\n};\n\n/** A track prepared for analysis: resolved metadata plus monophonic sub-voices. */\ntype PreparedTrack = {\n name: string;\n role: TrackRole;\n /**\n * The track's notes partitioned into monophonic sub-voices. Voice analysis\n * assumes one note at a time, so a polyphonic track (e.g. a 'harmony' track\n * playing block chords) is split here; a monophonic track yields exactly one\n * sub-voice.\n */\n voices: PreparedVoice[];\n};\n\n/** Reduce a pitch to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/** Whether a sounding span `[start, end)` covers a beat. */\nfunction covers(note: PreparedNote, beat: number): boolean {\n return beat >= note.startBeat - EPS && beat < note.endBeat - EPS;\n}\n\n/**\n * Every sounding note of every track pooled into one flat list. Zero- and\n * negative-length notes never sound, so they are dropped here (matching the\n * chord-inference ingest in the timeline module).\n */\nfunction poolNotes(tracks: ArrangementTrack[]): NoteEvent[] {\n const notes: NoteEvent[] = [];\n for (const track of tracks) {\n for (const note of track.notes) {\n if (note.durationBeat > 0) {\n notes.push(note);\n }\n }\n }\n return notes;\n}\n\n/**\n * Split a track's ordered notes into monophonic sub-voices.\n *\n * Greedy lane assignment: each note joins the first sub-voice that is free at\n * its onset (its last note has ended), otherwise it opens a new sub-voice. A\n * monophonic track therefore stays a single sub-voice, while block chords fan\n * out into one sub-voice per simultaneous note, keeping every sub-voice's\n * note-to-note adjacency genuinely melodic.\n */\nfunction splitIntoSubVoices(ordered: VoiceNote[]): VoiceNote[][] {\n const lanes: VoiceNote[][] = [];\n for (const note of ordered) {\n const lane = lanes.find((candidate) => {\n const last = candidate[candidate.length - 1];\n return last !== undefined && last.startBeat + last.durationBeat <= note.startBeat + EPS;\n });\n if (lane) {\n lane.push(note);\n } else {\n lanes.push([note]);\n }\n }\n return lanes;\n}\n\n/**\n * Resolve each track's metadata and derive its monophonic sub-voices.\n *\n * Notes are sorted by onset, then pitch, so ordering is deterministic, and ids\n * are assigned in that order. Zero- and negative-length notes never sound and\n * are dropped at ingest. Each track is then partitioned into monophonic\n * sub-voices (see {@link splitIntoSubVoices}); the predecessor pitch used for\n * suspension and parallel detection is the previous note of the same sub-voice,\n * never a simultaneous chord member.\n */\nfunction prepareTracks(tracks: ArrangementTrack[]): PreparedTrack[] {\n let nextId = 0;\n return tracks.map((track, index) => {\n const ordered: VoiceNote[] = track.notes\n .filter((note) => note.durationBeat > 0)\n .sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch)\n .map((note) => ({ ...note, id: nextId++ }));\n const voices: PreparedVoice[] = splitIntoSubVoices(ordered).map((voice) => ({\n voice,\n sounding: voice.map((note, i) => {\n const prev = i > 0 ? voice[i - 1] : undefined;\n return {\n pitch: note.pitch,\n prevPitch: prev?.pitch,\n startBeat: note.startBeat,\n endBeat: note.startBeat + note.durationBeat,\n };\n }),\n }));\n return {\n name: track.name ?? `track ${index + 1}`,\n role: track.role ?? 'other',\n voices,\n };\n });\n}\n\n/**\n * Sounding pitches of every sub-voice at a beat, excluding one sub-voice.\n *\n * Only the sub-voice under analysis is excluded — sibling sub-voices of the\n * same track are included, so dissonant clusters inside a single polyphonic\n * track are still detected.\n */\nfunction otherVoicesSounding(\n prepared: PreparedTrack[],\n excludeTrack: number,\n excludeVoice: number,\n beat: number,\n): VoiceSnapshot[] {\n const out: VoiceSnapshot[] = [];\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n for (let v = 0; v < track.voices.length; v += 1) {\n if (t === excludeTrack && v === excludeVoice) {\n continue;\n }\n const subVoice = track.voices[v];\n if (!subVoice) {\n continue;\n }\n for (const note of subVoice.sounding) {\n if (!covers(note, beat)) {\n continue;\n }\n const snap: VoiceSnapshot = { pitch: note.pitch };\n if (note.prevPitch !== undefined) {\n snap.prevPitch = note.prevPitch;\n }\n out.push(snap);\n }\n }\n }\n return out;\n}\n\n/**\n * The beats at which a note must be checked against the harmony: its onset,\n * plus the onset of every later chord segment the note sustains across. Each\n * crossed segment is visited exactly once (at its own start), so a boundary\n * beat is never evaluated twice for the same note.\n */\nfunction evaluationBeats(note: VoiceNote, timeline: ChordTimeline): number[] {\n const noteEnd = note.startBeat + note.durationBeat;\n const beats = [note.startBeat];\n for (const segment of timeline.segments) {\n if (segment.startBeat > note.startBeat + EPS && segment.startBeat < noteEnd - EPS) {\n beats.push(segment.startBeat);\n }\n }\n return beats;\n}\n\n/**\n * Analyse a whole arrangement against a single inferred harmony.\n *\n * The chord timeline and key are inferred from the pooled notes of every track\n * (see {@link chordTimelineFromNotes}); pooling all voices is robust even when\n * roles are absent or a track doubles the harmony, so it is preferred over\n * deriving the harmony from a subset. Zero- and negative-length notes never\n * sound, so they are dropped at ingest and appear in neither the annotations\n * nor the conflicts.\n *\n * Voice analysis assumes one monophonic voice at a time, so each track is\n * first partitioned into monophonic sub-voices (a polyphonic block-chord track\n * fans out into one sub-voice per simultaneous note; a monophonic track is\n * unaffected). Each sub-voice is labelled note-by-note against the harmony\n * with {@link analyzeVoice}, seeing every other sub-voice — including siblings\n * within the same track — as its accompaniment. Every note is then re-checked\n * with {@link evaluateSafety} at its onset and again at each chord change it\n * sustains across, so a held note that clashes with a later chord is caught:\n * evaluations that are not {@link NoteSafety.Safe} become conflicts, one per\n * clashing beat, sorted worst severity first and then by beat.\n *\n * @param tracks The tracks to analyse.\n * @param opts Analysis options; see {@link ArrangementOptions}.\n * @returns The inferred harmony, per-track annotations, cadences, and conflicts.\n * @example\n * ```ts\n * import { analyzeArrangement } from '@libraz/libcantus';\n * const melody = [\n * { pitch: 60, startBeat: 0, durationBeat: 2 },\n * { pitch: 67, startBeat: 2, durationBeat: 2 },\n * ];\n * const { key, conflicts } = analyzeArrangement([{ role: 'melody', notes: melody }]);\n * conflicts; // notes clashing with the inferred harmony, worst severity first\n * ```\n * @category Arrangement & Analysis\n */\nexport function analyzeArrangement(\n tracks: ArrangementTrack[],\n opts: ArrangementOptions = {},\n): ArrangementAnalysis {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const profile: SafetyProfile = opts.profile ?? 'pop';\n const pooled = poolNotes(tracks);\n\n const { timeline, key, segmentConfidence } = chordTimelineFromNotes(pooled, {\n key: opts.key,\n ts,\n harmonicRhythm: opts.harmonicRhythm,\n });\n const cadences = detectCadences(timeline, key);\n const prepared = prepareTracks(tracks);\n\n const trackAnalyses: TrackAnalysis[] = [];\n const conflicts: Conflict[] = [];\n\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n const notes: AnalyzedNote[] = [];\n for (let v = 0; v < track.voices.length; v += 1) {\n const subVoice = track.voices[v];\n if (!subVoice) {\n continue;\n }\n notes.push(\n ...analyzeVoice(subVoice.voice, timeline.at, key, (beat) =>\n otherVoicesSounding(prepared, t, v, beat),\n ),\n );\n\n for (const note of subVoice.voice) {\n for (const beat of evaluationBeats(note, timeline)) {\n const result = evaluateSafety({\n profile,\n candidatePitch: note.pitch,\n chord: timeline.at(beat),\n key,\n otherVoices: otherVoicesSounding(prepared, t, v, beat),\n strongBeat: isStrongBeat(beat, ts),\n });\n if (result.safety !== NoteSafety.Safe) {\n const conflict: Conflict = {\n beat,\n trackName: track.name,\n pitch: note.pitch,\n safety: result.safety,\n reasons: result.reasons,\n };\n if (result.rationale !== undefined) {\n conflict.rationale = result.rationale;\n }\n conflicts.push(conflict);\n }\n }\n }\n }\n // Sub-voice results interleave; restore the track's onset-then-pitch order.\n notes.sort((a, b) => a.noteId - b.noteId);\n trackAnalyses.push({ name: track.name, role: track.role, notes });\n }\n\n conflicts.sort((a, b) => b.safety - a.safety || a.beat - b.beat);\n\n return { key, timeline, segmentConfidence, cadences, tracks: trackAnalyses, conflicts };\n}\n\n/**\n * A tension reading sampled at a beat.\n *\n * @category Arrangement & Analysis\n */\nexport type TensionPoint = {\n beat: number;\n /** Combined tension in [0, 1]. */\n tension: number;\n};\n\n/** Tension contributed by the sounding chord's harmonic function. */\nconst FUNCTION_TENSION: Record<'tonic' | 'subdominant' | 'dominant', number> = {\n tonic: 0,\n subdominant: 0.5,\n dominant: 1,\n};\n\n/** Weight of the harmonic-function term in the combined tension score. */\nconst FUNCTION_WEIGHT = 0.5;\n/** Weight of the non-chord-tone / dissonance term. */\nconst DISSONANCE_WEIGHT = 0.35;\n/** Weight of the registral-span term. */\nconst SPAN_WEIGHT = 0.15;\n/** Pitch span, in semitones, that saturates the span term. */\nconst SPAN_SATURATION = 24;\n\n/** Clamp a value into [0, 1]. */\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\n/**\n * Sample the harmonic tension of an arrangement at regular beats.\n *\n * At each sample beat the tension combines three normalized terms:\n * - the sounding chord's harmonic function (dominant `1`, subdominant `0.5`,\n * tonic or no chord `0`), weighted {@link FUNCTION_WEIGHT};\n * - the dissonance of the sounding notes — the larger of the share of sounding\n * pitches that are not chord tones and the share that {@link evaluateSafety}\n * rates {@link NoteSafety.Dissonant} — weighted {@link DISSONANCE_WEIGHT};\n * - the registral span of the sounding notes, saturating at\n * {@link SPAN_SATURATION} semitones, weighted {@link SPAN_WEIGHT}.\n *\n * The weighted sum is clamped to [0, 1]. The harmony is inferred from all tracks\n * pooled together, so the result is deterministic and self-contained.\n *\n * @param tracks The tracks to sample.\n * @param opts Analysis options plus an optional `step` (default one beat).\n * @returns One {@link TensionPoint} per sampled beat, in beat order.\n * @throws If `step` is not positive.\n * @example\n * ```ts\n * import { tensionCurve } from '@libraz/libcantus';\n * const notes = [{ pitch: 60, startBeat: 0, durationBeat: 4 }];\n * const curve = tensionCurve([{ notes }], { step: 1 });\n * curve; // one { beat, tension } sample per beat, in beat order\n * ```\n * @category Arrangement & Analysis\n */\nexport function tensionCurve(\n tracks: ArrangementTrack[],\n opts: ArrangementOptions & { step?: number } = {},\n): TensionPoint[] {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const profile: SafetyProfile = opts.profile ?? 'pop';\n const step = opts.step ?? 1;\n if (!(step > 0)) {\n throw new Error(`Invalid tension sampling step: ${step}`);\n }\n\n const pooled = poolNotes(tracks);\n const totalBeats = pooled.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);\n const { timeline, key } = chordTimelineFromNotes(pooled, {\n key: opts.key,\n ts,\n harmonicRhythm: opts.harmonicRhythm,\n });\n\n const prepared = prepareTracks(tracks);\n const points: TensionPoint[] = [];\n const sampleCount = Math.max(0, Math.ceil(totalBeats / step - EPS));\n for (let i = 0; i < sampleCount; i += 1) {\n const beat = i * step;\n points.push({ beat, tension: sampleTension(prepared, timeline, key, ts, profile, beat) });\n }\n return points;\n}\n\n/** All sounding notes across every track at a beat, tagged with their track. */\nfunction allSounding(prepared: PreparedTrack[], beat: number): { pitch: number; track: number }[] {\n const out: { pitch: number; track: number }[] = [];\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n for (const subVoice of track.voices) {\n for (const note of subVoice.sounding) {\n if (covers(note, beat)) {\n out.push({ pitch: note.pitch, track: t });\n }\n }\n }\n }\n return out;\n}\n\n/** Combine the harmonic, dissonance, and span terms at one sample beat. */\nfunction sampleTension(\n prepared: PreparedTrack[],\n timeline: ChordTimeline,\n key: KeyScale,\n ts: TimeSignature,\n profile: SafetyProfile,\n beat: number,\n): number {\n const sounding = allSounding(prepared, beat);\n if (sounding.length === 0) {\n return 0;\n }\n const chord = timeline.at(beat);\n const functionScore = chord ? FUNCTION_TENSION[functionOf(chord, key)] : 0;\n\n const chordPcs = chord ? new Set(chordPitchClasses(chord)) : null;\n const strongBeat = isStrongBeat(beat, ts);\n let nonChord = 0;\n let dissonant = 0;\n for (let i = 0; i < sounding.length; i += 1) {\n const voice = sounding[i];\n if (!voice) {\n continue;\n }\n // Non-chord-tone share only applies when a chord is sounding; at a timeline\n // gap there is no reference harmony, so vertical dissonance alone drives the\n // dissonance term (the chord function term is already 0 there).\n if (chordPcs && !chordPcs.has(pitchClass(voice.pitch))) {\n nonChord += 1;\n }\n const others = sounding.filter((_, j) => j !== i).map((s) => ({ pitch: s.pitch }));\n const result = evaluateSafety({\n profile,\n candidatePitch: voice.pitch,\n chord,\n key,\n otherVoices: others,\n strongBeat,\n });\n if (result.safety === NoteSafety.Dissonant) {\n dissonant += 1;\n }\n }\n const dissonanceScore = Math.max(nonChord, dissonant) / sounding.length;\n\n let low = Number.POSITIVE_INFINITY;\n let high = Number.NEGATIVE_INFINITY;\n for (const voice of sounding) {\n low = Math.min(low, voice.pitch);\n high = Math.max(high, voice.pitch);\n }\n const spanScore = Math.min(1, (high - low) / SPAN_SATURATION);\n\n return clamp01(\n FUNCTION_WEIGHT * functionScore + DISSONANCE_WEIGHT * dissonanceScore + SPAN_WEIGHT * spanScore,\n );\n}\n","/**\n * Deterministic seeded pseudo-random number generation shared across the\n * generative modules (rhythm, drums, bass, groove, counter-melody). A single\n * mulberry32 core exposes the small set of samplers those modules need; given a\n * seed the stream is fully reproducible.\n */\n\n/**\n * A deterministic PRNG with the sampling helpers the generators need.\n *\n * @category Utilities\n */\nexport type Rng = {\n /** Next float in [0, 1). */\n next: () => number;\n /** True with probability `p`. */\n prob: (p: number) => boolean;\n /** Integer in the inclusive range [lo, hi]. */\n range: (lo: number, hi: number) => number;\n /** Float in [lo, hi). */\n float: (lo: number, hi: number) => number;\n};\n\n/**\n * Create a seeded PRNG (mulberry32) exposing the shared samplers.\n *\n * @param seed The 32-bit seed; the same seed always yields the same stream.\n * @returns The seeded generator.\n * @example\n * ```ts\n * import { createRng } from '@libraz/libcantus';\n * const rng = createRng(42);\n * rng.next(); // deterministic float in [0, 1)\n * rng.range(1, 6); // deterministic integer in [1, 6]\n * ```\n * @category Utilities\n */\nexport function createRng(seed: number): Rng {\n let state = seed >>> 0;\n const next = () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n return {\n next,\n prob: (p) => next() < p,\n range: (lo, hi) => lo + Math.floor(next() * (hi - lo + 1)),\n float: (lo, hi) => lo + next() * (hi - lo),\n };\n}\n","/**\n * Deterministic bass-line generation over a chord placement.\n *\n * Given a sequence of chord segments and a key, this builds a monophonic bass\n * line in a chosen low register. Several idiomatic styles are supported, from a\n * single held root per segment to a quarter-note walking line that leads by\n * step into each chord change. All pitches are kept in a narrow bass band and\n * consecutive notes move by small intervals; given a seed the output is fully\n * reproducible.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention.\n */\n\nimport type { Chord } from '../chord/index.js';\nimport { isStrongBeat, type TimeSignature } from '../meter/index.js';\nimport { createRng } from '../random/index.js';\nimport { nearestScaleTone } from '../scale/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/**\n * A chord sounding over a half-open beat span `[startBeat, endBeat)`.\n *\n * @category Composition\n */\nexport type BassSegment = {\n startBeat: number;\n endBeat: number;\n chord: Chord;\n};\n\n/**\n * The bass-line idiom to generate.\n *\n * @category Composition\n */\nexport type BassStyle = 'root' | 'rootFifth' | 'pop' | 'walking' | 'arpeggio';\n\n/**\n * Options controlling {@link generateBassLine}.\n *\n * @category Composition\n */\nexport type BassLineOptions = {\n /** Chord placement to follow; need not be pre-sorted. */\n segments: BassSegment[];\n /** Key/scale context, used for diatonic approach tones in `walking`. */\n key: KeyScale;\n /**\n * Time signature; used for metric accents.\n *\n * @defaultValue `{ numerator: 4, denominator: 4 }`\n */\n ts?: TimeSignature;\n /**\n * Bass-line idiom.\n *\n * @defaultValue `'root'`\n */\n style?: BassStyle;\n /**\n * Target register as a base MIDI octave; roots land around `octave*12+12`.\n *\n * @defaultValue 2\n */\n octave?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\nconst DEFAULT_STYLE: BassStyle = 'root';\nconst DEFAULT_OCTAVE = 2;\n\n/** Velocity for notes on metrically strong positions. */\nconst STRONG_VELOCITY = 100;\n/** Velocity for notes on weak positions. */\nconst WEAK_VELOCITY = 80;\n/** Probability of a weak-beat pickup in the `pop` style. */\nconst PICKUP_PROB = 0.35;\n\nconst EPS = 1e-9;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * Place a pitch class as a MIDI note near an anchor, clamped to the bass band.\n *\n * The octave nearest the anchor is chosen first (so motion from the previous\n * note is minimal), then the result is shifted by whole octaves into the band\n * `[low, low + 12]` if it falls outside.\n */\nfunction placePc(pc: number, anchor: number, low: number): number {\n const high = low + 12;\n let midi = pc + 12 * Math.round((anchor - pc) / 12);\n while (midi < low) {\n midi += 12;\n }\n while (midi > high) {\n midi -= 12;\n }\n return midi;\n}\n\n/** Chord-tone pitch classes in stacked-thirds order, deduplicated. */\nfunction chordTonePcs(chord: Chord): number[] {\n const seen = new Set<number>();\n const pcs: number[] = [];\n for (const interval of chord.intervals) {\n const pc = pitchClass(chord.rootPc + interval);\n if (!seen.has(pc)) {\n seen.add(pc);\n pcs.push(pc);\n }\n }\n if (pcs.length === 0) {\n pcs.push(pitchClass(chord.rootPc));\n }\n return pcs;\n}\n\n/**\n * The chord's fifth pitch class.\n *\n * Uses the perfect fifth when present, otherwise the chord's actual altered\n * fifth (diminished = 6, augmented = 8 semitones above the root), so dim/aug/\n * m7b5 chords sound their real fifth rather than a repeated root. Falls back to\n * the root only when the chord has no fifth degree at all.\n */\nfunction fifthPcOf(chord: Chord): number {\n const fifths = new Set(chord.intervals.map((i) => pitchClass(i)));\n const chosen = fifths.has(7) ? 7 : fifths.has(6) ? 6 : fifths.has(8) ? 8 : undefined;\n return chosen === undefined ? pitchClass(chord.rootPc) : pitchClass(chord.rootPc + chosen);\n}\n\n/** The sounding bass pitch class of a chord: its slash bass, else its root. */\nfunction bassPcOf(chord: Chord): number {\n return pitchClass(chord.bassPc ?? chord.rootPc);\n}\n\n/** Integer quarter-note beat positions within `[start, end)`, at least one. */\nfunction beatPositions(start: number, end: number): number[] {\n const positions: number[] = [];\n for (let p = start; p < end - EPS; p += 1) {\n positions.push(p);\n }\n if (positions.length === 0) {\n positions.push(start);\n }\n return positions;\n}\n\ntype RawNote = { startBeat: number; pitch: number; velocity: number };\n\n/** Working state threaded through the per-segment builders. */\ntype BuildContext = {\n ts: TimeSignature;\n low: number;\n key: KeyScale;\n rng: ReturnType<typeof createRng>;\n notes: RawNote[];\n prevMidi: number;\n};\n\n/** Append a note for pitch class `pc` at `pos`, placed near the running anchor. */\nfunction emit(ctx: BuildContext, pos: number, pc: number, midiOverride?: number): number {\n const midi = midiOverride ?? placePc(pc, ctx.prevMidi, ctx.low);\n const velocity = isStrongBeat(pos, ctx.ts) ? STRONG_VELOCITY : WEAK_VELOCITY;\n ctx.notes.push({ startBeat: pos, pitch: midi, velocity });\n return midi;\n}\n\n/** One root note per segment. */\nfunction buildRoot(ctx: BuildContext, seg: BassSegment): void {\n ctx.prevMidi = emit(ctx, seg.startBeat, bassPcOf(seg.chord));\n}\n\n/** Root on the downbeat, fifth on the segment's midpoint. */\nfunction buildRootFifth(ctx: BuildContext, seg: BassSegment): void {\n ctx.prevMidi = emit(ctx, seg.startBeat, bassPcOf(seg.chord));\n const mid = (seg.startBeat + seg.endBeat) / 2;\n if (mid > seg.startBeat + EPS && mid < seg.endBeat - EPS) {\n ctx.prevMidi = emit(ctx, mid, fifthPcOf(seg.chord));\n }\n}\n\n/** Root on every strong beat, with occasional octave/fifth pickups on weak beats. */\nfunction buildPop(ctx: BuildContext, seg: BassSegment): void {\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n const rootPc = bassPcOf(seg.chord);\n let emitted = false;\n for (const pos of positions) {\n if (isStrongBeat(pos, ctx.ts)) {\n ctx.prevMidi = emit(ctx, pos, rootPc);\n emitted = true;\n } else if (ctx.rng.prob(PICKUP_PROB)) {\n if (ctx.rng.prob(0.5)) {\n // Octave pickup: the root dropped toward the bottom of the register,\n // clamped so it never falls below the declared band.\n const base = placePc(rootPc, ctx.prevMidi, ctx.low);\n emit(ctx, pos, rootPc, Math.max(ctx.low, base - 12));\n } else {\n ctx.prevMidi = emit(ctx, pos, fifthPcOf(seg.chord));\n }\n }\n }\n if (!emitted) {\n ctx.prevMidi = emit(ctx, seg.startBeat, rootPc);\n }\n}\n\n/** Cycle root -> third -> fifth (-> seventh) across the segment's beats. */\nfunction buildArpeggio(ctx: BuildContext, seg: BassSegment): void {\n const tones = chordTonePcs(seg.chord);\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n positions.forEach((pos, i) => {\n const pc = tones[i % tones.length] ?? bassPcOf(seg.chord);\n ctx.prevMidi = emit(ctx, pos, pc);\n });\n}\n\n/** A diatonic or chromatic neighbor of `target`, a step toward `from`. */\nfunction approachNote(ctx: BuildContext, target: number, from: number): number {\n const dir = from <= target ? -1 : 1;\n if (ctx.rng.prob(0.5)) {\n return target + dir; // chromatic semitone\n }\n const cand = nearestScaleTone(target + dir * 2, ctx.key);\n const step = Math.abs(cand - target);\n return step >= 1 && step <= 2 ? cand : target + dir;\n}\n\n/** A quarter-note line of chord tones that leads by step into each chord change. */\nfunction buildWalking(ctx: BuildContext, seg: BassSegment, next: BassSegment | undefined): void {\n const tones = chordTonePcs(seg.chord);\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n const count = positions.length;\n positions.forEach((pos, i) => {\n if (i === 0) {\n ctx.prevMidi = emit(ctx, pos, bassPcOf(seg.chord));\n return;\n }\n if (next && count > 1 && i === count - 1) {\n const nextBass = placePc(bassPcOf(next.chord), ctx.prevMidi, ctx.low);\n const midi = approachNote(ctx, nextBass, ctx.prevMidi);\n ctx.prevMidi = emit(ctx, pos, pitchClass(midi), midi);\n return;\n }\n const pc = tones[i % tones.length] ?? bassPcOf(seg.chord);\n ctx.prevMidi = emit(ctx, pos, pc);\n });\n}\n\n/**\n * Generate a bass line following a chord placement.\n *\n * Each segment contributes notes in the chosen bass register per the selected\n * style; consecutive notes are kept within roughly a fifth. Every note's\n * duration extends to the next onset (the final note extends to the last\n * segment's end). Given a seed the output is fully reproducible.\n *\n * @param opts Segments, key, and generation options.\n * @returns Bass notes sorted by onset, non-overlapping.\n *\n * @example\n * ```ts\n * import { generateBassLine, makeChord, majorKey } from '@libraz/libcantus';\n * const segments = [\n * { startBeat: 0, endBeat: 4, chord: makeChord(0, 'maj') },\n * { startBeat: 4, endBeat: 8, chord: makeChord(7, 'maj') },\n * ];\n * const notes = generateBassLine({ segments, key: majorKey(0), style: 'walking' });\n * ```\n *\n * @category Composition\n */\nexport function generateBassLine(opts: BassLineOptions): NoteEvent[] {\n const segments = [...opts.segments].sort((a, b) => a.startBeat - b.startBeat);\n if (segments.length === 0) {\n return [];\n }\n\n const ts = opts.ts ?? DEFAULT_TS;\n const style = opts.style ?? DEFAULT_STYLE;\n const octave = opts.octave ?? DEFAULT_OCTAVE;\n const low = octave * 12 + 12;\n\n const ctx: BuildContext = {\n ts,\n low,\n key: opts.key,\n rng: createRng(opts.seed ?? 0),\n notes: [],\n prevMidi: low,\n };\n\n for (let s = 0; s < segments.length; s += 1) {\n const seg = segments[s];\n if (!seg) {\n continue;\n }\n switch (style) {\n case 'rootFifth':\n buildRootFifth(ctx, seg);\n break;\n case 'pop':\n buildPop(ctx, seg);\n break;\n case 'walking':\n buildWalking(ctx, seg, segments[s + 1]);\n break;\n case 'arpeggio':\n buildArpeggio(ctx, seg);\n break;\n default:\n buildRoot(ctx, seg);\n break;\n }\n }\n\n ctx.notes.sort((a, b) => a.startBeat - b.startBeat);\n const lastEnd = segments.reduce((m, seg) => Math.max(m, seg.endBeat), Number.NEGATIVE_INFINITY);\n\n const out: NoteEvent[] = [];\n for (let i = 0; i < ctx.notes.length; i += 1) {\n const note = ctx.notes[i];\n if (!note) {\n continue;\n }\n const nextStart = ctx.notes[i + 1]?.startBeat ?? lastEnd;\n const durationBeat = nextStart - note.startBeat;\n if (durationBeat <= EPS) {\n continue;\n }\n out.push({\n pitch: note.pitch,\n startBeat: note.startBeat,\n durationBeat,\n velocity: note.velocity,\n });\n }\n return out;\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport { NAMED_SCALES } from '../scale/index.js';\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Count the set bits (scale tones) in a 12-bit mode mask. */\nfunction popcount12(mask: number): number {\n let count = 0;\n for (let n = 0; n < 12; n += 1) {\n count += (mask >> n) & 1;\n }\n return count;\n}\n\n/** Test whether a pitch class belongs to a mode mask rooted on `scaleRootPc`. */\nfunction maskHasPitchClass(mask: number, scaleRootPc: number, pc: number): boolean {\n const offset = pitchClass(pc - scaleRootPc);\n return ((mask >> offset) & 1) === 1;\n}\n\n/**\n * Test whether every chord pitch class is contained in a scale.\n *\n * @param chordPcs The chord's pitch classes (0..11).\n * @param scaleMask The scale's 12-bit mode mask.\n * @param scaleRootPc The pitch class the mask is rooted on.\n * @returns True if the scale is a superset of the chord.\n *\n * @category Scales\n */\nexport function scaleMatchesChord(\n chordPcs: number[],\n scaleMask: number,\n scaleRootPc: number,\n): boolean {\n for (const pc of chordPcs) {\n if (!maskHasPitchClass(scaleMask, scaleRootPc, pc)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * A named scale rooted on a pitch class that fits over a chord.\n *\n * @category Scales\n */\nexport type ChordScaleMatch = {\n name: string;\n rootPc: number;\n};\n\n/**\n * Scale names whose mask duplicates another {@link NAMED_SCALES} entry\n * (major/ionian, naturalMinor/aeolian). Chord-scale analysis conventionally\n * speaks in mode names, so these aliases are skipped and only the modal name\n * is reported.\n */\nconst ALIASED_SCALE_NAMES = new Set(['major', 'naturalMinor']);\n\n/** Number of tones in a heptatonic (seven-note) scale. */\nconst HEPTATONIC_SIZE = 7;\n\n/**\n * List the scales that fit over a chord, best fit first.\n *\n * Only the chord root is considered as the scale root, matching the\n * conventional chord-scale relationship. Every entry of {@link NAMED_SCALES}\n * whose pitch-class set is a superset of the chord's is returned once per\n * distinct pitch-class set (aliased masks such as major/ionian report only the\n * modal name), ranked by fewest extra scale tones beyond the chord, then by\n * scale size (heptatonic before larger scales), then by scale name. For bare\n * triads and smaller chords, heptatonic scales rank before pentatonics and\n * other sizes: a pentatonic adds no modal color over a triad, so the seven-note\n * modes are the more useful answer. The chromatic scale is only returned as a\n * fallback when no other scale contains the chord.\n *\n * @param chord The chord to fit scales over.\n * @returns The matching scales rooted on the chord root, best fit first.\n *\n * @example\n * ```ts\n * import { makeChord, chordScales } from '@libraz/libcantus';\n * const scales = chordScales(makeChord(0, 'maj7'));\n * // scales for Cmaj7, best fit first; each is { name, rootPc: 0 }\n * ```\n *\n * @category Scales\n */\nexport function chordScales(chord: Chord): ChordScaleMatch[] {\n const chordPcs = chordPitchClasses(chord);\n const rootPc = pitchClass(chord.rootPc);\n const ranked: { name: string; extra: number; size: number }[] = [];\n const seenMasks = new Set<number>();\n for (const name of Object.keys(NAMED_SCALES)) {\n if (name === 'chromatic' || ALIASED_SCALE_NAMES.has(name)) {\n continue;\n }\n const mask = NAMED_SCALES[name];\n if (mask === undefined || seenMasks.has(mask)) {\n continue;\n }\n seenMasks.add(mask);\n if (scaleMatchesChord(chordPcs, mask, rootPc)) {\n const size = popcount12(mask);\n ranked.push({ name, extra: size - chordPcs.length, size });\n }\n }\n if (ranked.length === 0) {\n // No diatonic-style scale contains the chord; fall back to the chromatic\n // scale, which trivially contains every pitch class.\n if (NAMED_SCALES.chromatic !== undefined) {\n return [{ name: 'chromatic', rootPc }];\n }\n return [];\n }\n const preferHeptatonic = chordPcs.length <= 3;\n ranked.sort((a, b) => {\n if (preferHeptatonic && (a.size === HEPTATONIC_SIZE) !== (b.size === HEPTATONIC_SIZE)) {\n return a.size === HEPTATONIC_SIZE ? -1 : 1;\n }\n if (a.extra !== b.extra) {\n return a.extra - b.extra;\n }\n if (a.size !== b.size) {\n return a.size - b.size;\n }\n return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;\n });\n return ranked.map((entry) => ({ name: entry.name, rootPc }));\n}\n\n/**\n * List a scale's avoid notes over a chord.\n *\n * An avoid note is a non-chord scale tone that lies a semitone directly above a\n * chord tone; sounding it against the chord clashes. The scale is rooted on the\n * chord root. If the scale does not contain the chord, no avoid notes exist.\n *\n * @param chord The chord providing the chord tones.\n * @param scaleName A key of {@link NAMED_SCALES}.\n * @returns The avoid-note pitch classes, sorted ascending in [0, 11].\n *\n * @category Scales\n */\nexport function avoidNotes(chord: Chord, scaleName: string): number[] {\n const mask = NAMED_SCALES[scaleName];\n if (mask === undefined) {\n return [];\n }\n const rootPc = pitchClass(chord.rootPc);\n const chordPcs = chordPitchClasses(chord);\n if (!scaleMatchesChord(chordPcs, mask, rootPc)) {\n return [];\n }\n const chordSet = new Set(chordPcs);\n const avoid: number[] = [];\n for (let pc = 0; pc < 12; pc += 1) {\n if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc)) {\n continue;\n }\n if (chordSet.has(pitchClass(pc - 1))) {\n avoid.push(pc);\n }\n }\n return avoid.sort((a, b) => a - b);\n}\n\n/**\n * List a scale's available tensions over a chord.\n *\n * Available tensions are scale tones that are neither chord tones nor avoid\n * notes, i.e. the usable color tones (typically the 9/11/13 region). The scale\n * is rooted on the chord root. If the scale does not contain the chord, there\n * are no available tensions.\n *\n * @param chord The chord providing the chord tones.\n * @param scaleName A key of {@link NAMED_SCALES}.\n * @returns The available-tension pitch classes, sorted ascending in [0, 11].\n *\n * @example\n * ```ts\n * import { makeChord, availableTensions } from '@libraz/libcantus';\n * availableTensions(makeChord(0, 'maj7'), 'ionian'); // [2, 9] — color tones over Cmaj7\n * ```\n *\n * @category Scales\n */\nexport function availableTensions(chord: Chord, scaleName: string): number[] {\n const mask = NAMED_SCALES[scaleName];\n if (mask === undefined) {\n return [];\n }\n const rootPc = pitchClass(chord.rootPc);\n const chordPcs = chordPitchClasses(chord);\n if (!scaleMatchesChord(chordPcs, mask, rootPc)) {\n return [];\n }\n const chordSet = new Set(chordPcs);\n const avoidSet = new Set(avoidNotes(chord, scaleName));\n const tensions: number[] = [];\n for (let pc = 0; pc < 12; pc += 1) {\n if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc) || avoidSet.has(pc)) {\n continue;\n }\n tensions.push(pc);\n }\n return tensions.sort((a, b) => a - b);\n}\n\n/**\n * A scale fit over a chord together with its avoid notes and tensions.\n *\n * @category Scales\n */\nexport type ChordScaleReportEntry = {\n name: string;\n rootPc: number;\n avoid: number[];\n tensions: number[];\n};\n\n/**\n * Report the best-fitting scales for a chord with their avoid notes and tensions.\n *\n * Combines {@link chordScales}, {@link avoidNotes}, and {@link availableTensions}\n * into a single ergonomic result, ordered best fit first.\n *\n * @param chord The chord to analyze.\n * @param limit Optional maximum number of scales to report; all by default.\n * @returns One entry per reported scale, best fit first.\n *\n * @category Scales\n */\nexport function chordScaleReport(chord: Chord, limit?: number): ChordScaleReportEntry[] {\n const matches = chordScales(chord);\n const chosen = limit === undefined ? matches : matches.slice(0, Math.max(0, limit));\n return chosen.map((match) => ({\n name: match.name,\n rootPc: match.rootPc,\n avoid: avoidNotes(chord, match.name),\n tensions: availableTensions(chord, match.name),\n }));\n}\n\n/**\n * A chord paired with the scale chosen for it by {@link scalesForChanges}.\n *\n * @category Scales\n */\nexport type ScaleChoice = {\n chord: Chord;\n scale: ChordScaleMatch;\n};\n\n/**\n * Small per-candidate penalty added in {@link scalesForChanges} so that, among\n * choices of otherwise-equal transition cost, the tighter best-fit scale wins.\n */\nconst RANK_PENALTY = 0.01;\n\n/** Build the pitch-class set of a named scale rooted on `rootPc`. */\nfunction scalePitchClassSet(name: string, rootPc: number): Set<number> {\n const mask = NAMED_SCALES[name];\n const pcs = new Set<number>();\n if (mask === undefined) {\n return pcs;\n }\n for (let n = 0; n < 12; n += 1) {\n if (((mask >> n) & 1) === 1) {\n pcs.add(pitchClass(rootPc + n));\n }\n }\n return pcs;\n}\n\n/** Count pitch classes that belong to exactly one of two sets. */\nfunction symmetricDifferenceSize(a: Set<number>, b: Set<number>): number {\n let count = 0;\n for (const pc of a) {\n if (!b.has(pc)) {\n count += 1;\n }\n }\n for (const pc of b) {\n if (!a.has(pc)) {\n count += 1;\n }\n }\n return count;\n}\n\n/**\n * Choose one scale per chord across a progression, favoring continuity.\n *\n * Each chord's {@link chordScales} candidates form a stage in a Viterbi-style\n * dynamic program. The transition cost between adjacent choices is the number\n * of pitch classes that differ between their pitch-class sets (the symmetric\n * difference), plus a small penalty for straying from a chord's best-fit scale\n * so that ties break toward the tighter fit. The minimum-total-cost path is\n * returned, one {@link ScaleChoice} per input chord in the original order.\n *\n * @param chords The chord sequence to choose scales for.\n * @returns One scale choice per chord, in input order.\n *\n * @category Scales\n */\nexport function scalesForChanges(chords: Chord[]): ScaleChoice[] {\n if (chords.length === 0) {\n return [];\n }\n const candidateLists = chords.map((chord) => chordScales(chord));\n const pcSets = candidateLists.map((candidates) =>\n candidates.map((match) => scalePitchClassSet(match.name, match.rootPc)),\n );\n\n const first = candidateLists[0] ?? [];\n const dp: number[][] = [first.map((_, j) => j * RANK_PENALTY)];\n const back: number[][] = [first.map(() => -1)];\n\n for (let i = 1; i < candidateLists.length; i += 1) {\n const candidates = candidateLists[i] ?? [];\n const prevCosts = dp[i - 1] ?? [];\n const prevSets = pcSets[i - 1] ?? [];\n const curSets = pcSets[i] ?? [];\n const stageCosts: number[] = [];\n const stageBack: number[] = [];\n for (let j = 0; j < candidates.length; j += 1) {\n let bestCost = Number.POSITIVE_INFINITY;\n let bestPrev = -1;\n for (let k = 0; k < prevCosts.length; k += 1) {\n const transition = symmetricDifferenceSize(\n prevSets[k] ?? new Set(),\n curSets[j] ?? new Set(),\n );\n const cost = (prevCosts[k] ?? 0) + transition;\n if (cost < bestCost) {\n bestCost = cost;\n bestPrev = k;\n }\n }\n stageCosts.push(bestCost + j * RANK_PENALTY);\n stageBack.push(bestPrev);\n }\n dp.push(stageCosts);\n back.push(stageBack);\n }\n\n const lastCosts = dp[dp.length - 1] ?? [];\n let bestFinal = 0;\n for (let j = 1; j < lastCosts.length; j += 1) {\n if ((lastCosts[j] ?? Number.POSITIVE_INFINITY) < (lastCosts[bestFinal] ?? 0)) {\n bestFinal = j;\n }\n }\n\n const chosenIndices: number[] = new Array(candidateLists.length);\n let current = bestFinal;\n for (let i = candidateLists.length - 1; i >= 0; i -= 1) {\n chosenIndices[i] = current;\n current = back[i]?.[current] ?? -1;\n }\n\n return chords.map((chord, i) => {\n const candidates = candidateLists[i] ?? [];\n const scale = candidates[chosenIndices[i] ?? 0] ?? { name: 'chromatic', rootPc: chord.rootPc };\n return { chord, scale };\n });\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordToneRole } from '../chord/index.js';\nimport { createsParallelPerfect, isForbiddenMelodicLeap } from '../counterpoint/index.js';\nimport type { TimeSignature } from '../meter/index.js';\nimport { isStrongBeat } from '../meter/index.js';\nimport type { Rng } from '../random/index.js';\nimport { createRng } from '../random/index.js';\nimport type { VoiceSnapshot } from '../safety/index.js';\nimport { enumerateSafePitches } from '../safety/index.js';\nimport { nearestScaleTone } from '../scale/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/**\n * Options controlling {@link generateCounterMelody}.\n *\n * @category Voicing & Counterpoint\n */\nexport type CounterMelodyOptions = {\n /** The lead line to write against, in ascending onset order. */\n melody: NoteEvent[];\n /** Chord sounding at an absolute beat position, or null when none applies. */\n chordAt: (beat: number) => Chord | null;\n /** Key/scale context for scale-tone decisions. */\n key: KeyScale;\n /**\n * Meter used for strong-beat decisions.\n *\n * @defaultValue 4/4\n */\n ts?: TimeSignature;\n /**\n * Which side of the melody the counter line occupies.\n *\n * @defaultValue 'below'\n */\n register?: 'above' | 'below';\n /**\n * Onset strategy: `'complement'` moves where the melody holds or rests and\n * reinforces some strong beats; `'follow'` mirrors melody onsets.\n *\n * @defaultValue 'complement'\n */\n rhythm?: 'complement' | 'follow';\n /**\n * Safety profile applied to candidate pitches.\n *\n * @defaultValue 'pop'\n */\n profile?: 'strict' | 'pop';\n /** Lowest MIDI pitch the counter line may use (default derived from `register`). */\n pitchLow?: number;\n /** Highest MIDI pitch the counter line may use (default derived from `register`). */\n pitchHigh?: number;\n /**\n * PRNG seed; the same seed always yields the same line.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/** Meter assumed when none is supplied. */\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\n\n/** Tolerance for beat-position comparisons. */\nconst EPS = 1e-9;\n\n/** Grid resolution, in quarter-note beats, scanned for complement onsets. */\nconst GRID_STEP = 0.5;\n\n/** Minimum spacing between counter onsets, keeping the line uncluttered. */\nconst MIN_ONSET_GAP = 1;\n\n/** Semitone offset of the counter register's centre from the melody's mean pitch. */\nconst REGISTER_OFFSET = 12;\n\n/** Half-width, in semitones, of the default counter register. */\nconst DEFAULT_HALF_RANGE = 10;\n\n/** Probability of moving on a whole beat while the melody sustains. */\nconst HOLD_ON_BEAT_PROB = 0.55;\n\n/** Probability of moving on an off-beat subdivision while the melody sustains. */\nconst HOLD_OFF_BEAT_PROB = 0.2;\n\n/** Probability of reinforcing a strong beat that the melody also attacks. */\nconst REINFORCE_PROB = 0.35;\n\n/** Velocity assumed for melody notes that carry none. */\nconst DEFAULT_MELODY_VELOCITY = 96;\n\n/** How far below the concurrent melody velocity the counter line sits. */\nconst VELOCITY_DROP = 16;\n\n/** Whether a beat position falls on a whole quarter-note beat. */\nfunction isWholeBeat(beat: number): boolean {\n return Math.abs(beat - Math.round(beat)) < EPS;\n}\n\n/** The melody note sounding at a beat (latest onset wins on overlaps). */\nfunction melodyNoteAt(melody: NoteEvent[], beat: number): NoteEvent | undefined {\n let found: NoteEvent | undefined;\n for (const note of melody) {\n if (note.startBeat - EPS <= beat && beat < note.startBeat + note.durationBeat - EPS) {\n if (!found || note.startBeat > found.startBeat) {\n found = note;\n }\n }\n }\n return found;\n}\n\n/** Whether any melody note attacks exactly at a beat. */\nfunction melodyAttacksAt(melody: NoteEvent[], beat: number): boolean {\n return melody.some((note) => Math.abs(note.startBeat - beat) < EPS);\n}\n\n/** Counter onsets mirroring the melody's own onsets, deduplicated and sorted. */\nfunction followOnsets(melody: NoteEvent[]): number[] {\n return [...new Set(melody.map((note) => note.startBeat))].sort((a, b) => a - b);\n}\n\n/**\n * Counter onsets complementing the melody: whole beats inside rests are always\n * taken, positions where the melody sustains are taken probabilistically, and\n * strong beats the melody also attacks are occasionally reinforced. A minimum\n * gap between accepted onsets keeps the line sparse.\n */\nfunction complementOnsets(\n melody: NoteEvent[],\n ts: TimeSignature,\n spanStart: number,\n spanEnd: number,\n rng: Rng,\n): number[] {\n const onsets: number[] = [];\n const gridStart = Math.floor(spanStart / GRID_STEP) * GRID_STEP;\n let last = Number.NEGATIVE_INFINITY;\n for (let beat = gridStart; beat < spanEnd - EPS; beat += GRID_STEP) {\n const attacked = melodyAttacksAt(melody, beat);\n const sounding = melodyNoteAt(melody, beat) !== undefined;\n let place = false;\n if (!attacked && !sounding) {\n place = isWholeBeat(beat);\n } else if (!attacked) {\n place = rng.prob(isWholeBeat(beat) ? HOLD_ON_BEAT_PROB : HOLD_OFF_BEAT_PROB);\n } else if (isStrongBeat(beat, ts)) {\n place = rng.prob(REINFORCE_PROB);\n }\n if (place && beat - last >= MIN_ONSET_GAP - EPS) {\n onsets.push(beat);\n last = beat;\n }\n }\n return onsets;\n}\n\n/**\n * Preference score for one candidate counter pitch. Rewards imperfect\n * consonance with the melody, chord-tone membership, contrary or oblique\n * motion, and stepwise movement; penalizes wide or forbidden leaps, weak-beat\n * clashes, and drifting from the register centre.\n */\nfunction scoreCandidate(\n pitch: number,\n melPitch: number | undefined,\n melPrev: number | undefined,\n prevPitch: number | undefined,\n chord: Chord | null,\n center: number,\n): number {\n let score = 0;\n if (melPitch !== undefined) {\n const ic = Math.abs(pitch - melPitch) % 12;\n if (ic === 3 || ic === 4 || ic === 8 || ic === 9) {\n score += 2; // imperfect consonance: thirds and sixths\n } else if (ic === 0 || ic === 7) {\n score += 0.5; // perfect consonance: allowed but less colourful\n } else if (ic === 1 || ic === 2 || ic === 6 || ic === 10 || ic === 11) {\n score -= 2; // dissonant even on weak beats\n }\n }\n if (chord && chordToneRole(pitch, chord) !== null) {\n score += 1;\n }\n if (prevPitch !== undefined) {\n const move = pitch - prevPitch;\n const dist = Math.abs(move);\n score -= dist * 0.3;\n if (dist > 0 && dist <= 2) {\n score += 1; // stepwise motion\n }\n if (isForbiddenMelodicLeap(prevPitch, pitch)) {\n score -= 6;\n }\n if (melPitch !== undefined && melPrev !== undefined) {\n const melMove = melPitch - melPrev;\n if ((move > 0 && melMove < 0) || (move < 0 && melMove > 0)) {\n score += 2; // contrary motion\n } else if (move === 0 || melMove === 0) {\n score += 1; // oblique motion\n } else {\n score -= 1; // similar motion\n }\n }\n }\n score -= Math.abs(pitch - center) * 0.02;\n return score;\n}\n\n/**\n * Last-resort pitch when no safe candidate survives filtering: the scale tone\n * nearest the previous pitch (or the register centre), pushed onto the correct\n * side of the sounding melody note.\n */\nfunction fallbackPitch(\n melPitch: number | undefined,\n prevPitch: number | undefined,\n center: number,\n register: 'above' | 'below',\n low: number,\n high: number,\n key: KeyScale,\n): number {\n let target = prevPitch ?? Math.round(center);\n if (melPitch !== undefined) {\n if (register === 'below' && target >= melPitch) {\n target = melPitch - 5;\n } else if (register === 'above' && target <= melPitch) {\n target = melPitch + 5;\n }\n }\n target = Math.min(Math.max(target, low), high);\n let pitch = nearestScaleTone(target, key);\n // Push onto the requested side of the melody, but only by whole octaves that\n // keep the pitch inside [low, high]; the declared range is a hard bound while\n // the register side is a soft preference. A final clamp guarantees the range.\n if (melPitch !== undefined) {\n while (register === 'below' && pitch >= melPitch && pitch - 12 >= low) {\n pitch -= 12;\n }\n while (register === 'above' && pitch <= melPitch && pitch + 12 <= high) {\n pitch += 12;\n }\n }\n return Math.min(Math.max(pitch, low), high);\n}\n\n/**\n * Generate a counter melody against a lead line.\n *\n * Onsets are chosen per `rhythm`: `'follow'` places one counter note on each\n * melody onset; `'complement'` fills melody rests and sustains and reinforces\n * an occasional strong beat, spaced at least a beat apart. Each onset's pitch\n * is picked from the safe pitches in the counter register (chord tones and\n * consonant tensions against the sounding melody note), rejecting candidates\n * that would form a parallel perfect interval with the melody or sit on the\n * wrong side of it, then scored to favour contrary or oblique motion, imperfect\n * consonance, and stepwise movement. Ties break toward the lower pitch, so a\n * given seed always yields the same line. Notes extend to the next counter\n * onset (the last to the melody's end) at a velocity slightly under the melody.\n *\n * @param opts The lead line, chord context callback, key, and generation knobs.\n * @returns The counter line as note events sorted by onset; `[]` for an empty melody.\n * @example\n * ```ts\n * import { generateCounterMelody, majorKey, parseChordSymbol } from '@libraz/libcantus';\n * const melody = [{ pitch: 72, startBeat: 0, durationBeat: 2 }];\n * const counter = generateCounterMelody({\n * melody,\n * chordAt: () => parseChordSymbol('C'),\n * key: majorKey(0),\n * }); // note events below the melody, in onset order\n * ```\n * @category Voicing & Counterpoint\n */\nexport function generateCounterMelody(opts: CounterMelodyOptions): NoteEvent[] {\n const melody = [...opts.melody].sort((a, b) => a.startBeat - b.startBeat);\n if (melody.length === 0) {\n return [];\n }\n const ts = opts.ts ?? DEFAULT_TS;\n const register = opts.register ?? 'below';\n const rhythm = opts.rhythm ?? 'complement';\n const profile = opts.profile ?? 'pop';\n const rng = createRng(opts.seed ?? 0);\n\n const spanStart = melody[0]?.startBeat ?? 0;\n const spanEnd = melody.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), spanStart);\n const meanPitch = melody.reduce((sum, n) => sum + n.pitch, 0) / melody.length;\n const defaultCenter =\n register === 'below' ? meanPitch - REGISTER_OFFSET : meanPitch + REGISTER_OFFSET;\n const low = opts.pitchLow ?? Math.round(defaultCenter) - DEFAULT_HALF_RANGE;\n const high = opts.pitchHigh ?? Math.round(defaultCenter) + DEFAULT_HALF_RANGE;\n const center = (low + high) / 2;\n\n const onsets =\n rhythm === 'follow'\n ? followOnsets(melody)\n : complementOnsets(melody, ts, spanStart, spanEnd, rng);\n\n const out: NoteEvent[] = [];\n let prevPitch: number | undefined;\n let prevOnset: number | undefined;\n for (const beat of onsets) {\n const melNote = melodyNoteAt(melody, beat);\n const melPitch = melNote?.pitch;\n const melPrev = prevOnset !== undefined ? melodyNoteAt(melody, prevOnset)?.pitch : undefined;\n const chord = opts.chordAt(beat);\n const otherVoices: VoiceSnapshot[] =\n melPitch !== undefined ? [{ pitch: melPitch, prevPitch: melPrev }] : [];\n\n const candidates = enumerateSafePitches(\n {\n profile,\n prevPitch,\n chord,\n key: opts.key,\n otherVoices,\n strongBeat: isStrongBeat(beat, ts),\n vocalLow: low,\n vocalHigh: high,\n },\n low,\n high,\n );\n\n let bestPitch: number | undefined;\n let bestScore = Number.NEGATIVE_INFINITY;\n for (const candidate of candidates) {\n if (melPitch !== undefined) {\n if (register === 'below' && candidate >= melPitch) {\n continue;\n }\n if (register === 'above' && candidate <= melPitch) {\n continue;\n }\n if (\n prevPitch !== undefined &&\n melPrev !== undefined &&\n // Parallel octaves are the perfect-class-zero case of this predicate,\n // so a single check covers both parallel fifths and octaves.\n createsParallelPerfect(prevPitch, candidate, melPrev, melPitch)\n ) {\n continue;\n }\n }\n const score = scoreCandidate(candidate, melPitch, melPrev, prevPitch, chord, center);\n const tie =\n Math.abs(score - bestScore) <= EPS && candidate < (bestPitch ?? Number.POSITIVE_INFINITY);\n if (score > bestScore + EPS || tie) {\n bestScore = score;\n bestPitch = candidate;\n }\n }\n\n const pitch =\n bestPitch ?? fallbackPitch(melPitch, prevPitch, center, register, low, high, opts.key);\n const velocity = Math.max(\n 1,\n Math.min(127, Math.round((melNote?.velocity ?? DEFAULT_MELODY_VELOCITY) - VELOCITY_DROP)),\n );\n out.push({ pitch, startBeat: beat, durationBeat: GRID_STEP, velocity });\n prevPitch = pitch;\n prevOnset = beat;\n }\n\n // Extend each note to the next counter onset; the last to the melody's end.\n for (let i = 0; i < out.length; i += 1) {\n const note = out[i];\n if (!note) {\n continue;\n }\n const next = out[i + 1];\n const end = next ? next.startBeat : Math.max(spanEnd, note.startBeat + GRID_STEP);\n note.durationBeat = end - note.startBeat;\n }\n return out;\n}\n","/** General MIDI percussion note numbers used across the drum engine. */\nexport const GM = {\n BD: 36,\n SD: 38,\n SIDESTICK: 37,\n HANDCLAP: 39,\n CHH: 42,\n FHH: 44,\n OHH: 46,\n CRASH: 49,\n RIDE: 51,\n TAMBOURINE: 54,\n TOM_H: 50,\n TOM_M: 47,\n TOM_L: 45,\n SHAKER: 82,\n} as const;\n\n/** One beat and one sixteenth expressed as fractions of a beat. */\nexport const EIGHTH = 0.5;\nexport const SIXTEENTH = 0.25;\n\n/** Internal drum style selected by the public groove style. */\nexport type DrumStyle =\n | 'sparse'\n | 'standard'\n | 'fourOnFloor'\n | 'upbeat'\n | 'rock'\n | 'synth'\n | 'trap'\n | 'latin';\n\n/** Groove feel controlling off-beat swing. */\nexport type Feel = 'straight' | 'swing' | 'shuffle';\n\n/** Reduced section set the engine reasons about. */\nexport type SectionType = 'intro' | 'a' | 'b' | 'chorus' | 'bridge' | 'outro';\n\n/** Backing density bucket derived from the public density knob. */\nexport type BackingDensity = 'thin' | 'normal' | 'thick';\n\n/** Section energy level, used to shape fills. */\nexport type SectionEnergy = 'low' | 'medium' | 'high' | 'peak';\n\n/** Ghost-note mood category for the density table. */\nexport enum MoodCategory {\n Calm = 0,\n Standard = 1,\n Energetic = 2,\n}\n\n/** Percussion mood category for the activation table. */\nexport enum PercMoodCategory {\n Calm = 0,\n Standard = 1,\n Energetic = 2,\n Idol = 3,\n RockDark = 4,\n}\n\n/** Public groove style identifiers. */\nexport type GrooveStyle =\n | 'standard'\n | 'funk'\n | 'shuffle'\n | 'bossa'\n | 'trap'\n | 'halftime'\n | 'breakbeat'\n | 'house'\n | 'synthpop';\n\n/** Public role identifiers gating which voices are present. */\nexport type DrumRole = 'full' | 'ambient' | 'minimal' | 'fxOnly';\n\n/** Public section identifiers. */\nexport type PublicSection = 'intro' | 'verse' | 'prechorus' | 'chorus' | 'bridge' | 'outro';\n\n/** Resolved internal parameters for a public groove style. */\nexport type StyleMapping = {\n style: DrumStyle;\n feel: Feel;\n ghostBoost: boolean;\n snareBeat3: boolean;\n};\n\nconst STYLE_MAP: Record<GrooveStyle, StyleMapping> = {\n // Standard pop pulse: kick on beats 1 and 3, backbeat snare on 2 and 4.\n standard: { style: 'standard', feel: 'straight', ghostBoost: false, snareBeat3: false },\n funk: { style: 'upbeat', feel: 'straight', ghostBoost: true, snareBeat3: false },\n shuffle: { style: 'standard', feel: 'shuffle', ghostBoost: false, snareBeat3: false },\n bossa: { style: 'latin', feel: 'straight', ghostBoost: false, snareBeat3: false },\n trap: { style: 'trap', feel: 'straight', ghostBoost: false, snareBeat3: true },\n halftime: { style: 'sparse', feel: 'straight', ghostBoost: false, snareBeat3: true },\n breakbeat: { style: 'rock', feel: 'straight', ghostBoost: false, snareBeat3: false },\n // Four-on-the-floor dance kick with idol-style auxiliary percussion.\n house: { style: 'fourOnFloor', feel: 'straight', ghostBoost: false, snareBeat3: false },\n // Synth-pop pulse with denser 16th hi-hats and busy kick syncopation.\n synthpop: { style: 'synth', feel: 'straight', ghostBoost: true, snareBeat3: false },\n};\n\n/** Resolve the internal style/feel parameters for a public groove style. */\nexport function mapStyle(style: GrooveStyle): StyleMapping {\n return STYLE_MAP[style];\n}\n\n/** Map a public section to the internal section type. */\nexport function mapSection(section: PublicSection): SectionType {\n switch (section) {\n case 'intro':\n return 'intro';\n case 'verse':\n return 'a';\n case 'prechorus':\n return 'b';\n case 'chorus':\n return 'chorus';\n case 'bridge':\n return 'bridge';\n case 'outro':\n return 'outro';\n }\n}\n\n/** Bucket the 0..1 density knob into a backing-density level. */\nexport function mapDensity(density: number): BackingDensity {\n if (density < 0.34) {\n return 'thin';\n }\n if (density < 0.67) {\n return 'normal';\n }\n return 'thick';\n}\n\n/** Swing amount (0..1) implied by a groove feel. */\nexport function feelSwingAmount(feel: Feel): number {\n if (feel === 'swing') {\n return 0.33;\n }\n if (feel === 'shuffle') {\n return 0.5;\n }\n return 0;\n}\n\n/** Ghost-note mood category derived from the internal style. */\nexport function ghostMoodCategory(style: DrumStyle): MoodCategory {\n if (style === 'sparse') {\n return MoodCategory.Calm;\n }\n if (style === 'trap' || style === 'upbeat') {\n return MoodCategory.Energetic;\n }\n return MoodCategory.Standard;\n}\n\n/** Percussion mood category derived from the internal style. */\nexport function percMoodCategory(style: DrumStyle): PercMoodCategory {\n switch (style) {\n case 'sparse':\n return PercMoodCategory.Calm;\n case 'upbeat':\n case 'latin':\n return PercMoodCategory.Energetic;\n case 'fourOnFloor':\n return PercMoodCategory.Idol;\n case 'trap':\n case 'rock':\n return PercMoodCategory.RockDark;\n default:\n return PercMoodCategory.Standard;\n }\n}\n\n/** Zero-based section index shared by the ghost and percussion tables. */\nexport function sectionIndex(section: SectionType): number {\n switch (section) {\n case 'intro':\n return 0;\n case 'a':\n return 1;\n case 'b':\n return 2;\n case 'chorus':\n return 3;\n case 'bridge':\n return 4;\n case 'outro':\n return 6;\n }\n}\n\n/** Section energy used to size fills. */\nexport function sectionEnergy(section: SectionType): SectionEnergy {\n switch (section) {\n case 'intro':\n case 'outro':\n return 'low';\n case 'a':\n case 'bridge':\n return 'medium';\n case 'b':\n return 'high';\n case 'chorus':\n return 'peak';\n }\n}\n\n/** Section velocity multiplier applied to the base drum velocity. */\nexport function sectionVelocityMultiplier(section: SectionType): number {\n switch (section) {\n case 'intro':\n case 'outro':\n return 0.8;\n case 'a':\n return 0.9;\n case 'b':\n return 1.0;\n case 'chorus':\n return 1.1;\n case 'bridge':\n return 0.85;\n }\n}\n\n/** Section density multiplier before backing-density scaling. */\nexport function sectionDensityMultiplier(section: SectionType): number {\n switch (section) {\n case 'intro':\n return 0.5;\n case 'a':\n return 0.7;\n case 'b':\n return 0.85;\n case 'chorus':\n return 1.0;\n case 'bridge':\n return 0.6;\n case 'outro':\n return 0.6;\n }\n}\n\n/** Base drum velocity for a section beat (downbeats accented). */\nexport function calculateVelocity(section: SectionType, beat: number): number {\n const base = 80;\n const beatAdj = beat === 0 ? 10 : beat === 2 ? 5 : 0;\n const velocity = (base + beatAdj) * sectionVelocityMultiplier(section);\n return clampVel(velocity);\n}\n\n/** Round and clamp a velocity into the valid MIDI range. */\nexport function clampVel(velocity: number): number {\n return Math.max(1, Math.min(127, Math.round(velocity)));\n}\n","import type { BackingDensity, SectionType } from './internal.js';\nimport { MoodCategory, sectionIndex } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Ghost-note position within a beat: the \"e\" (1st 16th) or \"a\" (3rd 16th). */\nexport type GhostPosition = 'e' | 'a';\n\n/** Ghost density level ordinal (0 = none, 3 = heavy). */\ntype GhostDensityLevel = 0 | 1 | 2 | 3;\n\n// Ghost density level per [section index][mood category].\nconst GHOST_DENSITY_TABLE: GhostDensityLevel[][] = [\n /* intro */ [0, 1, 1],\n /* a */ [0, 1, 2],\n /* b */ [1, 2, 2],\n /* chorus */ [1, 2, 3],\n /* bridge */ [1, 1, 2],\n /* interlude */ [0, 1, 1],\n /* outro */ [0, 1, 1],\n];\n\nfunction levelToProbability(level: GhostDensityLevel): number {\n switch (level) {\n case 0:\n return 0;\n case 1:\n return 0.15;\n case 2:\n return 0.3;\n case 3:\n return 0.45;\n }\n}\n\nfunction clampLevel(level: number): GhostDensityLevel {\n return Math.max(0, Math.min(3, level)) as GhostDensityLevel;\n}\n\nfunction adjustForBpm(level: GhostDensityLevel, bpm: number): GhostDensityLevel {\n if (bpm >= 160 && level !== 0) {\n return clampLevel(level - 1);\n }\n if (bpm <= 90 && level !== 3) {\n return clampLevel(level + 1);\n }\n return level;\n}\n\n/** Ghost-note trigger probability for a section, mood, density, and tempo. */\nexport function getGhostDensity(\n mood: MoodCategory,\n section: SectionType,\n backingDensity: BackingDensity,\n bpm: number,\n): number {\n const row = GHOST_DENSITY_TABLE[sectionIndex(section)] ?? GHOST_DENSITY_TABLE[1];\n const level = adjustForBpm((row?.[mood] ?? 0) as GhostDensityLevel, bpm);\n\n if (backingDensity === 'thin' && level !== 0) {\n return levelToProbability(clampLevel(level - 1));\n }\n if (backingDensity === 'thick' && level !== 3) {\n return levelToProbability(clampLevel(level + 1));\n }\n return levelToProbability(level);\n}\n\n/** Ghost-note velocity multiplier for a section and metric position. */\nexport function getGhostVelocity(\n section: SectionType,\n beatPosition: number,\n isAfterSnare: boolean,\n): number {\n let base = 0.4;\n const even = beatPosition % 2 === 0 ? 0.05 : 0;\n switch (section) {\n case 'a':\n base = 0.35 + even;\n break;\n case 'chorus':\n base = 0.5 + even;\n break;\n case 'bridge':\n base = 0.25 + even;\n break;\n case 'b':\n base = 0.4 + even;\n break;\n case 'intro':\n case 'outro':\n base = 0.38;\n break;\n }\n if (isAfterSnare) {\n base += 0.1;\n }\n return Math.max(0.25, Math.min(0.65, base));\n}\n\n/** Probability of a ghost at a specific 16th position (higher near the snare). */\nexport function getGhostProbabilityAtPosition(beat: number, sixteenthInBeat: number): number {\n const nearSnare =\n (beat === 0 && sixteenthInBeat === 3) ||\n (beat === 1 && sixteenthInBeat === 1) ||\n (beat === 2 && sixteenthInBeat === 3) ||\n (beat === 3 && sixteenthInBeat === 1);\n return nearSnare ? 0.6 : 0.25;\n}\n\n/** Choose which ghost positions a groove favours. */\nexport function selectGhostPositions(mood: MoodCategory, rng: DrumRng): GhostPosition[] {\n if (mood === MoodCategory.Energetic) {\n return ['e', 'a'];\n }\n if (mood === MoodCategory.Calm) {\n return rng.prob(0.5) ? ['e'] : [];\n }\n return ['e'];\n}\n","import type { DrumRole, DrumStyle, SectionType } from './internal.js';\nimport { GM } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Hi-hat subdivision level. */\nexport type HiHatLevel = 'quarter' | 'eighth' | 'sixteenth';\n\n/** Hi-hat articulation type. */\nexport type HiHatType = 'closed' | 'pedal' | 'open' | 'halfOpen' | 'ride';\n\n/** BPM at or above which 16th-note hi-hats become 8ths for playability. */\nexport const HH_16TH_BPM_THRESHOLD = 150;\n\nconst FHH_VEL_MIN = 45;\nconst FHH_VEL_MAX = 60;\n/** Velocity boost applied to dynamic open hi-hat accents. */\nexport const OHH_VEL_BOOST = 7;\n\n/** True unless the role suppresses timekeeping cymbals entirely. */\nexport function shouldPlayHiHat(role: DrumRole): boolean {\n return role !== 'fxOnly';\n}\n\n/** Preferred timekeeping instrument for a role. */\nexport function roleHiHatInstrument(role: DrumRole, useRide: boolean): number {\n if (role === 'ambient') {\n return GM.RIDE;\n }\n return useRide ? GM.RIDE : GM.CHH;\n}\n\nfunction sparser(level: HiHatLevel): HiHatLevel {\n if (level === 'sixteenth') {\n return 'eighth';\n }\n if (level === 'eighth') {\n return 'quarter';\n }\n return 'quarter';\n}\n\nfunction denser(level: HiHatLevel): HiHatLevel {\n if (level === 'quarter') {\n return 'eighth';\n }\n if (level === 'eighth') {\n return 'sixteenth';\n }\n return 'sixteenth';\n}\n\n/** Choose the hi-hat subdivision for a section/style/density/BPM. */\nexport function getHiHatLevel(\n section: SectionType,\n style: DrumStyle,\n backingDensity: 'thin' | 'normal' | 'thick',\n bpm: number,\n rng: DrumRng,\n): HiHatLevel {\n const allow16th = bpm < HH_16TH_BPM_THRESHOLD;\n let base: HiHatLevel = 'eighth';\n\n if (style === 'sparse') {\n base = section === 'chorus' ? 'eighth' : 'quarter';\n } else if (style === 'fourOnFloor') {\n if (allow16th && section === 'chorus' && rng.prob(0.25)) {\n return 'sixteenth';\n }\n return 'eighth';\n } else if (style === 'synth') {\n if (!allow16th) {\n return 'eighth';\n }\n if (section === 'a' && rng.prob(0.2)) {\n return 'eighth';\n }\n return 'sixteenth';\n } else if (style === 'trap') {\n return allow16th ? 'sixteenth' : 'eighth';\n } else if (style === 'latin') {\n if (allow16th && section === 'chorus' && rng.prob(0.3)) {\n return 'sixteenth';\n }\n return 'eighth';\n } else {\n switch (section) {\n case 'intro':\n base = 'quarter';\n break;\n case 'outro':\n base = 'eighth';\n break;\n case 'a':\n base = rng.prob(0.3) ? 'quarter' : 'eighth';\n break;\n case 'b':\n base = allow16th && rng.prob(0.25) ? 'sixteenth' : 'eighth';\n break;\n case 'chorus':\n base = allow16th && rng.prob(0.35) ? 'sixteenth' : 'eighth';\n break;\n case 'bridge':\n base = 'eighth';\n break;\n }\n }\n\n if (backingDensity === 'thin') {\n base = sparser(base);\n } else if (backingDensity === 'thick') {\n base = denser(base);\n }\n\n if (!allow16th && base === 'sixteenth') {\n base = 'eighth';\n }\n return base;\n}\n\n/** Metric velocity multiplier for a 16th position within a beat. */\nexport function hiHatVelocityMultiplier(sixteenth: number, rng: DrumRng): number {\n let baseValue: number;\n switch (sixteenth) {\n case 0:\n baseValue = 0.95;\n break;\n case 2:\n baseValue = 0.75;\n break;\n case 1:\n baseValue = 0.55;\n break;\n default:\n baseValue = 0.5;\n break;\n }\n return baseValue * rng.float(0.95, 1.05);\n}\n\n/** Bars between dynamic open hi-hat accents (0 disables them). */\nexport function openHiHatBarInterval(section: SectionType, style: DrumStyle): number {\n if (style === 'sparse') {\n return section === 'chorus' ? 4 : 0;\n }\n switch (section) {\n case 'intro':\n return style === 'fourOnFloor' ? 4 : 0;\n case 'a':\n return style === 'fourOnFloor' || style === 'upbeat' ? 2 : 4;\n case 'b':\n return 2;\n case 'chorus':\n return style === 'rock' || style === 'fourOnFloor' ? 1 : 2;\n case 'bridge':\n return 0;\n case 'outro':\n return 4;\n }\n}\n\n/** Beat that receives the dynamic open hi-hat within a bar. */\nexport function openHiHatBeat(section: SectionType, rng: DrumRng): number {\n if (section === 'chorus') {\n const choice = rng.range(0, 3);\n if (choice < 2) {\n return 3;\n }\n if (choice < 3) {\n return 1;\n }\n return 2;\n }\n return 3;\n}\n\n/** Whether the section uses an independent foot hi-hat pulse. */\nexport function shouldUseFootHiHat(section: SectionType, role: DrumRole): boolean {\n if (role === 'fxOnly') {\n return false;\n }\n switch (section) {\n case 'intro':\n case 'bridge':\n case 'outro':\n return true;\n default:\n return role === 'ambient' || role === 'minimal';\n }\n}\n\n/** Primary hi-hat articulation for a section. */\nexport function sectionHiHatType(section: SectionType, role: DrumRole): HiHatType {\n if (role === 'ambient') {\n return 'ride';\n }\n if (role === 'minimal') {\n return 'pedal';\n }\n switch (section) {\n case 'intro':\n case 'a':\n return 'pedal';\n case 'b':\n return 'closed';\n case 'chorus':\n return 'open';\n case 'bridge':\n return 'ride';\n case 'outro':\n return 'halfOpen';\n }\n}\n\n/** GM note for a hi-hat articulation. */\nexport function hiHatNote(type: HiHatType): number {\n switch (type) {\n case 'pedal':\n return GM.FHH;\n case 'open':\n return GM.OHH;\n case 'ride':\n return GM.RIDE;\n default:\n return GM.CHH;\n }\n}\n\n/** Velocity multiplier for a hi-hat articulation. */\nexport function hiHatTypeVelocityMultiplier(type: HiHatType): number {\n switch (type) {\n case 'halfOpen':\n return 0.75;\n case 'pedal':\n return 0.65;\n case 'open':\n return 1.0;\n case 'ride':\n return 0.9;\n default:\n return 0.85;\n }\n}\n\n/** Whether to accent with an open hi-hat at a given beat. */\nexport function shouldAddOpenHHAccent(\n section: SectionType,\n beat: number,\n bar: number,\n rng: DrumRng,\n): boolean {\n if (section !== 'chorus' && section !== 'b') {\n return false;\n }\n if (section === 'chorus') {\n if (beat === 1 || beat === 3) {\n return rng.prob(0.6);\n }\n return false;\n }\n if (beat === 3 && bar % 2 === 1) {\n return rng.prob(0.4);\n }\n return false;\n}\n\n/** Foot hi-hat velocity with slight humanization. */\nexport function footHiHatVelocity(rng: DrumRng): number {\n return rng.range(FHH_VEL_MIN, FHH_VEL_MAX);\n}\n\n/** Whether the section uses a ride cymbal instead of hi-hats. */\nexport function shouldUseRideForSection(section: SectionType, style: DrumStyle): boolean {\n if (style === 'rock' && section === 'chorus') {\n return true;\n }\n if (style === 'sparse') {\n return false;\n }\n return section === 'bridge';\n}\n\n/** Whether a bridge beat is carried by a cross-stick instead of the hi-hat. */\nexport function shouldUseBridgeCrossStick(section: SectionType, beat: number): boolean {\n return section === 'bridge' && (beat === 1 || beat === 3);\n}\n","import type { Feel } from './internal.js';\n\nconst SIXTEENTH = 0.25;\nconst EIGHTH = 0.5;\nconst HALF_16TH = 0.125;\n/** Delay of an off-beat 16th at full swing (triplet minus straight), in beats. */\nconst DELTA_16 = 1 / 3 - 1 / 4; // 0.08333...\n/** Delay of an off-beat 8th at full swing, in beats. */\nconst DELTA_8 = (2 / 3 - 1 / 2) / 2 + (2 / 3 - 1 / 2) / 2; // 0.16667...\n\n/** Grid resolution for swing quantization. */\nexport type SwingResolution = 'eighth' | 'sixteenth';\n\n/** Effective swing after applying the groove feel to a base swing amount. */\nexport function effectiveSwing(feel: Feel, swingAmount: number): number {\n if (feel === 'straight') {\n return 0;\n }\n if (feel === 'shuffle') {\n return Math.min(1, swingAmount * 1.5);\n }\n return swingAmount;\n}\n\n/**\n * Push an off-beat position toward its triplet placement.\n *\n * On-beat positions are returned unchanged; off-beat 8ths and 16ths are delayed\n * proportionally to the swing amount.\n *\n * @param startBeat Absolute position in beats.\n * @param swing Swing amount in [0, 1] (already feel-adjusted).\n * @param resolution Whether to swing the 16th or only the 8th grid.\n * @returns The swung position in beats.\n */\nexport function quantizeSwing(\n startBeat: number,\n swing: number,\n resolution: SwingResolution,\n): number {\n const clamped = Math.max(0, Math.min(1, swing));\n if (clamped <= 0) {\n return startBeat;\n }\n const base = Math.floor(startBeat);\n const offset = startBeat - base;\n\n if (resolution === 'sixteenth') {\n if (offset >= HALF_16TH && offset < SIXTEENTH + HALF_16TH) {\n return base + SIXTEENTH + DELTA_16 * clamped;\n }\n if (offset >= SIXTEENTH + HALF_16TH && offset < EIGHTH + HALF_16TH) {\n return base + EIGHTH + DELTA_8 * clamped;\n }\n if (offset >= EIGHTH + HALF_16TH && offset < 3 * SIXTEENTH + HALF_16TH) {\n // The \"a\" 16th is the midpoint of the compressed second half of the beat\n // (between the swung \"and\" and the next downbeat), mirroring the \"e\" 16th\n // in the first half. Because DELTA_8 = 2 * DELTA_16, that midpoint reduces\n // to a single DELTA_16 delay off the straight position, so the \"a\" never\n // overshoots the downbeat and needs no clamp. At the default shuffle feel\n // (swing 0.75) this lands near 0.8125 rather than the doubly-swung 0.9375.\n return base + 3 * SIXTEENTH + DELTA_16 * clamped;\n }\n return startBeat;\n }\n\n if (offset >= SIXTEENTH && offset < 3 * SIXTEENTH) {\n return base + EIGHTH + DELTA_8 * clamped;\n }\n return startBeat;\n}\n","import {\n getGhostDensity,\n getGhostProbabilityAtPosition,\n getGhostVelocity,\n selectGhostPositions,\n} from './ghost.js';\nimport {\n footHiHatVelocity,\n type HiHatLevel,\n hiHatNote,\n hiHatTypeVelocityMultiplier,\n hiHatVelocityMultiplier,\n OHH_VEL_BOOST,\n roleHiHatInstrument,\n sectionHiHatType,\n shouldAddOpenHHAccent,\n shouldPlayHiHat,\n shouldUseBridgeCrossStick,\n} from './hihat.js';\nimport type { HitList } from './hit.js';\nimport type { BackingDensity, DrumRole, DrumStyle, Feel, SectionType } from './internal.js';\nimport { EIGHTH, GM, type MoodCategory, SIXTEENTH } from './internal.js';\nimport type { KickPattern } from './kick.js';\nimport type { DrumRng } from './rng.js';\nimport { effectiveSwing, quantizeSwing } from './swing.js';\n\n/** Per-section drum state shared across the bars of a section. */\nexport type SectionCtx = {\n style: DrumStyle;\n feel: Feel;\n densityMult: number;\n backingDensity: BackingDensity;\n hhLevel: HiHatLevel;\n useGhostNotes: boolean;\n ghostBoost: boolean;\n useRide: boolean;\n useFootHh: boolean;\n role: DrumRole;\n ghostMood: MoodCategory;\n snareBeat3: boolean;\n};\n\n/** Per-beat context passed to every beat processor. */\nexport type BeatCtx = {\n track: HitList;\n beatTick: number;\n beat: number;\n velocity: number;\n section: SectionType;\n bpm: number;\n bar: number;\n sectionBars: number;\n inPrechorusLift: boolean;\n swingAmount: number;\n barHasOpenHh: boolean;\n openHhBeat: number;\n rng: DrumRng;\n};\n\nfunction swing16(tick: number, feel: Feel, swingAmount: number): number {\n return quantizeSwing(tick, effectiveSwing(feel, swingAmount), 'sixteenth');\n}\n\nfunction hatSwingFactor(style: DrumStyle): number {\n if (style === 'trap') {\n return 0;\n }\n if (style === 'latin') {\n return 0.35;\n }\n return 0.5;\n}\n\n/** Emit the kick for one beat. */\nexport function generateKickForBeat(ctx: BeatCtx, sec: SectionCtx, kick: KickPattern): void {\n if (ctx.inPrechorusLift) {\n return;\n }\n const on = [kick.beat1, kick.beat2, kick.beat3, kick.beat4][ctx.beat] ?? false;\n const and = [kick.beat1and, kick.beat2and, kick.beat3and, kick.beat4and][ctx.beat] ?? false;\n\n if (on) {\n ctx.track.add(GM.BD, ctx.beatTick, EIGHTH, ctx.velocity);\n }\n if (and) {\n const andTick = swing16(ctx.beatTick + EIGHTH, sec.feel, ctx.swingAmount);\n ctx.track.add(GM.BD, andTick, EIGHTH, ctx.velocity * 0.85);\n }\n}\n\n/** Emit the backbeat snare (or side-stick) for one beat. */\nexport function generateSnareForBeat(ctx: BeatCtx, sec: SectionCtx, isIntroFirst: boolean): void {\n if (ctx.inPrechorusLift) {\n return;\n }\n const snareOn = sec.snareBeat3 ? ctx.beat === 2 : ctx.beat === 1 || ctx.beat === 3;\n if (!snareOn || isIntroFirst) {\n return;\n }\n if (sec.useRide && shouldUseBridgeCrossStick(ctx.section, ctx.beat)) {\n return;\n }\n\n const backbeatVel = Math.min(127, ctx.velocity + 16);\n const promoteSparseChorus =\n sec.style === 'sparse' && ctx.section === 'chorus' && sec.role === 'full';\n\n if (promoteSparseChorus) {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, backbeatVel);\n } else if (sec.style === 'sparse' || sec.role === 'ambient') {\n if (sec.role !== 'fxOnly' && sec.role !== 'minimal') {\n ctx.track.add(GM.SIDESTICK, ctx.beatTick, EIGHTH, ctx.velocity * 0.8);\n }\n } else {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, backbeatVel);\n }\n}\n\n/** Emit ghost snares at the \"e\"/\"a\" 16ths of beats 1 and 3. */\nexport function generateGhostNotesForBeat(ctx: BeatCtx, sec: SectionCtx): void {\n if (ctx.beat !== 0 && ctx.beat !== 2) {\n return;\n }\n const positions = selectGhostPositions(sec.ghostMood, ctx.rng);\n let ghostProb = getGhostDensity(sec.ghostMood, ctx.section, sec.backingDensity, ctx.bpm);\n if (sec.ghostBoost) {\n ghostProb = Math.min(1, ghostProb * 1.4);\n }\n\n for (const pos of positions) {\n const sixteenthInBeat = pos === 'e' ? 1 : 3;\n const posProb = getGhostProbabilityAtPosition(ctx.beat, sixteenthInBeat);\n if (!ctx.rng.prob(ghostProb * posProb)) {\n continue;\n }\n const variation = ctx.rng.float(0.85, 1.15);\n const ghostBase = getGhostVelocity(ctx.section, ctx.beat / 2, false);\n let ghostVel = ctx.velocity * ghostBase * variation;\n if (pos === 'a') {\n ghostVel *= 0.9;\n }\n const offset = pos === 'e' ? SIXTEENTH : 3 * SIXTEENTH;\n const tick = swing16(ctx.beatTick + offset, sec.feel, ctx.swingAmount);\n ctx.track.add(GM.SD, tick, SIXTEENTH, ghostVel);\n }\n}\n\n/** Emit the pre-chorus lift buildup for one beat. */\nexport function generatePreChorusBuildup(\n ctx: BeatCtx,\n sec: SectionCtx,\n isSectionLastBar: boolean,\n): void {\n if (sec.style === 'sparse') {\n if (isSectionLastBar && ctx.beat === 3) {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, Math.max(45, ctx.velocity * 0.75));\n ctx.track.add(GM.CRASH, ctx.beatTick + EIGHTH + SIXTEENTH, SIXTEENTH, ctx.velocity * 0.9);\n }\n return;\n }\n const barsInLift = 2;\n const barInLift = ctx.bar - (ctx.sectionBars - barsInLift);\n const progress = (barInLift * 4 + ctx.beat) / (barsInLift * 4);\n const buildupVel = ctx.velocity * (0.5 + 0.5 * progress);\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, buildupVel);\n ctx.track.add(GM.SD, ctx.beatTick + EIGHTH, EIGHTH, buildupVel * 0.85);\n if (isSectionLastBar && ctx.beat === 3) {\n ctx.track.add(GM.CRASH, ctx.beatTick + EIGHTH + SIXTEENTH, SIXTEENTH, ctx.velocity * 1.1);\n }\n}\n\n/** Emit the timekeeping hi-hat (or ride/foot) for one beat. */\nexport function generateHiHatForBeat(ctx: BeatCtx, sec: SectionCtx): void {\n if (!shouldPlayHiHat(sec.role)) {\n if (sec.useFootHh && (ctx.beat === 0 || ctx.beat === 2)) {\n ctx.track.add(GM.FHH, ctx.beatTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n return;\n }\n\n const crossStick = sec.useRide && shouldUseBridgeCrossStick(ctx.section, ctx.beat);\n const hhInstrument = crossStick ? GM.SIDESTICK : roleHiHatInstrument(sec.role, sec.useRide);\n const hhType = sectionHiHatType(ctx.section, sec.role);\n const typeMult = hiHatTypeVelocityMultiplier(hhType);\n const isDynamicOpen = ctx.barHasOpenHh && ctx.beat === ctx.openHhBeat;\n const dm = sec.densityMult;\n\n if (sec.hhLevel === 'quarter') {\n const introRest = ctx.section === 'intro' && ctx.beat !== 0;\n if (!introRest) {\n if (isDynamicOpen) {\n ctx.track.add(\n GM.OHH,\n ctx.beatTick,\n EIGHTH,\n ctx.velocity * dm * 0.75 * typeMult + OHH_VEL_BOOST,\n );\n } else {\n ctx.track.add(\n hhInstrument,\n ctx.beatTick,\n EIGHTH,\n Math.max(20, ctx.velocity * dm * 0.75 * typeMult),\n );\n }\n } else if (sec.useFootHh) {\n ctx.track.add(GM.FHH, ctx.beatTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n return;\n }\n\n if (sec.hhLevel === 'eighth') {\n for (let eighth = 0; eighth < 2; eighth += 1) {\n let hhTick = ctx.beatTick + eighth * EIGHTH;\n if (eighth === 1) {\n hhTick = swing16(hhTick, sec.feel, ctx.swingAmount);\n }\n if (ctx.section === 'intro' && eighth === 1) {\n if (sec.useFootHh && ctx.beat % 2 === 0) {\n ctx.track.add(GM.FHH, hhTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n continue;\n }\n const hhVel = Math.max(20, ctx.velocity * dm * typeMult * (eighth === 0 ? 0.9 : 0.65));\n if (isDynamicOpen && eighth === 0) {\n ctx.track.add(GM.OHH, hhTick, EIGHTH, hhVel + OHH_VEL_BOOST);\n continue;\n }\n let useOpen = false;\n if (sec.style === 'fourOnFloor' && eighth === 1) {\n const openProb = Math.max(0.15, Math.min(0.8, 45 / ctx.bpm));\n useOpen = (ctx.beat === 1 || ctx.beat === 3) && ctx.rng.prob(openProb);\n } else if (eighth === 0) {\n useOpen = shouldAddOpenHHAccent(ctx.section, ctx.beat, ctx.bar, ctx.rng);\n }\n if (useOpen) {\n ctx.track.add(hiHatNote('open'), hhTick, EIGHTH, Math.max(20, hhVel * 1.1));\n } else {\n ctx.track.add(hhInstrument, hhTick, EIGHTH / 2, hhVel);\n }\n }\n return;\n }\n\n for (let sixteenth = 0; sixteenth < 4; sixteenth += 1) {\n let hhTick = ctx.beatTick + sixteenth * SIXTEENTH;\n if (sixteenth === 1 || sixteenth === 3) {\n const swung = effectiveSwing(sec.feel, ctx.swingAmount) * hatSwingFactor(sec.style);\n hhTick = quantizeSwing(hhTick, swung, 'sixteenth');\n }\n const metricVel = hiHatVelocityMultiplier(sixteenth, ctx.rng);\n const hhVel = Math.max(20, ctx.velocity * dm * typeMult * metricVel);\n if (isDynamicOpen && sixteenth === 0) {\n ctx.track.add(GM.OHH, hhTick, SIXTEENTH, hhVel + OHH_VEL_BOOST);\n continue;\n }\n if (ctx.beat === 3 && sixteenth === 3) {\n const openProb = Math.max(0.1, Math.min(0.4, 30 / ctx.bpm));\n if (ctx.rng.prob(openProb)) {\n ctx.track.add(GM.OHH, hhTick, SIXTEENTH, Math.max(20, hhVel * 1.2));\n continue;\n }\n }\n ctx.track.add(hhInstrument, hhTick, SIXTEENTH / 2, hhVel);\n }\n}\n","/**\n * Generate a euclidean onset pattern (Bjorklund's algorithm), distributing\n * `pulses` as evenly as possible across `steps`, then rotating.\n *\n * @param pulses Number of onsets, clamped to [0, steps].\n * @param steps Total steps (>= 1).\n * @param rotation Steps to rotate onsets toward later positions.\n * @returns One boolean per step; true marks an onset.\n */\nexport function euclideanRhythm(pulses: number, steps: number, rotation = 0): boolean[] {\n if (steps < 1) {\n return [];\n }\n const p = Math.max(0, Math.min(pulses, steps));\n const base = bjorklund(p, steps);\n const shift = ((rotation % steps) + steps) % steps;\n if (shift === 0) {\n return base;\n }\n return base.map((_, i) => base[(i - shift + steps) % steps] ?? false);\n}\n\n/** True when the 16-step bitmask has an onset at `step`. */\nexport function hasHit(mask: number, step: number): boolean {\n return ((mask >> step) & 1) === 1;\n}\n\n/** Convert a euclidean boolean pattern to a 16-step bitmask (LSB = step 0). */\nexport function patternToMask(pattern: boolean[]): number {\n let mask = 0;\n for (let i = 0; i < pattern.length; i += 1) {\n if (pattern[i]) {\n mask |= 1 << i;\n }\n }\n return mask;\n}\n\nfunction bjorklund(pulses: number, steps: number): boolean[] {\n if (pulses === 0) {\n return Array.from({ length: steps }, () => false);\n }\n if (pulses >= steps) {\n return Array.from({ length: steps }, () => true);\n }\n let head: boolean[][] = Array.from({ length: pulses }, () => [true]);\n let remainder: boolean[][] = Array.from({ length: steps - pulses }, () => [false]);\n while (remainder.length > 1) {\n const count = Math.min(head.length, remainder.length);\n const next: boolean[][] = [];\n for (let i = 0; i < count; i += 1) {\n next.push([...(head[i] ?? []), ...(remainder[i] ?? [])]);\n }\n remainder = head.length > count ? head.slice(count) : remainder.slice(count);\n head = next;\n }\n return [...head.flat(), ...remainder.flat()];\n}\n","import type { HitList } from './hit.js';\nimport type { DrumStyle, SectionEnergy, SectionType } from './internal.js';\nimport { EIGHTH, GM, SIXTEENTH } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** The thirteen fill archetypes for section transitions. */\nexport type FillType =\n | 'snareRoll'\n | 'tomDescend'\n | 'tomAscend'\n | 'snareTomCombo'\n | 'simpleCrash'\n | 'linearFill'\n | 'ghostToAccent'\n | 'bdSnareAlternate'\n | 'hiHatChoke'\n | 'tomShuffle'\n | 'breakdownFill'\n | 'flamsAndDrags'\n | 'halfTimeFill';\n\n/** Beat at which a fill begins, widening with section energy. */\nexport function getFillStartBeat(energy: SectionEnergy): number {\n switch (energy) {\n case 'low':\n return 3;\n case 'medium':\n return 2;\n case 'high':\n case 'peak':\n return 0;\n }\n}\n\n/**\n * Pick a fill archetype for a section transition.\n *\n * The transition-specific archetypes (into a chorus, out of an intro) are\n * checked before the generic energy fills so every variation stays reachable;\n * with `from === to` the caller effectively asks for a within-section fill.\n *\n * @param from Section the fill leaves.\n * @param to Section the fill leads into.\n * @param style Internal drum style.\n * @param nextEnergy Energy of the section the fill leads into.\n * @param rng Deterministic PRNG.\n */\nexport function selectFillType(\n from: SectionType,\n to: SectionType,\n style: DrumStyle,\n nextEnergy: SectionEnergy,\n rng: DrumRng,\n): FillType {\n if (style === 'sparse') {\n return rng.range(0, 1) === 0 ? 'simpleCrash' : 'breakdownFill';\n }\n\n const toChorus = to === 'chorus';\n const fromIntro = from === 'intro';\n const highEnergy = style === 'rock' || style === 'fourOnFloor';\n\n // Dropping into a low-energy section: keep the phrase end gentle.\n if (nextEnergy === 'low') {\n switch (rng.range(0, 2)) {\n case 0:\n return 'simpleCrash';\n case 1:\n return 'breakdownFill';\n default:\n return 'halfTimeFill';\n }\n }\n\n // Big lead-ins to a chorus take precedence over the generic energy fills.\n if (toChorus) {\n const choice = rng.range(0, 7);\n if (highEnergy) {\n switch (choice) {\n case 0:\n case 1:\n return 'tomDescend';\n case 2:\n return 'snareRoll';\n case 3:\n return 'linearFill';\n case 4:\n return 'bdSnareAlternate';\n case 5:\n return 'flamsAndDrags';\n case 6:\n return 'tomShuffle';\n default:\n return 'ghostToAccent';\n }\n }\n switch (choice) {\n case 0:\n case 1:\n return 'snareTomCombo';\n case 2:\n return 'tomDescend';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'hiHatChoke';\n case 5:\n return 'linearFill';\n default:\n return 'snareRoll';\n }\n }\n\n // Leaving the intro: lighter, building character.\n if (fromIntro) {\n switch (rng.range(0, 5)) {\n case 0:\n case 1:\n return 'snareRoll';\n case 2:\n return 'simpleCrash';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'breakdownFill';\n default:\n return 'halfTimeFill';\n }\n }\n\n // Generic medium/high/peak fills, split by style energy.\n const choice = rng.range(0, 7);\n if (highEnergy) {\n switch (choice) {\n case 0:\n return 'tomDescend';\n case 1:\n return 'snareRoll';\n case 2:\n return 'tomAscend';\n case 3:\n return 'snareTomCombo';\n case 4:\n return 'linearFill';\n case 5:\n return 'bdSnareAlternate';\n case 6:\n return 'flamsAndDrags';\n default:\n return 'tomShuffle';\n }\n }\n\n switch (choice) {\n case 0:\n case 1:\n return 'snareRoll';\n case 2:\n return 'snareTomCombo';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'hiHatChoke';\n case 5:\n return 'halfTimeFill';\n default:\n return 'breakdownFill';\n }\n}\n\n/**\n * Emit a fill for a single beat of the fill bar.\n *\n * @param track Hit accumulator.\n * @param beatTick Absolute beat position of this beat.\n * @param beat Beat index within the bar (0-3).\n * @param fillType Selected fill archetype.\n * @param velocity Base velocity for the beat.\n */\nexport function generateFill(\n track: HitList,\n beatTick: number,\n beat: number,\n fillType: FillType,\n velocity: number,\n): void {\n const fillVel = velocity * 0.9;\n const accentVel = velocity * 0.95;\n const S = SIXTEENTH;\n const E = EIGHTH;\n\n if (beat === 0) {\n track.add(GM.BD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, E, fillVel - 5);\n return;\n }\n if (beat === 1) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_H, beatTick + E, E, fillVel - 3);\n return;\n }\n\n switch (fillType) {\n case 'snareRoll':\n if (beat === 2) {\n for (let i = 0; i < 4; i += 1) {\n track.add(GM.SD, beatTick + i * S, S, fillVel * (0.6 + 0.1 * i));\n }\n } else {\n for (let i = 0; i < 3; i += 1) {\n track.add(GM.SD, beatTick + i * S, S, fillVel * (0.7 + 0.1 * i));\n }\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'tomDescend':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_H, beatTick + E, E, fillVel - 5);\n } else {\n track.add(GM.TOM_H, beatTick, S, fillVel);\n track.add(GM.TOM_M, beatTick + S, S, fillVel - 3);\n track.add(GM.TOM_M, beatTick + E, S, fillVel - 5);\n track.add(GM.TOM_L, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'tomAscend':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_L, beatTick + E, E, fillVel - 5);\n } else {\n track.add(GM.TOM_L, beatTick, S, fillVel);\n track.add(GM.TOM_M, beatTick + S, S, fillVel + 3);\n track.add(GM.TOM_M, beatTick + E, S, fillVel + 5);\n track.add(GM.TOM_H, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'snareTomCombo':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, S, fillVel - 5);\n track.add(GM.TOM_H, beatTick + E + S, S, fillVel);\n } else {\n track.add(GM.TOM_M, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel - 3);\n track.add(GM.TOM_L, beatTick + E, S, fillVel + 2);\n track.add(GM.BD, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'simpleCrash':\n if (beat === 3) {\n track.add(GM.BD, beatTick + E + S, S, accentVel);\n track.add(GM.CRASH, beatTick + E + S, E, accentVel);\n }\n break;\n\n case 'linearFill':\n if (beat === 2) {\n track.add(GM.BD, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel);\n track.add(GM.TOM_H, beatTick + 2 * S, S, fillVel);\n track.add(GM.TOM_M, beatTick + 3 * S, S, fillVel);\n } else {\n track.add(GM.TOM_L, beatTick, S, fillVel + 3);\n track.add(GM.SD, beatTick + S, S, fillVel + 5);\n track.add(GM.BD, beatTick + 2 * S, S, fillVel + 7);\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'ghostToAccent':\n if (beat === 2) {\n const ghost = fillVel * 0.4;\n track.add(GM.SD, beatTick, S, ghost);\n track.add(GM.SD, beatTick + S, S, ghost + 10);\n track.add(GM.SD, beatTick + 2 * S, S, ghost + 20);\n track.add(GM.SD, beatTick + 3 * S, S, ghost + 30);\n } else {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, E, accentVel);\n }\n break;\n\n case 'bdSnareAlternate':\n if (beat === 2) {\n track.add(GM.BD, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel);\n track.add(GM.BD, beatTick + 2 * S, S, fillVel + 3);\n track.add(GM.SD, beatTick + 3 * S, S, fillVel + 3);\n } else {\n track.add(GM.BD, beatTick, S, fillVel + 5);\n track.add(GM.SD, beatTick + S, S, fillVel + 5);\n track.add(GM.BD, beatTick + 2 * S, S, accentVel);\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'hiHatChoke':\n if (beat === 2) {\n track.add(GM.OHH, beatTick, E, fillVel);\n track.add(GM.OHH, beatTick + E, E, fillVel + 5);\n } else {\n track.add(GM.OHH, beatTick, S, fillVel + 8);\n track.add(GM.CHH, beatTick + S, S, accentVel);\n track.add(GM.SD, beatTick + E, E, accentVel);\n }\n break;\n\n case 'tomShuffle':\n if (beat === 2) {\n track.add(GM.TOM_H, beatTick, E, fillVel);\n track.add(GM.TOM_M, beatTick + E + S / 2, S, fillVel - 5);\n } else {\n track.add(GM.TOM_M, beatTick, E, fillVel);\n track.add(GM.TOM_L, beatTick + E + S / 2, S, fillVel + 5);\n }\n break;\n\n case 'breakdownFill':\n if (beat === 3) {\n track.add(GM.SD, beatTick + E, S, accentVel);\n }\n break;\n\n case 'flamsAndDrags':\n if (beat === 2) {\n track.add(GM.SD, beatTick - S / 4, S / 4, fillVel * 0.5);\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, S / 2, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S / 2, S / 2, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S, E, fillVel);\n } else {\n track.add(GM.SD, beatTick - S / 4, S / 4, fillVel * 0.5);\n track.add(GM.SD, beatTick, 1, accentVel);\n }\n break;\n\n case 'halfTimeFill':\n if (beat === 2) {\n track.add(GM.SD, beatTick, 1, accentVel);\n track.add(GM.BD, beatTick, 1, fillVel);\n } else if (beat === 3) {\n // At low energy the fill spans only beat 3, so this branch keeps the\n // phrase end from going silent: a broad half-time backbeat snare with a\n // light pickup into the next section.\n track.add(GM.SD, beatTick, EIGHTH, accentVel);\n track.add(GM.SD, beatTick + E, S, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S, S, accentVel);\n }\n break;\n }\n}\n","import { clampVel, GM } from './internal.js';\n\n/** A single percussion onset. */\nexport type DrumHit = {\n pitch: number;\n startBeat: number;\n durationBeat: number;\n velocity: number;\n};\n\n/** Accumulator for drum onsets with velocity clamping and simple lookups. */\nexport class HitList {\n readonly hits: DrumHit[] = [];\n\n /** Append a hit, clamping velocity and dropping non-positive positions. */\n add(pitch: number, startBeat: number, durationBeat: number, velocity: number): void {\n this.hits.push({\n pitch,\n startBeat: Math.max(0, startBeat),\n durationBeat,\n velocity: clampVel(velocity),\n });\n }\n\n /** True when a crash already sits within a 16th of `startBeat`. */\n hasCrashNear(startBeat: number): boolean {\n return this.hits.some(\n (h) => h.pitch === GM.CRASH && h.startBeat >= startBeat && h.startBeat < startBeat + 0.25,\n );\n }\n}\n","import { hasHit } from './euclid.js';\nimport type { DrumStyle, SectionType } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Kick presence flags across the eight 8th-note slots of a bar. */\nexport type KickPattern = {\n beat1: boolean;\n beat1and: boolean;\n beat2: boolean;\n beat2and: boolean;\n beat3: boolean;\n beat3and: boolean;\n beat4: boolean;\n beat4and: boolean;\n};\n\nconst EMPTY: KickPattern = {\n beat1: false,\n beat1and: false,\n beat2: false,\n beat2and: false,\n beat3: false,\n beat3and: false,\n beat4: false,\n beat4and: false,\n};\n\n/**\n * Whether a pre-chorus bar sits in the two-bar lift into the chorus.\n *\n * @param section Current section.\n * @param bar Bar index within the section.\n * @param sectionBars Total bars in the section.\n * @param nextIsChorus Whether the following section is a chorus.\n */\nexport function isInPreChorusLift(\n section: SectionType,\n bar: number,\n sectionBars: number,\n nextIsChorus: boolean,\n): boolean {\n if (section !== 'b' || !nextIsChorus || sectionBars < 3) {\n return false;\n }\n return bar >= sectionBars - 2;\n}\n\n/** Convert a 16-step euclidean bitmask into an 8th-slot kick pattern. */\nexport function euclideanToKickPattern(mask: number): KickPattern {\n const slot = (step: number) => hasHit(mask, step) || hasHit(mask, (step + 15) % 16);\n return {\n beat1: slot(0),\n beat1and: slot(2),\n beat2: slot(4),\n beat2and: slot(6),\n beat3: slot(8),\n beat3and: slot(10),\n beat4: slot(12),\n beat4and: slot(14),\n };\n}\n\n/**\n * Build a section- and style-aware kick pattern.\n *\n * @param section Current section.\n * @param style Internal drum style.\n * @param bar Bar index (drives variation for a few styles).\n * @param rng Deterministic PRNG for probabilistic accents.\n */\nexport function getKickPattern(\n section: SectionType,\n style: DrumStyle,\n bar: number,\n rng: DrumRng,\n): KickPattern {\n const p: KickPattern = { ...EMPTY };\n\n if (section === 'outro') {\n p.beat1 = true;\n p.beat3 = true;\n return p;\n }\n\n switch (style) {\n case 'sparse':\n p.beat1 = true;\n if (section === 'chorus' && bar % 2 === 1) {\n p.beat3 = true;\n }\n break;\n\n case 'fourOnFloor':\n p.beat1 = p.beat2 = p.beat3 = p.beat4 = true;\n if (section === 'chorus' && rng.prob(0.2)) {\n p.beat2and = true;\n }\n break;\n\n case 'upbeat':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b' || section === 'chorus') {\n p.beat2and = rng.prob(0.7);\n }\n if (section === 'chorus') {\n p.beat4and = rng.prob(0.6);\n }\n break;\n\n case 'rock':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'chorus') {\n p.beat2and = rng.prob(0.65);\n p.beat4and = rng.prob(0.4);\n } else if (section === 'b') {\n p.beat2and = rng.prob(0.3);\n }\n break;\n\n case 'synth':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b' || section === 'chorus') {\n p.beat2and = rng.prob(0.75);\n }\n if (section === 'chorus') {\n p.beat4and = rng.prob(0.65);\n }\n break;\n\n case 'trap':\n p.beat1 = true;\n p.beat2and = rng.prob(0.8);\n p.beat3 = rng.prob(0.3);\n p.beat4and = rng.prob(0.7);\n break;\n\n case 'latin':\n p.beat1 = true;\n p.beat2and = true;\n p.beat3 = true;\n p.beat4and = rng.prob(0.5);\n break;\n\n default:\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b') {\n p.beat2and = rng.prob(0.5);\n } else if (section === 'chorus') {\n p.beat2and = rng.prob(0.55);\n p.beat4and = rng.prob(0.35);\n }\n break;\n }\n\n return p;\n}\n","import { HH_16TH_BPM_THRESHOLD } from './hihat.js';\nimport type { HitList } from './hit.js';\nimport type { DrumRole, SectionType } from './internal.js';\nimport { EIGHTH, GM, PercMoodCategory, SIXTEENTH, sectionIndex } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Enabled auxiliary percussion voices for a section. */\nexport type PercussionConfig = {\n tambourine: boolean;\n shaker: boolean;\n handclap: boolean;\n shaker16th: boolean;\n};\n\ntype PercActivation = [tambourine: boolean, shaker: boolean, handclap: boolean];\n\n// Percussion activation per [mood category][section index]. Columns:\n// intro, a, b, chorus, bridge, interlude, outro, chant, mixbreak.\nconst F: PercActivation = [false, false, false];\nconst PERC_TABLE: PercActivation[][] = [\n /* calm */ [F, F, F, F, F, F, F, F, F],\n /* std */ [F, F, [false, true, false], [true, false, true], F, F, F, F, [true, false, true]],\n /* ener */ [\n F,\n [false, true, false],\n [false, true, false],\n [true, true, true],\n F,\n F,\n F,\n F,\n [true, true, true],\n ],\n /* idol */ [\n F,\n [false, true, false],\n [false, true, false],\n [true, true, true],\n F,\n F,\n F,\n F,\n [true, true, true],\n ],\n /* rock */ [F, F, F, [false, false, true], F, F, F, F, [false, false, true]],\n];\n\n/** Resolve which auxiliary percussion voices play for a section. */\nexport function getPercussionConfig(\n mood: PercMoodCategory,\n section: SectionType,\n): PercussionConfig {\n const row = PERC_TABLE[mood] ?? PERC_TABLE[PercMoodCategory.Standard];\n const act = row?.[sectionIndex(section)] ?? F;\n return {\n tambourine: act[0],\n shaker: act[1],\n handclap: act[2],\n shaker16th: act[1],\n };\n}\n\n/** Emit one bar of auxiliary percussion (tambourine/shaker/handclap). */\nexport function generateAuxPercussionForBar(\n track: HitList,\n barStart: number,\n config: PercussionConfig,\n role: DrumRole,\n densityMult: number,\n rng: DrumRng,\n bpm: number,\n): void {\n if (role === 'minimal' || role === 'fxOnly') {\n return;\n }\n\n if (config.tambourine) {\n for (let beat = 1; beat <= 3; beat += 2) {\n const raw = 70 * densityMult * rng.float(0.9, 1.1);\n track.add(GM.TAMBOURINE, barStart + beat, EIGHTH, Math.max(40, Math.min(90, raw)));\n }\n }\n\n if (config.shaker) {\n const use16th = config.shaker16th && bpm < HH_16TH_BPM_THRESHOLD;\n if (use16th) {\n const velCurve = [0.75, 0.45, 0.6, 0.45];\n for (let beat = 0; beat < 4; beat += 1) {\n for (let sub = 0; sub < 4; sub += 1) {\n const raw = 80 * (velCurve[sub] ?? 0.5) * densityMult * rng.float(0.9, 1.1);\n track.add(\n GM.SHAKER,\n barStart + beat + sub * SIXTEENTH,\n SIXTEENTH,\n Math.max(25, Math.min(85, raw)),\n );\n }\n }\n } else {\n const velCurve = [0.75, 0.55];\n for (let beat = 0; beat < 4; beat += 1) {\n for (let sub = 0; sub < 2; sub += 1) {\n const raw = 80 * (velCurve[sub] ?? 0.6) * densityMult * rng.float(0.9, 1.1);\n track.add(\n GM.SHAKER,\n barStart + beat + sub * EIGHTH,\n EIGHTH,\n Math.max(25, Math.min(85, raw)),\n );\n }\n }\n }\n }\n\n if (config.handclap) {\n for (let beat = 1; beat <= 3; beat += 2) {\n const raw = 85 * densityMult * rng.float(0.9, 1.1);\n track.add(GM.HANDCLAP, barStart + beat, EIGHTH, Math.max(50, Math.min(100, raw)));\n }\n }\n}\n","import {\n type BeatCtx,\n generateGhostNotesForBeat,\n generateHiHatForBeat,\n generateKickForBeat,\n generatePreChorusBuildup,\n generateSnareForBeat,\n type SectionCtx,\n} from './beat.js';\nimport { euclideanRhythm, patternToMask } from './euclid.js';\nimport { type FillType, generateFill, getFillStartBeat, selectFillType } from './fills.js';\nimport {\n footHiHatVelocity,\n getHiHatLevel,\n openHiHatBarInterval,\n openHiHatBeat,\n shouldPlayHiHat,\n shouldUseFootHiHat,\n shouldUseRideForSection,\n} from './hihat.js';\nimport { type DrumHit, HitList } from './hit.js';\nimport {\n calculateVelocity,\n type DrumRole,\n type Feel,\n feelSwingAmount,\n GM,\n type GrooveStyle,\n ghostMoodCategory,\n mapDensity,\n mapSection,\n mapStyle,\n type PublicSection,\n percMoodCategory,\n sectionDensityMultiplier,\n sectionEnergy,\n} from './internal.js';\nimport {\n euclideanToKickPattern,\n getKickPattern,\n isInPreChorusLift,\n type KickPattern,\n} from './kick.js';\nimport { generateAuxPercussionForBar, getPercussionConfig } from './percussion.js';\nimport { createRng } from './rng.js';\n\n/**\n * A single drum onset emitted by {@link generateDrums}.\n *\n * @category Composition\n */\nexport type { DrumHit } from './hit.js';\n\n/**\n * Groove feel (the swing/straight rhythmic character) for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type GrooveFeel = Feel;\n\n/**\n * Drum voicing role and groove style identifiers for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type { DrumRole, GrooveStyle } from './internal.js';\n\n/**\n * Public section identifiers for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type Section = PublicSection;\n\n/**\n * A Euclidean (Bjorklund) kick pattern for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type EuclideanKick = {\n /** Number of kick onsets, clamped to `[0, steps]`. */\n pulses: number;\n /**\n * Total steps in the bar (1..16).\n *\n * @defaultValue 16\n */\n steps?: number;\n /**\n * Steps to rotate the onsets toward later positions.\n *\n * @defaultValue 0\n */\n rotation?: number;\n};\n\n/**\n * Options controlling {@link generateDrums}.\n *\n * @category Composition\n */\nexport type DrumGenOptions = {\n bars: number;\n bpm: number;\n style: GrooveStyle;\n section: Section;\n density: number;\n /**\n * Replace the final bar with a fill.\n *\n * @defaultValue false\n */\n fills?: boolean;\n feel?: GrooveFeel;\n /**\n * Voicing role; `'fxOnly'` suppresses the main kick/snare/ghost/fill voices.\n *\n * @defaultValue `'full'`\n */\n role?: DrumRole;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n /**\n * Section the final-bar fill leads into. Shapes which fill archetype is\n * chosen (into-chorus and out-of-intro fills differ from generic ones).\n * Defaults to `section`, i.e. a within-section fill.\n */\n nextSection?: Section;\n /**\n * When set, the kick follows this Euclidean rhythm instead of the\n * style/section pattern, giving direct access to evenly spread onsets.\n */\n euclideanKick?: EuclideanKick;\n};\n\n/**\n * Generate a drum performance as a flat list of onsets.\n *\n * Every voice (kick, snare, ghost snares, closed/open/foot hi-hats, ride, toms,\n * crash, and auxiliary percussion) is emitted as a {@link DrumHit} distinguished\n * by its General MIDI pitch. Groove style selects an internal style and feel;\n * `density` sets the backing-density level; `section` shapes kick, hi-hat, ghost,\n * and percussion density. 16th-note hi-hats drop to 8ths at or above 150 BPM.\n * When `fills` is true the final bar is replaced with a fill whose archetype is\n * shaped by `nextSection`; a fill that would emit nothing on its beat falls back\n * to the normal groove so the phrase end is never silent. `euclideanKick`\n * overrides the kick with an evenly-spread Euclidean pattern. Output is fully\n * determined by the options plus `seed`.\n *\n * @param opts Generation options.\n * @returns Percussion onsets in bar order.\n *\n * @example\n * ```ts\n * import { generateDrums } from '@libraz/libcantus';\n * const hits = generateDrums({ bars: 4, bpm: 120, style: 'standard', section: 'chorus', density: 0.6, fills: true });\n * // Fully determined by the options plus seed (defaults to 0).\n * ```\n *\n * @category Composition\n */\nexport function generateDrums(opts: DrumGenOptions): DrumHit[] {\n const track = new HitList();\n const rng = createRng(opts.seed ?? 0);\n const mapping = mapStyle(opts.style);\n const style = mapping.style;\n const feel: Feel = opts.feel ?? mapping.feel;\n const role: DrumRole = opts.role ?? 'full';\n // fxOnly leaves only fx/aux voices: the main kick, snare, ghost, and fill\n // voices are suppressed just as timekeeping hi-hats already are.\n const playMainVoices = role !== 'fxOnly';\n const section = mapSection(opts.section);\n const backingDensity = mapDensity(opts.density);\n const swingAmount = feelSwingAmount(feel);\n\n let densityMult = sectionDensityMultiplier(section);\n if (backingDensity === 'thin') {\n densityMult *= 0.75;\n } else if (backingDensity === 'thick') {\n densityMult *= 1.15;\n }\n\n const sec: SectionCtx = {\n style,\n feel,\n densityMult,\n backingDensity,\n hhLevel: getHiHatLevel(section, style, backingDensity, opts.bpm, rng),\n useGhostNotes:\n (section === 'b' || section === 'chorus' || section === 'bridge') && style !== 'sparse',\n ghostBoost: mapping.ghostBoost,\n useRide: shouldUseRideForSection(section, style),\n useFootHh: shouldUseFootHiHat(section, role),\n role,\n ghostMood: ghostMoodCategory(style),\n snareBeat3: mapping.snareBeat3,\n };\n\n const ohhBarInterval = openHiHatBarInterval(section, style);\n const energy = sectionEnergy(section);\n const fillStartBeat = getFillStartBeat(energy);\n const percMood = percMoodCategory(style);\n\n // The final-bar fill is shaped by the section it leads into. When no next\n // section is given the fill is treated as within-section (from === to).\n const nextSection = opts.nextSection ? mapSection(opts.nextSection) : section;\n const nextEnergy = sectionEnergy(nextSection);\n\n const euclidKick: KickPattern | undefined = opts.euclideanKick\n ? euclideanToKickPattern(\n patternToMask(\n euclideanRhythm(\n opts.euclideanKick.pulses,\n opts.euclideanKick.steps ?? 16,\n opts.euclideanKick.rotation ?? 0,\n ),\n ),\n )\n : undefined;\n\n const reuseSectionKick = (section === 'b' || section === 'chorus') && style !== 'sparse';\n let sectionKick: KickPattern | undefined;\n\n for (let bar = 0; bar < opts.bars; bar += 1) {\n const barStart = bar * 4;\n const isLastBar = bar === opts.bars - 1;\n\n if (bar === 0 && section === 'chorus') {\n track.add(GM.CRASH, barStart, 0.5, 100 * densityMult);\n }\n\n let barHasOpenHh = false;\n let openHhBeatIndex = 3;\n if (ohhBarInterval > 0 && bar % ohhBarInterval === ohhBarInterval - 1) {\n openHhBeatIndex = openHiHatBeat(section, rng);\n barHasOpenHh = !track.hasCrashNear(barStart + openHhBeatIndex);\n }\n\n let kick: KickPattern;\n if (euclidKick) {\n kick = euclidKick;\n } else if (reuseSectionKick) {\n sectionKick ??= getKickPattern(section, style, 0, rng);\n kick = sectionKick;\n } else {\n kick = getKickPattern(section, style, bar, rng);\n }\n\n const inLift = isInPreChorusLift(section, bar, opts.bars, section === 'b');\n let currentFill: FillType = 'snareRoll';\n\n for (let beat = 0; beat < 4; beat += 1) {\n const beatTick = barStart + beat;\n const velocity = calculateVelocity(section, beat);\n\n if (opts.fills && isLastBar && !inLift && beat >= fillStartBeat) {\n if (beat === fillStartBeat) {\n currentFill = selectFillType(section, nextSection, style, nextEnergy, rng);\n }\n if (playMainVoices) {\n const before = track.hits.length;\n generateFill(track, beatTick, beat, currentFill, velocity);\n if (track.hits.length > before) {\n continue;\n }\n // Safety net: an archetype that contributes nothing on this beat would\n // leave a silent phrase end, so fall through to the normal groove.\n } else {\n // fxOnly deliberately emits no main voices on the fill beats.\n continue;\n }\n }\n\n const ctx: BeatCtx = {\n track,\n beatTick,\n beat,\n velocity,\n section,\n bpm: opts.bpm,\n bar,\n sectionBars: opts.bars,\n inPrechorusLift: inLift,\n swingAmount,\n barHasOpenHh,\n openHhBeat: openHhBeatIndex,\n rng,\n };\n\n if (playMainVoices) {\n if (inLift) {\n generatePreChorusBuildup(ctx, sec, isLastBar);\n }\n generateKickForBeat(ctx, sec, kick);\n generateSnareForBeat(ctx, sec, section === 'intro' && bar === 0);\n if (sec.useGhostNotes && !inLift) {\n generateGhostNotesForBeat(ctx, sec);\n }\n }\n generateHiHatForBeat(ctx, sec);\n }\n\n if (sec.useFootHh && shouldPlayHiHat(role)) {\n for (let fhhBeat = 0; fhhBeat < 4; fhhBeat += 2) {\n const fhhTick = barStart + fhhBeat;\n const occupied = track.hits.some((h) => h.pitch === GM.FHH && h.startBeat === fhhTick);\n if (!occupied) {\n track.add(GM.FHH, fhhTick, 0.5, footHiHatVelocity(rng));\n }\n }\n }\n\n generateAuxPercussionForBar(\n track,\n barStart,\n getPercussionConfig(percMood, section),\n role,\n densityMult,\n rng,\n opts.bpm,\n );\n }\n\n return track.hits;\n}\n","/**\n * Groove and humanization: nudging quantized note events toward a more human\n * feel, and capturing/replaying the timing-and-velocity \"feel\" of a\n * performance as a reusable groove template.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention. Randomness, where used, always goes through the\n * seeded PRNG from the `random` module so results are fully reproducible.\n */\n\nimport {\n beatsPerBar,\n formatTimeSignature,\n metricWeight,\n type TimeSignature,\n} from '../meter/index.js';\nimport { createRng } from '../random/index.js';\nimport type { NoteEvent } from '../types.js';\n\n/**\n * Options controlling {@link humanize}.\n *\n * @category Rhythm & Meter\n */\nexport type HumanizeOptions = {\n /**\n * Time signature used to derive metric accents.\n *\n * @defaultValue 4/4\n */\n ts?: TimeSignature;\n /**\n * Maximum timing jitter in quarter-note beats, applied as ±this value.\n *\n * @defaultValue 0.02\n */\n timing?: number;\n /**\n * Maximum velocity jitter (MIDI units), applied as ±this value.\n *\n * @defaultValue 8\n */\n velocity?: number;\n /**\n * How much louder strong beats get relative to weak ones, in MIDI velocity units.\n *\n * @defaultValue 12\n */\n accent?: number;\n /**\n * Velocity assumed for events with no `velocity` of their own.\n *\n * @defaultValue 80\n */\n baseVelocity?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/** Default time signature for {@link humanize} when none is given. */\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\nconst DEFAULT_TIMING = 0.02;\nconst DEFAULT_VELOCITY_JITTER = 8;\nconst DEFAULT_ACCENT = 12;\nconst DEFAULT_BASE_VELOCITY = 80;\nconst MAX_METRIC_WEIGHT = 3;\nconst MIN_VELOCITY = 1;\nconst MAX_VELOCITY = 127;\n\n/**\n * Humanize a sequence of note events by nudging their timing and velocity\n * with small, deterministic (seeded) randomness plus a metric-accent shape:\n * events on strong beats (see {@link metricWeight}) come out louder on\n * average than events on weak ones.\n *\n * Each returned event is a copy; `startBeat` is jittered within\n * `[-timing, +timing]` beats and clamped to be non-negative, and `velocity`\n * is the event's own velocity (or `baseVelocity` if it has none) plus an\n * accent term scaled by the event's metric weight plus a jitter within\n * `[-velocity, +velocity]`, clamped to `[1, 127]` and rounded. The metric\n * weight is computed from each event's original (pre-jitter) `startBeat`.\n * `pitch` and `durationBeat` pass through unchanged, and the output keeps the\n * input order.\n *\n * @param events The events to humanize.\n * @param opts Humanization options.\n * @returns Humanized copies of `events`, in input order.\n * @example\n * ```ts\n * import { humanize } from '@libraz/libcantus';\n * const events = [{ pitch: 60, startBeat: 0, durationBeat: 1, velocity: 80 }];\n * humanize(events, { seed: 1, timing: 0.03 }); // copies with jittered timing and accented velocity\n * ```\n * @category Rhythm & Meter\n */\nexport function humanize(events: NoteEvent[], opts: HumanizeOptions = {}): NoteEvent[] {\n const ts = opts.ts ?? DEFAULT_TS;\n const timing = opts.timing ?? DEFAULT_TIMING;\n const velocityJitter = opts.velocity ?? DEFAULT_VELOCITY_JITTER;\n const accent = opts.accent ?? DEFAULT_ACCENT;\n const baseVelocity = opts.baseVelocity ?? DEFAULT_BASE_VELOCITY;\n const rng = createRng(opts.seed ?? 0);\n\n return events.map((event) => {\n const timingOffset = rng.float(-timing, timing);\n const startBeat = Math.max(0, event.startBeat + timingOffset);\n\n const weight = metricWeight(event.startBeat, ts);\n const accentBoost = (weight / MAX_METRIC_WEIGHT) * accent;\n const velocityOffset = rng.float(-velocityJitter, velocityJitter);\n const rawVelocity = (event.velocity ?? baseVelocity) + accentBoost + velocityOffset;\n const velocity = Math.min(MAX_VELOCITY, Math.max(MIN_VELOCITY, Math.round(rawVelocity)));\n\n return {\n pitch: event.pitch,\n startBeat,\n durationBeat: event.durationBeat,\n velocity,\n };\n });\n}\n\n/**\n * The recorded feel at a single grid slot: an average timing deviation and velocity.\n *\n * @category Rhythm & Meter\n */\nexport type GrooveSlot = {\n /** Average `actualStartBeat - quantizedBeat` (in quarter-note beats) for events landing on this slot. */\n timingOffset: number;\n /**\n * Average velocity of events landing on this slot, or `null` if no event\n * with a velocity did. `null` (not 0) is the \"unrecorded\" sentinel so that a\n * genuine velocity of 0 is preserved and applied like any other value.\n */\n velocity: number | null;\n};\n\n/**\n * A per-bar grid of timing and velocity deviations captured from a performance.\n *\n * @category Rhythm & Meter\n */\nexport type GrooveTemplate = {\n /** Grid resolution: equal grid steps per quarter-note beat. */\n subdivision: number;\n /** Number of grid slots per bar (`beatsPerBar(ts) * subdivision`). */\n slotsPerBar: number;\n /** One entry per grid slot, in slot-index order (slot 0 is the downbeat). */\n slots: GrooveSlot[];\n /**\n * The time signature the template was extracted under. {@link applyGrooveTemplate}\n * requires the apply-time meter to match this so the per-bar grid lines up\n * instead of silently drifting. Optional for backward compatibility with\n * templates constructed without it (in which case no check is performed).\n */\n ts?: TimeSignature;\n};\n\n/**\n * Quantize a beat position to the nearest grid slot at the given subdivision,\n * within the bar that contains it.\n *\n * @param beat Absolute position in quarter-note beats.\n * @param barBeats Bar length in quarter-note beats.\n * @param subdivision Grid steps per quarter-note beat.\n * @param slotsPerBar Number of grid slots per bar.\n * @returns The quantized absolute beat and its 0-based slot index within the bar.\n */\nfunction quantizeToGrid(\n beat: number,\n barBeats: number,\n subdivision: number,\n slotsPerBar: number,\n): { quantizedBeat: number; slotIndex: number } {\n const barIndex = Math.floor(beat / barBeats);\n const modBeat = beat - barIndex * barBeats;\n let slotIndex = Math.round(modBeat * subdivision);\n let effectiveBarIndex = barIndex;\n // Rounding the last slot in a bar up to the grid step count means it\n // actually lands on the next bar's downbeat.\n if (slotIndex >= slotsPerBar) {\n slotIndex = 0;\n effectiveBarIndex += 1;\n }\n return {\n quantizedBeat: effectiveBarIndex * barBeats + slotIndex / subdivision,\n slotIndex,\n };\n}\n\n/**\n * Extract a groove template from a set of note events: for each grid slot,\n * the average timing deviation from the quantized grid and the average\n * velocity of events landing on it. Slots with no velocity-carrying event\n * record `velocity: null` (the \"unrecorded\" sentinel); empty slots default to\n * `{ timingOffset: 0, velocity: null }`. The time signature is stored on the\n * template so {@link applyGrooveTemplate} can verify the meter matches.\n *\n * @param events The (typically \"groovy\", human-played) events to analyze.\n * @param ts The time signature, used to compute the bar length.\n * @param subdivision Grid resolution: equal grid steps per quarter-note beat.\n * @returns The extracted groove template.\n * @category Rhythm & Meter\n */\nexport function extractGrooveTemplate(\n events: NoteEvent[],\n ts: TimeSignature,\n subdivision: number,\n): GrooveTemplate {\n const barBeats = beatsPerBar(ts);\n const slotsPerBar = Math.round(barBeats * subdivision);\n const offsetSums = new Array<number>(slotsPerBar).fill(0);\n const velocitySums = new Array<number>(slotsPerBar).fill(0);\n const counts = new Array<number>(slotsPerBar).fill(0);\n const velocityCounts = new Array<number>(slotsPerBar).fill(0);\n\n for (const event of events) {\n const { quantizedBeat, slotIndex } = quantizeToGrid(\n event.startBeat,\n barBeats,\n subdivision,\n slotsPerBar,\n );\n offsetSums[slotIndex] = (offsetSums[slotIndex] ?? 0) + (event.startBeat - quantizedBeat);\n counts[slotIndex] = (counts[slotIndex] ?? 0) + 1;\n // Only events that carry a velocity contribute to the velocity average, so a\n // velocity-less event does not pull the slot's recorded velocity toward zero.\n if (event.velocity !== undefined) {\n velocitySums[slotIndex] = (velocitySums[slotIndex] ?? 0) + event.velocity;\n velocityCounts[slotIndex] = (velocityCounts[slotIndex] ?? 0) + 1;\n }\n }\n\n const slots: GrooveSlot[] = [];\n for (let i = 0; i < slotsPerBar; i += 1) {\n const count = counts[i] ?? 0;\n if (count === 0) {\n slots.push({ timingOffset: 0, velocity: null });\n continue;\n }\n const velocityCount = velocityCounts[i] ?? 0;\n slots.push({\n timingOffset: (offsetSums[i] ?? 0) / count,\n velocity: velocityCount > 0 ? (velocitySums[i] ?? 0) / velocityCount : null,\n });\n }\n\n return { subdivision, slotsPerBar, slots, ts };\n}\n\n/**\n * Apply a groove template to a set of (typically quantized) note events: each\n * event is snapped to its grid slot and then offset by that slot's recorded\n * timing deviation, pushing stiff timing toward the template's feel.\n * Velocity is set to the slot's recorded average when it recorded one (a\n * non-`null` velocity, including a genuine 0); otherwise the event's own\n * velocity is left untouched.\n *\n * If the template carries a time signature (see {@link GrooveTemplate.ts}) it\n * must match `ts`, since a differing bar length would misalign the per-bar\n * grid and drift the feel; a mismatch throws rather than corrupting timing\n * silently.\n *\n * @param events The events to reshape.\n * @param template The groove template, from {@link extractGrooveTemplate}.\n * @param ts The time signature, used to compute the bar length.\n * @returns Reshaped copies of `events`, in input order.\n * @throws If `template.ts` is set and does not match `ts`.\n * @example\n * ```ts\n * import { extractGrooveTemplate, applyGrooveTemplate, parseTimeSignature } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * // Learn the feel from a loosely played performance...\n * const groovy = [\n * { pitch: 36, startBeat: 0.02, durationBeat: 1, velocity: 100 },\n * { pitch: 38, startBeat: 1.06, durationBeat: 1, velocity: 70 },\n * ];\n * const template = extractGrooveTemplate(groovy, ts, 4);\n * // ...then impose it on stiff, quantized events.\n * const quantized = [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 80 }];\n * applyGrooveTemplate(quantized, template, ts); // events nudged toward the captured feel\n * ```\n * @category Rhythm & Meter\n */\nexport function applyGrooveTemplate(\n events: NoteEvent[],\n template: GrooveTemplate,\n ts: TimeSignature,\n): NoteEvent[] {\n if (\n template.ts &&\n (template.ts.numerator !== ts.numerator || template.ts.denominator !== ts.denominator)\n ) {\n throw new Error(\n `Groove template meter ${formatTimeSignature(template.ts)} does not match ` +\n `apply-time meter ${formatTimeSignature(ts)}`,\n );\n }\n const barBeats = beatsPerBar(ts);\n return events.map((event) => {\n const { quantizedBeat, slotIndex } = quantizeToGrid(\n event.startBeat,\n barBeats,\n template.subdivision,\n template.slotsPerBar,\n );\n const slot = template.slots[slotIndex];\n const startBeat = quantizedBeat + (slot?.timingOffset ?? 0);\n const velocity =\n slot && slot.velocity !== null && slot.velocity !== undefined\n ? Math.round(slot.velocity)\n : event.velocity;\n\n return {\n pitch: event.pitch,\n startBeat,\n durationBeat: event.durationBeat,\n velocity,\n };\n });\n}\n","import type { Chord } from '../chord/index.js';\n\n/**\n * Harmonic role a pitch plays within a chord.\n *\n * @category Functional Harmony\n */\nexport type HarmonyRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | 'tension' | 'doubling';\n\n/**\n * How firmly a pitch is locked to the chord's identity.\n *\n * - `identity`: moving it produces a different chord (the root).\n * - `quality`: moving it flips the chord quality (the third).\n * - `voicing`: it can move freely without changing chord identity or quality.\n *\n * @category Functional Harmony\n */\nexport type LockLevel = 'identity' | 'quality' | 'voicing';\n\n/**\n * A pitch's role, lock level, and owning chord.\n *\n * @category Functional Harmony\n */\nexport type VoicedRole = {\n role: HarmonyRole;\n lock: LockLevel;\n belongsToChordId: number;\n};\n\n/**\n * Classify a pitch's harmonic role and lock level within a chord.\n *\n * The role comes from the pitch's interval class above the chord root: root (0),\n * third (3/4), fifth (6/7/8), seventh (10/11), and 9/11/13 tensions (2/5/9, and\n * the flat ninth 1). The root locks the chord identity, the third locks its\n * quality, and everything else is free voicing. In a suspended chord (a chord\n * whose intervals include a 4th (5) or 2nd (2) but no third), the suspended tone\n * takes the third's place as the quality-defining tone and is locked to\n * `quality`, since moving it changes the chord. Detecting an octave doubling\n * requires the surrounding voicing, which this single-pitch query does not carry,\n * so `doubling` is part of the type but not returned here.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param chord The chord providing the root reference.\n * @param chordId Identifier stored on the result (defaults to 0).\n * @returns The pitch's role, lock level, and owning chord id.\n * @example\n * ```ts\n * import { roleOf, makeChord } from '@libraz/libcantus';\n * roleOf(64, makeChord(0, 'maj')); // E over C major\n * // { role: 'third', lock: 'quality', belongsToChordId: 0 }\n * ```\n * @category Functional Harmony\n */\nexport function roleOf(pitch: number, chord: Chord, chordId = 0): VoicedRole {\n const interval = (((Math.trunc(pitch) - chord.rootPc) % 12) + 12) % 12;\n const tones = new Set(chord.intervals.map((i) => ((i % 12) + 12) % 12));\n const hasHigherSeventh = tones.has(10) || tones.has(11);\n const hasThird = tones.has(3) || tones.has(4);\n const isSuspendedTone =\n !hasThird && ((interval === 5 && tones.has(5)) || (interval === 2 && tones.has(2)));\n let role: HarmonyRole;\n let lock: LockLevel;\n if (interval === 0) {\n role = 'root';\n lock = 'identity';\n } else if (isSuspendedTone) {\n role = 'third'; // suspended tone occupies the third's quality-defining slot\n lock = 'quality';\n } else if (interval === 3 || interval === 4) {\n role = 'third';\n lock = 'quality';\n } else if (interval === 6 || interval === 7 || interval === 8) {\n role = 'fifth';\n lock = 'voicing';\n } else if (interval === 9 && tones.has(3) && tones.has(6) && !hasHigherSeventh) {\n role = 'seventh'; // diminished seventh\n lock = 'voicing';\n } else if (interval === 9 && tones.has(9) && !hasHigherSeventh) {\n role = 'sixth';\n lock = 'voicing';\n } else if (interval === 10 || interval === 11) {\n role = 'seventh';\n lock = 'voicing';\n } else {\n role = 'tension';\n lock = 'voicing';\n }\n return { role, lock, belongsToChordId: chordId };\n}\n","import type { Chord, ChordQuality } from '../chord/index.js';\nimport { chordPitchClasses, diatonicTriad, makeChord } from '../chord/index.js';\nimport type { HarmonyRole } from '../harmony/index.js';\nimport { roleOf } from '../harmony/index.js';\nimport type { TimeSignature } from '../meter/index.js';\nimport { isStrongBeat } from '../meter/index.js';\nimport type { GeneratedChord } from '../progression/index.js';\nimport {\n isScaleTone,\n majorKey,\n minorKey,\n NATURAL_MINOR_MASK,\n scaleTonesInDegreeOrder,\n} from '../scale/index.js';\nimport type { KeyScale, NoteEvent } from '../types.js';\n\n/**\n * A melody note supplied to the harmonizer: a {@link NoteEvent}.\n *\n * @category Reharmonization\n */\nexport type MelodyNote = NoteEvent;\n\n/**\n * Options controlling {@link harmonizeMelody}.\n *\n * @category Reharmonization\n */\nexport type HarmonizeOptions = {\n melody: MelodyNote[];\n key: KeyScale | 'infer';\n harmonicRhythm: number;\n reharmonize: 'diatonic' | 'secondaryDominant' | 'borrowed';\n placement: { transposeSearch: boolean; octaveSearch: boolean };\n /**\n * Seed for the deterministic tie-break perturbation.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/**\n * The chosen transpose, key, chord path, and per-note roles.\n *\n * @category Reharmonization\n */\nexport type HarmonizeResult = {\n transposeSemitones: number;\n key: KeyScale;\n chords: GeneratedChord[];\n melodyRoles: { noteIndex: number; role: HarmonyRole }[];\n};\n\ntype Candidate = {\n rootPc: number;\n quality: ChordQuality;\n degree?: number;\n secondaryDominant: boolean;\n targetDegree?: number;\n base: number;\n};\n\ntype Segment = { startBeat: number; endBeat: number; noteIndices: number[] };\n\nconst FALLBACK: Candidate = { rootPc: 0, quality: 'maj', secondaryDominant: false, base: 0 };\n\n/** Default meter used to weight metric accents when none is supplied. */\nconst DEFAULT_METER: TimeSignature = { numerator: 4, denominator: 4 };\n\n/** Comfortable melodic range (MIDI) and the per-semitone cost of leaving it. */\nconst COMFORT_LOW = 55;\nconst COMFORT_HIGH = 79;\nconst TESSITURA_WEIGHT = 0.001;\n\n/**\n * Magnitude of the seed-driven per-candidate perturbation. Kept far below the\n * smallest real cost difference (transition/emission terms are on the order of\n * 0.3 and up), so it can only decide between candidates or paths whose costs are\n * otherwise exactly equal. The seed therefore breaks ties deterministically and\n * never overrides melody fit or functional flow.\n */\nconst TIE_BREAK_JITTER = 1e-6;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * Estimate the best-fit key from a melody's pitch-class weighting.\n *\n * Both major and natural-minor tonics are scored, so a minor melody is\n * recognized as its own minor key rather than being folded into the relative\n * major (which shares identical pitch-class content). Each in-scale note adds\n * its duration weight; notes matching the candidate tonic add a further\n * half-weight, and that tonic emphasis is what separates a minor key from its\n * relative major. For minor candidates the raised leading tone (the\n * harmonic-minor seventh) also counts as in-scale, so cadential leading tones do\n * not penalize the true minor key. Ties are broken toward the earlier candidate,\n * and major is scored before minor at each tonic.\n */\nfunction inferKey(melody: MelodyNote[]): KeyScale {\n let best: KeyScale = majorKey(0);\n let bestScore = Number.NEGATIVE_INFINITY;\n const candidates: KeyScale[] = [];\n for (let tonic = 0; tonic < 12; tonic += 1) {\n candidates.push(majorKey(tonic), minorKey(tonic));\n }\n for (const key of candidates) {\n const tonic = pitchClass(key.rootPc);\n const isMinor = key.modeMask12 === NATURAL_MINOR_MASK;\n const leadingTone = (tonic + 11) % 12;\n let score = 0;\n for (const n of melody) {\n const w = Math.max(0.25, n.durationBeat);\n const pc = pitchClass(n.pitch);\n if (isScaleTone(n.pitch, key) || (isMinor && pc === leadingTone)) {\n score += w;\n }\n if (pc === tonic) {\n score += 0.5 * w;\n }\n }\n if (score > bestScore) {\n bestScore = score;\n best = key;\n }\n }\n return best;\n}\n\n/** Enumerate candidate chords for the key, gated by reharmonization strength. */\nfunction buildCandidates(key: KeyScale, reharmonize: HarmonizeOptions['reharmonize']): Candidate[] {\n const tones = scaleTonesInDegreeOrder(key);\n const candidates: Candidate[] = tones.map((rootPc, degree) => ({\n rootPc,\n quality: diatonicTriad(degree, key).quality,\n degree,\n secondaryDominant: false,\n base: 0,\n }));\n\n const tonic = tones[0] ?? 0;\n if (reharmonize !== 'diatonic') {\n for (const target of [1, 3, 4, 5]) {\n const targetRoot = tones[target] ?? 0;\n candidates.push({\n rootPc: (targetRoot + 7) % 12,\n quality: 'dom7',\n secondaryDominant: true,\n targetDegree: target,\n base: 1.5,\n });\n }\n }\n\n if (reharmonize === 'borrowed') {\n candidates.push({\n rootPc: (tonic + 10) % 12,\n quality: 'maj',\n secondaryDominant: false,\n base: 2,\n }); // bVII\n candidates.push({\n rootPc: (tonic + 8) % 12,\n quality: 'maj',\n secondaryDominant: false,\n base: 2,\n }); // bVI\n candidates.push({\n rootPc: (tonic + 5) % 12,\n quality: 'min',\n secondaryDominant: false,\n base: 2,\n }); // iv\n }\n\n return candidates;\n}\n\n/**\n * Melody-fit cost of a candidate over a segment's notes.\n *\n * Each note is weighted by the portion of its duration that overlaps the\n * segment, so a note sustained across a boundary contributes to every segment\n * it sounds in rather than only the one it starts in.\n */\nfunction emissionCost(seg: Segment, cand: Candidate, melody: MelodyNote[], key: KeyScale): number {\n const pcs = chordPitchClasses(makeChord(cand.rootPc, cand.quality));\n let cost = cand.base;\n for (const idx of seg.noteIndices) {\n const note = melody[idx];\n if (!note) {\n continue;\n }\n const overlapStart = Math.max(note.startBeat, seg.startBeat);\n const overlap = Math.min(note.startBeat + note.durationBeat, seg.endBeat) - overlapStart;\n if (overlap <= 0) {\n continue;\n }\n const w = Math.max(0.25, overlap);\n if (pcs.includes(pitchClass(note.pitch))) {\n continue;\n }\n const strong = isStrongBeat(overlapStart, DEFAULT_METER);\n cost += (strong ? 10 : 2) * w;\n if (!isScaleTone(note.pitch, key)) {\n cost += w;\n }\n }\n return cost;\n}\n\n/**\n * Register cost of a placed melody: a small penalty for notes pushed outside a\n * comfortable range. Kept far below emission/transition costs so it only breaks\n * ties between otherwise-equal octave placements.\n */\nfunction tessituraCost(melody: MelodyNote[]): number {\n let cost = 0;\n for (const n of melody) {\n if (n.pitch < COMFORT_LOW) {\n cost += (COMFORT_LOW - n.pitch) * TESSITURA_WEIGHT;\n } else if (n.pitch > COMFORT_HIGH) {\n cost += (n.pitch - COMFORT_HIGH) * TESSITURA_WEIGHT;\n }\n }\n return cost;\n}\n\n/** Functional-flow cost of moving from one candidate chord to the next. */\nfunction transitionCost(prev: Candidate, cur: Candidate, tonicPc: number): number {\n let cost = 0;\n if ((prev.rootPc - cur.rootPc + 12) % 12 === 7) {\n cost -= 2; // descending-fifth root motion\n }\n if (\n prev.rootPc === (tonicPc + 7) % 12 &&\n (prev.quality === 'maj' || prev.quality === 'dom7') &&\n cur.rootPc === tonicPc\n ) {\n cost -= 3; // V -> I\n }\n if (prev.secondaryDominant) {\n cost += cur.degree === prev.targetDegree ? -3 : 2;\n }\n const dist = Math.min((prev.rootPc - cur.rootPc + 12) % 12, (cur.rootPc - prev.rootPc + 12) % 12);\n cost += dist * 0.3;\n return cost;\n}\n\n/** Run one Viterbi harmonization pass over a fixed melody and key. */\nfunction harmonizeOnce(\n melody: MelodyNote[],\n key: KeyScale,\n candidates: Candidate[],\n segments: Segment[],\n jitter: number[],\n): { cost: number; path: number[] } {\n const tonicPc = pitchClass(key.rootPc);\n const n = candidates.length;\n const candAt = (i: number): Candidate => candidates[i] ?? FALLBACK;\n const seg0 = segments[0];\n\n let dp = candidates.map(\n (c, ci) => (seg0 ? emissionCost(seg0, c, melody, key) : 0) + (jitter[ci] ?? 0),\n );\n const back: number[][] = [];\n\n for (let s = 1; s < segments.length; s += 1) {\n const seg = segments[s];\n if (!seg) {\n continue;\n }\n const next: number[] = [];\n const ptr: number[] = [];\n for (let c = 0; c < n; c += 1) {\n let best = Number.POSITIVE_INFINITY;\n let bestPrev = 0;\n for (let p = 0; p < n; p += 1) {\n const cost =\n (dp[p] ?? Number.POSITIVE_INFINITY) + transitionCost(candAt(p), candAt(c), tonicPc);\n if (cost < best) {\n best = cost;\n bestPrev = p;\n }\n }\n next[c] = best + emissionCost(seg, candAt(c), melody, key) + (jitter[c] ?? 0);\n ptr[c] = bestPrev;\n }\n dp = next;\n back.push(ptr);\n }\n\n let bestCost = Number.POSITIVE_INFINITY;\n let bestEnd = 0;\n for (let c = 0; c < n; c += 1) {\n const cadence = candAt(c).rootPc === tonicPc ? -2 : 0;\n const total = (dp[c] ?? Number.POSITIVE_INFINITY) + cadence;\n if (total < bestCost) {\n bestCost = total;\n bestEnd = c;\n }\n }\n\n const path: number[] = new Array<number>(segments.length).fill(bestEnd);\n for (let s = segments.length - 2; s >= 0; s -= 1) {\n const ptr = back[s];\n const nextIdx = path[s + 1] ?? bestEnd;\n path[s] = ptr ? (ptr[nextIdx] ?? bestEnd) : bestEnd;\n }\n return { cost: bestCost, path };\n}\n\n/**\n * Harmonize a melody with a min-cost chord progression.\n *\n * The melody is segmented by `harmonicRhythm`; each segment is scored against\n * diatonic (and, per `reharmonize`, secondary-dominant and borrowed) candidate\n * chords by melody fit, and a Viterbi search picks the lowest-cost path using a\n * functional-flow transition cost. When `placement.transposeSearch`/`octaveSearch`\n * is set, the whole melody is transposed across a range and the best\n * `(transpose, progression)` pair is returned; a small tessitura cost breaks\n * ties toward placements that keep the melody in a comfortable register.\n *\n * The `seed` drives a deterministic tie-break only: it perturbs candidates by a\n * magnitude far below any real cost difference (see {@link TIE_BREAK_JITTER}),\n * so it can decide between chords or paths of otherwise-equal cost but never\n * overrides melody fit or functional flow. For a well-determined melody the\n * result is identical across seeds; the same seed always yields the same result.\n *\n * @param opts Melody, key (or `'infer'`), harmonic rhythm, reharmonization\n * strength, height-search flags, and seed.\n * @returns The chosen transpose, key, chord path, and per-note roles.\n * @example\n * ```ts\n * import { harmonizeMelody, majorKey } from '@libraz/libcantus';\n * const result = harmonizeMelody({\n * melody: [\n * { pitch: 60, startBeat: 0, durationBeat: 1 },\n * { pitch: 64, startBeat: 1, durationBeat: 1 },\n * ],\n * key: majorKey(0),\n * harmonicRhythm: 1,\n * reharmonize: 'diatonic',\n * placement: { transposeSearch: false, octaveSearch: false },\n * });\n * result.chords; // one GeneratedChord per harmonic-rhythm segment\n * ```\n * @category Reharmonization\n */\nexport function harmonizeMelody(opts: HarmonizeOptions): HarmonizeResult {\n const key = opts.key === 'infer' ? inferKey(opts.melody) : opts.key;\n const candidates = buildCandidates(key, opts.reharmonize);\n const candAt = (i: number): Candidate => candidates[i] ?? FALLBACK;\n const rng = mulberry32(opts.seed ?? 0);\n const jitter = candidates.map(() => rng() * TIE_BREAK_JITTER);\n\n const melodyEnd = opts.melody.reduce((m, n) => Math.max(m, n.startBeat + n.durationBeat), 0);\n const hr = Math.max(0.25, opts.harmonicRhythm);\n const segCount = Math.max(1, Math.ceil(melodyEnd / hr));\n const segments: Segment[] = [];\n for (let s = 0; s < segCount; s += 1) {\n const startBeat = s * hr;\n const endBeat = startBeat + hr;\n const noteIndices = opts.melody\n .map((n, i) => ({ n, i }))\n .filter(({ n }) => n.startBeat < endBeat && n.startBeat + n.durationBeat > startBeat)\n .map(({ i }) => i);\n segments.push({ startBeat, endBeat, noteIndices });\n }\n\n const transposes: number[] = [0];\n if (opts.placement.transposeSearch) {\n for (let s = -6; s <= 6; s += 1) {\n if (s !== 0) {\n transposes.push(s);\n }\n }\n }\n if (opts.placement.octaveSearch) {\n for (const o of [-12, 12]) {\n if (!transposes.includes(o)) {\n transposes.push(o);\n }\n }\n }\n\n let bestCost = Number.POSITIVE_INFINITY;\n let bestTs = 0;\n let bestPath: number[] = [];\n let bestMelody = opts.melody;\n for (const ts of transposes) {\n const shifted = opts.melody.map((n) => ({ ...n, pitch: n.pitch + ts }));\n const { cost, path } = harmonizeOnce(shifted, key, candidates, segments, jitter);\n const total = cost + tessituraCost(shifted);\n if (total < bestCost) {\n bestCost = total;\n bestTs = ts;\n bestPath = path;\n bestMelody = shifted;\n }\n }\n\n const chords: GeneratedChord[] = bestPath.map((ci, s) => {\n const cand = candAt(ci);\n const chord: GeneratedChord = {\n rootPc: cand.rootPc,\n quality: cand.quality,\n startBeat: segments[s]?.startBeat ?? s * hr,\n };\n if (cand.degree !== undefined) {\n chord.degree = cand.degree;\n }\n if (cand.secondaryDominant) {\n chord.secondaryDominant = true;\n }\n return chord;\n });\n\n const melodyRoles = bestMelody.map((note, noteIndex) => {\n const segIdx = Math.min(segments.length - 1, Math.max(0, Math.floor(note.startBeat / hr)));\n const cand = candAt(bestPath[segIdx] ?? 0);\n const chord: Chord = makeChord(cand.rootPc, cand.quality);\n return { noteIndex, role: roleOf(note.pitch, chord).role };\n });\n\n return { transposeSemitones: bestTs, key, chords, melodyRoles };\n}\n","/**\n * Pitch spelling: letter-name notes, enharmonic-aware conversion, and spelled\n * intervals.\n *\n * The rest of the library works in pitch classes (0..11), which cannot tell a\n * G# from an Ab or an augmented fourth from a diminished fifth. This module adds\n * an explicit spelling layer — a note is a diatonic letter plus a chromatic\n * alteration — so interval quality (P/M/m/A/d) and enharmonic identity are\n * preserved.\n */\n\n/** Semitone offset of each natural letter above C: C D E F G A B. */\nconst LETTER_SEMITONES = [0, 2, 4, 5, 7, 9, 11] as const;\n\n/** Letter glyphs indexed by letter number (0 = C .. 6 = B). */\nconst LETTER_NAMES = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] as const;\n\n/**\n * A spelled note: a diatonic letter, a chromatic alteration, and an optional\n * octave.\n *\n * - `letter` is 0..6 for C..B.\n * - `alter` is the number of semitones of alteration: -2 double-flat, -1 flat,\n * 0 natural, +1 sharp, +2 double-sharp.\n * - `octave` follows scientific pitch notation (middle C = C4 = MIDI 60). When\n * absent, the note denotes a bare pitch class.\n *\n * @category Pitch & Intervals\n */\nexport type Note = {\n letter: number;\n alter: number;\n octave?: number;\n};\n\n/**\n * A spelled interval: a diatonic number, a quality label, and its semitone span.\n *\n * @category Pitch & Intervals\n */\nexport type SpelledInterval = {\n /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */\n number: number;\n /** Quality label: 'P', 'M', 'm', or repeated 'A'/'d' for (multiply) aug/dim. */\n quality: string;\n /** Signed semitone distance from the first note to the second. */\n semitones: number;\n};\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/** Reduce any integer to [0, 7). */\nfunction mod7(n: number): number {\n return ((n % 7) + 7) % 7;\n}\n\n/**\n * Parse scientific pitch notation into a {@link Note}.\n *\n * Accepts a letter (case-insensitive) followed by any number of same-direction\n * accidentals and an optional octave, e.g. `\"C\"`, `\"C#4\"`, `\"Bb\"`, `\"F##3\"`,\n * `\"Ebb2\"`. Both `#` and `x` (double-sharp) are accepted for sharps; `b` for\n * flats. Mixing sharps and flats (e.g. `\"C#b\"`) is rejected.\n *\n * @param text The note text.\n * @returns The parsed note.\n * @throws If the text is not a valid note.\n * @example\n * ```ts\n * import { parseNote, noteToMidi } from '@libraz/libcantus';\n * const n = parseNote('C#4');\n * noteToMidi(n); // 61\n * ```\n * @category Pitch & Intervals\n */\nexport function parseNote(text: string): Note {\n const match = /^([A-Ga-g])([#x]*|b*)(-?\\d+)?$/.exec(text.trim());\n if (!match) {\n throw new Error(`Invalid note: ${text}`);\n }\n const letterGlyph = (match[1] ?? '').toUpperCase();\n const letter = LETTER_NAMES.indexOf(letterGlyph as (typeof LETTER_NAMES)[number]);\n let alter = 0;\n for (const ch of match[2] ?? '') {\n if (ch === '#') {\n alter += 1;\n } else if (ch === 'x') {\n alter += 2;\n } else if (ch === 'b') {\n alter -= 1;\n }\n }\n const note: Note = { letter, alter };\n if (match[3] !== undefined) {\n note.octave = Number.parseInt(match[3], 10);\n }\n return note;\n}\n\n/** Render an alteration as accidental glyphs (`##`, `b`, empty for natural). */\nfunction formatAlter(alter: number): string {\n if (alter > 0) {\n return '#'.repeat(alter);\n }\n if (alter < 0) {\n return 'b'.repeat(-alter);\n }\n return '';\n}\n\n/**\n * Render a {@link Note} as scientific pitch notation.\n *\n * @param note The note to format.\n * @returns The note text, including the octave when present.\n * @example\n * ```ts\n * import { formatNote, parseNote } from '@libraz/libcantus';\n * formatNote(parseNote('C#4')); // 'C#4'\n * ```\n * @category Pitch & Intervals\n */\nexport function formatNote(note: Note): string {\n const glyph = LETTER_NAMES[mod7(note.letter)] ?? 'C';\n const octave = note.octave === undefined ? '' : String(note.octave);\n return `${glyph}${formatAlter(note.alter)}${octave}`;\n}\n\n/**\n * Pitch class (0..11) of a note, ignoring octave.\n *\n * @param note The note.\n * @returns The pitch class.\n * @example\n * ```ts\n * import { noteToPitchClass, parseNote } from '@libraz/libcantus';\n * noteToPitchClass(parseNote('Db')); // 1\n * ```\n * @category Pitch & Intervals\n */\nexport function noteToPitchClass(note: Note): number {\n const natural = LETTER_SEMITONES[mod7(note.letter)] ?? 0;\n return mod12(natural + note.alter);\n}\n\n/**\n * MIDI number of a note (middle C = C4 = 60).\n *\n * @param note The note; must carry an octave.\n * @returns The MIDI number.\n * @throws If the note has no octave.\n * @example\n * ```ts\n * import { noteToMidi, parseNote } from '@libraz/libcantus';\n * noteToMidi(parseNote('A4')); // 69\n * ```\n * @category Pitch & Intervals\n */\nexport function noteToMidi(note: Note): number {\n if (note.octave === undefined) {\n throw new Error('noteToMidi requires an octave');\n }\n const natural = LETTER_SEMITONES[mod7(note.letter)] ?? 0;\n return (note.octave + 1) * 12 + natural + note.alter;\n}\n\n/** Preferred spelling when naming a black key from a bare MIDI number. */\nconst SHARP_SPELLING: readonly [number, number][] = [\n [0, 0],\n [0, 1],\n [1, 0],\n [1, 1],\n [2, 0],\n [3, 0],\n [3, 1],\n [4, 0],\n [4, 1],\n [5, 0],\n [5, 1],\n [6, 0],\n];\n\nconst FLAT_SPELLING: readonly [number, number][] = [\n [0, 0],\n [1, -1],\n [1, 0],\n [2, -1],\n [2, 0],\n [3, 0],\n [4, -1],\n [4, 0],\n [5, -1],\n [5, 0],\n [6, -1],\n [6, 0],\n];\n\n/**\n * Name a MIDI number as a {@link Note}, choosing sharp or flat spelling.\n *\n * The input is rounded to the nearest integer but is not clamped to the MIDI\n * range 0..127: out-of-range values extrapolate linearly (e.g. `-1` -> `B-2`,\n * `128` -> `G#9`) and remain an exact inverse of {@link noteToMidi}.\n *\n * @param midi The MIDI number.\n * @param spelling Whether to prefer sharps or flats for black keys.\n * @returns The spelled note, with octave.\n * @example\n * ```ts\n * import { midiToNote, formatNote } from '@libraz/libcantus';\n * formatNote(midiToNote(61)); // 'C#4'\n * formatNote(midiToNote(61, 'flat')); // 'Db4'\n * ```\n * @category Pitch & Intervals\n */\nexport function midiToNote(midi: number, spelling: 'sharp' | 'flat' = 'sharp'): Note {\n const rounded = Math.round(midi);\n const pc = mod12(rounded);\n const octave = Math.floor(rounded / 12) - 1;\n const table = spelling === 'sharp' ? SHARP_SPELLING : FLAT_SPELLING;\n const entry = table[pc] ?? [0, 0];\n return { letter: entry[0], alter: entry[1], octave };\n}\n\n/** Reference semitone span of a perfect/major simple interval by diatonic number. */\nconst SIMPLE_REFERENCE = [0, 0, 2, 4, 5, 7, 9, 11] as const;\n\n/** Whether a simple diatonic number (1..7 within an octave) is a perfect kind. */\nfunction isPerfectNumber(simpleNumber: number): boolean {\n return simpleNumber === 1 || simpleNumber === 4 || simpleNumber === 5;\n}\n\n/** Quality label from a diatonic number and its actual semitone span. */\nfunction qualityFromSpan(numberValue: number, semitones: number): string {\n const octaves = Math.floor((numberValue - 1) / 7);\n const simple = numberValue - 7 * octaves;\n const reference = (SIMPLE_REFERENCE[simple] ?? 0) + 12 * octaves;\n const delta = semitones - reference;\n if (isPerfectNumber(simple)) {\n if (delta === 0) {\n return 'P';\n }\n return delta > 0 ? 'A'.repeat(delta) : 'd'.repeat(-delta);\n }\n if (delta === 0) {\n return 'M';\n }\n if (delta === -1) {\n return 'm';\n }\n return delta > 0 ? 'A'.repeat(delta) : 'd'.repeat(-delta - 1);\n}\n\n/** Diatonic ladder index of a note (letter + 7 * octave when octave-bearing). */\nfunction diatonicIndex(note: Note): number {\n return mod7(note.letter) + 7 * (note.octave ?? 0);\n}\n\n/**\n * The spelled interval from one note to another.\n *\n * When both notes carry octaves, the interval reflects their full signed\n * distance (so `C4 -> C5` is a perfect octave). When either lacks an octave the\n * interval is measured within a single ascending octave from `a` to `b`.\n *\n * @param a The lower/first note.\n * @param b The upper/second note.\n * @returns The diatonic number, quality, and semitone span.\n * @example\n * ```ts\n * import { spelledInterval, parseNote } from '@libraz/libcantus';\n * spelledInterval(parseNote('C4'), parseNote('G4'));\n * // { number: 5, quality: 'P', semitones: 7 }\n * ```\n * @category Pitch & Intervals\n */\nexport function spelledInterval(a: Note, b: Note): SpelledInterval {\n const octaved = a.octave !== undefined && b.octave !== undefined;\n let letterSteps: number;\n let semitones: number;\n if (octaved) {\n letterSteps = diatonicIndex(b) - diatonicIndex(a);\n // Signed pitch distance from a to b, so a note below a yields a negative span.\n semitones = noteToMidi(b) - noteToMidi(a);\n } else {\n letterSteps = mod7(b.letter - a.letter);\n let rawSemis = mod12(noteToPitchClass(b) - noteToPitchClass(a));\n // Lift the chromatic span into the octave nearest the diatonic reference so\n // wraparound intervals stay consistent with the diatonic number instead of\n // collapsing modulo 12. The correction is bidirectional: an upward wrap\n // (e.g. Ab -> G# = augmented seventh) adds an octave, while a same-letter or\n // downward chromatic step (e.g. E -> Eb, F# -> F, C -> Cb = descending\n // diminished/augmented unison) subtracts one so the sign follows pitch\n // direction instead of returning a garbage stack of augmentations.\n const reference = SIMPLE_REFERENCE[letterSteps + 1] ?? 0;\n if (reference - rawSemis > 6) {\n rawSemis += 12;\n } else if (rawSemis - reference > 6) {\n rawSemis -= 12;\n }\n semitones = rawSemis;\n }\n const absSteps = Math.abs(letterSteps);\n const number = absSteps + 1;\n // Quality comes from the absolute chromatic span; semitones keeps its sign.\n const quality = qualityFromSpan(number, Math.abs(semitones));\n return { number, quality, semitones };\n}\n","/**\n * Reharmonization: chord substitution, modal-interchange palettes, and negative\n * harmony. These transforms take an existing chord (or a key) and propose\n * alternative harmonies that preserve a chosen relationship — a shared function,\n * a common tone, a tonicizing dominant, or a reflection across the key axis.\n *\n * Roots are pitch classes (0..11); no spelled key signature is required.\n */\n\nimport {\n type Chord,\n type ChordQuality,\n chordPitchClasses,\n diatonicTriad,\n makeChord,\n} from '../chord/index.js';\nimport { detectChordBest } from '../detect/index.js';\nimport {\n type BorrowedSource,\n borrowedSource,\n chordToRoman,\n functionOf,\n type HarmonicFunction,\n isDiatonic,\n parallelKey,\n} from '../functional/index.js';\nimport { scaleTonesInDegreeOrder } from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/**\n * The kind of substitution relationship a candidate realizes.\n *\n * @category Reharmonization\n */\nexport type SubstitutionType =\n | 'tritone'\n | 'relative'\n | 'borrowed'\n | 'chromatic-mediant'\n | 'secondary-dominant';\n\n/**\n * A proposed chord substitution with its relationship, numeral, and function.\n *\n * @category Reharmonization\n */\nexport type Substitution = {\n chord: Chord;\n type: SubstitutionType;\n roman: string;\n function: HarmonicFunction;\n};\n\n/**\n * Options controlling which substitutions {@link substituteChord} returns.\n *\n * @category Reharmonization\n */\nexport type SubstituteOptions = {\n /**\n * Melody pitch classes that must remain chord tones. When given, only\n * substitutions whose pitch classes contain every listed pitch class are\n * kept, so the melody stays consonant against the new harmony.\n */\n melodyPcs?: number[];\n};\n\n/** Whether the chord's template carries a given interval (mod 12). */\nfunction hasInterval(chord: Chord, semitone: number): boolean {\n return chord.intervals.some((iv) => mod12(iv) === semitone);\n}\n\n/** Whether a chord is a dominant type: a major third with a minor seventh. */\nfunction isDominantType(chord: Chord): boolean {\n return hasInterval(chord, 4) && hasInterval(chord, 10);\n}\n\n/**\n * A chord that can be tonicized: it has a perfect fifth and a third but is not\n * itself a dominant seventh (which is an unstable, tonicizing sonority rather\n * than a stable target).\n */\nfunction isStableTarget(chord: Chord): boolean {\n const hasFifth = hasInterval(chord, 7);\n const hasThird = hasInterval(chord, 3) || hasInterval(chord, 4);\n return hasFifth && hasThird && !isDominantType(chord);\n}\n\n/** The triad pitch classes (root, third, fifth) implied by a chord's template. */\nfunction triadPitchClasses(chord: Chord): number[] {\n const third = hasInterval(chord, 4) ? 4 : hasInterval(chord, 3) ? 3 : 4;\n const fifth = hasInterval(chord, 8) ? 8 : hasInterval(chord, 6) ? 6 : 7;\n return [mod12(chord.rootPc), mod12(chord.rootPc + third), mod12(chord.rootPc + fifth)];\n}\n\n/** Count the pitch classes shared between two pitch-class sets. */\nfunction commonToneCount(a: number[], b: number[]): number {\n const set = new Set(b);\n return a.filter((pc) => set.has(pc)).length;\n}\n\n/** The diatonic triads of a key, one per scale degree. */\nfunction diatonicTriadsOf(key: KeyScale): Chord[] {\n const degrees = scaleTonesInDegreeOrder(key).length;\n const triads: Chord[] = [];\n for (let degree = 0; degree < degrees; degree += 1) {\n triads.push(diatonicTriad(degree, key));\n }\n return triads;\n}\n\n/** Whether two chords share the same root pitch class and quality. */\nfunction sameChord(a: Chord, b: Chord): boolean {\n return mod12(a.rootPc) === mod12(b.rootPc) && a.quality === b.quality;\n}\n\n/** Root offsets (semitones) that form a third above or below a root. */\nconst THIRD_OFFSETS = [3, 4, 8, 9] as const;\n\n/**\n * Propose substitutions for a chord within a key.\n *\n * Candidates are generated by several relationships and deduplicated against the\n * original chord and each other:\n *\n * - `tritone`: for a dominant-type chord, the dominant seventh a tritone away.\n * - `secondary-dominant`: for a stable target, the dominant seventh a fifth\n * above its root (tonicizing it).\n * - `relative`: a diatonic triad a third away that shares two common tones.\n * - `borrowed`: a triad from the parallel mode with the same harmonic function.\n * - `chromatic-mediant`: a major/minor triad a third away sharing one common\n * tone.\n *\n * Each result carries its Roman numeral and harmonic function in `key`. When\n * `opts.melodyPcs` is given, only substitutions whose pitch classes contain all\n * of those pitch classes are returned.\n *\n * @param chord The chord to reharmonize.\n * @param key The prevailing key.\n * @param opts Optional melody-preservation constraint.\n * @returns The deduplicated substitution candidates.\n * @example\n * ```ts\n * import { substituteChord, makeChord, majorKey } from '@libraz/libcantus';\n * const subs = substituteChord(makeChord(7, 'dom7'), majorKey(0));\n * // includes the tritone sub Db7 (rootPc 1, quality 'dom7')\n * ```\n * @category Reharmonization\n */\nexport function substituteChord(\n chord: Chord,\n key: KeyScale,\n opts?: SubstituteOptions,\n): Substitution[] {\n const original = triadPitchClasses(chord);\n const candidates: { chord: Chord; type: SubstitutionType }[] = [];\n\n // Tritone substitution: only for dominant-type chords.\n if (isDominantType(chord)) {\n candidates.push({ chord: makeChord(mod12(chord.rootPc + 6), 'dom7'), type: 'tritone' });\n }\n\n // Secondary dominant: the V7 tonicizing a stable target.\n if (isStableTarget(chord)) {\n candidates.push({\n chord: makeChord(mod12(chord.rootPc + 7), 'dom7'),\n type: 'secondary-dominant',\n });\n }\n\n // Relative: a diatonic triad a third away sharing two common tones.\n for (const triad of diatonicTriadsOf(key)) {\n const offset = mod12(triad.rootPc - chord.rootPc);\n if (\n (THIRD_OFFSETS as readonly number[]).includes(offset) &&\n commonToneCount(original, chordPitchClasses(triad)) === 2\n ) {\n candidates.push({ chord: triad, type: 'relative' });\n }\n }\n\n // Borrowed: a parallel-mode triad sharing the original's harmonic function.\n const targetFunction = functionOf(chord, key);\n for (const triad of diatonicTriadsOf(parallelKey(key))) {\n if (functionOf(triad, key) === targetFunction && !isDiatonic(triad, key)) {\n candidates.push({ chord: triad, type: 'borrowed' });\n }\n }\n\n // Chromatic mediants: major/minor triads a third away sharing one common tone.\n for (const offset of THIRD_OFFSETS) {\n for (const quality of ['maj', 'min'] as const) {\n const mediant = makeChord(mod12(chord.rootPc + offset), quality);\n if (\n commonToneCount(original, chordPitchClasses(mediant)) === 1 &&\n !isDiatonic(mediant, key)\n ) {\n candidates.push({ chord: mediant, type: 'chromatic-mediant' });\n }\n }\n }\n\n const melodyPcs = opts?.melodyPcs?.map(mod12);\n const seen = new Set<string>();\n const results: Substitution[] = [];\n for (const candidate of candidates) {\n if (sameChord(candidate.chord, chord)) {\n continue;\n }\n const dedupeKey = `${mod12(candidate.chord.rootPc)}:${candidate.chord.quality}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n if (melodyPcs !== undefined) {\n const pcs = new Set(chordPitchClasses(candidate.chord));\n if (!melodyPcs.every((pc) => pcs.has(pc))) {\n continue;\n }\n }\n results.push({\n chord: candidate.chord,\n type: candidate.type,\n roman: chordToRoman(candidate.chord, key),\n function: functionOf(candidate.chord, key),\n });\n }\n return results;\n}\n\n/**\n * A borrowed chord in the modal-interchange palette of a key.\n *\n * @category Reharmonization\n */\nexport type BorrowedChord = {\n chord: Chord;\n roman: string;\n source: BorrowedSource;\n};\n\n/**\n * The modal-interchange palette of a key.\n *\n * Lists the diatonic triads of the {@link parallelKey} that are not diatonic to\n * `key` (the classic borrowed chords such as `iv`, `bVI`, and `bVII` in a major\n * key), plus the Neapolitan (a major triad on the flat second degree). Each\n * carries its Roman numeral and {@link borrowedSource} relative to `key`.\n *\n * @param key The prevailing key.\n * @returns The borrowed-chord palette.\n * @category Reharmonization\n */\nexport function modalInterchangePalette(key: KeyScale): BorrowedChord[] {\n const palette: BorrowedChord[] = [];\n const seen = new Set<string>();\n const add = (chord: Chord) => {\n const dedupeKey = `${mod12(chord.rootPc)}:${chord.quality}`;\n if (seen.has(dedupeKey)) {\n return;\n }\n seen.add(dedupeKey);\n palette.push({\n chord,\n roman: chordToRoman(chord, key),\n source: borrowedSource(chord, key),\n });\n };\n\n for (const triad of diatonicTriadsOf(parallelKey(key))) {\n if (!isDiatonic(triad, key)) {\n add(triad);\n }\n }\n // The Neapolitan (major triad on b2) sits outside both parallel modes, so it\n // is added explicitly — unless b2 is already diatonic (e.g. in a Phrygian key,\n // where it is a native chord rather than a borrowing).\n const neapolitan = makeChord(mod12(key.rootPc + 1), 'maj');\n if (!isDiatonic(neapolitan, key)) {\n add(neapolitan);\n }\n return palette;\n}\n\n/**\n * Reflect a chord across the tonic–dominant axis of a key (negative harmony).\n *\n * Every pitch class `p` maps to `(2*T + 7 - p) mod 12`, where `T` is the key\n * tonic — the reflection that swaps the tonic with the dominant. The mirrored\n * pitch classes (including the bass, if set) are reassembled into a chord by\n * {@link detectChordBest}; when no chord is recognized, the mirrored root and\n * the original quality are used as a fallback.\n *\n * @param chord The chord to reflect.\n * @param key The prevailing key.\n * @returns The negative-harmony counterpart of the chord.\n * @example\n * ```ts\n * import { negativeHarmonyMirror, makeChord, majorKey } from '@libraz/libcantus';\n * negativeHarmonyMirror(makeChord(7, 'maj'), majorKey(0));\n * // G major reflected across C's axis => F minor (rootPc 5, quality 'min')\n * ```\n * @category Reharmonization\n */\nexport function negativeHarmonyMirror(chord: Chord, key: KeyScale): Chord {\n const tonic = mod12(key.rootPc);\n const mirror = (p: number) => mod12(2 * tonic + 7 - p);\n const pcs = chordPitchClasses(chord).map(mirror);\n const bassPc = chord.bassPc !== undefined ? mirror(chord.bassPc) : undefined;\n // Place the mirrored bass an octave below so it is recognized as the lowest\n // note and preserved through detection.\n const pitches = bassPc !== undefined ? [bassPc - 12, ...pcs] : pcs;\n const detected = detectChordBest(pitches);\n if (detected) {\n // Without an input bass the mirrored tones are octave-less, so detection may\n // read the lowest pitch class as a slash bass and report a spurious\n // inversion. Restore the recognized chord to root position in that case.\n if (bassPc === undefined && detected.bassPc !== undefined) {\n return makeChord(detected.rootPc, detected.quality);\n }\n return detected;\n }\n const quality: ChordQuality = chord.quality;\n return makeChord(mirror(chord.rootPc), quality, bassPc);\n}\n","/**\n * Spelling: derive letter-name notes for scales and chords from a spelled tonic.\n *\n * The theory core works in pitch classes, which cannot choose between (say) a\n * G# and an Ab. Given a spelled tonic, this module assigns diatonic letters to\n * scale degrees and chord tones so a C major scale spells as C D E F G A B and\n * A harmonic minor spells its seventh as G#.\n */\n\nimport type { Chord } from '../chord/index.js';\nimport type { Note } from '../pitch/index.js';\nimport { formatNote } from '../pitch/index.js';\nimport { scaleTonesInDegreeOrder } from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/** Semitone offset of each natural letter above C: C D E F G A B. */\nconst LETTER_SEMITONES = [0, 2, 4, 5, 7, 9, 11] as const;\n\n/**\n * Conventional degree assignment for each chromatic offset above the tonic.\n *\n * The letter is derived from the tonic's letter plus `degreeOffset` (so the\n * spelling follows the key's diatonic letters), and the accidental is recomputed\n * for that letter. This covers the flat-side alterations (b2, b3, b6, b7), the\n * raised fourth (#4), and the raised degrees of a minor key: the raised sixth\n * (#6) and the raised leading tone (#7). The latter two keep sharp-side minor\n * keys spelling their raised degrees with the key-correct letter (e.g. F# minor\n * spells its leading tone E#, not F).\n *\n * The `alter` field is illustrative only; `spellPitchClass` recomputes the\n * accidental from the chosen letter.\n */\nconst CHROMATIC_SPELLING: Record<number, { degreeOffset: number; alter: number }> = {\n 1: { degreeOffset: 1, alter: -1 }, // b2\n 3: { degreeOffset: 2, alter: -1 }, // b3\n 6: { degreeOffset: 3, alter: 1 }, // #4\n 8: { degreeOffset: 5, alter: -1 }, // b6\n 9: { degreeOffset: 5, alter: 1 }, // #6 (raised sixth of a minor key)\n 10: { degreeOffset: 6, alter: -1 }, // b7\n 11: { degreeOffset: 6, alter: 1 }, // #7 (raised leading tone of a minor key)\n};\n\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\nfunction mod7(n: number): number {\n return ((n % 7) + 7) % 7;\n}\n\n/** Natural pitch class of a letter (0 = C .. 6 = B). */\nfunction naturalPc(letter: number): number {\n return LETTER_SEMITONES[mod7(letter)] ?? 0;\n}\n\n/** Shortest signed alteration (in [-6, 6]) taking a letter's natural pc to `pc`. */\nfunction alterFor(letter: number, pc: number): number {\n let d = mod12(pc - naturalPc(letter));\n if (d > 6) {\n d -= 12;\n }\n return d;\n}\n\n/** Whether the key's scale is a seven-note (heptatonic) scale. */\nfunction isHeptatonic(key: KeyScale): boolean {\n return scaleTonesInDegreeOrder(key).length === 7;\n}\n\n/**\n * Spell a single pitch class relative to a spelled tonic and key.\n *\n * Diatonic pitch classes take the scale's letter for their degree; the common\n * chromatic tones (b2, b3, #4, b6, b7) and a minor key's raised degrees (#6, #7)\n * take their conventional, key-correct accidental spelling; anything else falls\n * back to a sharp spelling of the nearest natural.\n *\n * @param pc The pitch class to spell.\n * @param tonic The spelled tonic (its letter anchors the spelling).\n * @param key The key/scale.\n * @returns The spelled note (without octave).\n * @category Pitch & Intervals\n */\nexport function spellPitchClass(pc: number, tonic: Note, key: KeyScale): Note {\n const tonicPc = mod12(naturalPc(tonic.letter) + tonic.alter);\n const offset = mod12(pc - tonicPc);\n const tones = scaleTonesInDegreeOrder(key);\n\n if (isHeptatonic(key)) {\n const degree = tones.indexOf(mod12(pc));\n if (degree >= 0) {\n const letter = mod7(tonic.letter + degree);\n return { letter, alter: alterFor(letter, pc) };\n }\n const chromatic = CHROMATIC_SPELLING[offset];\n if (chromatic) {\n const letter = mod7(tonic.letter + chromatic.degreeOffset);\n return { letter, alter: alterFor(letter, pc) };\n }\n }\n\n // Fallback: name the pitch class from the nearest natural, preferring a sharp.\n for (let letter = 0; letter < 7; letter += 1) {\n if (naturalPc(letter) === mod12(pc)) {\n return { letter, alter: 0 };\n }\n }\n const belowLetter = mod7([0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6][mod12(pc)] ?? 0);\n return { letter: belowLetter, alter: alterFor(belowLetter, pc) };\n}\n\n/**\n * Spell every pitch class of a scale, in ascending scale-degree order.\n *\n * Correct for heptatonic scales (each degree gets the next letter). Non-standard\n * scales are spelled tone-by-tone with a sharp preference.\n *\n * @param tonic The spelled tonic.\n * @param key The key/scale.\n * @returns Spelled notes, one per scale degree.\n * @example\n * ```ts\n * import { spellScale, noteNames, parseNote, majorKey } from '@libraz/libcantus';\n * noteNames(spellScale(parseNote('C'), majorKey(0)));\n * // ['C', 'D', 'E', 'F', 'G', 'A', 'B']\n * ```\n * @category Pitch & Intervals\n */\nexport function spellScale(tonic: Note, key: KeyScale): Note[] {\n return scaleTonesInDegreeOrder(key).map((pc) => spellPitchClass(pc, tonic, key));\n}\n\n/**\n * Spell an arbitrary list of pitch classes relative to a key.\n *\n * @param pcs The pitch classes.\n * @param tonic The spelled tonic.\n * @param key The key/scale.\n * @returns Spelled notes, in input order.\n * @category Pitch & Intervals\n */\nexport function spellPitchClasses(pcs: number[], tonic: Note, key: KeyScale): Note[] {\n return pcs.map((pc) => spellPitchClass(pc, tonic, key));\n}\n\n/**\n * Spell a chord's tones, in the chord's own (tertian) order, relative to a key.\n *\n * Diatonic chords spell exactly (e.g. G7 in C major -> G B D F). Chromatic chord\n * tones take their conventional spelling; enharmonically ambiguous altered\n * tensions may be spelled by the general convention rather than by chord\n * function.\n *\n * @param chord The chord.\n * @param tonic The spelled tonic of the key.\n * @param key The key/scale.\n * @returns Spelled chord tones, root first.\n * @example\n * ```ts\n * import { spellChord, noteNames, parseNote, majorKey, makeChord } from '@libraz/libcantus';\n * // G7 in C major\n * noteNames(spellChord(makeChord(7, 'dom7'), parseNote('C'), majorKey(0)));\n * // ['G', 'B', 'D', 'F']\n * ```\n * @category Pitch & Intervals\n */\nexport function spellChord(chord: Chord, tonic: Note, key: KeyScale): Note[] {\n return chord.intervals.map((interval) =>\n spellPitchClass(mod12(chord.rootPc + interval), tonic, key),\n );\n}\n\n/**\n * Convenience: render spelled notes as letter-name strings.\n *\n * @param notes The notes.\n * @returns Their formatted names.\n * @category Pitch & Intervals\n */\nexport function noteNames(notes: Note[]): string[] {\n return notes.map(formatNote);\n}\n","/**\n * Lead-sheet chord symbol parsing and formatting.\n *\n * Bridges the informal `<root><quality>[/<bass>]` notation musicians write\n * (`Cmaj7`, `F#m7b5`, `Bb7`, `C/G`) and the library's structured {@link Chord}\n * type, so callers can accept/emit plain text at the edges of the API.\n */\nimport { type Chord, type ChordQuality, makeChord, type PitchSpelling } from '../chord/index.js';\nimport { formatNote, midiToNote, type Note, noteToPitchClass, parseNote } from '../pitch/index.js';\n\n/**\n * Matches a chord root: a letter A-G (case-insensitive, like {@link parseNote})\n * with an optional single-direction accidental.\n */\nconst ROOT_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?/;\n\n/** Matches a bare note usable as a slash-chord bass (no octave). */\nconst BASS_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?$/;\n\n/** Recognized quality suffixes, keyed by their exact lead-sheet spelling. */\nconst QUALITY_MAP: Record<string, ChordQuality> = {\n '': 'maj',\n m: 'min',\n min: 'min',\n '-': 'min',\n dim: 'dim',\n '°': 'dim',\n aug: 'aug',\n '+': 'aug',\n maj7: 'maj7',\n M7: 'maj7',\n Δ: 'maj7',\n Δ7: 'maj7',\n m7: 'min7',\n min7: 'min7',\n '-7': 'min7',\n '7': 'dom7',\n dim7: 'dim7',\n '°7': 'dim7',\n m7b5: 'm7b5',\n ø: 'm7b5',\n ø7: 'm7b5',\n min7b5: 'm7b5',\n mMaj7: 'minMaj7',\n mM7: 'minMaj7',\n minMaj7: 'minMaj7',\n aug7: 'aug7',\n '+7': 'aug7',\n '7#5': 'aug7',\n augMaj7: 'augMaj7',\n augM7: 'augMaj7',\n '+maj7': 'augMaj7',\n '+M7': 'augMaj7',\n majb5: 'majb5',\n 'maj(b5)': 'majb5',\n '(b5)': 'majb5',\n '6': '6',\n m6: 'min6',\n min6: 'min6',\n '6/9': '6/9',\n '69': '6/9',\n sus2: 'sus2',\n sus: 'sus4',\n sus4: 'sus4',\n add9: 'add9',\n add11: 'add11',\n maj9: 'maj9',\n M9: 'maj9',\n m9: 'min9',\n min9: 'min9',\n '9': 'dom9',\n '7b9': '7b9',\n '7#9': '7#9',\n '7#11': '7#11',\n '7b13': '7b13',\n '11': '11',\n '13': '13',\n '5': '5',\n};\n\n/** Canonical lead-sheet suffix emitted for each chord quality when formatting. */\nconst CANONICAL_SUFFIX: Record<ChordQuality, string> = {\n maj: '',\n min: 'm',\n dim: 'dim',\n aug: 'aug',\n maj7: 'maj7',\n min7: 'm7',\n dom7: '7',\n dim7: 'dim7',\n m7b5: 'm7b5',\n minMaj7: 'mMaj7',\n aug7: 'aug7',\n augMaj7: 'augMaj7',\n majb5: 'maj(b5)',\n '6': '6',\n min6: 'm6',\n '6/9': '6/9',\n sus2: 'sus2',\n sus4: 'sus4',\n add9: 'add9',\n add11: 'add11',\n maj9: 'maj9',\n min9: 'm9',\n dom9: '9',\n '7b9': '7b9',\n '7#9': '7#9',\n '7#11': '7#11',\n '7b13': '7b13',\n '11': '11',\n '13': '13',\n '5': '5',\n};\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Build a chord and record the parsed spellings as enharmonic hints. */\nfunction makeSpelledChord(root: Note, quality: ChordQuality, bass?: Note): Chord {\n const chord = makeChord(\n noteToPitchClass(root),\n quality,\n bass === undefined ? undefined : noteToPitchClass(bass),\n );\n chord.rootSpelling = { letter: root.letter, alter: root.alter };\n if (bass !== undefined) {\n chord.bassSpelling = { letter: bass.letter, alter: bass.alter };\n }\n return chord;\n}\n\n/**\n * Parse a lead-sheet chord symbol into a {@link Chord}.\n *\n * Accepts `<root><quality>[/<bass>]`, e.g. `Cmaj7`, `F#m7b5`, `Bb7`, `C/G`,\n * `C6/9`, `C6/9/E`. Root and bass letters are case-insensitive, matching\n * {@link parseNote}. A `/` is ambiguous between a slash bass and the `6/9`\n * quality; the text splits at the last `/` whose right-hand side is a valid\n * bare note preceded by a recognized quality, so `6/9` (with or without a\n * further slash bass) parses as a quality.\n *\n * The parsed chord carries the root/bass spellings as enharmonic hints\n * (`rootSpelling`/`bassSpelling`) so {@link formatChordSymbol} can reproduce\n * flat spellings such as `Bbmaj7` instead of respelling them with sharps.\n *\n * @param text The chord symbol text.\n * @returns The parsed chord.\n * @throws If the root or quality is not recognized.\n * @example\n * ```ts\n * import { parseChordSymbol, formatChordSymbol } from '@libraz/libcantus';\n * const c = parseChordSymbol('Bbmaj7');\n * formatChordSymbol(c); // 'Bbmaj7' — flat spelling is preserved on round-trip\n * ```\n * @category Chords\n */\nexport function parseChordSymbol(text: string): Chord {\n const trimmed = text.trim();\n const rootMatch = ROOT_RE.exec(trimmed);\n if (!rootMatch) {\n throw new Error(`Invalid chord symbol: ${text}`);\n }\n const rootToken = rootMatch[0];\n const rootNote = parseNote(rootToken);\n const rest = trimmed.slice(rootToken.length);\n\n // Split at the last '/' so the '6/9' quality's own slash never masks a\n // trailing slash bass (e.g. 'C6/9/E').\n const slashIndex = rest.lastIndexOf('/');\n if (slashIndex !== -1) {\n const before = rest.slice(0, slashIndex);\n const after = rest.slice(slashIndex + 1);\n const beforeQuality = QUALITY_MAP[before];\n if (beforeQuality !== undefined && BASS_RE.test(after)) {\n return makeSpelledChord(rootNote, beforeQuality, parseNote(after));\n }\n }\n\n const quality = QUALITY_MAP[rest];\n if (quality === undefined) {\n throw new Error(`Unrecognized chord quality: ${text}`);\n }\n return makeSpelledChord(rootNote, quality);\n}\n\n/**\n * Name a pitch class, preferring a spelling hint when it is still valid.\n *\n * A hint is used only when no explicit sharp/flat preference was given and the\n * hint still resolves to `pc` (a stale hint left over after transposition is\n * ignored). Otherwise the pitch class is respelled from the requested table.\n */\nfunction pitchClassName(pc: number, hint: PitchSpelling | undefined, flats?: boolean): string {\n if (flats === undefined && hint !== undefined && noteToPitchClass(hint) === pc) {\n return formatNote(hint);\n }\n const note = midiToNote(60 + pc, flats ? 'flat' : 'sharp');\n return formatNote({ letter: note.letter, alter: note.alter });\n}\n\n/**\n * Format a {@link Chord} as a lead-sheet chord symbol.\n *\n * The inverse of {@link parseChordSymbol}: each quality maps to one canonical\n * suffix spelling, and a slash bass is appended only when it differs from the\n * root. When the chord carries `rootSpelling`/`bassSpelling` hints (as chords\n * from {@link parseChordSymbol} do) and no explicit `flats` preference is\n * given, the hints are reused so flat symbols round-trip unchanged.\n *\n * @param chord The chord to format.\n * @param opts Formatting options.\n * @param opts.flats Prefer flat spellings over sharps for altered roots/basses;\n * passing either `true` or `false` overrides any spelling hints.\n * @returns The chord symbol text.\n * @example\n * ```ts\n * import { makeChord, formatChordSymbol } from '@libraz/libcantus';\n * formatChordSymbol(makeChord(0, 'min7')); // 'Cm7'\n * ```\n * @category Chords\n */\nexport function formatChordSymbol(chord: Chord, opts?: { flats?: boolean }): string {\n const rootPc = pitchClass(chord.rootPc);\n const rootName = pitchClassName(rootPc, chord.rootSpelling, opts?.flats);\n const suffix = CANONICAL_SUFFIX[chord.quality];\n let symbol = `${rootName}${suffix}`;\n if (chord.bassPc !== undefined && pitchClass(chord.bassPc) !== rootPc) {\n symbol += `/${pitchClassName(pitchClass(chord.bassPc), chord.bassSpelling, opts?.flats)}`;\n }\n return symbol;\n}\n\n/**\n * Transpose a chord symbol by a number of semitones.\n *\n * @param text The chord symbol text.\n * @param semitones Signed semitone offset to apply to the root and bass.\n * @param opts Formatting options for the result; see {@link formatChordSymbol}.\n * @returns The transposed chord symbol text.\n * @throws If `text` does not parse as a chord symbol.\n * @example\n * ```ts\n * import { transposeChordSymbol } from '@libraz/libcantus';\n * transposeChordSymbol('C/G', 2); // 'D/A'\n * ```\n * @category Chords\n */\nexport function transposeChordSymbol(\n text: string,\n semitones: number,\n opts?: { flats?: boolean },\n): string {\n const chord = parseChordSymbol(text);\n const transposed: Chord = { ...chord, rootPc: pitchClass(chord.rootPc + semitones) };\n if (chord.bassPc !== undefined) {\n transposed.bassPc = pitchClass(chord.bassPc + semitones);\n }\n return formatChordSymbol(transposed, opts);\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses, chordToneRole } from '../chord/index.js';\nimport {\n createsHiddenParallelPerfect,\n createsParallelPerfect,\n createsVoiceCrossing,\n createsVoiceOverlap,\n exceedsSpacing,\n} from '../counterpoint/index.js';\n\n/**\n * An inclusive MIDI pitch range for a single voice.\n *\n * @category Voicing & Counterpoint\n */\nexport type VoiceRange = {\n min: number;\n max: number;\n};\n\n/**\n * Default four-voice SATB ranges, ascending (index 0 = lowest):\n * bass E2–C4 (40–60), tenor C3–G4 (48–67), alto G3–D5 (55–74),\n * soprano C4–G5 (60–79).\n *\n * @category Voicing & Counterpoint\n */\nexport const SATB_RANGES: readonly VoiceRange[] = [\n { min: 40, max: 60 },\n { min: 48, max: 67 },\n { min: 55, max: 74 },\n { min: 60, max: 79 },\n];\n\n/**\n * Options controlling {@link voiceChord} and {@link voiceProgression}.\n *\n * @category Voicing & Counterpoint\n */\nexport type VoicingOptions = {\n /**\n * Number of voices to realize. Ignored when `ranges` is given.\n *\n * @defaultValue 4\n */\n voices?: number;\n /** Explicit per-voice ranges, ascending (index 0 = lowest). Takes precedence over `voices`. */\n ranges?: VoiceRange[];\n /**\n * Maximum spacing in semitones between adjacent upper voices.\n *\n * @defaultValue 12\n */\n maxSpacing?: number;\n};\n\n/** Default maximum spacing between adjacent upper voices (one octave). */\nconst DEFAULT_MAX_SPACING = 12;\n\n/** Overall pitch floor/ceiling used when deriving ranges for arbitrary voice counts. */\nconst DERIVED_LOW = 40;\nconst DERIVED_HIGH = 79;\n/** Span of each derived per-voice range in semitones. */\nconst DERIVED_SPAN = 19;\n\n/** Score penalty per counterpoint violation between consecutive voicings. */\nconst VIOLATION_PENALTY = 1000;\n/** Score penalty per chord tone absent from a voicing. */\nconst MISSING_TONE_PENALTY = 500;\n/** Score penalty per doubled tone that is neither the root nor the fifth. */\nconst POOR_DOUBLING_PENALTY = 4;\n/**\n * Moderate penalty for a hidden/direct perfect fifth or octave reached on the\n * outer-voice (bass–soprano) pair. Unlike a true parallel perfect it is\n * discouraged rather than forbidden, so the weight sits alongside voice-leading\n * motion rather than the hard {@link VIOLATION_PENALTY}.\n */\nconst HIDDEN_PERFECT_PENALTY = 6;\n/** Hard cap on candidate voicings evaluated per chord, keeping the search bounded. */\nconst MAX_CANDIDATES = 4000;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * Resolve the per-voice ranges implied by the options: explicit `ranges` win,\n * four voices use {@link SATB_RANGES}, and other counts get evenly spaced\n * ranges spanning roughly the bass-to-soprano compass.\n */\nfunction resolveRanges(opts?: VoicingOptions): VoiceRange[] {\n if (opts?.ranges !== undefined) {\n if (opts.ranges.length === 0) {\n throw new Error('ranges must contain at least one voice range');\n }\n return opts.ranges.map((range) => ({ ...range }));\n }\n const voices = opts?.voices ?? 4;\n if (voices < 1) {\n throw new Error('voices must be at least 1');\n }\n if (voices === 4) {\n return SATB_RANGES.map((range) => ({ ...range }));\n }\n if (voices === 1) {\n return [{ min: DERIVED_LOW, max: DERIVED_HIGH }];\n }\n const ranges: VoiceRange[] = [];\n for (let i = 0; i < voices; i += 1) {\n const min = Math.round(\n DERIVED_LOW + (i * (DERIVED_HIGH - DERIVED_SPAN - DERIVED_LOW)) / (voices - 1),\n );\n ranges.push({ min, max: min + DERIVED_SPAN });\n }\n return ranges;\n}\n\n/**\n * All MIDI pitches of a pitch class inside an inclusive range, ordered from the\n * centre of the range outward (ties break toward the lower pitch). Enumerating\n * centre-outward keeps the candidate set balanced around the register when it\n * is truncated at {@link MAX_CANDIDATES}, instead of skewing to the low octaves\n * that a plain ascending scan would visit first.\n */\nfunction pitchesForPc(pc: number, range: VoiceRange): number[] {\n const result: number[] = [];\n for (let midi = Math.ceil(range.min); midi <= range.max; midi += 1) {\n if (pitchClass(midi) === pc) {\n result.push(midi);\n }\n }\n const center = (range.min + range.max) / 2;\n return result.sort((a, b) => {\n const da = Math.abs(a - center);\n const db = Math.abs(b - center);\n return da === db ? a - b : da - db;\n });\n}\n\n/**\n * Enumerate candidate voicings for a chord: the bass takes the chord's bass\n * (or root) pitch class at each available octave, and each upper voice takes\n * any chord pitch class within its range. Candidates are built in ascending\n * voice order and pruned to exclude voice crossings and over-wide adjacent\n * spacing (the bass–tenor pair is allowed an extra octave, per convention).\n * Enumeration is deterministic and capped at {@link MAX_CANDIDATES}.\n */\nfunction enumerateVoicings(chord: Chord, ranges: VoiceRange[], maxSpacing: number): number[][] {\n const chordPcs = chordPitchClasses(chord);\n const bassPc = pitchClass(chord.bassPc ?? chord.rootPc);\n const results: number[][] = [];\n const current: number[] = [];\n const build = (voice: number): void => {\n if (results.length >= MAX_CANDIDATES) {\n return;\n }\n if (voice === ranges.length) {\n results.push([...current]);\n return;\n }\n const range = ranges[voice];\n if (range === undefined) {\n return;\n }\n const pcs = voice === 0 ? [bassPc] : chordPcs;\n const prev = current[voice - 1];\n for (const pc of pcs) {\n for (const pitch of pitchesForPc(pc, range)) {\n if (prev !== undefined) {\n if (pitch < prev) {\n continue; // would cross below the next lower voice\n }\n const spacingLimit = voice === 1 ? maxSpacing + 12 : maxSpacing;\n if (pitch - prev > spacingLimit) {\n continue;\n }\n }\n current.push(pitch);\n build(voice + 1);\n current.pop();\n }\n }\n };\n build(0);\n return results;\n}\n\n/**\n * Structural quality penalty of a single voicing: heavily penalize missing\n * chord tones, mildly penalize doubling anything other than the root or fifth.\n */\nfunction structuralPenalty(pitches: number[], chord: Chord): number {\n const counts = new Map<number, number>();\n for (const pitch of pitches) {\n const pc = pitchClass(pitch);\n counts.set(pc, (counts.get(pc) ?? 0) + 1);\n }\n let penalty = 0;\n for (const pc of chordPitchClasses(chord)) {\n if (!counts.has(pc)) {\n penalty += MISSING_TONE_PENALTY;\n }\n }\n const rootPc = pitchClass(chord.rootPc);\n const fifthPc = pitchClass(chord.rootPc + 7);\n for (const [pc, count] of counts) {\n if (count > 1 && pc !== rootPc && pc !== fifthPc) {\n penalty += (count - 1) * POOR_DOUBLING_PENALTY;\n }\n }\n return penalty;\n}\n\n/**\n * Count counterpoint violations between two consecutive voicings of equal\n * length: parallel perfects (fifths and octaves alike, since octaves are the\n * perfect-class-zero case of {@link createsParallelPerfect}) on every voice\n * pair, voice crossings in the new voicing, and — on adjacent pairs — voice\n * overlaps and over-wide spacing between upper voices.\n */\nfunction violationCount(prev: number[], cur: number[], maxSpacing: number): number {\n let count = 0;\n for (let lower = 0; lower < cur.length; lower += 1) {\n for (let upper = lower + 1; upper < cur.length; upper += 1) {\n const prevLower = prev[lower];\n const prevUpper = prev[upper];\n const curLower = cur[lower];\n const curUpper = cur[upper];\n if (\n prevLower === undefined ||\n prevUpper === undefined ||\n curLower === undefined ||\n curUpper === undefined\n ) {\n continue;\n }\n if (createsParallelPerfect(prevUpper, curUpper, prevLower, curLower)) {\n count += 1;\n }\n if (createsVoiceCrossing(curUpper, curLower)) {\n count += 1;\n }\n if (upper === lower + 1) {\n if (createsVoiceOverlap(prevUpper, curUpper, prevLower, curLower)) {\n count += 1;\n }\n if (lower > 0 && exceedsSpacing(curUpper, curLower, maxSpacing)) {\n count += 1;\n }\n }\n }\n }\n return count;\n}\n\n/**\n * Total voice-leading cost between two voicings: the sum of absolute semitone\n * motion across voices, plus a moderate {@link HIDDEN_PERFECT_PENALTY} when the\n * outer-voice (bass–soprano) pair reaches a hidden/direct perfect fifth or\n * octave by similar motion. The arrays must be the same length; when they\n * differ the voicings are not comparable and the cost is `Infinity`.\n *\n * @param from The previous voicing, one MIDI pitch per voice.\n * @param to The next voicing, one MIDI pitch per voice.\n * @returns The summed absolute motion (plus any hidden-perfect penalty), or\n * `Infinity` when lengths differ.\n * @category Voicing & Counterpoint\n */\nexport function voiceLeadingCost(from: number[], to: number[]): number {\n if (from.length !== to.length) {\n return Number.POSITIVE_INFINITY;\n }\n let total = 0;\n for (let i = 0; i < from.length; i += 1) {\n const a = from[i];\n const b = to[i];\n if (a === undefined || b === undefined) {\n continue;\n }\n total += Math.abs(b - a);\n }\n // Discourage hidden/direct perfects between the outermost voices, where they\n // are most audible. True parallels are handled (and forbidden) elsewhere.\n if (from.length >= 2) {\n const bassPrev = from[0];\n const bassCur = to[0];\n const sopPrev = from[from.length - 1];\n const sopCur = to[to.length - 1];\n if (\n bassPrev !== undefined &&\n bassCur !== undefined &&\n sopPrev !== undefined &&\n sopCur !== undefined &&\n createsHiddenParallelPerfect(bassPrev, bassCur, sopPrev, sopCur)\n ) {\n total += HIDDEN_PERFECT_PENALTY;\n }\n }\n return total;\n}\n\n/**\n * Realize a single chord as one MIDI pitch per voice, ascending (index 0 =\n * lowest). The bass voice takes the chord's `bassPc` when set, otherwise the\n * root; upper voices take chord pitch classes, doubling the root or fifth as\n * needed to fill all voices. The result stays inside each voice's range, keeps\n * adjacent upper voices within `maxSpacing`, avoids voice crossing, and is\n * deterministic: a compact close-position voicing centered in the ranges.\n *\n * @param chord The chord to voice.\n * @param opts Voicing options; defaults to four voices in {@link SATB_RANGES}.\n * @returns MIDI pitches, ascending, one per voice.\n * @throws If no voicing fits the given ranges.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceChord } from '@libraz/libcantus';\n * const chord = parseChordSymbol('Cmaj7');\n * voiceChord(chord); // four ascending MIDI pitches within the SATB ranges\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceChord(chord: Chord, opts?: VoicingOptions): number[] {\n const ranges = resolveRanges(opts);\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n let score = structuralPenalty(candidate, chord);\n for (let i = 0; i < candidate.length; i += 1) {\n const pitch = candidate[i];\n const range = ranges[i];\n if (pitch === undefined || range === undefined) {\n continue;\n }\n // Prefer pitches near the middle of each voice's range for a centered,\n // compact default voicing.\n score += Math.abs(pitch - (range.min + range.max) / 2);\n }\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n return best;\n}\n\n/**\n * Voice a chord progression with smooth voice leading. The first chord is\n * voiced with {@link voiceChord}; each subsequent chord picks, from a bounded\n * deterministic candidate set, the voicing minimizing the voice-leading cost\n * from the previous voicing plus a large penalty per counterpoint violation\n * (parallel perfects/octaves, voice crossing, voice overlap, and over-wide\n * upper-voice spacing).\n *\n * @param chords The chords to voice in order.\n * @param opts Voicing options; defaults to four voices in {@link SATB_RANGES}.\n * @returns One voicing per chord, each ascending with one MIDI pitch per voice.\n * @throws If any chord admits no voicing within the given ranges.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceProgression } from '@libraz/libcantus';\n * const chords = ['C', 'Am', 'F', 'G'].map((s) => parseChordSymbol(s));\n * voiceProgression(chords); // one four-voice voicing per chord, smoothly led\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceProgression(chords: Chord[], opts?: VoicingOptions): number[][] {\n const ranges = resolveRanges(opts);\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const result: number[][] = [];\n let prev: number[] | undefined;\n for (const chord of chords) {\n if (prev === undefined) {\n prev = voiceChord(chord, opts);\n result.push(prev);\n continue;\n }\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const score =\n structuralPenalty(candidate, chord) +\n voiceLeadingCost(prev, candidate) +\n VIOLATION_PENALTY * violationCount(prev, candidate, maxSpacing);\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n result.push(best);\n prev = best;\n }\n return result;\n}\n\n/**\n * A tertian voicing style for {@link voiceChordStyled}.\n *\n * - `close`: the plain close-position tertian stack.\n * - `drop2`: the second voice from the top dropped an octave (drop-2 voicing).\n * - `drop3`: the third voice from the top dropped an octave (drop-3 voicing).\n * - `shell`: root plus guide tones (third and seventh) for seventh chords, or\n * root/third/fifth for triads; the fifth and tensions are omitted.\n * - `rootless`: the root omitted, keeping third/fifth/seventh and tensions\n * (a typical left-hand jazz voicing).\n *\n * @category Voicing & Counterpoint\n */\nexport type VoicingStyle = 'close' | 'drop2' | 'drop3' | 'shell' | 'rootless';\n\n/**\n * Options controlling {@link voiceChordStyled}.\n *\n * @category Voicing & Counterpoint\n */\nexport type StyledVoicingOptions = {\n /**\n * Voicing style to build.\n *\n * @defaultValue 'close'\n */\n style?: VoicingStyle;\n /** Constrain the highest voice to this pitch class (0..11) when given. */\n topNote?: number;\n /**\n * Base octave for the close stack; the stack begins near `12 * octave`.\n *\n * @defaultValue 4\n */\n octave?: number;\n /**\n * Omit the root regardless of style (relevant for jazz voicings).\n *\n * @defaultValue false\n */\n rootless?: boolean;\n};\n\n/** Default base octave for a styled close-position stack. */\nconst DEFAULT_STYLE_OCTAVE = 4;\n\n/** Return the pitch classes of a list in order, without duplicates. */\nfunction dedupePcs(pcs: number[]): number[] {\n const seen = new Set<number>();\n const result: number[] = [];\n for (const pc of pcs) {\n if (!seen.has(pc)) {\n seen.add(pc);\n result.push(pc);\n }\n }\n return result;\n}\n\n/** The lowest MIDI pitch of a pitch class at or above a floor. */\nfunction lowestPitchAtOrAbove(pc: number, floor: number): number {\n return floor + ((((pc - pitchClass(floor)) % 12) + 12) % 12);\n}\n\n/** The pitch class in `pcs` whose circular distance to `target` is smallest. */\nfunction nearestPc(target: number, pcs: number[]): number {\n let best = pcs[0] ?? target;\n let bestDist = 12;\n for (const pc of pcs) {\n const dist = Math.min((((pc - target) % 12) + 12) % 12, (((target - pc) % 12) + 12) % 12);\n if (dist < bestDist) {\n bestDist = dist;\n best = pc;\n }\n }\n return best;\n}\n\n/**\n * Realize a single chord as an explicit tertian voicing in a chosen style,\n * independent of the SATB range search used by {@link voiceChord}.\n *\n * The chord tones are stacked in close position from the bass (`bassPc`, else\n * `rootPc`) in the given scientific-pitch `octave` upward (octave 4 starts the\n * bass near C4 = MIDI 60, matching {@link midiToNote} and the bass module).\n * When `topNote` is given the stack is rotated so the highest voice's pitch\n * class equals that note (or the nearest chord tone). The chosen\n * {@link VoicingStyle} then transforms the stack, and the result is returned as\n * ascending MIDI pitches (index 0 = lowest).\n *\n * @param chord The chord to voice.\n * @param opts Styled voicing options; defaults to a close voicing at octave 4.\n * @returns MIDI pitches, ascending, one per retained voice.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceChordStyled } from '@libraz/libcantus';\n * const chord = parseChordSymbol('Dm7');\n * voiceChordStyled(chord, { style: 'drop2' }); // ascending MIDI pitches, drop-2 voicing\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceChordStyled(chord: Chord, opts?: StyledVoicingOptions): number[] {\n const style = opts?.style ?? 'close';\n const base = 12 * ((opts?.octave ?? DEFAULT_STYLE_OCTAVE) + 1);\n const rootPc = pitchClass(chord.rootPc);\n const bassPc = pitchClass(chord.bassPc ?? chord.rootPc);\n const omitRoot = style === 'rootless' || opts?.rootless === true;\n\n // Tertian chord tones in order, with the bass tone rotated to the bottom.\n let order = dedupePcs(chord.intervals.map((interval) => pitchClass(chord.rootPc + interval)));\n const bassIndex = order.indexOf(bassPc);\n if (bassIndex > 0) {\n order = [...order.slice(bassIndex), ...order.slice(0, bassIndex)];\n } else if (bassIndex < 0) {\n order = [bassPc, ...order];\n }\n\n if (style === 'shell') {\n const roles = order.map((pc) => chordToneRole(pc, chord));\n // The guide tone is the seventh when present; on a sixth chord the sixth\n // stands in for it, and otherwise the voicing falls back to the fifth.\n const guide = roles.includes('seventh')\n ? 'seventh'\n : roles.includes('sixth')\n ? 'sixth'\n : 'fifth';\n order = order.filter((_pc, i) => {\n const role = roles[i];\n return role === 'root' || role === 'third' || role === guide;\n });\n }\n\n if (omitRoot) {\n order = order.filter((pc) => pc !== rootPc);\n }\n\n if (order.length === 0) {\n return [];\n }\n\n if (opts?.topNote !== undefined) {\n const target = order.includes(pitchClass(opts.topNote))\n ? pitchClass(opts.topNote)\n : nearestPc(pitchClass(opts.topNote), order);\n const targetIndex = order.indexOf(target);\n order = [...order.slice(targetIndex + 1), ...order.slice(0, targetIndex + 1)];\n }\n\n // Stack the ordered pitch classes upward in close position.\n const stack: number[] = [];\n let prev: number | undefined;\n for (const pc of order) {\n if (prev === undefined) {\n prev = lowestPitchAtOrAbove(pc, base);\n } else {\n let delta = (((pc - pitchClass(prev)) % 12) + 12) % 12;\n if (delta === 0) {\n delta = 12;\n }\n prev += delta;\n }\n stack.push(prev);\n }\n\n if (style === 'drop2' && stack.length >= 2) {\n stack[stack.length - 2] = (stack[stack.length - 2] ?? 0) - 12;\n } else if (style === 'drop3' && stack.length >= 3) {\n stack[stack.length - 3] = (stack[stack.length - 3] ?? 0) - 12;\n }\n\n return stack.sort((a, b) => a - b);\n}\n\n/**\n * Voice a single chord to follow smoothly from an arbitrary current voicing.\n *\n * Candidate voicings of `chord` are enumerated within ranges taken from `opts`,\n * or — when neither `voices` nor `ranges` is given — from a one-octave window\n * around each pitch of `current` (so the result matches `current`'s voice\n * count). Each candidate is scored by structural quality, voice-leading motion\n * from `current`, and a large penalty per counterpoint violation; the lowest\n * scoring candidate is returned, ascending.\n *\n * @param current The current voicing to lead from, ascending (index 0 = lowest).\n * @param chord The next chord to voice.\n * @param opts Voicing options; when omitted, ranges follow `current`'s span.\n * @returns The chosen voicing, ascending with one MIDI pitch per voice.\n * @throws If no voicing fits the derived ranges.\n * @category Voicing & Counterpoint\n */\nexport function nextVoicing(current: number[], chord: Chord, opts?: VoicingOptions): number[] {\n const ranges =\n opts?.ranges !== undefined || opts?.voices !== undefined\n ? resolveRanges(opts)\n : current.map((pitch) => {\n // Window one octave around each current pitch, clamped so extreme-low\n // or extreme-high input can never yield MIDI outside [0, 127].\n const centre = Math.min(127, Math.max(0, pitch));\n return { min: Math.max(0, centre - 12), max: Math.min(127, centre + 12) };\n });\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const score =\n structuralPenalty(candidate, chord) +\n voiceLeadingCost(current, candidate) +\n VIOLATION_PENALTY * violationCount(current, candidate, maxSpacing);\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n return best;\n}\n","/**\n * Fluent, immutable object model over the functional core.\n *\n * Each class wraps one of the library's plain data types (spelled notes,\n * chords, key/scales) and delegates every operation to the existing pure\n * functions. All instances are immutable: fields are read-only, transforming\n * methods return new instances, and getters hand out defensive copies of any\n * mutable data.\n */\n\nimport {\n type Chord as ChordData,\n type ChordQuality,\n chordFromDegree,\n chordPitchClasses,\n diatonicSeventh,\n diatonicTriad,\n makeChord,\n} from '../chord/index.js';\nimport {\n availableTensions,\n avoidNotes,\n type ChordScaleMatch,\n chordScales,\n} from '../chordscale/index.js';\nimport { detectChord, detectChordBest } from '../detect/index.js';\nimport {\n analyzeChord,\n type BorrowedSource,\n borrowedSource,\n type Cadence,\n type ChordAnalysis,\n chordToRoman,\n detectCadence,\n functionOf,\n type HarmonicFunction,\n isBorrowedChord,\n isMinorKey,\n romanToChord,\n} from '../functional/index.js';\nimport {\n formatNote,\n midiToNote,\n type Note as NoteData,\n noteToMidi,\n noteToPitchClass,\n parseNote,\n type SpelledInterval,\n spelledInterval,\n} from '../pitch/index.js';\nimport { negativeHarmonyMirror } from '../reharmony/index.js';\nimport {\n isScaleTone,\n majorKey,\n minorKey,\n scaleByName,\n scaleTonesInDegreeOrder,\n} from '../scale/index.js';\nimport { spellChord, spellScale } from '../spelling/index.js';\nimport { formatChordSymbol, parseChordSymbol } from '../symbol/index.js';\nimport type { KeyScale } from '../types.js';\nimport {\n type StyledVoicingOptions,\n type VoicingOptions,\n voiceChord,\n voiceChordStyled,\n voiceProgression,\n} from '../voicing/index.js';\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/** Defensive copy of a plain note. */\nfunction copyNote(data: NoteData): NoteData {\n const copy: NoteData = { letter: data.letter, alter: data.alter };\n if (data.octave !== undefined) {\n copy.octave = data.octave;\n }\n return copy;\n}\n\n/**\n * Defensive copy of a plain chord.\n *\n * Any enharmonic spelling hints (`rootSpelling`/`bassSpelling`, populated by\n * `parseChordSymbol`) are carried through so a flat-named chord round-trips\n * through the class API; a hint that no longer matches its pitch class is\n * simply ignored by the formatter.\n */\nfunction copyChord(data: ChordData): ChordData {\n const copy: ChordData = {\n rootPc: data.rootPc,\n quality: data.quality,\n intervals: [...data.intervals],\n };\n if (data.bassPc !== undefined) {\n copy.bassPc = data.bassPc;\n }\n if (data.rootSpelling !== undefined) {\n copy.rootSpelling = { letter: data.rootSpelling.letter, alter: data.rootSpelling.alter };\n }\n if (data.bassSpelling !== undefined) {\n copy.bassSpelling = { letter: data.bassSpelling.letter, alter: data.bassSpelling.alter };\n }\n return copy;\n}\n\n/** Spell a bare pitch class as an octave-less note with a sharp/flat preference. */\nfunction spellPitchClassBare(pc: number, spelling: 'sharp' | 'flat'): NoteData {\n const spelled = midiToNote(60 + mod12(pc), spelling);\n return { letter: spelled.letter, alter: spelled.alter };\n}\n\n/**\n * An immutable spelled note: a diatonic letter plus a chromatic alteration and\n * an optional octave. Wraps the plain note object and delegates to the pitch\n * module; every transformation returns a new instance.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.of('C4').transpose(7).name; // 'G4'\n * ```\n */\nexport class Note {\n readonly #data: NoteData;\n\n /**\n * Wrap a plain note object.\n *\n * @param data The spelled note; it is copied, never retained or mutated.\n */\n constructor(data: NoteData) {\n this.#data = copyNote(data);\n }\n\n /**\n * Parse scientific pitch notation (e.g. `'C#4'`, `'Bb'`, `'F##3'`).\n *\n * @param name The note text.\n * @returns The parsed note.\n * @throws If the text is not a valid note.\n */\n static of(name: string): Note {\n return new Note(parseNote(name));\n }\n\n /**\n * Name a MIDI number (middle C = C4 = 60) as a note.\n *\n * @param midi The MIDI number.\n * @param spelling Whether to prefer sharps or flats for black keys.\n * @returns The spelled note, with octave.\n */\n static fromMidi(midi: number, spelling: 'sharp' | 'flat' = 'sharp'): Note {\n return new Note(midiToNote(midi, spelling));\n }\n\n /**\n * Wrap an existing plain note object.\n *\n * @param data The plain note.\n * @returns The wrapped note.\n */\n static fromData(data: NoteData): Note {\n return new Note(data);\n }\n\n /** The note rendered as scientific pitch notation, e.g. `'G4'` or `'Bb'`. */\n get name(): string {\n return formatNote(this.#data);\n }\n\n /** The pitch class (0..11), ignoring octave. */\n get pitchClass(): number {\n return noteToPitchClass(this.#data);\n }\n\n /**\n * The MIDI number (middle C = C4 = 60).\n *\n * @throws If the note has no octave and therefore no fixed pitch.\n */\n get midi(): number {\n if (this.#data.octave === undefined) {\n throw new Error(`note ${this.name} has no octave, so it has no MIDI number`);\n }\n return noteToMidi(this.#data);\n }\n\n /** The diatonic letter number: 0..6 for C..B. */\n get letter(): number {\n return this.#data.letter;\n }\n\n /** The chromatic alteration in semitones: -1 flat, 0 natural, +1 sharp, ... */\n get alter(): number {\n return this.#data.alter;\n }\n\n /** The octave (scientific pitch notation), or undefined for a bare pitch class. */\n get octave(): number | undefined {\n return this.#data.octave;\n }\n\n /** A copy of the underlying plain note object. */\n get data(): NoteData {\n return copyNote(this.#data);\n }\n\n /**\n * Transpose by a signed number of semitones.\n *\n * When the note carries an octave the transposition happens in MIDI space and\n * the result is spelled with a sharp preference. An octave-less note stays\n * octave-less: only its pitch class is moved. Transposing by zero is the\n * identity: the original spelling is preserved (no enharmonic respelling).\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed note.\n */\n transpose(semitones: number): Note {\n if (semitones === 0) {\n return new Note(this.#data);\n }\n if (this.#data.octave !== undefined) {\n return Note.fromMidi(this.midi + semitones);\n }\n return new Note(spellPitchClassBare(this.pitchClass + semitones, 'sharp'));\n }\n\n /**\n * The spelled interval from this note to another.\n *\n * @param other The second note.\n * @returns The diatonic number, quality, and semitone span.\n */\n intervalTo(other: Note): SpelledInterval {\n return spelledInterval(this.#data, other.#data);\n }\n\n /**\n * Whether another note has the same letter, alteration, and octave.\n *\n * @param other The note to compare.\n * @returns True if the spellings are identical.\n */\n equals(other: Note): boolean {\n return (\n this.#data.letter === other.#data.letter &&\n this.#data.alter === other.#data.alter &&\n this.#data.octave === other.#data.octave\n );\n }\n\n /**\n * The plain note data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(note)` from collapsing to `{}`.\n *\n * @returns A copy of the underlying plain note object.\n */\n toJSON(): NoteData {\n return this.data;\n }\n}\n\n/**\n * An immutable spelled interval value: a diatonic number, a quality label, and\n * a signed semitone span. A thin convenience wrapper over the pitch module's\n * plain interval result.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Interval, Note } from '@libraz/libcantus';\n * Interval.between(Note.of('C4'), Note.of('G4')).name; // 'P5'\n * ```\n */\nexport class Interval {\n readonly #number: number;\n readonly #quality: string;\n readonly #semitones: number;\n\n private constructor(numberValue: number, quality: string, semitones: number) {\n this.#number = numberValue;\n this.#quality = quality;\n this.#semitones = semitones;\n }\n\n /**\n * The spelled interval between two notes.\n *\n * @param a The first note.\n * @param b The second note.\n * @returns The interval from `a` to `b`.\n */\n static between(a: Note, b: Note): Interval {\n const spelled = a.intervalTo(b);\n return new Interval(spelled.number, spelled.quality, spelled.semitones);\n }\n\n /**\n * Build an interval from explicit components.\n *\n * @param numberValue Diatonic size: 1 = unison, 2 = second, ... 8 = octave.\n * @param quality Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`.\n * @param semitones Signed semitone span.\n * @returns The interval.\n */\n static of(numberValue: number, quality: string, semitones: number): Interval {\n return new Interval(numberValue, quality, semitones);\n }\n\n /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */\n get number(): number {\n return this.#number;\n }\n\n /** Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`. */\n get quality(): string {\n return this.#quality;\n }\n\n /** Signed semitone span. */\n get semitones(): number {\n return this.#semitones;\n }\n\n /** A readable label composed of quality and number, e.g. `'P5'` or `'M3'`. */\n get name(): string {\n return `${this.#quality}${this.#number}`;\n }\n\n /**\n * The plain interval data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(interval)` from collapsing to `{}`.\n *\n * @returns The diatonic number, quality, and semitone span.\n */\n toJSON(): SpelledInterval {\n return { number: this.#number, quality: this.#quality, semitones: this.#semitones };\n }\n}\n\n/** Resolve a string or numeric key root into a spelled tonic note. */\nfunction resolveTonic(root: string | number, spelling: 'sharp' | 'flat'): Note {\n return typeof root === 'string' ? Note.of(root) : new Note(spellPitchClassBare(root, spelling));\n}\n\n/** Total accidentals a spelled tonic produces across a key's whole scale. */\nfunction accidentalLoad(tonic: NoteData, scale: KeyScale): number {\n return spellScale(tonic, scale).reduce((sum, note) => sum + Math.abs(note.alter), 0);\n}\n\n/**\n * Choose the tonic spelling (sharp- or flat-side) that spells `scale` with the\n * fewest accidentals, so a numeric root never yields a double-flat/double-sharp\n * scale (e.g. pitch class 6 minor spells as F# minor, not Gb minor with Bbb).\n */\nfunction bestTonicForScale(rootPc: number, scale: KeyScale): Note {\n const sharp = spellPitchClassBare(rootPc, 'sharp');\n const flat = spellPitchClassBare(rootPc, 'flat');\n if (sharp.letter === flat.letter && sharp.alter === flat.alter) {\n return new Note(sharp);\n }\n return accidentalLoad(flat, scale) <= accidentalLoad(sharp, scale)\n ? new Note(flat)\n : new Note(sharp);\n}\n\n/**\n * An immutable key/scale: a `KeyScale` (root pitch class plus mode mask) paired\n * with a spelled tonic that anchors letter-name spelling. Acts as the factory\n * for key-aware chords.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').chord(4).symbol(); // 'G' (the diatonic triad on scale degree 4)\n * ```\n */\nexport class Key {\n readonly #scale: KeyScale;\n readonly #tonic: Note;\n\n /**\n * Wrap a key/scale and its spelled tonic.\n *\n * @param scale The key/scale; its root is normalized to a pitch class.\n * @param tonic The spelled tonic anchoring letter-name spelling.\n */\n constructor(scale: KeyScale, tonic: Note) {\n this.#scale = { rootPc: mod12(scale.rootPc), modeMask12: scale.modeMask12 };\n this.#tonic = tonic;\n }\n\n /**\n * A major key.\n *\n * @param root Tonic as a note name (e.g. `'Eb'`) or a pitch class; a numeric\n * root is spelled with whichever accidental side yields the fewest\n * accidentals across the scale.\n * @returns The major key.\n */\n static major(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.of(root);\n return new Key(majorKey(tonic.pitchClass), tonic);\n }\n const scale = majorKey(root);\n return new Key(scale, bestTonicForScale(root, scale));\n }\n\n /**\n * A natural-minor key.\n *\n * @param root Tonic as a note name or a pitch class; a numeric root is\n * spelled with whichever accidental side yields the fewest accidentals\n * across the scale.\n * @returns The minor key.\n */\n static minor(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.of(root);\n return new Key(minorKey(tonic.pitchClass), tonic);\n }\n const scale = minorKey(root);\n return new Key(scale, bestTonicForScale(root, scale));\n }\n\n /**\n * A key on a named scale (e.g. `'dorian'`, `'harmonicMinor'`).\n *\n * @param name The scale name, a key of the scale module's named-scale table.\n * @param root Tonic as a note name or a pitch class.\n * @returns The key.\n * @throws If the name is not a known scale.\n */\n static named(name: string, root: string | number): Key {\n const tonic = resolveTonic(root, 'sharp');\n return new Key(scaleByName(name, tonic.pitchClass), tonic);\n }\n\n /**\n * Wrap an existing `KeyScale`, synthesizing a spelled tonic when none is\n * given (flat-preferred for minor-third scales, sharp-preferred otherwise).\n *\n * @param scale The key/scale to wrap.\n * @param tonic Optional spelled tonic.\n * @returns The key.\n */\n static of(scale: KeyScale, tonic?: Note): Key {\n const spelled =\n tonic ?? new Note(spellPitchClassBare(scale.rootPc, isMinorKey(scale) ? 'flat' : 'sharp'));\n return new Key(scale, spelled);\n }\n\n /** A copy of the underlying plain `KeyScale`. */\n get scale(): KeyScale {\n return { rootPc: this.#scale.rootPc, modeMask12: this.#scale.modeMask12 };\n }\n\n /** The spelled tonic. */\n get tonic(): Note {\n return this.#tonic;\n }\n\n /** The tonic pitch class (0..11). */\n get rootPc(): number {\n return this.#scale.rootPc;\n }\n\n /** Whether the scale has a minor third and no major third. */\n get isMinor(): boolean {\n return isMinorKey(this.#scale);\n }\n\n /**\n * The scale's pitch classes in ascending scale-degree order (degree 0 first).\n *\n * @returns One pitch class per scale degree.\n */\n pitchClasses(): number[] {\n return scaleTonesInDegreeOrder(this.#scale);\n }\n\n /**\n * The spelled scale, one note per degree (e.g. C D E F G A B for C major).\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n notes(): Note[] {\n return spellScale(this.#tonic.data, this.#scale).map((note) => new Note(note));\n }\n\n /**\n * Alias of {@link Key.notes}.\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n spell(): Note[] {\n return this.notes();\n }\n\n /**\n * The spelled scale as letter-name strings.\n *\n * @returns One name per scale degree.\n */\n noteNames(): string[] {\n return this.notes().map((note) => note.name);\n }\n\n /**\n * Build a chord on a scale degree, carrying this key as context.\n *\n * With an explicit quality the quality's interval template is attached to the\n * degree's diatonic root; without one the scale-correct diatonic triad is\n * stacked (e.g. a diminished triad on the leading tone of a major key).\n *\n * @param degree 0-based scale degree of the chord root.\n * @param quality Optional chord quality.\n * @returns The chord, with this key attached.\n */\n chord(degree: number, quality?: ChordQuality): Chord {\n const data =\n quality === undefined\n ? diatonicTriad(degree, this.#scale)\n : chordFromDegree(degree, quality, this.#scale);\n return new Chord(data, this);\n }\n\n /**\n * The diatonic triad on a scale degree, carrying this key as context.\n *\n * @param degree 0-based scale degree of the chord root.\n * @returns The triad, with this key attached.\n */\n diatonicTriad(degree: number): Chord {\n return new Chord(diatonicTriad(degree, this.#scale), this);\n }\n\n /**\n * The diatonic seventh chord on a scale degree, carrying this key as context.\n *\n * @param degree 0-based scale degree of the chord root.\n * @returns The seventh chord, with this key attached.\n */\n diatonicSeventh(degree: number): Chord {\n return new Chord(diatonicSeventh(degree, this.#scale), this);\n }\n\n /**\n * Build the chord denoted by a Roman numeral in this key (including applied\n * chords such as `'V7/V'`), carrying this key as context.\n *\n * @param text The Roman numeral.\n * @returns The chord, with this key attached.\n * @throws If the numeral is not valid.\n */\n roman(text: string): Chord {\n return new Chord(romanToChord(text, this.#scale), this);\n }\n\n /**\n * Whether a pitch belongs to the scale.\n *\n * @param x A MIDI pitch, bare pitch class, or note.\n * @returns True if the pitch class is a scale tone.\n */\n contains(x: number | Note): boolean {\n return isScaleTone(typeof x === 'number' ? x : x.pitchClass, this.#scale);\n }\n\n /**\n * The plain key data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(key)` from collapsing to `{}`. The result pairs the\n * `KeyScale` with the spelled tonic, enough to reconstruct the key via\n * {@link Key.of}.\n *\n * @returns The key/scale and its spelled tonic.\n */\n toJSON(): { scale: KeyScale; tonic: NoteData } {\n return { scale: this.scale, tonic: this.#tonic.data };\n }\n}\n\n/**\n * An immutable chord: a root pitch class, quality, interval template, and\n * optional slash bass, optionally carrying a {@link Key} context. Analysis\n * methods (`roman`, `function`, `analyze`, ...) use an explicitly passed key\n * first and fall back to the carried context.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').invert(1).symbol(); // 'Cmaj7/E' (third in the bass)\n * ```\n */\nexport class Chord {\n readonly #data: ChordData;\n readonly #key: Key | undefined;\n\n /**\n * Wrap a plain chord object.\n *\n * @param data The chord; it is copied, never retained or mutated.\n * @param key Optional key context for analysis methods.\n */\n constructor(data: ChordData, key?: Key) {\n this.#data = copyChord(data);\n this.#key = key;\n }\n\n /**\n * Build a chord from a root and quality.\n *\n * @param root Root as a note name (e.g. `'Eb'`) or a pitch class.\n * @param quality The chord quality.\n * @param bass Optional slash-chord bass pitch class.\n * @returns The chord (without key context).\n */\n static of(root: string | number, quality: ChordQuality, bass?: number): Chord {\n const rootPc = typeof root === 'string' ? Note.of(root).pitchClass : root;\n return new Chord(makeChord(rootPc, quality, bass));\n }\n\n /**\n * Wrap an existing plain chord object.\n *\n * @param data The plain chord.\n * @returns The wrapped chord (without key context).\n */\n static from(data: ChordData): Chord {\n return new Chord(data);\n }\n\n /**\n * Parse a lead-sheet chord symbol (e.g. `'Cmaj7'`, `'F#m7b5'`, `'C/G'`).\n *\n * @param symbol The chord symbol.\n * @returns The chord (without key context).\n * @throws If the root or quality is not recognized.\n */\n static parse(symbol: string): Chord {\n return new Chord(parseChordSymbol(symbol));\n }\n\n /**\n * Identify the chords matching a set of pitches, best interpretation first.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns Ranked chord interpretations (may be empty).\n */\n static detect(pitches: number[]): Chord[] {\n return detectChord(pitches).map(\n (match) => new Chord(makeChord(match.rootPc, match.quality, match.bassPc)),\n );\n }\n\n /**\n * The single best chord interpretation of a pitch set.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns The top-ranked chord, or null when nothing matches.\n */\n static detectBest(pitches: number[]): Chord | null {\n const best = detectChordBest(pitches);\n return best === null ? null : new Chord(best);\n }\n\n /** The root pitch class (0..11). */\n get rootPc(): number {\n return this.#data.rootPc;\n }\n\n /** The chord quality. */\n get quality(): ChordQuality {\n return this.#data.quality;\n }\n\n /** A copy of the semitone offsets above the root. */\n get intervals(): number[] {\n return [...this.#data.intervals];\n }\n\n /** The slash-chord bass pitch class, or undefined in root position. */\n get bassPc(): number | undefined {\n return this.#data.bassPc;\n }\n\n /** A copy of the underlying plain chord object. */\n get data(): ChordData {\n return copyChord(this.#data);\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /**\n * A copy of this chord carrying the given key context.\n *\n * @param key The key context to attach.\n * @returns The new chord.\n */\n withKey(key: Key): Chord {\n return new Chord(this.#data, key);\n }\n\n /**\n * The chord's sorted, deduplicated pitch classes.\n *\n * @returns Pitch classes ascending in [0, 11].\n */\n pitchClasses(): number[] {\n return chordPitchClasses(this.#data);\n }\n\n /**\n * The chord's Roman numeral in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The Roman numeral string.\n * @throws If no key is given and none is carried.\n */\n roman(key?: Key): string {\n return chordToRoman(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The chord's harmonic function (tonic / subdominant / dominant) in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The harmonic function.\n * @throws If no key is given and none is carried.\n */\n function(key?: Key): HarmonicFunction {\n return functionOf(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * Full functional analysis: function, borrowing, and Roman numeral.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The chord analysis.\n * @throws If no key is given and none is carried.\n */\n analyze(key?: Key): ChordAnalysis {\n return analyzeChord(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * Whether the chord is borrowed from the parallel mode (modal interchange).\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns True if the chord is borrowed.\n * @throws If no key is given and none is carried.\n */\n isBorrowed(key?: Key): boolean {\n return isBorrowedChord(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The origin of a non-diatonic chord (parallel mode or Neapolitan), or null.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The borrowing source, or null.\n * @throws If no key is given and none is carried.\n */\n borrowedSource(key?: Key): BorrowedSource {\n return borrowedSource(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The chord rendered as a lead-sheet symbol (e.g. `'Cmaj7'`, `'F#m7'`, `'C/G'`).\n *\n * @param opts Set `flats: true` to spell the root/bass with flats.\n * @returns The chord symbol.\n */\n symbol(opts?: { flats?: boolean }): string {\n return formatChordSymbol(this.#data, opts);\n }\n\n /**\n * Realize the chord as one MIDI pitch per voice, ascending.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns MIDI pitches, ascending, one per voice.\n * @throws If no voicing fits the given ranges.\n */\n voice(opts?: VoicingOptions): number[] {\n return voiceChord(this.#data, opts);\n }\n\n /**\n * Realize the chord as a single styled voicing (`close`, `drop2`, `drop3`,\n * `shell`, or `rootless`), optionally constraining the top voice.\n *\n * @param opts Styled-voicing options; defaults to a close-position voicing.\n * @returns MIDI pitches, ascending.\n */\n styledVoicing(opts?: StyledVoicingOptions): number[] {\n return voiceChordStyled(this.#data, opts);\n }\n\n /**\n * The negative-harmony mirror of the chord about the key's tonic–dominant\n * axis (major becomes minor and vice versa).\n *\n * @param key Key providing the reflection axis; falls back to the carried\n * context.\n * @returns The mirrored chord, keeping any key context.\n * @throws If no key is given and none is carried.\n */\n negativeHarmony(key?: Key): Chord {\n const resolved = this.#resolveKey(key);\n // Retain the key that anchored the reflection (explicit first, then carried)\n // so a later no-arg analysis method still has a key context.\n return new Chord(negativeHarmonyMirror(this.#data, resolved.scale), key ?? this.#key);\n }\n\n /**\n * The n-th inversion: a copy whose bass is the chord tone `n` steps above the\n * root in the interval template (`invert(1)` puts the third in the bass).\n * `n` wraps around the template length; negative values count backwards.\n *\n * `invert(0)` (and any `n` that wraps to it) is root position, so it carries\n * no slash bass and equals the original chord.\n *\n * @param n The inversion number.\n * @returns The inverted chord, keeping any key context.\n * @throws If the chord has no intervals.\n */\n invert(n: number): Chord {\n const intervals = this.#data.intervals;\n const length = intervals.length;\n if (length === 0) {\n throw new Error('cannot invert a chord with no intervals');\n }\n const index = ((n % length) + length) % length;\n const data = copyChord(this.#data);\n if (index === 0) {\n delete data.bassPc;\n } else {\n data.bassPc = mod12(this.#data.rootPc + (intervals[index] ?? 0));\n }\n return new Chord(data, this.#key);\n }\n\n /**\n * The named scales that fit over this chord, best fit first, rooted on the\n * chord root.\n *\n * @returns The matching scales.\n */\n scales(): ChordScaleMatch[] {\n return chordScales(this.#data);\n }\n\n /**\n * The available tensions (usable non-chord, non-avoid scale tones) of a\n * scale over this chord.\n *\n * @param scaleName A named scale, rooted on the chord root.\n * @returns Tension pitch classes, ascending in [0, 11].\n */\n tensions(scaleName: string): number[] {\n return availableTensions(this.#data, scaleName);\n }\n\n /**\n * The avoid notes (scale tones a semitone above a chord tone) of a scale\n * over this chord.\n *\n * @param scaleName A named scale, rooted on the chord root.\n * @returns Avoid-note pitch classes, ascending in [0, 11].\n */\n avoidNotes(scaleName: string): number[] {\n return avoidNotes(this.#data, scaleName);\n }\n\n /**\n * Spell the chord tones with letter names, root first, in the key's spelling.\n *\n * @param key Key providing the spelled tonic; falls back to the carried\n * context.\n * @returns Spelled octave-less notes in the chord's own (tertian) order.\n * @throws If no key is given and none is carried.\n */\n spell(key?: Key): Note[] {\n const resolved = this.#resolveKey(key);\n return spellChord(this.#data, resolved.tonic.data, resolved.scale).map(\n (note) => new Note(note),\n );\n }\n\n /**\n * Start a progression with this chord followed by others, carrying this\n * chord's key context (if any).\n *\n * @param others The chords following this one.\n * @returns The progression.\n */\n progressionTo(...others: Chord[]): Progression {\n return new Progression([this, ...others], this.#key);\n }\n\n /**\n * Whether another chord has the same root, quality, intervals, and bass.\n * Key context is not compared.\n *\n * @param other The chord to compare.\n * @returns True if the chord data is identical.\n */\n equals(other: Chord): boolean {\n const a = this.#data;\n const b = other.#data;\n return (\n a.rootPc === b.rootPc &&\n a.quality === b.quality &&\n a.bassPc === b.bassPc &&\n a.intervals.length === b.intervals.length &&\n a.intervals.every((interval, i) => interval === b.intervals[i])\n );\n }\n\n /**\n * The plain chord data, for JSON serialization.\n *\n * @returns A copy of the underlying plain chord object.\n */\n toJSON(): ChordData {\n return this.data;\n }\n\n /** Resolve the key for an analysis method: explicit first, then carried. */\n #resolveKey(key?: Key): Key {\n const resolved = key ?? this.#key;\n if (resolved === undefined) {\n throw new Error('chord has no key context; pass a Key or attach one with withKey()');\n }\n return resolved;\n }\n}\n\n/**\n * An immutable ordered sequence of chords, optionally carrying a {@link Key}\n * context shared by its analysis methods.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const key = Key.major('C');\n * key.chord(1).progressionTo(key.chord(4), key.chord(0)).roman();\n * // ['ii', 'V', 'I']\n * ```\n */\nexport class Progression {\n readonly #chords: readonly Chord[];\n readonly #key: Key | undefined;\n\n /**\n * Wrap a chord sequence.\n *\n * @param chords The chords in order; the array is copied.\n * @param key Optional key context for analysis methods.\n */\n constructor(chords: readonly Chord[], key?: Key) {\n this.#chords = [...chords];\n this.#key = key;\n }\n\n /** A copy of the chord sequence. */\n get chords(): readonly Chord[] {\n return [...this.#chords];\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /** The number of chords. */\n get length(): number {\n return this.#chords.length;\n }\n\n /**\n * A copy of this progression with a chord appended.\n *\n * @param chord The chord to append.\n * @returns The new progression.\n */\n add(chord: Chord): Progression {\n return new Progression([...this.#chords, chord], this.#key);\n }\n\n /**\n * A copy of this progression carrying the given key context.\n *\n * @param key The key context to attach.\n * @returns The new progression.\n */\n withKey(key: Key): Progression {\n return new Progression(this.#chords, key);\n }\n\n /**\n * Voice the progression with smooth voice leading.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns One ascending voicing (MIDI pitches) per chord.\n * @throws If any chord admits no voicing within the given ranges.\n */\n voice(opts?: VoicingOptions): number[][] {\n return voiceProgression(\n this.#chords.map((chord) => chord.data),\n opts,\n );\n }\n\n /**\n * The Roman numeral of each chord in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns One numeral per chord.\n * @throws If no key is given and none is carried.\n */\n roman(key?: Key): string[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.roman(resolved));\n }\n\n /**\n * The harmonic function of each chord in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns One function per chord.\n * @throws If no key is given and none is carried.\n */\n functions(key?: Key): HarmonicFunction[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.function(resolved));\n }\n\n /**\n * Analyze every chord and classify the closing cadence.\n *\n * The cadence is detected on the final chord pair and is null when the\n * progression has fewer than two chords.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns Per-chord analyses and the closing cadence.\n * @throws If no key is given and none is carried.\n */\n analyze(key?: Key): { chords: ChordAnalysis[]; cadence: Cadence } {\n const resolved = this.#resolveKey(key);\n const chords = this.#chords.map((chord) => chord.analyze(resolved));\n const from = this.#chords[this.#chords.length - 2];\n const to = this.#chords[this.#chords.length - 1];\n const cadence =\n from !== undefined && to !== undefined\n ? detectCadence(from.data, to.data, resolved.scale)\n : null;\n return { chords, cadence };\n }\n\n /**\n * The plain progression data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(progression)` from collapsing to `{}`. The chords are\n * emitted as plain data and the carried key, when present, as its own data.\n *\n * @returns The chord data sequence and the carried key, if any.\n */\n toJSON(): { chords: ChordData[]; key: { scale: KeyScale; tonic: NoteData } | undefined } {\n return {\n chords: this.#chords.map((chord) => chord.data),\n key: this.#key?.toJSON(),\n };\n }\n\n /** Resolve the key for an analysis method: explicit first, then carried. */\n #resolveKey(key?: Key): Key {\n const resolved = key ?? this.#key;\n if (resolved === undefined) {\n throw new Error('progression has no key context; pass a Key or attach one with withKey()');\n }\n return resolved;\n }\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport { isScaleTone, nearestScaleTone } from '../scale/index.js';\nimport type { ChordTimeline } from '../timeline/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * A transformation applicable to a motif cell.\n *\n * @category Composition\n */\nexport type MotifTransform =\n | 'transposeDiatonic'\n | 'transposeChromatic'\n | 'invert'\n | 'retrograde'\n | 'augment'\n | 'diminish'\n | 'sequence';\n\n/**\n * A single note within a motif cell.\n *\n * @category Composition\n */\nexport type MotifNote = {\n pitch: number;\n startBeat: number;\n durationBeat: number;\n};\n\n/**\n * A short melodic cell.\n *\n * @category Composition\n */\nexport type MotifCell = {\n notes: MotifNote[];\n};\n\n/**\n * Melodic contour shape for {@link generateMotif}.\n *\n * @category Composition\n */\nexport type MotifContour = 'arch' | 'ascending' | 'descending' | 'wave';\n\n/**\n * Options controlling {@link generateMotif}.\n *\n * @category Composition\n */\nexport type GenerateMotifOptions = {\n key: KeyScale;\n chord?: Chord | null;\n bars: number;\n /**\n * Melodic contour shape the line follows.\n *\n * @defaultValue `'arch'`\n */\n contour?: MotifContour;\n /**\n * Probability in [0, 1] that a note is nudged by a single diatonic step. The\n * nudge direction is balanced (up or down with equal odds), so it adds\n * variety without biasing the line off its contour. Default 0, which\n * reproduces the requested contour exactly (no drift, tails return to tonic).\n *\n * @defaultValue 0\n */\n jitter?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/**\n * Smallest span, in beats, treated as a distinct tile step. A positive but\n * near-zero cell span is clamped to this so tiling cannot stall.\n */\nconst MIN_TILE_SPAN = 1 / 256;\n\n/** Nearest in-scale pitch strictly above `pitch`. */\nfunction upScaleTone(pitch: number, key: KeyScale): number {\n for (let d = 1; d <= 12; d += 1) {\n if (isScaleTone(pitch + d, key)) {\n return pitch + d;\n }\n }\n return pitch + 12;\n}\n\n/** Nearest in-scale pitch strictly below `pitch`. */\nfunction downScaleTone(pitch: number, key: KeyScale): number {\n for (let d = 1; d <= 12; d += 1) {\n if (isScaleTone(pitch - d, key)) {\n return pitch - d;\n }\n }\n return pitch - 12;\n}\n\n/** Shift a pitch by a number of diatonic scale degrees. */\nfunction stepDiatonic(pitch: number, degrees: number, key: KeyScale): number {\n let p = nearestScaleTone(pitch, key);\n const steps = Math.abs(Math.trunc(degrees));\n for (let i = 0; i < steps; i += 1) {\n p = degrees >= 0 ? upScaleTone(p, key) : downScaleTone(p, key);\n }\n return p;\n}\n\n/** Nearest chord tone to `pitch`, preferring the lower pitch on a tie. */\nfunction nearestChordTone(pitch: number, chord: Chord): number {\n const pcs = chordPitchClasses(chord);\n for (let d = 0; d <= 12; d += 1) {\n if (pcs.includes(pitchClass(pitch - d))) {\n return pitch - d;\n }\n if (pcs.includes(pitchClass(pitch + d))) {\n return pitch + d;\n }\n }\n return pitch;\n}\n\n/** Earliest onset in a cell; the time origin for timing transforms. */\nfunction cellOrigin(notes: MotifNote[]): number {\n return notes.length === 0 ? 0 : Math.min(...notes.map((n) => n.startBeat));\n}\n\n/** Total beat span covered by a cell (from first onset to last offset). */\nfunction cellSpan(cell: MotifCell): number {\n if (cell.notes.length === 0) {\n return 0;\n }\n const start = cellOrigin(cell.notes);\n const end = Math.max(...cell.notes.map((n) => n.startBeat + n.durationBeat));\n return end - start;\n}\n\nfunction clone(cell: MotifCell): MotifCell {\n return { notes: cell.notes.map((n) => ({ ...n })) };\n}\n\n/** Deterministic 32-bit PRNG in [0, 1). */\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Diatonic scale-degree offsets shaping a contour of `count` notes. */\nfunction contourOffsets(contour: MotifContour, count: number): number[] {\n const offsets: number[] = [];\n for (let i = 0; i < count; i += 1) {\n switch (contour) {\n case 'ascending':\n offsets.push(i);\n break;\n case 'descending':\n offsets.push(-i);\n break;\n case 'arch':\n // Symmetric rise-and-fall: a palindrome that starts and ends on the\n // tonic (offset 0) for both odd and even lengths.\n offsets.push(Math.min(i, count - 1 - i));\n break;\n case 'wave':\n offsets.push([0, 1, 0, -1][i % 4] ?? 0);\n break;\n }\n }\n return offsets;\n}\n\n/**\n * Generate a short seed motif over `bars`.\n *\n * The melody follows the requested contour in diatonic steps from the tonic,\n * snapped to the key. When a chord is supplied, notes landing on bar downbeats\n * are pulled to the nearest chord tone. An optional `jitter` adds balanced\n * per-note variation without biasing the contour; it is off by default, so the\n * contour is reproduced exactly. Output is deterministic for a given seed.\n *\n * @param opts Key, optional chord, length, contour, jitter, and seed.\n * @returns The generated motif cell.\n *\n * @example\n * ```ts\n * import { generateMotif, majorKey } from '@libraz/libcantus';\n * const cell = generateMotif({ key: majorKey(0), bars: 2, contour: 'arch' });\n * // cell.notes is a deterministic MotifCell (seed defaults to 0)\n * ```\n *\n * @category Composition\n */\nexport function generateMotif(opts: GenerateMotifOptions): MotifCell {\n const contour = opts.contour ?? 'arch';\n const bars = Math.max(1, Math.trunc(opts.bars));\n const totalBeats = bars * 4;\n const noteCount = Math.max(3, bars * 2);\n const beatsPerNote = totalBeats / noteCount;\n const rng = mulberry32(opts.seed ?? 0);\n const jitterProb = Math.min(1, Math.max(0, opts.jitter ?? 0));\n const tonic = pitchClass(opts.key.rootPc) + 60;\n const offsets = contourOffsets(contour, noteCount);\n\n const notes: MotifNote[] = [];\n for (let i = 0; i < noteCount; i += 1) {\n // Opt-in, direction-balanced jitter: disabled by default so the contour is\n // preserved exactly. When enabled it nudges up or down with equal odds,\n // avoiding the upward bias that used to drift arch/wave tails off the tonic.\n let jitter = 0;\n if (jitterProb > 0 && rng() < jitterProb) {\n jitter = rng() < 0.5 ? 1 : -1;\n }\n let pitch = stepDiatonic(tonic, (offsets[i] ?? 0) + jitter, opts.key);\n const startBeat = i * beatsPerNote;\n if (opts.chord && startBeat % 4 === 0) {\n pitch = nearestChordTone(pitch, opts.chord);\n }\n notes.push({ pitch, startBeat, durationBeat: beatsPerNote });\n }\n return { notes };\n}\n\n/**\n * Apply a transformation to a motif cell.\n *\n * `invert` reflects pitches about the first note (chromatic, self-inverse);\n * `retrograde` mirrors onsets about the cell span, preserving rests (self-inverse);\n * `augment`/`diminish` scale time by `amount ?? 2` and its reciprocal;\n * `transposeChromatic` adds `amount` semitones; `transposeDiatonic` shifts by\n * `amount` scale degrees when a `key` is given, or — with no `key` — falls back\n * to a chromatic shift of `amount` semitones; `sequence` appends a shifted copy\n * (by `amount` diatonic degrees with a `key`, or by `amount` semitones without\n * one, since it delegates to `transposeDiatonic`).\n *\n * @param cell The cell to transform.\n * @param t The transformation.\n * @param amount Optional parameter (semitones, degrees, or time factor).\n * @param key Key context for the diatonic transforms; without it,\n * `transposeDiatonic` and `sequence` shift chromatically by semitones.\n * @returns The transformed cell.\n *\n * @example\n * ```ts\n * import { generateMotif, transformMotif, majorKey } from '@libraz/libcantus';\n * const cell = generateMotif({ key: majorKey(0), bars: 1 });\n * const inverted = transformMotif(cell, 'invert');\n * ```\n *\n * @category Composition\n */\nexport function transformMotif(\n cell: MotifCell,\n t: MotifTransform,\n amount?: number,\n key?: KeyScale,\n): MotifCell {\n const notes = cell.notes;\n switch (t) {\n case 'transposeChromatic': {\n const semis = amount ?? 0;\n return { notes: notes.map((n) => ({ ...n, pitch: n.pitch + semis })) };\n }\n case 'transposeDiatonic': {\n const degrees = amount ?? 1;\n return {\n notes: notes.map((n) => ({\n ...n,\n // With a key, shift by scale degrees; without one, fall back to a\n // chromatic shift of `degrees` semitones.\n pitch: key ? stepDiatonic(n.pitch, degrees, key) : n.pitch + degrees,\n })),\n };\n }\n case 'invert': {\n const pivot = notes[0]?.pitch ?? 0;\n return { notes: notes.map((n) => ({ ...n, pitch: 2 * pivot - n.pitch })) };\n }\n case 'retrograde': {\n if (notes.length === 0) {\n return { notes: [] };\n }\n const start = cellOrigin(notes);\n const end = Math.max(...notes.map((n) => n.startBeat + n.durationBeat));\n return {\n notes: notes.map((n) => ({\n pitch: n.pitch,\n startBeat: start + (end - (n.startBeat + n.durationBeat)),\n durationBeat: n.durationBeat,\n })),\n };\n }\n case 'augment':\n return scaleTime(cell, amount ?? 2);\n case 'diminish':\n return scaleTime(cell, 1 / (amount ?? 2));\n case 'sequence': {\n const degrees = amount ?? 2;\n const span = cellSpan(cell);\n // Delegates to transposeDiatonic: a diatonic shift when `key` is given,\n // otherwise a chromatic shift of `degrees` semitones.\n const copy = transformMotif(cell, 'transposeDiatonic', degrees, key);\n const shifted = copy.notes.map((n) => ({ ...n, startBeat: n.startBeat + span }));\n return { notes: [...clone(cell).notes, ...shifted] };\n }\n }\n}\n\n/** Scale a cell's timing about its origin by `factor`. */\nfunction scaleTime(cell: MotifCell, factor: number): MotifCell {\n const origin = cellOrigin(cell.notes);\n return {\n notes: cell.notes.map((n) => ({\n pitch: n.pitch,\n startBeat: origin + (n.startBeat - origin) * factor,\n durationBeat: n.durationBeat * factor,\n })),\n };\n}\n\n/**\n * Lay a motif across `bars` and snap it to a chord timeline.\n *\n * The cell is tiled back-to-back to fill the requested span; each note is then\n * pulled to the nearest chord tone of the segment sounding at its onset, so the\n * developed line spells the underlying harmony.\n *\n * @param cell The source motif.\n * @param timeline Chord segments to snap against.\n * @param key Key context (used to keep snapped pitches sensible).\n * @param bars Number of four-beat bars to fill.\n * @returns The developed, harmony-aware cell.\n *\n * @example\n * ```ts\n * import { chordTimelineFromChords, developMotif, generateMotif, majorKey } from '@libraz/libcantus';\n * const key = majorKey(0);\n * const timeline = chordTimelineFromChords([{ rootPc: 0, quality: 'maj', startBeat: 0 }], 8);\n * const developed = developMotif(generateMotif({ key, bars: 1 }), timeline, key, 2);\n * ```\n *\n * @category Composition\n */\nexport function developMotif(\n cell: MotifCell,\n timeline: ChordTimeline,\n key: KeyScale,\n bars: number,\n): MotifCell {\n const span = cellSpan(cell);\n const totalBeats = Math.max(1, Math.trunc(bars)) * 4;\n const origin = cellOrigin(cell.notes);\n const out: MotifNote[] = [];\n\n if (span <= 0) {\n return clone(cell);\n }\n\n // Clamp a degenerate near-zero span so the tile count stays finite, and step\n // the offset multiplicatively so rounding error cannot accumulate over tiles.\n const tileSpan = Math.max(span, MIN_TILE_SPAN);\n const tileCount = Math.ceil(totalBeats / tileSpan);\n for (let k = 0; k < tileCount; k += 1) {\n const offset = k * tileSpan;\n for (const n of cell.notes) {\n const startBeat = offset + (n.startBeat - origin);\n if (startBeat >= totalBeats) {\n continue;\n }\n const chord = timeline.at(startBeat);\n let pitch = n.pitch;\n if (chord) {\n const isMember = chordPitchClasses(chord).includes(pitchClass(pitch));\n pitch = isMember ? pitch : nearestChordTone(pitch, chord);\n } else {\n pitch = nearestScaleTone(pitch, key);\n }\n out.push({ pitch, startBeat, durationBeat: n.durationBeat });\n }\n }\n return { notes: out };\n}\n","import type { ChordQuality } from '../chord/index.js';\nimport { diatonicTriad } from '../chord/index.js';\nimport { scaleTonesInDegreeOrder } from '../scale/index.js';\nimport type { KeyScale } from '../types.js';\n\n/**\n * Broad production style a progression preset suits.\n *\n * @category Composition\n */\nexport type ProgStyle = 'minimal' | 'dance' | 'idol' | 'rock';\n\n/**\n * Harmonic-function role of a progression as a whole.\n *\n * @category Composition\n */\nexport type ProgFunction = 'loop' | 'tensionBuild' | 'cadenceStrong' | 'stable';\n\n/**\n * A named chord-progression preset expressed in scale degrees.\n *\n * @category Composition\n */\nexport type ProgressionPreset = {\n id: string;\n name: string;\n degrees: number[];\n functional: ProgFunction;\n styles: ProgStyle[];\n};\n\n/**\n * A chord placed on the timeline by {@link generateProgression}.\n *\n * @category Composition\n */\nexport type GeneratedChord = {\n rootPc: number;\n quality: ChordQuality;\n startBeat: number;\n bassPc?: number;\n /** 0-based scale degree of the chord root, when known. */\n degree?: number;\n /** True when the chord is a secondary dominant tonicizing another degree. */\n secondaryDominant?: boolean;\n};\n\n/**\n * Options controlling {@link generateProgression}.\n *\n * @category Composition\n */\nexport type GenerateProgressionOptions = {\n key: KeyScale;\n style: ProgStyle;\n bars: number;\n presetId?: string;\n ext?: ChordQuality | 'auto';\n reharmonize?: boolean;\n /**\n * Seed for the deterministic preset choice and reharmonization.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nconst PRESETS: ProgressionPreset[] = [\n {\n id: 'fourChordPop',\n name: 'Four Chord Pop',\n degrees: [0, 4, 5, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'pop1',\n name: 'Pop 1',\n degrees: [0, 5, 3, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'axis',\n name: 'Axis',\n degrees: [5, 3, 0, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol', 'rock'],\n },\n {\n id: 'pop2',\n name: 'Pop 2',\n degrees: [3, 0, 4, 5],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'classic',\n name: 'Classic',\n degrees: [0, 3, 4, 0],\n functional: 'cadenceStrong',\n styles: ['dance', 'idol', 'rock'],\n },\n {\n id: 'pop3',\n name: 'Pop 3',\n degrees: [0, 3, 5, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'royalRoad',\n name: 'Royal Road',\n degrees: [3, 4, 2, 5],\n functional: 'tensionBuild',\n styles: ['dance', 'idol'],\n },\n {\n id: 'minor1',\n name: 'Minor 1',\n degrees: [5, 4, 3, 4],\n functional: 'tensionBuild',\n styles: ['idol', 'rock'],\n },\n {\n id: 'minor2',\n name: 'Minor 2',\n degrees: [5, 3, 4, 0],\n functional: 'tensionBuild',\n styles: ['idol', 'rock'],\n },\n {\n id: 'pop4',\n name: 'Pop 4',\n degrees: [0, 4, 2, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'pop5',\n name: 'Pop 5',\n degrees: [0, 2, 3, 4],\n functional: 'stable',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'rock1',\n name: 'Rock 1',\n degrees: [0, 10, 3, 0],\n functional: 'tensionBuild',\n styles: ['rock'],\n },\n {\n id: 'rock2',\n name: 'Rock 2',\n degrees: [0, 3, 10, 0],\n functional: 'tensionBuild',\n styles: ['rock'],\n },\n {\n id: 'extended4',\n name: 'Extended 4',\n degrees: [0, 4, 5, 2],\n functional: 'stable',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'minor3',\n name: 'Minor 3',\n degrees: [5, 0, 4, 3],\n functional: 'loop',\n styles: ['dance', 'idol'],\n },\n {\n id: 'aeolianPop',\n name: 'Aeolian Pop',\n degrees: [5, 8, 10, 0],\n functional: 'tensionBuild',\n styles: ['minimal', 'dance', 'idol', 'rock'],\n },\n {\n id: 'animeHighEnergy1',\n name: 'Anime High Energy 1',\n degrees: [5, 2, 3, 0],\n functional: 'loop',\n styles: ['dance', 'idol'],\n },\n {\n id: 'jazzPop',\n name: 'Jazz Pop',\n degrees: [1, 4, 0, 5],\n functional: 'cadenceStrong',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'animeHighEnergy2',\n name: 'Anime High Energy 2',\n degrees: [5, 1, 4, 0],\n functional: 'cadenceStrong',\n styles: ['dance', 'idol'],\n },\n {\n id: 'cityPop',\n name: 'City Pop',\n degrees: [0, 5, 1, 4],\n functional: 'stable',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'extended5',\n name: 'Extended 5',\n degrees: [0, 4, 5, 2, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'neapolitanPop',\n name: 'Neapolitan Pop',\n degrees: [5, 12, 13, 4, 0],\n functional: 'cadenceStrong',\n styles: ['minimal', 'dance', 'idol'],\n },\n];\n\n/** Chromatic semitone offset from the tonic for borrowed (non-diatonic) degrees. */\nconst BORROWED_OFFSET: Record<number, number> = {\n 8: 8, // bVI\n 10: 10, // bVII\n 11: 3, // bIII\n 12: 5, // iv\n 13: 1, // bII\n 14: 6, // #IV\n};\n\n/**\n * All built-in progression presets.\n *\n * @category Composition\n */\nexport function progressions(): ProgressionPreset[] {\n return PRESETS.map((p) => ({ ...p, degrees: [...p.degrees], styles: [...p.styles] }));\n}\n\n/**\n * Presets whose style list includes the given style.\n *\n * @category Composition\n */\nexport function progressionsByStyle(style: ProgStyle): ProgressionPreset[] {\n return progressions().filter((p) => p.styles.includes(style));\n}\n\n/** Deterministic 32-bit PRNG producing a float in [0, 1). */\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Root pitch class of a scale degree in the given key, including borrowed degrees. */\nfunction degreeToRootPc(degree: number, key: KeyScale): number {\n if (degree >= 0 && degree <= 6) {\n const tones = scaleTonesInDegreeOrder(key);\n return tones.length > 0 ? (tones[degree % tones.length] ?? key.rootPc % 12) : key.rootPc % 12;\n }\n const offset = BORROWED_OFFSET[degree] ?? 0;\n return ((((key.rootPc % 12) + offset) % 12) + 12) % 12;\n}\n\n/**\n * Diatonic (or borrowed) triad quality of a degree in the given key.\n *\n * Diatonic degrees (0-6) take their scale-correct triad quality, so non-major\n * keys yield diatonic chords. Borrowed degrees keep their fixed chromatic\n * qualities (`#IV` diminished, `iv` minor, the rest major).\n */\nfunction autoQuality(degree: number, key: KeyScale): ChordQuality {\n if (degree >= 0 && degree <= 6) {\n return diatonicTriad(degree, key).quality;\n }\n if (degree === 14) {\n return 'dim';\n }\n if (degree === 12) {\n return 'min';\n }\n return 'maj';\n}\n\n/**\n * Generate a chord progression laid out one chord per bar.\n *\n * A preset is chosen by `presetId` when given, otherwise deterministically from\n * the presets matching `style`, seeded by `seed`. An unknown `presetId` is a\n * caller error and throws rather than silently falling back to a random preset.\n * The preset's degrees cycle to\n * fill `bars`; each bar is four beats, so `startBeat` is `barIndex * 4`. Chord\n * roots come from the key's diatonic scale-degree mapping. When `ext` is\n * omitted or `'auto'`, each chord takes its diatonic triad quality; otherwise\n * `ext` is forced on every chord. When `reharmonize` is set, some chords are\n * deterministically replaced with the secondary dominant (V7) of the following\n * chord, flagged with `secondaryDominant`.\n *\n * @param opts Generation options.\n * @returns One chord per bar in timeline order.\n * @throws If `presetId` is given but does not match any built-in preset.\n *\n * @example\n * ```ts\n * import { generateProgression, majorKey } from '@libraz/libcantus';\n * const chords = generateProgression({ key: majorKey(0), style: 'dance', bars: 4 });\n * // Deterministic for a given seed (defaults to 0); one GeneratedChord per bar.\n * ```\n *\n * @category Composition\n */\nexport function generateProgression(opts: GenerateProgressionOptions): GeneratedChord[] {\n const seed = opts.seed ?? 0;\n let preset: ProgressionPreset | undefined;\n if (opts.presetId !== undefined) {\n preset = PRESETS.find((p) => p.id === opts.presetId);\n if (preset === undefined) {\n throw new Error(`Unknown progression preset: ${opts.presetId}`);\n }\n }\n if (preset === undefined) {\n const pool = PRESETS.filter((p) => p.styles.includes(opts.style));\n const candidates = pool.length > 0 ? pool : PRESETS;\n const rng = mulberry32(seed);\n const index = Math.floor(rng() * candidates.length) % candidates.length;\n preset = candidates[index] ?? PRESETS[0];\n }\n const degrees = preset?.degrees ?? [0];\n const chords: GeneratedChord[] = [];\n for (let bar = 0; bar < opts.bars; bar += 1) {\n const degree = degrees[bar % degrees.length] ?? 0;\n const quality =\n opts.ext !== undefined && opts.ext !== 'auto' ? opts.ext : autoQuality(degree, opts.key);\n const chord: GeneratedChord = {\n rootPc: degreeToRootPc(degree, opts.key),\n quality,\n startBeat: bar * 4,\n degree: degree >= 0 && degree <= 6 ? degree : undefined,\n };\n chords.push(chord);\n }\n\n if (opts.reharmonize) {\n const tonicPc = (((opts.key.rootPc % 12) + 12) % 12) as number;\n const rrng = mulberry32((seed ^ 0x9e3779b9) >>> 0);\n for (let i = 0; i < chords.length - 1; i += 1) {\n const cur = chords[i];\n const next = chords[i + 1];\n if (!cur || !next) {\n continue;\n }\n const domRoot = (next.rootPc + 7) % 12;\n const targetsTonic = (next.rootPc - tonicPc + 12) % 12 === 0;\n const alreadySecondary = cur.rootPc === domRoot && cur.quality === 'dom7';\n // A secondary dominant inserted at i-1 resolves onto this chord; replacing\n // it here would orphan that dominant.\n const isResolutionTarget = chords[i - 1]?.secondaryDominant === true;\n if (targetsTonic || alreadySecondary || isResolutionTarget) {\n continue;\n }\n if (rrng() < 0.5) {\n chords[i] = {\n rootPc: domRoot,\n quality: 'dom7',\n startBeat: cur.startBeat,\n secondaryDominant: true,\n };\n }\n }\n }\n\n return chords;\n}\n","/**\n * Deterministic rhythm generation over a metric grid.\n *\n * Builds a fixed-resolution grid across one or more bars of a time signature\n * and decides, per grid slot, whether it becomes a note onset. Onset\n * probability follows the metric-accent hierarchy from the `meter` module, so\n * strong positions (downbeats, secondary pulses) are favored over weak\n * off-pulse subdivisions. Given a seed the output is fully reproducible.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention.\n */\n\nimport { beatsPerBar, metricWeight, type TimeSignature } from '../meter/index.js';\nimport { createRng } from '../random/index.js';\n\n/**\n * A single rhythmic note: an onset position and how long it sounds.\n *\n * @category Rhythm & Meter\n */\nexport type RhythmEvent = {\n /** Onset position in quarter-note beats, absolute from the start of the span. */\n position: number;\n /** Duration in quarter-note beats, extending to the next onset. */\n duration: number;\n};\n\n/**\n * Options controlling {@link generateRhythm}.\n *\n * @category Rhythm & Meter\n */\nexport type RhythmOptions = {\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n /**\n * Number of bars to generate.\n *\n * @defaultValue 1\n */\n bars?: number;\n /**\n * Grid resolution as the number of equal grid steps per quarter-note beat.\n * The default of 2 yields an eighth-note grid; 4 yields a sixteenth-note\n * grid, 3 an eighth-note triplet grid, and so on.\n *\n * @defaultValue 2\n */\n subdivision?: number;\n /**\n * Overall onset density in [0, 1]. Scales the per-slot onset probability, so\n * higher values fill more grid slots. Values outside [0, 1] are clamped into\n * range.\n *\n * @defaultValue 0.5\n */\n density?: number;\n};\n\nconst DEFAULT_SUBDIVISION = 2;\nconst DEFAULT_DENSITY = 0.5;\nconst DEFAULT_BARS = 1;\n\n/**\n * Map a metric weight (0–3 from {@link metricWeight}) to a base onset\n * probability before density scaling. Strong positions are much more likely to\n * carry an onset than weak ones; the curve is intentionally small and explicit\n * so its behavior is easy to inspect and test.\n *\n * @param weight The metric weight, 0 (off-pulse) to 3 (downbeat).\n * @returns A base onset probability in [0, 1].\n * @category Rhythm & Meter\n */\nexport function onsetWeightCurve(weight: number): number {\n switch (weight) {\n case 3:\n return 1;\n case 2:\n return 0.8;\n case 1:\n return 0.55;\n default:\n return 0.25;\n }\n}\n\n/**\n * Generate a deterministic rhythmic pattern over `bars` bars of a time\n * signature. A grid is built at the chosen subdivision; each slot becomes an\n * onset with a probability derived from its metric weight scaled by `density`\n * and sampled from the seeded PRNG. Every bar's downbeat is always an onset, so\n * a pattern of any length has a reliable pulse independent of the seed. Each\n * event's duration extends to the next onset, and the last event extends to the\n * end of the span. `density` is clamped to [0, 1].\n *\n * @param ts The time signature.\n * @param opts Generation options.\n * @returns Onset events sorted by position, non-overlapping, covering the span.\n * @example\n * ```ts\n * import { parseTimeSignature, generateRhythm } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * generateRhythm(ts, { seed: 42, density: 0.6 }); // onset events over one bar\n * ```\n * @category Rhythm & Meter\n */\nexport function generateRhythm(ts: TimeSignature, opts: RhythmOptions = {}): RhythmEvent[] {\n const seed = opts.seed ?? 0;\n const bars = opts.bars ?? DEFAULT_BARS;\n const subdivision = opts.subdivision ?? DEFAULT_SUBDIVISION;\n const density = Math.min(1, Math.max(0, opts.density ?? DEFAULT_DENSITY));\n\n const barBeats = beatsPerBar(ts);\n const spanBeats = barBeats * bars;\n const step = 1 / subdivision;\n const slotCount = Math.round(spanBeats * subdivision);\n const slotsPerBar = Math.round(barBeats * subdivision);\n const rng = createRng(seed);\n\n const positions: number[] = [];\n for (let i = 0; i < slotCount; i += 1) {\n const position = i * step;\n // Force every bar's downbeat so the pulse is reliable regardless of seed.\n if (i % slotsPerBar === 0) {\n positions.push(position);\n continue;\n }\n const weight = metricWeight(position, ts);\n const probability = onsetWeightCurve(weight) * density;\n if (rng.prob(probability)) {\n positions.push(position);\n }\n }\n\n const events: RhythmEvent[] = [];\n for (let i = 0; i < positions.length; i += 1) {\n const position = positions[i] ?? 0;\n const nextPosition = positions[i + 1] ?? spanBeats;\n events.push({ position, duration: nextPosition - position });\n }\n return events;\n}\n\n/**\n * Onset density of a generated pattern: the mean number of onsets per bar.\n *\n * @param events Events from {@link generateRhythm}.\n * @param ts The time signature.\n * @returns The onset count divided by the number of bars the events span.\n * @category Rhythm & Meter\n */\nexport function rhythmDensity(events: RhythmEvent[], ts: TimeSignature): number {\n if (events.length === 0) {\n return 0;\n }\n const last = events[events.length - 1];\n const spanBeats = (last?.position ?? 0) + (last?.duration ?? 0);\n const bars = spanBeats / beatsPerBar(ts);\n return bars > 0 ? events.length / bars : 0;\n}\n","/**\n * Tuning and microtonality: frequency conversion, cents, arbitrary equal\n * temperaments (EDO), and just-intonation ratios.\n *\n * The rest of the library reasons in twelve-tone pitch classes, which is a\n * deliberate scope choice for tonal theory. This module is the escape hatch for\n * anyone who needs actual frequencies, cents, non-12 equal temperaments, or the\n * acoustic (just) tuning behind the tempered intervals.\n */\n\n/**\n * An equal-tempered tuning: a reference pitch and a number of equal divisions of\n * the octave. With `divisions === 12` a step index is an ordinary MIDI number.\n *\n * @category Pitch & Intervals\n */\nexport type Tuning = {\n /** Step index (MIDI number when `divisions` is 12) whose frequency is `refFreq`. */\n refStep: number;\n /** Frequency in Hz of `refStep`. */\n refFreq: number;\n /** Equal divisions of the octave (12 standard; e.g. 19 or 31 for microtonal). */\n divisions: number;\n};\n\n/**\n * Standard twelve-tone equal temperament, A4 (MIDI 69) = 440 Hz.\n *\n * @category Pitch & Intervals\n */\nexport const TWELVE_TET: Tuning = { refStep: 69, refFreq: 440, divisions: 12 };\n\n/**\n * Build an equal temperament with `n` divisions of the octave.\n *\n * @param n Divisions of the octave (e.g. 19, 24, 31).\n * @param refFreq Reference frequency in Hz (default 440).\n * @param refStep Step index of the reference (default 69).\n * @returns The tuning.\n * @example\n * ```ts\n * import { edo, frequencyOf } from '@libraz/libcantus';\n * const et19 = edo(19); // { refStep: 69, refFreq: 440, divisions: 19 }\n * frequencyOf(70, et19); // one 19-EDO step above A4\n * ```\n * @category Pitch & Intervals\n */\nexport function edo(n: number, refFreq = 440, refStep = 69): Tuning {\n return { refStep, refFreq, divisions: n };\n}\n\n/**\n * Frequency in Hz of a step index under a tuning.\n *\n * @param step Step index (a MIDI number under 12-EDO).\n * @param tuning The tuning (default 12-TET).\n * @returns The frequency in Hz.\n * @example\n * ```ts\n * import { frequencyOf } from '@libraz/libcantus';\n * frequencyOf(69); // 440 (A4 in 12-TET)\n * frequencyOf(60); // middle C in Hz\n * ```\n * @category Pitch & Intervals\n */\nexport function frequencyOf(step: number, tuning: Tuning = TWELVE_TET): number {\n return tuning.refFreq * 2 ** ((step - tuning.refStep) / tuning.divisions);\n}\n\n/**\n * Nearest step index to a frequency under a tuning (the inverse of\n * {@link frequencyOf}, rounded).\n *\n * @param freq Frequency in Hz.\n * @param tuning The tuning (default 12-TET).\n * @returns The nearest step index.\n * @category Pitch & Intervals\n */\nexport function nearestStep(freq: number, tuning: Tuning = TWELVE_TET): number {\n return Math.round(tuning.refStep + tuning.divisions * Math.log2(freq / tuning.refFreq));\n}\n\n/**\n * Interval in cents between two frequencies.\n *\n * @param a Lower/first frequency in Hz.\n * @param b Upper/second frequency in Hz.\n * @returns Cents from `a` to `b` (negative if `b` is lower).\n * @category Pitch & Intervals\n */\nexport function centsBetweenFreq(a: number, b: number): number {\n return 1200 * Math.log2(b / a);\n}\n\n/**\n * Cents spanned by a number of equal-temperament steps.\n *\n * @param steps Number of steps.\n * @param tuning The tuning (default 12-TET).\n * @returns The cents.\n * @category Pitch & Intervals\n */\nexport function centsOfSteps(steps: number, tuning: Tuning = TWELVE_TET): number {\n return (steps * 1200) / tuning.divisions;\n}\n\n/**\n * Cents of a frequency ratio, e.g. `ratioToCents(3, 2)` ≈ 701.955 for the just\n * perfect fifth.\n *\n * @param numerator Ratio numerator.\n * @param denominator Ratio denominator.\n * @returns The interval in cents.\n * @category Pitch & Intervals\n */\nexport function ratioToCents(numerator: number, denominator: number): number {\n return 1200 * Math.log2(numerator / denominator);\n}\n\n/**\n * Five-limit just-intonation ratios for the twelve interval classes above a\n * unison, indexed by semitone class (0..12).\n *\n * @category Pitch & Intervals\n */\nexport const JUST_RATIOS: Record<number, [number, number]> = {\n 0: [1, 1],\n 1: [16, 15],\n 2: [9, 8],\n 3: [6, 5],\n 4: [5, 4],\n 5: [4, 3],\n 6: [45, 32],\n 7: [3, 2],\n 8: [8, 5],\n 9: [5, 3],\n 10: [9, 5],\n 11: [15, 8],\n 12: [2, 1],\n};\n\n/**\n * Cents by which a five-limit just interval departs from its 12-TET tempering\n * (positive means the just interval is wider).\n *\n * @param semitoneClass Semitone class in [0, 12].\n * @returns The deviation in cents, or NaN if the class has no listed ratio.\n * @category Pitch & Intervals\n */\nexport function justDeviationCents(semitoneClass: number): number {\n const ratio = JUST_RATIOS[semitoneClass];\n if (!ratio) {\n return Number.NaN;\n }\n return ratioToCents(ratio[0], ratio[1]) - semitoneClass * 100;\n}\n"],"mappings":"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","names":["pitchClass","IntervalQuality","pitchClass","pitchClass","hasMajorThird","degreeNumber","EPS","NoteSafety","ReasonFlag","pitchClass","intervalAboveRoot","isChordMember","stepResolution","describe","pitchClass","EPS","pitchClass","EPS","pitchClass","EPS","pitchClass","pitchClass","DEFAULT_TS","EPS","SIXTEENTH","EIGHTH","choice","DEFAULT_TS","pitchClass","mod12","mod12","sameChord","LETTER_SEMITONES","mod12","mod7","pitchClass","pitchClass","mod12","pitchClass","mulberry32","mulberry32"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/meter/index.ts","../src/theory/scale/degrees.ts","../src/theory/scale/masks.ts","../src/theory/scale/key.ts","../src/theory/chord/index.ts","../src/core/interval/index.ts","../src/theory/counterpoint/index.ts","../src/theory/safety/index.ts","../src/analyze/functional/internal.ts","../src/analyze/functional/roman.ts","../src/analyze/functional/function.ts","../src/analyze/functional/borrowed.ts","../src/analyze/functional/cadence.ts","../src/analyze/detect/index.ts","../src/analyze/timeline/index.ts","../src/analyze/arrange/internal.ts","../src/analyze/arrange/tension.ts","../src/analyze/voice/index.ts","../src/analyze/arrange/tracks.ts","../src/core/pitch/index.ts","../src/core/random/index.ts","../src/core/tuning/index.ts","../src/generate/bass/index.ts","../src/generate/countermelody/index.ts","../src/generate/drums/internal.ts","../src/generate/drums/ghost.ts","../src/generate/drums/hihat.ts","../src/generate/drums/swing.ts","../src/generate/drums/beat.ts","../src/generate/drums/euclid.ts","../src/generate/drums/fills.ts","../src/generate/drums/hit.ts","../src/generate/drums/kick.ts","../src/generate/drums/percussion.ts","../src/generate/drums/index.ts","../src/generate/groove/index.ts","../src/theory/harmony/index.ts","../src/generate/harmonize/index.ts","../src/generate/motif/index.ts","../src/generate/progression/index.ts","../src/generate/reharmony/index.ts","../src/generate/rhythm/index.ts","../src/theory/chordscale/index.ts","../src/theory/spelling/index.ts","../src/theory/symbol/index.ts","../src/theory/voicing/internal.ts","../src/theory/voicing/satb.ts","../src/theory/voicing/leading.ts","../src/theory/voicing/styled.ts","../src/model/shared.ts","../src/model/note.ts","../src/model/progression.ts","../src/model/chord.ts","../src/model/interval.ts","../src/model/key.ts"],"sourcesContent":["export type {\n ArrangementAnalysis,\n ArrangementOptions,\n ArrangementTrack,\n Conflict,\n TensionPoint,\n TrackAnalysis,\n TrackRole,\n} from './analyze/arrange/index.js';\nexport { analyzeArrangement, tensionCurve } from './analyze/arrange/index.js';\nexport type { ChordMatch, KeyMatch } from './analyze/detect/index.js';\nexport { detectChord, detectChordBest, detectKey } from './analyze/detect/index.js';\nexport type {\n BorrowedSource,\n Cadence,\n ChordAnalysis,\n HarmonicFunction,\n} from './analyze/functional/index.js';\nexport {\n analyzeChord,\n borrowedSource,\n chordToRoman,\n detectCadence,\n functionOf,\n isBorrowedChord,\n isDiatonic,\n isMinorKey,\n parallelKey,\n romanToChord,\n secondaryDominant,\n} from './analyze/functional/index.js';\nexport type {\n CadenceHit,\n ChordSegment,\n ChordTimeline,\n ChordTimelineOptions,\n ChordTimelineResult,\n} from './analyze/timeline/index.js';\nexport {\n chordTimelineFromChords,\n chordTimelineFromNotes,\n detectCadences,\n} from './analyze/timeline/index.js';\nexport type { AnalyzedNote, TheoryLabel, VoiceNote } from './analyze/voice/index.js';\nexport { analyzeVoice } from './analyze/voice/index.js';\nexport {\n classifyInterval,\n IntervalQuality,\n isConsonantInterval,\n isPerfectInterval,\n} from './core/interval/index.js';\nexport type { BarPosition, TimeSignature } from './core/meter/index.js';\nexport {\n barPositionToBeat,\n beatsPerBar,\n beatToBarPosition,\n formatTimeSignature,\n isCompound,\n isStrongBeat,\n metricWeight,\n parseTimeSignature,\n pulsesPerBar,\n tuplet,\n} from './core/meter/index.js';\nexport type { Note as NoteData, SpelledInterval } from './core/pitch/index.js';\nexport {\n formatNote,\n midiToNote,\n noteToMidi,\n noteToPitchClass,\n parseNote,\n spelledInterval,\n} from './core/pitch/index.js';\nexport type { Rng } from './core/random/index.js';\nexport { createRng } from './core/random/index.js';\nexport type { Tuning } from './core/tuning/index.js';\nexport {\n centsBetweenFreq,\n centsOfSteps,\n edo,\n frequencyOf,\n JUST_RATIOS,\n justDeviationCents,\n nearestStep,\n ratioToCents,\n TWELVE_TET,\n} from './core/tuning/index.js';\nexport type { KeyScale, NoteEvent } from './core/types.js';\nexport type { BassLineOptions, BassSegment, BassStyle } from './generate/bass/index.js';\nexport { generateBassLine } from './generate/bass/index.js';\nexport type { CounterMelodyOptions } from './generate/countermelody/index.js';\nexport { generateCounterMelody } from './generate/countermelody/index.js';\nexport type {\n DrumHit,\n DrumRole,\n DrumsOptions,\n EuclideanKick,\n GrooveFeel,\n GrooveStyle,\n Section,\n} from './generate/drums/index.js';\nexport { generateDrums } from './generate/drums/index.js';\nexport type { GrooveSlot, GrooveTemplate, HumanizeOptions } from './generate/groove/index.js';\nexport { applyGrooveTemplate, extractGrooveTemplate, humanize } from './generate/groove/index.js';\nexport type {\n HarmonizeOptions,\n HarmonizeResult,\n MelodyNote,\n} from './generate/harmonize/index.js';\nexport { harmonizeMelody } from './generate/harmonize/index.js';\nexport type {\n MotifCell,\n MotifContour,\n MotifNote,\n MotifOptions,\n MotifTransform,\n} from './generate/motif/index.js';\nexport { developMotif, generateMotif, transformMotif } from './generate/motif/index.js';\nexport type {\n ChordSpan,\n ProgFunction,\n ProgressionOptions,\n ProgressionPreset,\n ProgStyle,\n} from './generate/progression/index.js';\nexport {\n generateProgression,\n progressions,\n progressionsByStyle,\n} from './generate/progression/index.js';\nexport type {\n BorrowedChord,\n SubstituteOptions,\n Substitution,\n SubstitutionType,\n} from './generate/reharmony/index.js';\nexport {\n modalInterchangePalette,\n negativeHarmonyMirror,\n substituteChord,\n} from './generate/reharmony/index.js';\nexport type { RhythmEvent, RhythmOptions } from './generate/rhythm/index.js';\nexport { generateRhythm, onsetWeightCurve, rhythmDensity } from './generate/rhythm/index.js';\nexport { Chord, Interval, Key, Note, Progression } from './model/index.js';\nexport type { Chord as ChordData, ChordQuality } from './theory/chord/index.js';\nexport {\n chordFromDegree,\n chordPitchClasses,\n chordQualities,\n chordToneRole,\n diatonicSeventh,\n diatonicTriad,\n makeChord,\n} from './theory/chord/index.js';\nexport type {\n ChordScaleMatch,\n ChordScaleReportEntry,\n ScaleChoice,\n} from './theory/chordscale/index.js';\nexport {\n availableTensions,\n avoidNotes,\n chordScaleReport,\n chordScales,\n scaleMatchesChord,\n scalesForChanges,\n} from './theory/chordscale/index.js';\nexport {\n createsHiddenParallelPerfect,\n createsParallelOctave,\n createsParallelPerfect,\n createsParallelUnison,\n createsVerticalDissonance,\n createsVoiceCrossing,\n createsVoiceOverlap,\n exceedsSpacing,\n isForbiddenMelodicLeap,\n isLeadingToneResolution,\n} from './theory/counterpoint/index.js';\nexport type { HarmonyRole, LockLevel, VoicedRole } from './theory/harmony/index.js';\nexport { roleOf } from './theory/harmony/index.js';\nexport type {\n SafetyProfile,\n SafetyQuery,\n SafetyResult,\n VoiceSnapshot,\n} from './theory/safety/index.js';\nexport {\n enumerateSafePitches,\n evaluateSafety,\n NoteSafety,\n ReasonFlag,\n} from './theory/safety/index.js';\nexport {\n BLUES_MASK,\n CHROMATIC_MASK,\n DORIAN_MASK,\n diatonicPitchClasses,\n HARMONIC_MINOR_MASK,\n isScaleTone,\n LOCRIAN_MASK,\n LYDIAN_MASK,\n MAJOR_MASK,\n MAJOR_PENTATONIC_MASK,\n MELODIC_MINOR_MASK,\n MINOR_PENTATONIC_MASK,\n MIXOLYDIAN_MASK,\n majorKey,\n maskFromOffsets,\n minorKey,\n NAMED_SCALES,\n NATURAL_MINOR_MASK,\n nearestScaleTone,\n OCTATONIC_HALF_WHOLE_MASK,\n OCTATONIC_WHOLE_HALF_MASK,\n PHRYGIAN_MASK,\n pitchToScaleDegree,\n scaleByName,\n scaleTonesInDegreeOrder,\n WHOLE_TONE_MASK,\n} from './theory/scale/index.js';\nexport {\n noteNames,\n spellChord,\n spellPitchClass,\n spellPitchClasses,\n spellScale,\n} from './theory/spelling/index.js';\nexport {\n formatChordSymbol,\n parseChordSymbol,\n transposeChordSymbol,\n} from './theory/symbol/index.js';\nexport type {\n StyledVoicingOptions,\n VoiceRange,\n VoicingOptions,\n VoicingStyle,\n} from './theory/voicing/index.js';\nexport {\n nextVoicing,\n SATB_RANGES,\n voiceChord,\n voiceChordStyled,\n voiceLeadingCost,\n voiceProgression,\n} from './theory/voicing/index.js';\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 */\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 additive grouping of the bar's main pulses, as the felt-beat\n * lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or\n * `[3, 2]` for 5/8. The entries must be positive integers summing to\n * {@link pulsesPerBar}. When present, the head pulse of each group (other\n * than the downbeat) is treated as a secondary strong pulse by\n * {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses\n * are weighted equally as flat, evenly divided pulses.\n */\n grouping?: number[];\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 bar: number;\n /** Quarter-note offset from the start of the bar. */\n beat: number;\n};\n\nconst EPS = 1e-9;\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\"`.\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.\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 const match = /^\\s*(\\d+)\\s*\\/\\s*(\\d+)\\s*$/.exec(text);\n if (!match) {\n throw new Error(`Invalid time signature: ${text}`);\n }\n const numerator = Number.parseInt(match[1] ?? '', 10);\n const denominator = Number.parseInt(match[2] ?? '', 10);\n if (numerator <= 0 || denominator <= 0) {\n throw new Error(`Invalid time signature: ${text}`);\n }\n return { numerator, denominator };\n}\n\n/**\n * Render a time signature as `\"n/d\"`.\n *\n * @category Rhythm & Meter\n */\nexport function formatTimeSignature(ts: TimeSignature): string {\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.\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 return ts.numerator % 3 === 0 && ts.numerator > 3;\n}\n\n/** Length of one denominator unit in quarter-note beats. */\nfunction unitBeats(ts: TimeSignature): number {\n return 4 / ts.denominator;\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 return ts.numerator * unitBeats(ts);\n}\n\n/** Length of one main pulse (a dotted value in compound meters) in quarter notes. */\nfunction pulseBeats(ts: TimeSignature): number {\n return isCompound(ts) ? 3 * unitBeats(ts) : unitBeats(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 return beatsPerBar(ts) / pulseBeats(ts);\n}\n\n/**\n * Whether `grouping` is a valid additive grouping for a bar of `pulses` main\n * pulses: a non-empty list of positive integers summing to `pulses`.\n */\nfunction isValidGrouping(grouping: number[], pulses: number): boolean {\n if (grouping.length === 0) {\n return false;\n }\n let sum = 0;\n for (const g of grouping) {\n if (!Number.isInteger(g) || g <= 0) {\n return false;\n }\n sum += g;\n }\n return sum === pulses;\n}\n\n/** Whether `pulseIndex` is the head pulse of one of the additive groups. */\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 * 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 ts The time signature.\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, ts: TimeSignature): BarPosition {\n const barLen = beatsPerBar(ts);\n const bar = Math.floor(beatInQuarters / barLen);\n return { bar, beat: beatInQuarters - bar * barLen };\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 ts The time signature.\n * @returns The absolute position in quarter-note beats.\n * @category Rhythm & Meter\n */\nexport function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number {\n return pos.bar * beatsPerBar(ts) + 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).\n *\n * @param beatInQuarters Absolute or in-bar quarter-note position.\n * @param ts The time signature.\n * @returns The metric weight (0–3).\n * @throws If `ts.grouping` is present but is not a positive-integer list\n * summing to {@link pulsesPerBar}.\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, ts: TimeSignature): number {\n const { beat } = beatToBarPosition(beatInQuarters, ts);\n const pulse = pulseBeats(ts);\n if (!isMultiple(beat, pulse)) {\n return 0;\n }\n const pulses = pulsesPerBar(ts);\n const pulseIndex = Math.round(beat / pulse) % pulses;\n if (pulseIndex === 0) {\n return 3;\n }\n const grouping = ts.grouping;\n if (grouping !== undefined) {\n if (!isValidGrouping(grouping, pulses)) {\n throw new Error(\n `Invalid grouping [${grouping.join(', ')}] for ${formatTimeSignature(ts)}: ` +\n `entries must be positive integers summing to ${pulses}`,\n );\n }\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 or in-bar quarter-note position.\n * @param ts The time signature.\n * @returns True on strong beats.\n * @category Rhythm & Meter\n */\nexport function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolean {\n return metricWeight(beatInQuarters, ts) >= 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 if (!Number.isInteger(count) || count <= 0) {\n throw new Error(`Invalid tuplet count: ${count}`);\n }\n return new Array<number>(count).fill(totalBeats / count);\n}\n","import type { KeyScale } from '../../core/types.js';\n\n/** Reduce a pitch (or pitch class) to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/** Scale offset of a pitch relative to the key root, in [0, 11]. */\nfunction scaleOffset(pitch: number, key: KeyScale): number {\n return (pitchClass(pitch) - pitchClass(key.rootPc) + 12) % 12;\n}\n\n/**\n * Test whether a pitch belongs to the scale.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param key The key/scale to test against.\n * @returns True if the pitch class is a member of the scale.\n *\n * @example\n * ```ts\n * import { majorKey, isScaleTone } from '@libraz/libcantus';\n * const key = majorKey(0); // C major\n * isScaleTone(64, key); // true — E is in C major\n * isScaleTone(61, key); // false — C# is not\n * ```\n *\n * @category Scales\n */\nexport function isScaleTone(pitch: number, key: KeyScale): boolean {\n return ((key.modeMask12 >> scaleOffset(pitch, key)) & 1) === 1;\n}\n\n/**\n * Find the nearest MIDI pitch whose pitch class is in the scale.\n *\n * The search expands symmetrically outward from `pitch`. On a tie (equal\n * distance above and below) the lower pitch is returned.\n *\n * @param pitch MIDI pitch to snap.\n * @param key The key/scale to snap to.\n * @returns The nearest in-scale MIDI pitch.\n *\n * @category Scales\n */\nexport function nearestScaleTone(pitch: number, key: KeyScale): number {\n const base = Math.round(pitch);\n for (let distance = 0; distance < 12; distance += 1) {\n const lower = base - distance;\n if (isScaleTone(lower, key)) {\n return lower;\n }\n const higher = base + distance;\n if (isScaleTone(higher, key)) {\n return higher;\n }\n }\n return base;\n}\n\n/**\n * Get the 0-based scale degree of a pitch.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param key The key/scale to measure against.\n * @returns The 0-based degree, or -1 if the pitch is not in the scale.\n *\n * @category Scales\n */\nexport function pitchToScaleDegree(pitch: number, key: KeyScale): number {\n const offset = scaleOffset(pitch, key);\n if (((key.modeMask12 >> offset) & 1) === 0) {\n return -1;\n }\n let degree = 0;\n for (let n = 0; n < offset; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n degree += 1;\n }\n }\n return degree;\n}\n\n/**\n * List the pitch classes of a key's scale.\n *\n * @param key The key/scale to enumerate.\n * @returns The member pitch classes, sorted ascending in [0, 11].\n *\n * @category Scales\n */\nexport function diatonicPitchClasses(key: KeyScale): number[] {\n const root = pitchClass(key.rootPc);\n const pcs: number[] = [];\n for (let n = 0; n < 12; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n pcs.push((root + n) % 12);\n }\n }\n return pcs.sort((a, b) => a - b);\n}\n\n/**\n * List the pitch classes of a key's scale in ascending scale-degree order.\n *\n * Degree 0 is the root; degrees follow the mask bits in offset order rather\n * than sorted pitch-class order.\n *\n * @param key The key/scale to enumerate.\n * @returns The member pitch classes ordered by scale degree.\n *\n * @category Scales\n */\nexport function scaleTonesInDegreeOrder(key: KeyScale): number[] {\n const root = pitchClass(key.rootPc);\n const pcs: number[] = [];\n for (let n = 0; n < 12; n += 1) {\n if (((key.modeMask12 >> n) & 1) === 1) {\n pcs.push((root + n) % 12);\n }\n }\n return pcs;\n}\n","/**\n * Build a 12-bit mode mask from a list of semitone offsets above the root.\n *\n * Bit 0 (the root) is always set, enforcing the `KeyScale` invariant that the\n * root is a scale tone even when the offset list omits 0.\n *\n * @category Scales\n */\nexport function maskFromOffsets(offsets: readonly number[]): number {\n let mask = 1;\n for (const offset of offsets) {\n mask |= 1 << (((offset % 12) + 12) % 12);\n }\n return mask;\n}\n\n/**\n * Mode mask for the major (Ionian) scale: offsets {0, 2, 4, 5, 7, 9, 11}.\n *\n * @category Scales\n */\nexport const MAJOR_MASK = 0b101010110101;\n\n/**\n * Mode mask for the natural minor (Aeolian) scale: offsets {0, 2, 3, 5, 7, 8, 10}.\n *\n * @category Scales\n */\nexport const NATURAL_MINOR_MASK = 0b010110101101;\n\n/**\n * Harmonic minor: natural minor with a raised seventh — offsets {0,2,3,5,7,8,11}.\n *\n * @category Scales\n */\nexport const HARMONIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 8, 11]);\n\n/**\n * Ascending melodic minor: offsets {0,2,3,5,7,9,11}.\n *\n * @category Scales\n */\nexport const MELODIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 11]);\n\n/**\n * Dorian mode: offsets {0,2,3,5,7,9,10}.\n *\n * @category Scales\n */\nexport const DORIAN_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 10]);\n\n/**\n * Phrygian mode: offsets {0,1,3,5,7,8,10}.\n *\n * @category Scales\n */\nexport const PHRYGIAN_MASK = maskFromOffsets([0, 1, 3, 5, 7, 8, 10]);\n\n/**\n * Lydian mode: offsets {0,2,4,6,7,9,11}.\n *\n * @category Scales\n */\nexport const LYDIAN_MASK = maskFromOffsets([0, 2, 4, 6, 7, 9, 11]);\n\n/**\n * Mixolydian mode: offsets {0,2,4,5,7,9,10}.\n *\n * @category Scales\n */\nexport const MIXOLYDIAN_MASK = maskFromOffsets([0, 2, 4, 5, 7, 9, 10]);\n\n/**\n * Locrian mode: offsets {0,1,3,5,6,8,10}.\n *\n * @category Scales\n */\nexport const LOCRIAN_MASK = maskFromOffsets([0, 1, 3, 5, 6, 8, 10]);\n\n/**\n * Major pentatonic: offsets {0,2,4,7,9}.\n *\n * @category Scales\n */\nexport const MAJOR_PENTATONIC_MASK = maskFromOffsets([0, 2, 4, 7, 9]);\n\n/**\n * Minor pentatonic: offsets {0,3,5,7,10}.\n *\n * @category Scales\n */\nexport const MINOR_PENTATONIC_MASK = maskFromOffsets([0, 3, 5, 7, 10]);\n\n/**\n * Hexatonic blues scale: minor pentatonic plus the flat-fifth — {0,3,5,6,7,10}.\n *\n * @category Scales\n */\nexport const BLUES_MASK = maskFromOffsets([0, 3, 5, 6, 7, 10]);\n\n/**\n * Whole-tone scale: offsets {0,2,4,6,8,10}.\n *\n * @category Scales\n */\nexport const WHOLE_TONE_MASK = maskFromOffsets([0, 2, 4, 6, 8, 10]);\n\n/**\n * Octatonic (half-step first): offsets {0,1,3,4,6,7,9,10}.\n *\n * @category Scales\n */\nexport const OCTATONIC_HALF_WHOLE_MASK = maskFromOffsets([0, 1, 3, 4, 6, 7, 9, 10]);\n\n/**\n * Octatonic (whole-step first): offsets {0,2,3,5,6,8,9,11}.\n *\n * @category Scales\n */\nexport const OCTATONIC_WHOLE_HALF_MASK = maskFromOffsets([0, 2, 3, 5, 6, 8, 9, 11]);\n\n/**\n * Chromatic scale: all twelve pitch classes.\n *\n * @category Scales\n */\nexport const CHROMATIC_MASK = 0b111111111111;\n\n/**\n * Named scale masks addressable by {@link scaleByName}.\n *\n * @category Scales\n */\nexport const NAMED_SCALES: Record<string, number> = {\n major: MAJOR_MASK,\n ionian: MAJOR_MASK,\n naturalMinor: NATURAL_MINOR_MASK,\n aeolian: NATURAL_MINOR_MASK,\n harmonicMinor: HARMONIC_MINOR_MASK,\n melodicMinor: MELODIC_MINOR_MASK,\n dorian: DORIAN_MASK,\n phrygian: PHRYGIAN_MASK,\n lydian: LYDIAN_MASK,\n mixolydian: MIXOLYDIAN_MASK,\n locrian: LOCRIAN_MASK,\n majorPentatonic: MAJOR_PENTATONIC_MASK,\n minorPentatonic: MINOR_PENTATONIC_MASK,\n blues: BLUES_MASK,\n wholeTone: WHOLE_TONE_MASK,\n octatonicHalfWhole: OCTATONIC_HALF_WHOLE_MASK,\n octatonicWholeHalf: OCTATONIC_WHOLE_HALF_MASK,\n chromatic: CHROMATIC_MASK,\n};\n","import type { KeyScale } from '../../core/types.js';\nimport { MAJOR_MASK, NAMED_SCALES, NATURAL_MINOR_MASK } from './masks.js';\n\n/**\n * Build a `KeyScale` for a major key on the given root pitch class.\n *\n * @example\n * ```ts\n * import { majorKey } from '@libraz/libcantus';\n * const cMajor = majorKey(0); // C major: { rootPc: 0, modeMask12: MAJOR_MASK }\n * ```\n *\n * @category Scales\n */\nexport function majorKey(rootPc: number): KeyScale {\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: MAJOR_MASK };\n}\n\n/**\n * Build a `KeyScale` for a natural-minor key on the given root pitch class.\n *\n * @example\n * ```ts\n * import { minorKey } from '@libraz/libcantus';\n * const aMinor = minorKey(9); // A natural minor: { rootPc: 9, modeMask12: NATURAL_MINOR_MASK }\n * ```\n *\n * @category Scales\n */\nexport function minorKey(rootPc: number): KeyScale {\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: NATURAL_MINOR_MASK };\n}\n\n/**\n * Build a `KeyScale` from a named scale (see {@link NAMED_SCALES}).\n *\n * @param name The scale name, e.g. `'dorian'` or `'harmonicMinor'`.\n * @param rootPc The root pitch class.\n * @returns The key/scale.\n * @throws If the name is not a known scale.\n *\n * @example\n * ```ts\n * import { scaleByName } from '@libraz/libcantus';\n * const dDorian = scaleByName('dorian', 2); // D Dorian, rootPc 2\n * ```\n *\n * @category Scales\n */\nexport function scaleByName(name: string, rootPc: number): KeyScale {\n const mask = NAMED_SCALES[name];\n if (mask === undefined) {\n throw new Error(`Unknown scale: ${name}`);\n }\n return { rootPc: ((rootPc % 12) + 12) % 12, modeMask12: mask };\n}\n","import type { KeyScale } from '../../core/types.js';\nimport { scaleTonesInDegreeOrder } from '../scale/index.js';\n\n/**\n * Chord quality identifiers understood by the chord builder.\n *\n * @category Chords\n */\nexport type ChordQuality =\n | 'maj'\n | 'min'\n | 'dim'\n | 'aug'\n | 'maj7'\n | 'min7'\n | 'dom7'\n | 'dim7'\n | 'm7b5'\n | 'minMaj7'\n | 'aug7'\n | 'augMaj7'\n | 'majb5'\n | '6'\n | 'min6'\n | '6/9'\n | 'sus2'\n | 'sus4'\n | 'add9'\n | 'add11'\n | 'maj9'\n | 'min9'\n | 'dom9'\n | '7b9'\n | '7#9'\n | '7#11'\n | '7b13'\n | '11'\n | '13'\n | '5';\n\n/**\n * A bare spelled pitch used as an enharmonic hint: a diatonic letter\n * (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).\n * Mirrors the letter/alter half of the pitch module's `Note` without an octave.\n *\n * @category Chords\n */\nexport type PitchSpelling = {\n letter: number;\n alter: number;\n};\n\n/**\n * A chord expressed as a root pitch class plus semitone offsets.\n *\n * `rootSpelling`/`bassSpelling` are optional enharmonic hints recorded by\n * parsers (e.g. `parseChordSymbol('Bb7')`) so formatters can reproduce the\n * original spelling instead of defaulting to sharps. Consumers may ignore\n * them; a hint is only trusted when its pitch class still matches the\n * corresponding `rootPc`/`bassPc`.\n *\n * @category Chords\n */\nexport type Chord = {\n rootPc: number;\n quality: ChordQuality;\n intervals: number[];\n bassPc?: number;\n rootSpelling?: PitchSpelling;\n bassSpelling?: PitchSpelling;\n};\n\n/**\n * A chord positioned in time: a root pitch class and quality placed at a beat,\n * with optional harmonic-analysis hints. Serves as the neutral exchange record\n * between progression generators and timeline analysers.\n *\n * @category Composition\n */\nexport type ChordSpan = {\n rootPc: number;\n quality: ChordQuality;\n startBeat: number;\n bassPc?: number;\n /** 0-based scale degree of the chord root, when known. */\n degree?: number;\n /** True when the chord is a secondary dominant tonicizing another degree. */\n secondaryDominant?: boolean;\n};\n\n/** Semitone offsets from the root for each supported chord quality. */\nconst QUALITY_INTERVALS: Record<ChordQuality, number[]> = {\n maj: [0, 4, 7],\n min: [0, 3, 7],\n dim: [0, 3, 6],\n aug: [0, 4, 8],\n majb5: [0, 4, 6],\n maj7: [0, 4, 7, 11],\n min7: [0, 3, 7, 10],\n dom7: [0, 4, 7, 10],\n dim7: [0, 3, 6, 9],\n m7b5: [0, 3, 6, 10],\n minMaj7: [0, 3, 7, 11],\n aug7: [0, 4, 8, 10],\n augMaj7: [0, 4, 8, 11],\n '6': [0, 4, 7, 9],\n min6: [0, 3, 7, 9],\n '6/9': [0, 4, 7, 9, 14],\n sus2: [0, 2, 7],\n sus4: [0, 5, 7],\n add9: [0, 4, 7, 14],\n add11: [0, 4, 7, 17],\n maj9: [0, 4, 7, 11, 14],\n min9: [0, 3, 7, 10, 14],\n dom9: [0, 4, 7, 10, 14],\n '7b9': [0, 4, 7, 10, 13],\n '7#9': [0, 4, 7, 10, 15],\n '7#11': [0, 4, 7, 10, 18],\n '7b13': [0, 4, 7, 10, 20],\n '11': [0, 7, 10, 14, 17],\n '13': [0, 4, 7, 10, 14, 21],\n '5': [0, 7],\n};\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * All chord qualities the builder understands, longest templates last.\n *\n * @category Chords\n */\nexport function chordQualities(): ChordQuality[] {\n return Object.keys(QUALITY_INTERVALS) as ChordQuality[];\n}\n\n/**\n * Build a chord rooted on a diatonic scale degree.\n *\n * The root pitch class is the degree's diatonic pitch class in `key`; the\n * quality's interval template is attached unchanged. Degrees beyond the scale\n * length wrap around.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param ext Chord quality to apply.\n * @param key Key context supplying the diatonic root.\n * @returns The constructed chord.\n *\n * @category Chords\n */\nexport function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScale): Chord {\n const tones = scaleTonesInDegreeOrder(key);\n const length = tones.length;\n const index = length > 0 ? ((degree % length) + length) % length : 0;\n const rootPc = tones[index] ?? pitchClass(key.rootPc);\n return { rootPc, quality: ext, intervals: [...QUALITY_INTERVALS[ext]] };\n}\n\n/**\n * Build a chord from an explicit root pitch class and quality.\n *\n * @param rootPc Root pitch class (0..11).\n * @param quality Chord quality supplying the interval template.\n * @param bassPc Optional slash-chord bass pitch class.\n * @returns The constructed chord.\n *\n * @example\n * ```ts\n * import { makeChord } from '@libraz/libcantus';\n * const cmaj7 = makeChord(0, 'maj7');\n * // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }\n * ```\n *\n * @category Chords\n */\nexport function makeChord(rootPc: number, quality: ChordQuality, bassPc?: number): Chord {\n const chord: Chord = {\n rootPc: pitchClass(rootPc),\n quality,\n intervals: [...QUALITY_INTERVALS[quality]],\n };\n if (bassPc !== undefined) {\n chord.bassPc = pitchClass(bassPc);\n }\n return chord;\n}\n\n/**\n * Get the sorted, deduplicated pitch classes of a chord.\n *\n * @param chord The chord to enumerate.\n * @returns The chord's pitch classes, sorted ascending in [0, 11].\n *\n * @example\n * ```ts\n * import { makeChord, chordPitchClasses } from '@libraz/libcantus';\n * chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]\n * ```\n *\n * @category Chords\n */\nexport function chordPitchClasses(chord: Chord): number[] {\n const set = new Set<number>();\n for (const interval of chord.intervals) {\n set.add(pitchClass(chord.rootPc + interval));\n }\n return [...set].sort((a, b) => a - b);\n}\n\n/** The chord-tone offsets present in a chord, reduced to pitch-class space. */\nfunction chordToneOffsets(chord: Chord): Set<number> {\n return new Set(chord.intervals.map((i) => ((i % 12) + 12) % 12));\n}\n\n/**\n * Determine a pitch's harmonic role within a chord.\n *\n * The role is derived from the pitch's interval above the chord root, reduced\n * modulo 12. A major sixth (9) reads as a `sixth` for sixth chords but as a\n * `seventh` for a diminished-seventh chord; ninths and other tensions have no\n * basic role and return null.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param chord The chord providing the root reference.\n * @returns The chord-tone role, or null if the pitch has no basic role.\n *\n * @category Chords\n */\nexport function chordToneRole(\n pitch: number,\n chord: Chord,\n): 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | null {\n const interval = (pitchClass(pitch) - pitchClass(chord.rootPc) + 12) % 12;\n const tones = chordToneOffsets(chord);\n if (interval === 0) {\n return 'root';\n }\n if (interval === 3 || interval === 4) {\n return tones.has(interval) ? 'third' : null;\n }\n if (interval === 7) {\n return tones.has(7) ? 'fifth' : null;\n }\n if (interval === 6) {\n // A diminished fifth is the chord's fifth only when no perfect fifth is\n // present; alongside a perfect fifth it is a #11 tension, not a fifth.\n return tones.has(6) && !tones.has(7) ? 'fifth' : null;\n }\n if (interval === 8) {\n // An augmented fifth is the chord's fifth only without a perfect fifth;\n // alongside a perfect fifth it is a b13 tension, not a fifth.\n return tones.has(8) && !tones.has(7) ? 'fifth' : null;\n }\n if (interval === 9) {\n const hasHigherSeventh = tones.has(10) || tones.has(11);\n const isDiminishedSeventh = tones.has(3) && tones.has(6) && !hasHigherSeventh;\n if (isDiminishedSeventh) {\n return 'seventh';\n }\n if (tones.has(9) && !hasHigherSeventh) {\n return 'sixth';\n }\n return null;\n }\n if (interval === 10 || interval === 11) {\n return tones.has(interval) ? 'seventh' : null;\n }\n return null;\n}\n\n/** Classify a stacked-thirds triad into a chord quality from its interval set. */\nfunction classifyTriad(thirdIc: number, fifthIc: number): ChordQuality {\n if (thirdIc === 4 && fifthIc === 8) {\n return 'aug';\n }\n if (thirdIc === 4 && fifthIc === 6) {\n return 'majb5';\n }\n if (thirdIc === 3 && fifthIc === 6) {\n return 'dim';\n }\n if (thirdIc === 3) {\n return 'min';\n }\n return 'maj';\n}\n\n/** Classify a stacked-thirds seventh chord into a chord quality. */\nfunction classifySeventh(thirdIc: number, fifthIc: number, seventhIc: number): ChordQuality {\n if (thirdIc === 3 && fifthIc === 6 && seventhIc === 9) {\n return 'dim7';\n }\n if (thirdIc === 3 && fifthIc === 6 && seventhIc === 10) {\n return 'm7b5';\n }\n if (thirdIc === 3 && seventhIc === 11) {\n return 'minMaj7';\n }\n if (thirdIc === 3) {\n return 'min7';\n }\n if (fifthIc === 8 && seventhIc === 10) {\n return 'aug7';\n }\n if (fifthIc === 8 && seventhIc === 11) {\n return 'augMaj7';\n }\n if (seventhIc === 11) {\n return 'maj7';\n }\n return 'dom7';\n}\n\n/** Stack scale thirds from a scale degree into a chord of `size` notes. */\nfunction stackThirds(degree: number, key: KeyScale, size: 3 | 4): Chord {\n const tones = scaleTonesInDegreeOrder(key);\n const length = tones.length;\n if (length === 0) {\n return { rootPc: pitchClass(key.rootPc), quality: 'maj', intervals: [0, 4, 7] };\n }\n const idx = (step: number) => (((degree + step) % length) + length) % length;\n const rootPc = tones[idx(0)] ?? pitchClass(key.rootPc);\n const offsets = [0, 2, 4, 6].slice(0, size).map((step) => {\n const pc = tones[idx(step)] ?? rootPc;\n return (((pc - rootPc) % 12) + 12) % 12;\n });\n const thirdIc = offsets[1] ?? 4;\n const fifthIc = offsets[2] ?? 7;\n const quality =\n size === 3\n ? classifyTriad(thirdIc, fifthIc)\n : classifySeventh(thirdIc, fifthIc, offsets[3] ?? 11);\n return { rootPc, quality, intervals: offsets };\n}\n\n/**\n * Build the diatonic triad rooted on a scale degree by stacking scale thirds.\n *\n * Unlike {@link chordFromDegree}, the chord quality is derived from the scale\n * rather than supplied, so degrees yield their scale-correct triads (e.g. a\n * diminished triad on the leading tone of a major key). Intended for heptatonic\n * scales; other scales stack by scale step regardless.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param key Key/scale context.\n * @returns The diatonic triad.\n *\n * @example\n * ```ts\n * import { majorKey, diatonicTriad } from '@libraz/libcantus';\n * const tonic = diatonicTriad(0, majorKey(0)); // C major triad (degree 0 of C major)\n * ```\n *\n * @category Chords\n */\nexport function diatonicTriad(degree: number, key: KeyScale): Chord {\n return stackThirds(degree, key, 3);\n}\n\n/**\n * Build the diatonic seventh chord rooted on a scale degree.\n *\n * @param degree 0-based scale degree of the chord root.\n * @param key Key/scale context.\n * @returns The diatonic seventh chord.\n *\n * @category Chords\n */\nexport function diatonicSeventh(degree: number, key: KeyScale): Chord {\n return stackThirds(degree, key, 4);\n}\n","/**\n * Counterpoint classification of a harmonic interval.\n *\n * @category Pitch & Intervals\n */\nexport enum IntervalQuality {\n PerfectConsonance = 0,\n ImperfectConsonance = 1,\n Dissonance = 2,\n}\n\n/** Reduce an interval to a simple interval class in the range [0, 11]. */\nfunction simpleInterval(semitones: number): number {\n return Math.abs(semitones) % 12;\n}\n\n/**\n * Classify an interval for counterpoint evaluation.\n *\n * The interval is reduced modulo 12, so compound intervals classify as their\n * simple equivalents. The perfect fourth (5) is context-dependent: with\n * `twoVoice` (the default) it classifies as a dissonance, matching\n * {@link isConsonantInterval}; otherwise it is an imperfect consonance.\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @param twoVoice When true, the perfect fourth is treated as dissonant.\n * @returns The counterpoint quality of the interval.\n * @example\n * ```ts\n * import { classifyInterval, IntervalQuality } from '@libraz/libcantus';\n * classifyInterval(7); // IntervalQuality.PerfectConsonance\n * classifyInterval(5); // IntervalQuality.Dissonance (two-voice)\n * classifyInterval(5, false); // IntervalQuality.ImperfectConsonance\n * ```\n * @category Pitch & Intervals\n */\nexport function classifyInterval(semitones: number, twoVoice = true): IntervalQuality {\n const pc = simpleInterval(semitones);\n if (pc === 0 || pc === 7) {\n return IntervalQuality.PerfectConsonance;\n }\n if (pc === 3 || pc === 4 || pc === 8 || pc === 9) {\n return IntervalQuality.ImperfectConsonance;\n }\n if (pc === 5) {\n return twoVoice ? IntervalQuality.Dissonance : IntervalQuality.ImperfectConsonance;\n }\n return IntervalQuality.Dissonance;\n}\n\n/**\n * Test whether an interval is a perfect interval (unison/octave or fifth).\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @returns True for the unison/octave (0) and the perfect fifth (7) mod 12.\n * @category Pitch & Intervals\n */\nexport function isPerfectInterval(semitones: number): boolean {\n const pc = simpleInterval(semitones);\n return pc === 0 || pc === 7;\n}\n\n/**\n * Test whether an interval is consonant.\n *\n * The consonant set is {0, 3, 4, 5, 7, 8, 9} mod 12. In two-voice counterpoint\n * the perfect fourth (5) is treated as a dissonance, so `twoVoice` set to true\n * excludes it.\n *\n * @param semitones Interval size in semitones (may be negative or compound).\n * @param twoVoice When true, the perfect fourth is treated as dissonant.\n * @returns True if the interval is consonant in the given context.\n * @category Pitch & Intervals\n */\nexport function isConsonantInterval(semitones: number, twoVoice = true): boolean {\n const pc = simpleInterval(semitones);\n if (pc === 5) {\n return !twoVoice;\n }\n return pc === 0 || pc === 3 || pc === 4 || pc === 7 || pc === 8 || pc === 9;\n}\n","import { isConsonantInterval } from '../../core/interval/index.js';\nimport type { KeyScale } from '../../core/types.js';\n\n/** Reduce a MIDI pitch (or pitch class) to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/**\n * Whether an upper voice has crossed below a lower voice.\n *\n * @param upperPitch Pitch of the nominally higher voice.\n * @param lowerPitch Pitch of the nominally lower voice.\n * @returns True when the upper voice sits below the lower voice.\n * @category Voicing & Counterpoint\n */\nexport function createsVoiceCrossing(upperPitch: number, lowerPitch: number): boolean {\n return upperPitch < lowerPitch;\n}\n\n/**\n * Whether two simultaneous pitches form a dissonance.\n *\n * @param a First pitch.\n * @param b Second pitch.\n * @param twoVoice When true, the perfect fourth counts as dissonant.\n * @returns True when the vertical interval is dissonant.\n * @category Voicing & Counterpoint\n */\nexport function createsVerticalDissonance(a: number, b: number, twoVoice: boolean): boolean {\n return !isConsonantInterval(a - b, twoVoice);\n}\n\n/**\n * Whether a melodic move is a forbidden leap: a tritone, either seventh (minor\n * or major), or any leap wider than an octave.\n *\n * Operates on the raw absolute distance, so compound leaps are not reduced to\n * their simple class before the octave check.\n *\n * @param prev Starting pitch.\n * @param cur Ending pitch.\n * @returns True when the leap is forbidden in strict counterpoint.\n * @category Voicing & Counterpoint\n */\nexport function isForbiddenMelodicLeap(prev: number, cur: number): boolean {\n const semis = Math.abs(cur - prev);\n return semis === 6 || semis === 10 || semis === 11 || semis > 12;\n}\n\n/** Reduce an interval to its simple class in [0, 11]. */\nfunction simpleClass(semitones: number): number {\n return Math.abs(semitones) % 12;\n}\n\n/** Whether a simple interval class is a perfect kind (unison/octave or fifth). */\nfunction isPerfectClass(cls: number): boolean {\n return cls === 0 || cls === 7;\n}\n\n/** Whether two voices move in the same direction (similar or parallel motion). */\nfunction similarMotion(aMove: number, bMove: number): boolean {\n return aMove !== 0 && bMove !== 0 && aMove > 0 === bMove > 0;\n}\n\n/** Whether both voices actually move (neither is stationary — excludes oblique motion). */\nfunction bothVoicesMove(aMove: number, bMove: number): boolean {\n return aMove !== 0 && bMove !== 0;\n}\n\n/**\n * Whether two voices move into consecutive perfect intervals of the same kind\n * (fifth-to-fifth, octave-to-octave, unison-to-unison).\n *\n * Both true parallels (similar motion) and anti-parallels — the same perfect\n * class reached by contrary motion, e.g. octave to octave with the voices moving\n * in opposite directions — are flagged, as both are forbidden in strict two-voice\n * counterpoint. The rule requires that both voices actually move: oblique motion\n * (either voice stationary) and the no-change case (identical pitches) are excluded.\n *\n * A fifth expanding to a twelfth counts (same perfect class); a fifth moving to\n * an octave does not (different perfect kinds — the direct/hidden case owned by\n * {@link createsHiddenParallelPerfect}).\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelPerfect(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (!bothVoicesMove(aCur - aPrev, bCur - bPrev)) {\n return false;\n }\n const nowClass = simpleClass(aCur - bCur);\n const prevClass = simpleClass(aPrev - bPrev);\n return isPerfectClass(nowClass) && nowClass === prevClass;\n}\n\n/**\n * Whether two voices move in consecutive parallel octaves (or unisons) by\n * similar motion.\n *\n * This is a strict subset of {@link createsParallelPerfect}: a similar-motion\n * octave-to-octave is the perfect-class-zero case that predicate already flags\n * (and it additionally catches the contrary-motion anti-parallel). Callers that\n * tally parallel violations should therefore use {@link createsParallelPerfect}\n * alone to avoid double counting; this predicate remains for callers wanting a\n * dedicated similar-motion octave test.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelOctave(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (!similarMotion(aCur - aPrev, bCur - bPrev)) {\n return false;\n }\n return simpleClass(aCur - bCur) === 0 && simpleClass(aPrev - bPrev) === 0;\n}\n\n/**\n * Whether two voices move in consecutive parallel unisons — both landing on the\n * same pitch, having shared a pitch on the previous move.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsParallelUnison(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n if (aCur === aPrev || bCur === bPrev) {\n return false;\n }\n return aCur === bCur && aPrev === bPrev;\n}\n\n/**\n * Whether two voices reach a perfect interval by similar motion from an\n * imperfect one (a hidden/direct fifth or octave).\n *\n * The traditional step exception is applied: the approach is allowed when the\n * upper of the two voices moves by step, so only leaps into the perfect\n * interval are flagged.\n *\n * @category Voicing & Counterpoint\n */\nexport function createsHiddenParallelPerfect(\n aPrev: number,\n aCur: number,\n bPrev: number,\n bCur: number,\n): boolean {\n const aMove = aCur - aPrev;\n const bMove = bCur - bPrev;\n if (!similarMotion(aMove, bMove)) {\n return false;\n }\n const nowClass = simpleClass(aCur - bCur);\n const prevClass = simpleClass(aPrev - bPrev);\n // Approaching the same perfect class (e.g. fifth to fifth) is a true parallel\n // owned by createsParallelPerfect; approaching a different perfect interval\n // (fifth to octave, or vice versa) is the hidden/direct case flagged here.\n if (!isPerfectClass(nowClass) || prevClass === nowClass) {\n return false;\n }\n const upperMove = aCur >= bCur ? aMove : bMove;\n if (Math.abs(upperMove) <= 2) {\n return false; // upper voice moves by step — direct interval is acceptable\n }\n return true;\n}\n\n/**\n * Whether two voices overlap: the upper voice descends below where the lower\n * voice just was, or the lower voice rises above where the upper voice just was.\n * Distinct from a simultaneous voice crossing.\n *\n * @param upperPrev Previous pitch of the upper voice.\n * @param upperCur Current pitch of the upper voice.\n * @param lowerPrev Previous pitch of the lower voice.\n * @param lowerCur Current pitch of the lower voice.\n * @category Voicing & Counterpoint\n */\nexport function createsVoiceOverlap(\n upperPrev: number,\n upperCur: number,\n lowerPrev: number,\n lowerCur: number,\n): boolean {\n return upperCur < lowerPrev || lowerCur > upperPrev;\n}\n\n/**\n * Whether two adjacent upper voices are spaced more than a maximum apart\n * (commonly an octave). Bass-to-tenor spacing is conventionally exempt, so this\n * is meant for the upper voice pairs.\n *\n * @param upperPitch Pitch of the higher voice.\n * @param lowerPitch Pitch of the lower voice.\n * @param maxSemitones Maximum allowed spacing in semitones (default an octave).\n * @category Voicing & Counterpoint\n */\nexport function exceedsSpacing(upperPitch: number, lowerPitch: number, maxSemitones = 12): boolean {\n return Math.abs(upperPitch - lowerPitch) > maxSemitones;\n}\n\n/**\n * Whether a leading tone resolves correctly upward to the tonic.\n *\n * @param prev The leading-tone pitch.\n * @param cur The following pitch.\n * @param key Key context supplying the tonic.\n * @returns True when `prev` is the leading tone and `cur` is the tonic a step above.\n * @category Voicing & Counterpoint\n */\nexport function isLeadingToneResolution(prev: number, cur: number, key: KeyScale): boolean {\n const tonic = pitchClass(key.rootPc);\n const leading = (tonic + 11) % 12;\n if (pitchClass(prev) !== leading || pitchClass(cur) !== tonic) {\n return false;\n }\n return cur > prev && cur - prev <= 2;\n}\n","import type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport {\n createsHiddenParallelPerfect,\n createsParallelPerfect,\n createsVerticalDissonance,\n isForbiddenMelodicLeap,\n} from '../counterpoint/index.js';\nimport { isScaleTone } from '../scale/index.js';\n\n/**\n * Severity policy: `strict` counterpoint vs. lenient `pop` voice-leading.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyProfile = 'strict' | 'pop';\n\n/**\n * Overall placeability verdict for a candidate pitch.\n *\n * @category Arrangement & Analysis\n */\nexport enum NoteSafety {\n Safe = 0,\n Warning = 1,\n Dissonant = 2,\n}\n\n/**\n * Bit flags describing why a pitch received its verdict.\n *\n * @category Arrangement & Analysis\n */\nexport enum ReasonFlag {\n ChordTone = 1 << 0,\n Tension = 1 << 1,\n AvoidNote = 1 << 2,\n ScaleTone = 1 << 3,\n NonScale = 1 << 4,\n OutOfRange = 1 << 5,\n Tritone = 1 << 6,\n LargeLeap = 1 << 7,\n MinorSecond = 1 << 8,\n MajorSeventh = 1 << 9,\n VerticalDissonance = 1 << 10,\n ParallelPerfect = 1 << 11,\n HiddenParallel = 1 << 12,\n VoiceCrossing = 1 << 13,\n Suspension = 1 << 14,\n NeedsResolution = 1 << 15,\n}\n\n/**\n * A neighbouring voice's current and previous pitch.\n *\n * @category Arrangement & Analysis\n */\nexport type VoiceSnapshot = {\n pitch: number;\n prevPitch?: number;\n};\n\n/**\n * Everything needed to evaluate one candidate pitch.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyQuery = {\n profile: SafetyProfile;\n candidatePitch: number;\n prevPitch?: number;\n chord: Chord | null;\n key: KeyScale;\n otherVoices: VoiceSnapshot[];\n strongBeat: boolean;\n vocalLow?: number;\n vocalHigh?: number;\n};\n\n/**\n * The verdict, reason flags, and optional resolution guidance.\n *\n * @category Arrangement & Analysis\n */\nexport type SafetyResult = {\n safety: NoteSafety;\n reasons: number;\n resolveTo?: number;\n suggestions?: number[];\n rationale?: string;\n};\n\n/** Semitone radius searched around a rejected candidate for safe alternatives. */\nconst SUGGESTION_WINDOW = 12;\n/** Maximum number of alternative pitches returned in `SafetyResult.suggestions`. */\nconst MAX_SUGGESTIONS = 3;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction intervalAboveRoot(pitch: number, chord: Chord): number {\n return (((pitchClass(pitch) - pitchClass(chord.rootPc)) % 12) + 12) % 12;\n}\n\nfunction isChordMember(pitch: number, chord: Chord): boolean {\n return chordPitchClasses(chord).includes(pitchClass(pitch));\n}\n\n/** Whether the perfect fourth is an avoid note over this chord. */\nfunction avoidsFourth(chord: Chord): boolean {\n return chord.intervals.includes(4) && !chord.intervals.includes(5);\n}\n\n/** Whether the major seventh is an avoid note over this chord (dominant). */\nfunction avoidsMajorSeventh(chord: Chord): boolean {\n return chord.intervals.includes(4) && chord.intervals.includes(10);\n}\n\n/** Nearest chord tone at or below the candidate, within two semitones. */\nfunction stepResolution(pitch: number, chord: Chord): number | undefined {\n for (let delta = 1; delta <= 2; delta += 1) {\n if (isChordMember(pitch - delta, chord)) {\n return pitch - delta;\n }\n }\n return undefined;\n}\n\n/**\n * Evaluate the safety of placing a candidate pitch in a voice.\n *\n * Reasons are merged from harmonic context (chord tone / tension / avoid / scale)\n * and counterpoint (vertical dissonance, parallels, voice crossing). The `strict`\n * profile treats avoid notes and parallels as dissonant; `pop` treats them as\n * warnings. The final verdict is the worst severity among the reasons.\n *\n * @param q The candidate and its harmonic/voice-leading context.\n * @returns The verdict, reason bitmask, and optional resolution guidance.\n * @example\n * ```ts\n * import { evaluateSafety, makeChord, majorKey, NoteSafety } from '@libraz/libcantus';\n * const result = evaluateSafety({\n * profile: 'pop',\n * candidatePitch: 60, // C over a C major chord\n * chord: makeChord(0, 'maj'),\n * key: majorKey(0),\n * otherVoices: [],\n * strongBeat: true,\n * });\n * result.safety === NoteSafety.Safe; // true — C is a chord tone\n * ```\n * @category Arrangement & Analysis\n */\nexport function evaluateSafety(q: SafetyQuery): SafetyResult {\n return evaluateInternal(q, true);\n}\n\n/**\n * Core safety evaluation.\n *\n * @param q The candidate and its harmonic/voice-leading context.\n * @param collectSuggestions Whether to search for safe alternatives on a\n * non-Safe verdict. Set false during that search itself to bound recursion.\n * @returns The verdict, reason bitmask, and optional guidance.\n */\nfunction evaluateInternal(q: SafetyQuery, collectSuggestions: boolean): SafetyResult {\n let reasons = 0;\n let level = NoteSafety.Safe;\n let resolveTo: number | undefined;\n const raise = (l: NoteSafety) => {\n if (l > level) {\n level = l;\n }\n };\n const avoidSeverity = q.profile === 'strict' ? NoteSafety.Dissonant : NoteSafety.Warning;\n const parallelSeverity = avoidSeverity;\n const pitch = q.candidatePitch;\n\n if (\n (q.vocalLow !== undefined && pitch < q.vocalLow) ||\n (q.vocalHigh !== undefined && pitch > q.vocalHigh)\n ) {\n reasons |= ReasonFlag.OutOfRange;\n raise(NoteSafety.Warning);\n }\n\n const inScale = isScaleTone(pitch, q.key);\n const chord = q.chord;\n\n if (chord && isChordMember(pitch, chord)) {\n reasons |= ReasonFlag.ChordTone;\n } else if (chord) {\n const ic = intervalAboveRoot(pitch, chord);\n const isTension = ic === 2 || ic === 5 || ic === 9;\n const avoid = (ic === 5 && avoidsFourth(chord)) || (ic === 11 && avoidsMajorSeventh(chord));\n if (avoid) {\n reasons |= ReasonFlag.AvoidNote;\n if (isTension) {\n reasons |= ReasonFlag.Tension;\n }\n reasons |= ReasonFlag.NeedsResolution;\n resolveTo = stepResolution(pitch, chord);\n raise(avoidSeverity);\n } else if (isTension && inScale) {\n reasons |= ReasonFlag.Tension;\n raise(NoteSafety.Warning);\n } else if (inScale) {\n reasons |= ReasonFlag.ScaleTone;\n raise(NoteSafety.Warning);\n } else {\n reasons |= ReasonFlag.NonScale;\n raise(NoteSafety.Dissonant);\n }\n } else if (inScale) {\n reasons |= ReasonFlag.ScaleTone;\n raise(NoteSafety.Warning);\n } else {\n reasons |= ReasonFlag.NonScale;\n raise(NoteSafety.Dissonant);\n }\n\n // Harmonic tritone against a chord tone (except in dominant chords, where the\n // tritone is a defining, stable colour).\n if (chord && !(chord.intervals.includes(4) && chord.intervals.includes(10))) {\n const ic = intervalAboveRoot(pitch, chord);\n const toneOffsets = chord.intervals.map((i) => ((i % 12) + 12) % 12);\n if (toneOffsets.some((t) => Math.abs(ic - t) === 6)) {\n reasons |= ReasonFlag.Tritone;\n }\n }\n\n if (q.prevPitch !== undefined) {\n // Quality flags reduce the melodic interval to its pitch-class interval so\n // compound intervals are treated uniformly with their simple form. The\n // forbidden-leap flag defers to the counterpoint rule, which preserves the\n // octave boundary (an octave leap is allowed, wider leaps are not).\n const pc = Math.abs(pitch - q.prevPitch) % 12;\n if (pc === 6) {\n reasons |= ReasonFlag.Tritone;\n }\n if (isForbiddenMelodicLeap(q.prevPitch, pitch)) {\n reasons |= ReasonFlag.LargeLeap;\n }\n if (pc === 1) {\n reasons |= ReasonFlag.MinorSecond;\n }\n if (pc === 11) {\n reasons |= ReasonFlag.MajorSeventh;\n }\n }\n\n if (q.strongBeat) {\n const twoVoice = q.otherVoices.length === 1;\n const prev = q.prevPitch;\n for (const ov of q.otherVoices) {\n if (!createsVerticalDissonance(pitch, ov.pitch, twoVoice)) {\n continue;\n }\n reasons |= ReasonFlag.VerticalDissonance;\n raise(NoteSafety.Dissonant);\n // A held pitch that was consonant on the previous step and is now\n // dissonant against the same voice is a prepared suspension.\n if (\n prev !== undefined &&\n pitch === prev &&\n ov.prevPitch !== undefined &&\n !createsVerticalDissonance(prev, ov.prevPitch, twoVoice)\n ) {\n reasons |= ReasonFlag.Suspension;\n }\n }\n }\n\n if (q.prevPitch !== undefined) {\n const prev = q.prevPitch;\n for (const ov of q.otherVoices) {\n if (ov.prevPitch === undefined) {\n continue;\n }\n // createsParallelPerfect covers every perfect class (unison/octave and\n // fifth), so no separate octave check is needed.\n if (createsParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {\n reasons |= ReasonFlag.ParallelPerfect;\n raise(parallelSeverity);\n }\n if (createsHiddenParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {\n reasons |= ReasonFlag.HiddenParallel;\n raise(parallelSeverity);\n }\n const crossedNow = pitch - ov.pitch;\n const crossedPrev = prev - ov.prevPitch;\n if (crossedNow !== 0 && crossedPrev !== 0 && crossedNow > 0 !== crossedPrev > 0) {\n reasons |= ReasonFlag.VoiceCrossing;\n raise(parallelSeverity);\n }\n }\n }\n\n const result: SafetyResult = { safety: level, reasons, rationale: describe(reasons, q) };\n if (resolveTo !== undefined) {\n result.resolveTo = resolveTo;\n }\n if (collectSuggestions && level !== NoteSafety.Safe) {\n const suggestions = findSafeNearby(q, pitch);\n if (suggestions.length > 0) {\n result.suggestions = suggestions;\n }\n }\n return result;\n}\n\n/**\n * Find safe alternative pitches near a rejected candidate.\n *\n * Searches outward from the candidate within `SUGGESTION_WINDOW` semitones,\n * probing the pitch below before the one above at each distance so the result\n * is deterministic and ordered by nearness.\n *\n * @param q The safety context of the rejected candidate.\n * @param candidate The candidate pitch that was not Safe.\n * @returns Up to `MAX_SUGGESTIONS` safe pitches, nearest first.\n */\nfunction findSafeNearby(q: SafetyQuery, candidate: number): number[] {\n const out: number[] = [];\n for (let d = 1; d <= SUGGESTION_WINDOW; d += 1) {\n for (const p of [candidate - d, candidate + d]) {\n if (evaluateInternal({ ...q, candidatePitch: p }, false).safety === NoteSafety.Safe) {\n out.push(p);\n if (out.length >= MAX_SUGGESTIONS) {\n return out;\n }\n }\n }\n }\n return out;\n}\n\n/** Build a short human explanation from the reason flags. */\nfunction describe(reasons: number, q: SafetyQuery): string {\n if (reasons & ReasonFlag.OutOfRange) {\n return 'Outside the target vocal range';\n }\n if (reasons & ReasonFlag.Suspension) {\n return 'Prepared suspension — a held consonance now dissonant, awaiting resolution';\n }\n if (reasons & ReasonFlag.VerticalDissonance) {\n return 'Dissonant against a sounding voice on a strong beat';\n }\n if (reasons & ReasonFlag.AvoidNote) {\n return 'Avoid note — clashes with a chord tone a semitone away';\n }\n if (reasons & ReasonFlag.ParallelPerfect) {\n return 'Parallel perfect interval with another voice';\n }\n if (reasons & ReasonFlag.HiddenParallel) {\n return 'Hidden perfect interval by similar motion';\n }\n if (reasons & ReasonFlag.VoiceCrossing) {\n return 'Crosses another voice';\n }\n if (reasons & ReasonFlag.ChordTone) {\n return 'Chord tone';\n }\n if (reasons & ReasonFlag.Tension) {\n return 'Chord tension';\n }\n if (reasons & ReasonFlag.NonScale) {\n return 'Outside the key';\n }\n if (reasons & ReasonFlag.ScaleTone) {\n return 'Scale tone, not in the chord';\n }\n return q.chord ? 'Placeable' : 'No chord context';\n}\n\n/**\n * Enumerate placeable pitches in a range, chord tones first, descending.\n *\n * @param q The safety context minus the candidate pitch.\n * @param pitchLow Lowest MIDI pitch to consider (inclusive).\n * @param pitchHigh Highest MIDI pitch to consider (inclusive).\n * @returns Placeable pitches (non-dissonant), chord tones before others, each group descending.\n * @example\n * ```ts\n * import { enumerateSafePitches, makeChord, majorKey } from '@libraz/libcantus';\n * const pitches = enumerateSafePitches(\n * { profile: 'pop', chord: makeChord(0, 'maj'), key: majorKey(0), otherVoices: [], strongBeat: true },\n * 60,\n * 72,\n * );\n * pitches; // placeable pitches in [60, 72], chord tones first, each group descending\n * ```\n * @category Arrangement & Analysis\n */\nexport function enumerateSafePitches(\n q: Omit<SafetyQuery, 'candidatePitch'>,\n pitchLow: number,\n pitchHigh: number,\n): number[] {\n const chordTones: number[] = [];\n const others: number[] = [];\n if (!Number.isFinite(pitchLow) || !Number.isFinite(pitchHigh)) {\n return [];\n }\n for (let pitch = pitchHigh; pitch >= pitchLow; pitch -= 1) {\n const result = evaluateInternal({ ...q, candidatePitch: pitch }, false);\n if (result.safety === NoteSafety.Dissonant) {\n continue;\n }\n if (result.reasons & ReasonFlag.ChordTone) {\n chordTones.push(pitch);\n } else {\n others.push(pitch);\n }\n }\n return [...chordTones, ...others];\n}\n","/**\n * Shared helpers for the functional-harmony modules.\n *\n * Roots are pitch classes measured against the key tonic, so borrowed and\n * chromatic chords are handled by their semitone offset rather than requiring a\n * spelled key signature.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { scaleTonesInDegreeOrder } from '../../theory/scale/index.js';\n\nexport function mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/** Diatonic pitch class of a 1-based scale degree in a key. */\nexport function degreeRootPc(degreeNumber: number, key: KeyScale): number {\n const tones = scaleTonesInDegreeOrder(key);\n if (tones.length === 0) {\n return mod12(key.rootPc);\n }\n return tones[(degreeNumber - 1) % tones.length] ?? mod12(key.rootPc);\n}\n\n/** Whether a chord is the Neapolitan: a major triad on the flat second degree. */\nexport function isNeapolitan(chord: Chord, key: KeyScale): boolean {\n return mod12(chord.rootPc - key.rootPc) === 1 && chord.quality === 'maj';\n}\n","/**\n * Roman-numeral parsing and formatting.\n *\n * The {@link ROMAN_STYLE} table is the single source of truth for both\n * directions, so {@link chordToRoman} and {@link romanToChord} stay mutual\n * inverses by construction.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord, ChordQuality } from '../../theory/chord/index.js';\nimport { makeChord } from '../../theory/chord/index.js';\nimport { majorKey, scaleTonesInDegreeOrder } from '../../theory/scale/index.js';\nimport { degreeRootPc, mod12 } from './internal.js';\n\n/** Roman numeral glyphs indexed by degree number - 1. */\nconst ROMAN = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII'] as const;\n\n/** Roman glyph -> degree number (1..7). */\nconst ROMAN_TO_DEGREE: Record<string, number> = {\n I: 1,\n II: 2,\n III: 3,\n IV: 4,\n V: 5,\n VI: 6,\n VII: 7,\n};\n\n/** Major-key Roman spelling for each semitone offset above the tonic. */\nconst OFFSET_SPELLING: readonly [number, string][] = [\n [1, ''],\n [2, 'b'],\n [2, ''],\n [3, 'b'],\n [3, ''],\n [4, ''],\n [4, '#'],\n [5, ''],\n [6, 'b'],\n [6, ''],\n [7, 'b'],\n [7, ''],\n];\n\n/** Choose a seventh-chord quality from a triad label and the numeral case. */\nfunction seventhQuality(base: 'maj' | 'min' | 'dim' | 'aug', halfDim: boolean): ChordQuality {\n if (halfDim) {\n return 'm7b5';\n }\n if (base === 'dim') {\n return 'dim7';\n }\n if (base === 'aug') {\n return 'aug7';\n }\n return base === 'maj' ? 'dom7' : 'min7';\n}\n\n/** Figure strings that denote a recognized figured-bass inversion. */\nconst INVERSION_FIGURES = new Set(['6', '64', '65', '43', '42', '2', '7']);\n\n/**\n * Canonical Roman-numeral rendering (numeral case and quality suffix) for every\n * supported chord quality. The table is the single source of truth for both\n * directions: {@link chordToRoman} renders from it and {@link romanToChord}\n * recognizes its exact case-sensitive suffixes, so the two stay mutual\n * inverses by construction. Suffixes are chosen to never collide with\n * figured-bass inversion digits (`6`, `64`, `65`, `43`, `42`, `2`) — the added\n * sixth is `add6`, the six-nine chord is `69` — and each (case, suffix) pair is\n * unique.\n */\nconst ROMAN_STYLE: Record<ChordQuality, { lower: boolean; suffix: string }> = {\n maj: { lower: false, suffix: '' },\n min: { lower: true, suffix: '' },\n dim: { lower: true, suffix: 'o' },\n aug: { lower: false, suffix: '+' },\n maj7: { lower: false, suffix: 'maj7' },\n min7: { lower: true, suffix: '7' },\n dom7: { lower: false, suffix: '7' },\n dim7: { lower: true, suffix: 'o7' },\n m7b5: { lower: true, suffix: 'ø7' },\n minMaj7: { lower: true, suffix: 'maj7' },\n aug7: { lower: false, suffix: '+7' },\n augMaj7: { lower: false, suffix: '+maj7' },\n majb5: { lower: false, suffix: 'b5' },\n '6': { lower: false, suffix: 'add6' },\n min6: { lower: true, suffix: 'add6' },\n '6/9': { lower: false, suffix: '69' },\n sus2: { lower: false, suffix: 'sus2' },\n sus4: { lower: false, suffix: 'sus4' },\n add9: { lower: false, suffix: 'add9' },\n add11: { lower: false, suffix: 'add11' },\n maj9: { lower: false, suffix: 'maj9' },\n min9: { lower: true, suffix: '9' },\n dom9: { lower: false, suffix: '9' },\n '7b9': { lower: false, suffix: '7b9' },\n '7#9': { lower: false, suffix: '7#9' },\n '7#11': { lower: false, suffix: '7#11' },\n '7b13': { lower: false, suffix: '7b13' },\n '11': { lower: false, suffix: '11' },\n '13': { lower: false, suffix: '13' },\n '5': { lower: false, suffix: '5' },\n};\n\n/** Reverse lookup of {@link ROMAN_STYLE}: `(case, exact suffix) -> quality`. */\nconst SUFFIX_QUALITY: ReadonlyMap<string, ChordQuality> = new Map(\n (Object.entries(ROMAN_STYLE) as [ChordQuality, { lower: boolean; suffix: string }][]).map(\n ([quality, style]) => [`${style.lower ? 'l' : 'u'}:${style.suffix}`, quality],\n ),\n);\n\n/** Read figured-bass digits into a chord inversion and whether a seventh is implied. */\nfunction parseInversion(figures: string): { inversion: number; seventh: boolean } {\n if (figures === '65') {\n return { inversion: 1, seventh: true };\n }\n if (figures === '43') {\n return { inversion: 2, seventh: true };\n }\n if (figures === '42' || figures === '2') {\n return { inversion: 3, seventh: true };\n }\n if (figures === '7') {\n return { inversion: 0, seventh: true };\n }\n if (figures === '64') {\n return { inversion: 2, seventh: false };\n }\n if (figures === '6') {\n return { inversion: 1, seventh: false };\n }\n return { inversion: 0, seventh: false };\n}\n\n/** Parse a Roman numeral (no secondary '/') into a root, quality, and inversion. */\nfunction parseSimpleRoman(\n text: string,\n key: KeyScale,\n): { rootPc: number; quality: ChordQuality; inversion: number } {\n const match = /^([b#]?)([iIvV]+)(.*)$/.exec(text.trim());\n if (!match) {\n throw new Error(`Invalid Roman numeral: ${text}`);\n }\n const accidental = match[1] === 'b' ? -1 : match[1] === '#' ? 1 : 0;\n const glyph = (match[2] ?? '').toUpperCase();\n const degreeNumber = ROMAN_TO_DEGREE[glyph];\n if (degreeNumber === undefined) {\n throw new Error(`Invalid Roman numeral: ${text}`);\n }\n const isUpper = (match[2] ?? '')[0] === (match[2] ?? '')[0]?.toUpperCase();\n const suffix = match[3] ?? '';\n const rootPc = mod12(degreeRootPc(degreeNumber, key) + accidental);\n\n // Canonical quality suffixes (exact match, case-sensitive on the numeral)\n // come first so every chordToRoman rendering re-parses to the same quality:\n // `V9` -> dom9 but `ii9` -> min9 and `Imaj9` -> maj9, and added-tone suffixes\n // whose digits would otherwise be misread as figured bass (`Iadd6`, `I69`,\n // `Isus2`, `Iadd11`) resolve to their qualities in root position.\n const canonical = SUFFIX_QUALITY.get(`${isUpper ? 'u' : 'l'}:${suffix}`);\n if (canonical !== undefined) {\n return { rootPc, quality: canonical, inversion: 0 };\n }\n\n const isDim = /o|°|dim/.test(suffix);\n const isAug = /\\+|aug/.test(suffix);\n const isHalfDim = /ø/.test(suffix);\n const explicitMaj7 = /maj7|M7/.test(suffix);\n const figures = suffix.replace(/maj7|M7/g, '').replace(/[^0-9]/g, '');\n\n // Reject figure strings that are neither a known figured-bass inversion nor a\n // canonical quality suffix rather than silently degrading to a root triad.\n if (figures !== '' && !INVERSION_FIGURES.has(figures)) {\n throw new Error(`Unsupported figured-bass or extension \"${figures}\" in Roman numeral: ${text}`);\n }\n\n const { inversion, seventh } = parseInversion(figures);\n // The ø glyph is the half-diminished seventh by definition (there is no\n // half-diminished triad), so it always implies a seventh.\n const hasSeventh = explicitMaj7 || seventh || isHalfDim;\n\n let base: 'maj' | 'min' | 'dim' | 'aug';\n if (isDim || isHalfDim) {\n base = 'dim';\n } else if (isAug) {\n base = 'aug';\n } else {\n base = isUpper ? 'maj' : 'min';\n }\n\n let quality: ChordQuality;\n if (explicitMaj7) {\n quality = base === 'min' ? 'minMaj7' : base === 'aug' ? 'augMaj7' : 'maj7';\n } else if (hasSeventh) {\n quality = seventhQuality(base, isHalfDim);\n } else if (base === 'dim') {\n quality = 'dim';\n } else if (base === 'aug') {\n quality = 'aug';\n } else {\n quality = base;\n }\n return { rootPc, quality, inversion };\n}\n\n/** Build a chord from a parsed Roman numeral, attaching a bass for inversions. */\nfunction chordFromParsed(parsed: {\n rootPc: number;\n quality: ChordQuality;\n inversion: number;\n}): Chord {\n const chord = makeChord(parsed.rootPc, parsed.quality);\n if (parsed.inversion > 0 && parsed.inversion < chord.intervals.length) {\n chord.bassPc = mod12(parsed.rootPc + (chord.intervals[parsed.inversion] ?? 0));\n }\n return chord;\n}\n\n/**\n * Build the chord denoted by a Roman numeral in a key.\n *\n * Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`\n * suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions\n * (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash\n * (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree\n * whose root becomes a local major tonic for the applied chord. Inverted chords\n * carry a `bassPc`.\n *\n * The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==\n * `m7b5`), since no half-diminished triad exists. Extension and added-tone\n * suffixes are the canonical case-sensitive forms emitted by\n * {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->\n * `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->\n * `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->\n * `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.\n * A figure string that is neither a recognized inversion nor a supported\n * quality suffix throws rather than silently degrading to a triad.\n *\n * @param text The Roman numeral.\n * @param key The prevailing key.\n * @returns The chord.\n * @example\n * ```ts\n * import { romanToChord, majorKey } from '@libraz/libcantus';\n * romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }\n * ```\n * @category Functional Harmony\n */\nexport function romanToChord(text: string, key: KeyScale): Chord {\n const trimmed = text.trim();\n const slash = trimmed.indexOf('/');\n if (slash >= 0) {\n const applied = trimmed.slice(0, slash);\n const target = trimmed.slice(slash + 1);\n const targetRoot = parseSimpleRoman(target, key).rootPc;\n const localKey = majorKey(targetRoot);\n return chordFromParsed(parseSimpleRoman(applied, localKey));\n }\n return chordFromParsed(parseSimpleRoman(trimmed, key));\n}\n\n/** Case and suffix for rendering a chord quality as a Roman numeral. */\nfunction romanStyle(quality: ChordQuality): { lower: boolean; suffix: string } {\n return ROMAN_STYLE[quality];\n}\n\n/** Choose the degree number and accidental to spell a root as a Roman numeral. */\nfunction romanSpelling(\n rootPc: number,\n key: KeyScale,\n): { degreeNumber: number; accidental: string } {\n const tones = scaleTonesInDegreeOrder(key);\n const diatonic = tones.indexOf(mod12(rootPc));\n if (diatonic >= 0) {\n return { degreeNumber: diatonic + 1, accidental: '' };\n }\n // Chromatic root: prefer a flat of the diatonic degree a semitone above it,\n // then a sharp of the degree a semitone below. Degree 1 (the tonic) and\n // degree 5 (the dominant) are skipped in the flat pass, so a raised leading\n // tone spells as `#vii` rather than a flat tonic `bI`, and the tritone above\n // the tonic spells as `#iv` rather than a flat fifth `bV` (matching the\n // conventional `OFFSET_SPELLING` for offset 6).\n for (let i = 0; i < tones.length; i += 1) {\n const degreeNumber = i + 1;\n if (degreeNumber === 1 || degreeNumber === 5) {\n continue;\n }\n if (mod12((tones[i] ?? 0) - 1) === mod12(rootPc)) {\n return { degreeNumber, accidental: 'b' };\n }\n }\n for (let i = 0; i < tones.length; i += 1) {\n if (mod12((tones[i] ?? 0) + 1) === mod12(rootPc)) {\n return { degreeNumber: i + 1, accidental: '#' };\n }\n }\n const [degreeNumber, accidental] = OFFSET_SPELLING[mod12(rootPc - key.rootPc)] ?? [1, ''];\n return { degreeNumber, accidental };\n}\n\n/** Quality marker (without the seventh digit) used when a figure carries the 7. */\nfunction baseMarker(quality: ChordQuality): string {\n if (quality === 'dim' || quality === 'dim7') {\n return 'o';\n }\n if (quality === 'm7b5') {\n return 'ø';\n }\n if (quality === 'aug' || quality === 'aug7') {\n return '+';\n }\n if (quality === 'augMaj7') {\n return '+maj7';\n }\n if (quality === 'maj7' || quality === 'minMaj7') {\n return 'maj7';\n }\n return '';\n}\n\nconst TRIAD_FIGURES: Record<number, string> = { 1: '6', 2: '64' };\nconst SEVENTH_FIGURES: Record<number, string> = { 1: '65', 2: '43', 3: '42' };\n\n/** Qualities whose inversions render as lossless triad figures (6, 64). */\nconst TRIAD_FIGURE_QUALITIES: ReadonlySet<ChordQuality> = new Set(['maj', 'min', 'dim', 'aug']);\n\n/**\n * Qualities carrying a chordal seventh, whose inversions render as seventh\n * figures (65, 43, 42). Membership is decided by the quality itself — a 7th\n * above the root (10 or 11 semitones, or the diminished 7th of `dim7`) — never\n * by interval count, which would turn added-tone chords into false sevenths.\n */\nconst SEVENTH_FIGURE_QUALITIES: ReadonlySet<ChordQuality> = new Set([\n 'maj7',\n 'min7',\n 'dom7',\n 'dim7',\n 'm7b5',\n 'minMaj7',\n 'aug7',\n 'augMaj7',\n]);\n\n/**\n * Render a chord as a Roman numeral relative to a key.\n *\n * Diatonic roots take their scale-degree numeral directly, so numerals are\n * correct in both major and minor keys (and any custom scale). The quality\n * selects the case and suffix; chromatic roots receive a flat/sharp spelling by\n * convention. When the chord carries a `bassPc` on a chord tone, a figured-bass\n * inversion (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true\n * seventh chords; added-tone and extended qualities have no lossless figure and\n * render in root position instead (the bass is dropped, pitch classes are\n * preserved).\n *\n * @param chord The chord to name.\n * @param key The prevailing key.\n * @returns The Roman numeral string.\n * @example\n * ```ts\n * import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';\n * chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)\n * ```\n * @category Functional Harmony\n */\nexport function chordToRoman(chord: Chord, key: KeyScale): string {\n const { degreeNumber, accidental } = romanSpelling(chord.rootPc, key);\n const { lower, suffix } = romanStyle(chord.quality);\n const numeral: string = ROMAN[degreeNumber - 1] ?? 'I';\n const cased = lower ? numeral.toLowerCase() : numeral;\n\n let inversion = 0;\n if (chord.bassPc !== undefined) {\n const idx = chord.intervals.findIndex((iv) => mod12(chord.rootPc + iv) === chord.bassPc);\n if (idx > 0) {\n inversion = idx;\n }\n }\n if (inversion > 0) {\n const figure = SEVENTH_FIGURE_QUALITIES.has(chord.quality)\n ? SEVENTH_FIGURES[inversion]\n : TRIAD_FIGURE_QUALITIES.has(chord.quality)\n ? TRIAD_FIGURES[inversion]\n : undefined;\n if (figure !== undefined) {\n return `${accidental}${cased}${baseMarker(chord.quality)}${figure}`;\n }\n // No lossless figured-bass symbol exists — the quality is an added-tone or\n // extended chord, or the bass falls on a tension beyond the seventh — so\n // fall back to root-position rendering with the quality suffix rather than\n // emitting a figure that would re-parse as a different chord.\n }\n return `${accidental}${cased}${suffix}`;\n}\n","/**\n * Harmonic function (tonic / subdominant / dominant), diatonicity, parallel-key\n * mirroring, and full chord analysis.\n *\n * Roots are pitch classes measured against the key tonic, so borrowed and\n * chromatic chords are handled by their semitone offset rather than requiring a\n * spelled key signature.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord, ChordQuality } from '../../theory/chord/index.js';\nimport { chordPitchClasses, makeChord } from '../../theory/chord/index.js';\nimport { isScaleTone, MAJOR_MASK, NATURAL_MINOR_MASK } from '../../theory/scale/index.js';\nimport { type BorrowedSource, borrowedSource } from './borrowed.js';\nimport { degreeRootPc, isNeapolitan, mod12 } from './internal.js';\nimport { chordToRoman } from './roman.js';\n\n/**\n * The three broad harmonic functions of tonal music.\n *\n * @category Functional Harmony\n */\nexport type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';\n\n/** Harmonic function of each semitone offset above the tonic (major context). */\nconst FUNCTION_BY_OFFSET: readonly HarmonicFunction[] = [\n 'tonic', // 0 I\n 'subdominant', // 1 bII (Neapolitan)\n 'subdominant', // 2 ii\n 'tonic', // 3 bIII\n 'tonic', // 4 iii\n 'subdominant', // 5 IV\n 'dominant', // 6 #IV / bV\n 'dominant', // 7 V\n 'subdominant', // 8 bVI\n 'tonic', // 9 vi\n 'subdominant', // 10 bVII\n 'dominant', // 11 vii\n];\n\n/**\n * Whether a key's scale has a minor third and no major third (a minor key).\n *\n * @category Functional Harmony\n */\nexport function isMinorKey(key: KeyScale): boolean {\n const hasMinorThird = (key.modeMask12 >> 3) & 1;\n const hasMajorThird = (key.modeMask12 >> 4) & 1;\n return Boolean(hasMinorThird) && !hasMajorThird;\n}\n\n/**\n * The harmonic function of a chord in a key, from its root's offset above the\n * tonic. The mapping follows common-practice major-key function and is a useful\n * approximation in minor and for borrowed chords.\n *\n * @param chord The chord.\n * @param key The prevailing key.\n * @returns The harmonic function.\n * @category Functional Harmony\n */\nexport function functionOf(chord: Chord, key: KeyScale): HarmonicFunction {\n return FUNCTION_BY_OFFSET[mod12(chord.rootPc - key.rootPc)] ?? 'tonic';\n}\n\n/**\n * The result of {@link analyzeChord}: function, borrowing, and Roman numeral.\n *\n * @category Functional Harmony\n */\nexport type ChordAnalysis = {\n function: HarmonicFunction;\n borrowed: boolean;\n source: BorrowedSource;\n roman: string;\n};\n\n/**\n * Whether every pitch class of a chord belongs to the key's scale.\n *\n * The test is strict against the key's own mode mask: in a natural-minor key\n * the harmonic-minor dominant (major V) is *not* diatonic, since the raised\n * leading tone lies outside the mask. Borrowing predicates treat that case as\n * an in-key alteration separately (see {@link isBorrowedChord}).\n *\n * @param chord The chord to test.\n * @param key The prevailing key.\n * @returns True if all chord pitch classes are scale tones.\n * @category Functional Harmony\n */\nexport function isDiatonic(chord: Chord, key: KeyScale): boolean {\n return chordPitchClasses(chord).every((pc) => isScaleTone(pc, key));\n}\n\n/**\n * The parallel key: same tonic, opposite mode.\n *\n * A key with a minor third (natural/harmonic/melodic minor, dorian, phrygian)\n * maps to the parallel major; any other key maps to the parallel natural minor.\n *\n * @param key The key to mirror.\n * @returns The parallel major or natural-minor key on the same tonic.\n * @category Functional Harmony\n */\nexport function parallelKey(key: KeyScale): KeyScale {\n return {\n rootPc: mod12(key.rootPc),\n modeMask12: isMinorKey(key) ? MAJOR_MASK : NATURAL_MINOR_MASK,\n };\n}\n\n/** Diminished-family qualities: diminished triad, dim7, half-diminished. */\nfunction isDiminishedQuality(quality: ChordQuality): boolean {\n return quality === 'dim' || quality === 'dim7' || quality === 'm7b5';\n}\n\n/** Whether the chord's interval template carries a major third above the root. */\nfunction hasMajorThird(chord: Chord): boolean {\n return chord.intervals.some((interval) => mod12(interval) === 4);\n}\n\n/**\n * Quality-aware harmonic function, refining the offset table where chord\n * quality disambiguates: diminished chords on the leading tone or the raised\n * subdominant resolve by semitone and act as dominants; the Neapolitan and the\n * major-third chords on bVI/bVII borrowed from the parallel minor act as\n * subdominant (predominant) harmony. All other chords keep {@link functionOf}.\n */\nfunction qualityAwareFunction(chord: Chord, key: KeyScale): HarmonicFunction {\n const offset = mod12(chord.rootPc - key.rootPc);\n if (isDiminishedQuality(chord.quality) && (offset === 11 || offset === 6)) {\n return 'dominant';\n }\n if (isNeapolitan(chord, key)) {\n return 'subdominant';\n }\n if (!isMinorKey(key) && hasMajorThird(chord) && (offset === 8 || offset === 10)) {\n return 'subdominant';\n }\n return functionOf(chord, key);\n}\n\n/**\n * Analyze a chord in a key: harmonic function, borrowing, and Roman numeral.\n *\n * The function is quality-aware (see the predicates behind it), the source\n * follows {@link borrowedSource}, and the numeral comes from\n * {@link chordToRoman}. `borrowed` is true whenever a source is identified —\n * including the Neapolitan, which the stricter parallel-mode predicate\n * {@link isBorrowedChord} does not count.\n *\n * @param chord The chord to analyze.\n * @param key The prevailing key.\n * @returns The chord analysis.\n * @example\n * ```ts\n * import { analyzeChord, makeChord, majorKey } from '@libraz/libcantus';\n * analyzeChord(makeChord(7, 'dom7'), majorKey(0));\n * // { function: 'dominant', borrowed: false, source: null, roman: 'V7' }\n * ```\n * @category Functional Harmony\n */\nexport function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis {\n const source = borrowedSource(chord, key);\n return {\n function: qualityAwareFunction(chord, key),\n borrowed: source !== null,\n source,\n roman: chordToRoman(chord, key),\n };\n}\n\n/**\n * The secondary dominant (V7) that tonicizes a scale degree.\n *\n * @param targetDegree 0-based scale degree to tonicize.\n * @param key The prevailing key.\n * @returns A dominant-seventh chord a fifth above the target's root.\n * @category Functional Harmony\n */\nexport function secondaryDominant(targetDegree: number, key: KeyScale): Chord {\n const targetRoot = degreeRootPc(targetDegree + 1, key);\n return makeChord(mod12(targetRoot + 7), 'dom7');\n}\n","/**\n * Borrowed chords (modal interchange) and the Neapolitan.\n *\n * Roots are pitch classes measured against the key tonic, so borrowed and\n * chromatic chords are handled by their semitone offset rather than requiring a\n * spelled key signature.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { HARMONIC_MINOR_MASK } from '../../theory/scale/index.js';\nimport { isDiatonic, isMinorKey, parallelKey } from './function.js';\nimport { isNeapolitan, mod12 } from './internal.js';\n\n/**\n * The origin of a recognized non-diatonic chord, or null when none applies.\n *\n * @category Functional Harmony\n */\nexport type BorrowedSource = 'parallel-minor' | 'parallel-major' | 'neapolitan' | null;\n\n/**\n * In a minor key, whether a non-diatonic chord is explained by the harmonic\n * minor scale on the same tonic (major V, V7, the raised-leading-tone viio).\n * Such chords are in-key chromatic alterations, not modal interchange.\n */\nfunction isHarmonicMinorAlteration(chord: Chord, key: KeyScale): boolean {\n return (\n isMinorKey(key) &&\n isDiatonic(chord, { rootPc: mod12(key.rootPc), modeMask12: HARMONIC_MINOR_MASK })\n );\n}\n\n/**\n * Whether a chord is borrowed from the parallel mode (modal interchange).\n *\n * True when the chord is not diatonic to `key` but is diatonic to its\n * {@link parallelKey} — e.g. iv, bVI, or bVII in a major key, or the Picardy\n * tonic and major IV in a minor key. Two non-diatonic families are excluded:\n * chords diatonic to neither mode (they are chromatic, not borrowed), and, in\n * a minor key, chords explained by the harmonic minor scale (the major\n * dominant and raised-leading-tone chords), which are in-key alterations\n * rather than interchange even though they happen to fit the parallel major.\n *\n * @param chord The chord to test.\n * @param key The prevailing key.\n * @returns True if the chord is borrowed from the parallel mode.\n * @category Functional Harmony\n */\nexport function isBorrowedChord(chord: Chord, key: KeyScale): boolean {\n if (isDiatonic(chord, key)) {\n return false;\n }\n if (isHarmonicMinorAlteration(chord, key)) {\n return false;\n }\n return isDiatonic(chord, parallelKey(key));\n}\n\n/**\n * Identify where a non-diatonic chord comes from.\n *\n * The Neapolitan (major triad on b2) is recognized first, since it sits\n * outside both parallel modes; parallel-mode borrowing follows the\n * {@link isBorrowedChord} rules. Diatonic chords, harmonic-minor alterations,\n * and unrecognized chromatic chords all yield null.\n *\n * @param chord The chord to classify.\n * @param key The prevailing key.\n * @returns The borrowing source, or null.\n * @category Functional Harmony\n */\nexport function borrowedSource(chord: Chord, key: KeyScale): BorrowedSource {\n if (isDiatonic(chord, key)) {\n return null;\n }\n if (isNeapolitan(chord, key)) {\n return 'neapolitan';\n }\n if (isBorrowedChord(chord, key)) {\n return isMinorKey(key) ? 'parallel-major' : 'parallel-minor';\n }\n return null;\n}\n","/**\n * Cadence detection between two successive chords.\n *\n * Roots are pitch classes measured against the key tonic, so borrowed and\n * chromatic chords are handled by their semitone offset rather than requiring a\n * spelled key signature.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { isMinorKey } from './function.js';\nimport { mod12 } from './internal.js';\n\n/**\n * A recognized cadence type, or null when a chord pair forms none.\n *\n * @category Functional Harmony\n */\nexport type Cadence = 'authentic' | 'plagal' | 'half' | 'deceptive' | null;\n\n/**\n * Classify the cadence formed by moving from one chord to the next.\n *\n * - authentic: V (dominant a fifth above the tonic) to I\n * - plagal: IV (a fourth above the tonic) to I\n * - deceptive: V to the submediant (diatonic vi or borrowed bVI in major, VI in\n * minor)\n * - half: any chord other than the dominant itself to V\n *\n * A static V-to-V repeat with no root motion is not a cadence and yields null.\n *\n * @param from The penultimate chord.\n * @param to The final chord.\n * @param key The prevailing key.\n * @returns The cadence type, or null.\n * @example\n * ```ts\n * import { detectCadence, makeChord, majorKey } from '@libraz/libcantus';\n * detectCadence(makeChord(7, 'maj'), makeChord(0, 'maj'), majorKey(0)); // => 'authentic'\n * ```\n * @category Functional Harmony\n */\nexport function detectCadence(from: Chord, to: Chord, key: KeyScale): Cadence {\n const tonic = mod12(key.rootPc);\n const fromOffset = mod12(from.rootPc - tonic);\n const toOffset = mod12(to.rootPc - tonic);\n // Deceptive targets: the diatonic submediant (vi at offset 9 in major, VI at\n // offset 8 in minor) plus, in a major key, the borrowed flat-submediant bVI\n // at offset 8.\n const deceptiveTargets = isMinorKey(key) ? [8] : [8, 9];\n if (fromOffset === 7 && toOffset === 0) {\n return 'authentic';\n }\n if (fromOffset === 5 && toOffset === 0) {\n return 'plagal';\n }\n if (fromOffset === 7 && deceptiveTargets.includes(toOffset)) {\n return 'deceptive';\n }\n // A move to the dominant is a half cadence, but a no-root-motion V-to-V repeat\n // is not a cadence at all.\n if (toOffset === 7 && fromOffset !== 7) {\n return 'half';\n }\n return null;\n}\n","/**\n * Recognition: infer a chord name from a set of pitches, or a key from a set of\n * pitch classes. This is the inverse direction of the chord/scale builders,\n * which only go name -> notes.\n */\n\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord, ChordQuality } from '../../theory/chord/index.js';\nimport { chordPitchClasses, chordQualities, makeChord } from '../../theory/chord/index.js';\nimport {\n HARMONIC_MINOR_MASK,\n MAJOR_MASK,\n MELODIC_MINOR_MASK,\n majorKey,\n minorKey,\n NATURAL_MINOR_MASK,\n} from '../../theory/scale/index.js';\n\n/**\n * A candidate chord interpretation of a pitch set.\n *\n * @category Recognition\n */\nexport type ChordMatch = {\n rootPc: number;\n quality: ChordQuality;\n /** Chord tones absent from the input (an incomplete voicing). */\n missingPcs: number[];\n /** Input pitch classes not belonging to the chord. */\n extraPcs: number[];\n /** True when the input pitch-class set equals the chord exactly. */\n exact: boolean;\n /** Inversion implied by the lowest note: 0 root position, 1 first, ... */\n inversion: number;\n /** Bass pitch class when inverted (the lowest note is not the root). */\n bassPc?: number;\n};\n\n/**\n * A candidate key interpretation of a pitch-class set.\n *\n * @category Recognition\n */\nexport type KeyMatch = {\n key: KeyScale;\n mode: 'major' | 'minor';\n /** Fraction of input pitch classes that are in the scale, in [0, 1]. */\n fit: number;\n};\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Unique pitch classes of the input, sorted ascending. */\nfunction uniquePitchClasses(pitches: number[]): number[] {\n return [...new Set(pitches.map(pitchClass))].sort((a, b) => a - b);\n}\n\n/**\n * Identify chords matching a set of pitches.\n *\n * Every input pitch class is tried as a root against every known chord quality.\n * A match is reported when all of the chord's tones are present in the input, or\n * when the only absent tone is the perfect fifth (a common omission in shell\n * voicings); matches are ranked best-first by fewest extra notes, then fewest\n * missing notes, then most specific (largest) chord. An exact match (no extras,\n * no missing) is flagged and ranked first.\n *\n * @param pitches MIDI pitches or bare pitch classes (octave-agnostic).\n * @returns Ranked chord interpretations (may be empty).\n * @example\n * ```ts\n * import { detectChord } from '@libraz/libcantus';\n * const matches = detectChord([60, 64, 67]); // C E G\n * matches[0]; // { rootPc: 0, quality: 'maj', exact: true, ... }\n * ```\n * @category Recognition\n */\nexport function detectChord(pitches: number[]): ChordMatch[] {\n const input = uniquePitchClasses(pitches);\n if (input.length === 0) {\n return [];\n }\n const bassPc = pitchClass(Math.min(...pitches));\n const inputSet = new Set(input);\n const matches: ChordMatch[] = [];\n const qualities = chordQualities();\n for (const rootPc of input) {\n for (const quality of qualities) {\n const chord = makeChord(rootPc, quality);\n const tones = chordPitchClasses(chord);\n const toneSet = new Set(tones);\n const missingPcs = tones.filter((pc) => !inputSet.has(pc));\n // Accept an exact-tone match, or one whose only absent tone is the perfect\n // fifth; any other missing tone (third, sus tone, seventh, ...) rejects.\n const fifthPc = pitchClass(rootPc + 7);\n if (missingPcs.length > 1 || (missingPcs.length === 1 && missingPcs[0] !== fifthPc)) {\n continue;\n }\n const extraPcs = input.filter((pc) => !toneSet.has(pc));\n const bassIndex = chord.intervals.findIndex((iv) => pitchClass(rootPc + iv) === bassPc);\n const inversion = bassIndex > 0 ? bassIndex : 0;\n const match: ChordMatch = {\n rootPc,\n quality,\n missingPcs,\n extraPcs,\n exact: extraPcs.length === 0 && missingPcs.length === 0,\n inversion,\n };\n if (inversion > 0) {\n match.bassPc = bassPc;\n }\n matches.push(match);\n }\n }\n matches.sort((a, b) => {\n if (a.extraPcs.length !== b.extraPcs.length) {\n return a.extraPcs.length - b.extraPcs.length;\n }\n if (a.missingPcs.length !== b.missingPcs.length) {\n return a.missingPcs.length - b.missingPcs.length;\n }\n // Prefer root position (the bass is the chord root) on a tie.\n if ((a.inversion === 0) !== (b.inversion === 0)) {\n return a.inversion === 0 ? -1 : 1;\n }\n const aSize = chordPitchClasses(makeChord(a.rootPc, a.quality)).length;\n const bSize = chordPitchClasses(makeChord(b.rootPc, b.quality)).length;\n return bSize - aSize;\n });\n return matches;\n}\n\n/**\n * The single best chord interpretation of a pitch set, or null if none.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns The top-ranked chord, or null when nothing matches.\n * @example\n * ```ts\n * import { detectChordBest } from '@libraz/libcantus';\n * detectChordBest([60, 64, 67]); // C major triad: { rootPc: 0, quality: 'maj', ... }\n * ```\n * @category Recognition\n */\nexport function detectChordBest(pitches: number[]): Chord | null {\n const best = detectChord(pitches)[0];\n if (!best) {\n return null;\n }\n return makeChord(best.rootPc, best.quality, best.bassPc);\n}\n\n/**\n * Minor-scale variants scored for each minor-key candidate. Scoring against all\n * three lets the raised sixth and seventh (e.g. the leading tone G# in A minor)\n * count toward their own tonic instead of only penalizing it.\n */\nconst MINOR_MASK_VARIANTS = [NATURAL_MINOR_MASK, HARMONIC_MINOR_MASK, MELODIC_MINOR_MASK];\n\n/**\n * Rank major and minor keys by how well they contain a set of pitch classes.\n *\n * The tonic is weighted so that, among equally-fitting keys, the one whose root\n * appears in the input is preferred. Minor candidates are scored against the\n * natural, harmonic, and melodic minor variants and keep the best of the three,\n * so a minor cadence containing the leading tone still resolves to its own\n * tonic; the returned key is always the natural-minor scale. Returns all 24\n * keys ranked best-first, or an empty array for an empty input (mirroring\n * {@link detectChord}).\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns Ranked key interpretations (empty for an empty input).\n * @example\n * ```ts\n * import { detectKey } from '@libraz/libcantus';\n * const keys = detectKey([60, 62, 64, 65, 67, 69, 71]); // C major scale\n * keys[0].mode; // 'major', with keys[0].key.rootPc === 0\n * ```\n * @category Recognition\n */\nexport function detectKey(pitches: number[]): KeyMatch[] {\n const input = uniquePitchClasses(pitches);\n if (input.length === 0) {\n return [];\n }\n const counts = new Map<number, number>();\n for (const pc of pitches.map(pitchClass)) {\n counts.set(pc, (counts.get(pc) ?? 0) + 1);\n }\n const total = pitches.length;\n const results: (KeyMatch & { score: number })[] = [];\n for (let tonic = 0; tonic < 12; tonic += 1) {\n for (const mode of ['major', 'minor'] as const) {\n const key = mode === 'major' ? majorKey(tonic) : minorKey(tonic);\n const masks = mode === 'major' ? [MAJOR_MASK] : MINOR_MASK_VARIANTS;\n // Score each scale variant and keep the best; ties keep the earlier\n // (more diatonic) variant.\n let inScale = 0;\n let weighted = Number.NEGATIVE_INFINITY;\n for (const mask of masks) {\n let variantInScale = 0;\n let variantWeighted = 0;\n for (const pc of input) {\n const offset = (pc - tonic + 12) % 12;\n if ((mask >> offset) & 1) {\n variantInScale += 1;\n }\n }\n for (const [pc, count] of counts) {\n const offset = (pc - tonic + 12) % 12;\n if ((mask >> offset) & 1) {\n variantWeighted += count;\n }\n }\n if (variantWeighted > weighted) {\n weighted = variantWeighted;\n inScale = variantInScale;\n }\n }\n weighted += (counts.get(tonic) ?? 0) * 0.5;\n results.push({\n key,\n mode,\n fit: inScale / input.length,\n score: weighted / total,\n });\n }\n }\n results.sort((a, b) => b.score - a.score);\n return results.map(({ key, mode, fit }) => ({ key, mode, fit }));\n}\n","import type { TimeSignature } from '../../core/meter/index.js';\nimport { beatsPerBar, metricWeight, parseTimeSignature } from '../../core/meter/index.js';\nimport type { KeyScale, NoteEvent } from '../../core/types.js';\nimport type { Chord, ChordSpan } from '../../theory/chord/index.js';\nimport { chordPitchClasses, makeChord } from '../../theory/chord/index.js';\nimport { isScaleTone, majorKey } from '../../theory/scale/index.js';\nimport type { ChordMatch } from '../detect/index.js';\nimport { detectChord, detectChordBest, detectKey } from '../detect/index.js';\nimport type { Cadence } from '../functional/index.js';\nimport { detectCadence } from '../functional/index.js';\n\n/**\n * A chord occupying a half-open beat span.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordSegment = {\n startBeat: number;\n endBeat: number;\n chord: Chord;\n};\n\n/**\n * A beat-indexed sequence of chord segments.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimeline = {\n /** The chord sounding at a beat, or null when no segment covers it. */\n at: (beat: number) => Chord | null;\n segments: ChordSegment[];\n};\n\n/**\n * Build a chord timeline from placed chords.\n *\n * Each chord spans from its `startBeat` to the next chord's `startBeat`; the last\n * chord runs to `totalBeats`. Segments with no positive length (from duplicate\n * onsets or a last chord at or past `totalBeats`) are dropped. `at(beat)` returns\n * the covering segment's chord, or null when the beat lies outside every segment.\n *\n * @param chords Placed chords in time order.\n * @param totalBeats End of the timeline in beats.\n * @returns A queryable chord timeline.\n * @category Arrangement & Analysis\n */\nexport function chordTimelineFromChords(chords: ChordSpan[], totalBeats: number): ChordTimeline {\n const sorted = [...chords].sort((a, b) => a.startBeat - b.startBeat);\n const segments: ChordSegment[] = sorted\n .map((gc, i) => {\n const next = sorted[i + 1];\n const endBeat = Math.max(gc.startBeat, next ? next.startBeat : totalBeats);\n return {\n startBeat: gc.startBeat,\n endBeat,\n chord: makeChord(gc.rootPc, gc.quality, gc.bassPc),\n };\n })\n .filter((seg) => seg.endBeat > seg.startBeat);\n\n return { at: segmentLookup(segments), segments };\n}\n\n/** Build the `at(beat)` lookup over a segment list. */\nfunction segmentLookup(segments: ChordSegment[]): (beat: number) => Chord | null {\n return (beat) => {\n for (const seg of segments) {\n if (beat >= seg.startBeat && beat < seg.endBeat) {\n return seg.chord;\n }\n }\n return null;\n };\n}\n\nconst EPS = 1e-9;\n\n/** Fraction of the strongest pitch-class weight below which a pc is noise. */\nconst NOISE_THRESHOLD_RATIO = 0.2;\n\n/** Maximum number of pitch classes fed to chord detection per window. */\nconst MAX_DETECTION_PCS = 6;\n\n/** Number of top-weighted pitch classes tried in the detection fallback. */\nconst FALLBACK_PCS = 3;\n\n/** Confidence multiplier applied when the chosen chord match is inexact. */\nconst INEXACT_CONFIDENCE_FACTOR = 0.85;\n\n/** Score bonus for a match whose tones are all in the key. */\nconst DIATONIC_BONUS = 0.5;\n\n/** Score bonus for an exact match (no extra and no missing tones). */\nconst EXACT_BONUS = 0.5;\n\n/** Score penalty per extra or missing tone in a match. */\nconst MISMATCH_PENALTY = 0.3;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * Options controlling {@link chordTimelineFromNotes}.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimelineOptions = {\n /** Key context; inferred from the notes with {@link detectKey} when omitted. */\n key?: KeyScale;\n /**\n * Time signature used for metric accents; defaults to 4/4.\n *\n * @defaultValue `4/4`\n */\n ts?: TimeSignature;\n /**\n * Window length in beats per chord slot; defaults to one bar of `ts`.\n *\n * @defaultValue one bar of `ts`\n */\n harmonicRhythm?: number;\n /**\n * End of the analyzed span in beats; defaults to the end of the last note.\n *\n * @defaultValue the end of the last note\n */\n totalBeats?: number;\n};\n\n/**\n * The result of {@link chordTimelineFromNotes}.\n *\n * @category Arrangement & Analysis\n */\nexport type ChordTimelineResult = {\n /** The inferred timeline, with adjacent identical chords merged. */\n timeline: ChordTimeline;\n /** The key used for the analysis (given or inferred). */\n key: KeyScale;\n /** One confidence value in [0, 1] per segment, in segment order. */\n segmentConfidence: number[];\n};\n\n/** A window's inferred chord and its confidence, or null for an empty window. */\ntype WindowChord = {\n chord: Chord;\n confidence: number;\n};\n\n/**\n * Score a chord match against a window's pitch-class weights: a heavily\n * weighted root, in-key tones, and exactness all raise the score; extra or\n * missing tones lower it.\n */\nfunction scoreMatch(\n match: ChordMatch,\n weights: number[],\n maxWeight: number,\n key: KeyScale,\n): number {\n const rootWeight = maxWeight > 0 ? (weights[match.rootPc] ?? 0) / maxWeight : 0;\n const tones = chordPitchClasses(makeChord(match.rootPc, match.quality));\n let score = rootWeight;\n if (tones.every((pc) => isScaleTone(pc, key))) {\n score += DIATONIC_BONUS;\n }\n if (match.exact) {\n score += EXACT_BONUS;\n }\n score -= MISMATCH_PENALTY * (match.extraPcs.length + match.missingPcs.length);\n return score;\n}\n\n/** Confidence of a chord for a window: chord-tone weight over total weight. */\nfunction chordConfidence(\n chord: Chord,\n weights: number[],\n totalWeight: number,\n exact: boolean,\n): number {\n const tones = new Set(chordPitchClasses(chord));\n let chordWeight = 0;\n for (let pc = 0; pc < 12; pc += 1) {\n if (tones.has(pc)) {\n chordWeight += weights[pc] ?? 0;\n }\n }\n const raw = totalWeight > 0 ? chordWeight / totalWeight : 0;\n const confidence = Math.min(1, Math.max(0, raw));\n return exact ? confidence : confidence * INEXACT_CONFIDENCE_FACTOR;\n}\n\n/**\n * Infer the chord sounding in one window from the notes overlapping it.\n *\n * Builds a pitch-class weight histogram (overlap duration x velocity x\n * metric-accent bonus for onsets inside the window), keeps the significantly\n * weighted pitch classes, and picks the best {@link detectChord} match by\n * root weight, key membership, and exactness.\n */\nfunction analyzeWindow(\n notes: NoteEvent[],\n windowStart: number,\n windowEnd: number,\n ts: TimeSignature,\n key: KeyScale,\n): WindowChord | null {\n const weights = new Array<number>(12).fill(0);\n let lowestPitch = Number.POSITIVE_INFINITY;\n for (const note of notes) {\n const noteEnd = note.startBeat + note.durationBeat;\n const overlap = Math.min(noteEnd, windowEnd) - Math.max(note.startBeat, windowStart);\n if (overlap <= EPS) {\n continue;\n }\n const velocityFactor = note.velocity !== undefined ? note.velocity / 127 : 1;\n const onsetInWindow = note.startBeat >= windowStart - EPS && note.startBeat < windowEnd - EPS;\n const accent = onsetInWindow ? 1 + metricWeight(note.startBeat, ts) / 3 : 1;\n const pc = pitchClass(note.pitch);\n weights[pc] = (weights[pc] ?? 0) + overlap * velocityFactor * accent;\n if (note.pitch < lowestPitch) {\n lowestPitch = note.pitch;\n }\n }\n let totalWeight = 0;\n let maxWeight = 0;\n for (const w of weights) {\n totalWeight += w;\n maxWeight = Math.max(maxWeight, w);\n }\n if (totalWeight <= EPS) {\n return null;\n }\n\n // Keep pitch classes with meaningful weight, strongest first.\n const ranked = weights\n .map((weight, pc) => ({ pc, weight }))\n .filter(({ weight }) => weight > 0)\n .sort((a, b) => b.weight - a.weight || a.pc - b.pc);\n const selected = ranked\n .filter(({ weight }) => weight >= maxWeight * NOISE_THRESHOLD_RATIO)\n .slice(0, MAX_DETECTION_PCS)\n .map(({ pc }) => pc);\n\n // Feed detection with the window's true bass as the lowest pitch so inversion\n // detection works; when the bass pc was filtered out as noise, anchor on the\n // heaviest pc instead so no spurious inversion is reported.\n const bassPc = pitchClass(lowestPitch);\n const anchorPc = selected.includes(bassPc) ? bassPc : (selected[0] ?? bassPc);\n const detectionPitches = selected.map((pc) => (pc === anchorPc ? pc : pc + 12));\n\n const matches = detectChord(detectionPitches);\n let bestMatch: ChordMatch | null = null;\n let bestScore = Number.NEGATIVE_INFINITY;\n for (const match of matches) {\n const score = scoreMatch(match, weights, maxWeight, key);\n if (score > bestScore) {\n bestScore = score;\n bestMatch = match;\n }\n }\n if (bestMatch) {\n const chord = makeChord(bestMatch.rootPc, bestMatch.quality, bestMatch.bassPc);\n return { chord, confidence: chordConfidence(chord, weights, totalWeight, bestMatch.exact) };\n }\n\n // Fallback: retry on only the top-weighted pitch classes.\n const fallback = detectChordBest(selected.slice(0, FALLBACK_PCS));\n if (fallback) {\n return { chord: fallback, confidence: chordConfidence(fallback, weights, totalWeight, false) };\n }\n return null;\n}\n\n/** Whether two chords are the same root, quality, and bass. */\nfunction sameChord(a: Chord, b: Chord): boolean {\n return a.rootPc === b.rootPc && a.quality === b.quality && a.bassPc === b.bassPc;\n}\n\n/**\n * Infer a chord timeline from raw multi-track notes.\n *\n * The span `[0, totalBeats)` is sliced into `harmonicRhythm`-beat windows; each\n * window's chord is inferred from a pitch-class weight histogram of the notes\n * overlapping it (weight = overlap duration x velocity x metric-accent bonus\n * for onsets in the window). Adjacent windows carrying the identical chord are\n * merged into one segment; windows with no notes produce no segment, so\n * `at(beat)` returns null there. Each segment carries a confidence in [0, 1]:\n * the fraction of the window weight explained by chord tones, reduced when the\n * match is inexact, and duration-weighted across merged windows.\n *\n * Notes with a zero or negative duration never sound, so they are dropped at\n * ingest: they contribute to neither the key inference, the span, nor any\n * window's histogram.\n *\n * @param notes The notes to analyze (any number of tracks, flattened).\n * @param opts Analysis options; see {@link ChordTimelineOptions}.\n * @returns The inferred timeline, the key used, and per-segment confidences.\n * @throws If `harmonicRhythm` is not positive.\n * @example\n * ```ts\n * import { chordTimelineFromNotes } from '@libraz/libcantus';\n * const notes = [\n * { pitch: 60, startBeat: 0, durationBeat: 2 }, // C\n * { pitch: 64, startBeat: 0, durationBeat: 2 }, // E\n * { pitch: 67, startBeat: 0, durationBeat: 2 }, // G\n * ];\n * const { timeline, key } = chordTimelineFromNotes(notes);\n * timeline.at(0); // the chord inferred over beat 0, or null\n * ```\n * @category Arrangement & Analysis\n */\nexport function chordTimelineFromNotes(\n notes: NoteEvent[],\n opts: ChordTimelineOptions = {},\n): ChordTimelineResult {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const harmonicRhythm = opts.harmonicRhythm ?? beatsPerBar(ts);\n if (!(harmonicRhythm > 0)) {\n throw new Error(`Invalid harmonic rhythm: ${harmonicRhythm}`);\n }\n // Zero/negative-length notes never sound; drop them before any inference.\n const sounding = notes.filter((note) => note.durationBeat > 0);\n const lastNoteEnd = sounding.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);\n const totalBeats = opts.totalBeats ?? lastNoteEnd;\n const key = opts.key ?? detectKey(sounding.map((n) => n.pitch))[0]?.key ?? majorKey(0);\n\n const segments: ChordSegment[] = [];\n const segmentConfidence: number[] = [];\n const windowCount = Math.max(0, Math.ceil(totalBeats / harmonicRhythm - EPS));\n for (let i = 0; i < windowCount; i += 1) {\n const start = i * harmonicRhythm;\n const end = Math.min(start + harmonicRhythm, totalBeats);\n const inferred = analyzeWindow(sounding, start, end, ts, key);\n if (!inferred) {\n continue;\n }\n const last = segments[segments.length - 1];\n if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) < EPS) {\n // Merge into the previous segment, blending confidence by duration.\n const lastLength = last.endBeat - last.startBeat;\n const length = end - start;\n const lastConfidence = segmentConfidence[segmentConfidence.length - 1] ?? 0;\n segmentConfidence[segmentConfidence.length - 1] =\n (lastConfidence * lastLength + inferred.confidence * length) / (lastLength + length);\n last.endBeat = end;\n } else {\n segments.push({ startBeat: start, endBeat: end, chord: inferred.chord });\n segmentConfidence.push(inferred.confidence);\n }\n }\n\n return {\n timeline: { at: segmentLookup(segments), segments },\n key,\n segmentConfidence,\n };\n}\n\n/**\n * A cadence found between two consecutive timeline segments.\n *\n * @category Arrangement & Analysis\n */\nexport type CadenceHit = {\n /** The beat where the cadence arrives (the second chord's onset). */\n atBeat: number;\n type: Exclude<Cadence, null>;\n from: Chord;\n to: Chord;\n};\n\n/**\n * Find cadences between consecutive segments of a chord timeline.\n *\n * Each temporally adjacent segment pair is classified with\n * {@link detectCadence}; pairs forming no cadence are skipped. Segments\n * separated by a gap (a rest in the timeline) are not a chord-to-chord\n * progression, so they are never paired.\n *\n * @param timeline The chord timeline to scan.\n * @param key The prevailing key.\n * @returns The cadences found, in time order.\n * @example\n * ```ts\n * import { chordTimelineFromNotes, detectCadences } from '@libraz/libcantus';\n * const notes = [\n * { pitch: 67, startBeat: 0, durationBeat: 4 }, // G, a dominant\n * { pitch: 60, startBeat: 4, durationBeat: 4 }, // C, the tonic\n * ];\n * const { timeline, key } = chordTimelineFromNotes(notes);\n * const cadences = detectCadences(timeline, key);\n * ```\n * @category Arrangement & Analysis\n */\nexport function detectCadences(timeline: ChordTimeline, key: KeyScale): CadenceHit[] {\n const hits: CadenceHit[] = [];\n for (let i = 1; i < timeline.segments.length; i += 1) {\n const prev = timeline.segments[i - 1];\n const cur = timeline.segments[i];\n if (!prev || !cur) {\n continue;\n }\n if (Math.abs(cur.startBeat - prev.endBeat) > EPS) {\n continue; // A rest separates the chords; no cadential motion across it.\n }\n const type = detectCadence(prev.chord, cur.chord, key);\n if (type !== null) {\n hits.push({ atBeat: cur.startBeat, type, from: prev.chord, to: cur.chord });\n }\n }\n return hits;\n}\n","/**\n * Shared helpers for the arrangement-analysis modules: pooling every track's\n * sounding notes and partitioning a track into monophonic sub-voices, plus the\n * small geometric primitives both the track-role and tension passes rely on.\n */\n\nimport type { NoteEvent } from '../../core/types.js';\nimport type { VoiceNote } from '../voice/index.js';\nimport type { ArrangementTrack, TrackRole } from './tracks.js';\n\n/** Float tolerance for beat boundary comparisons. */\nexport const EPS = 1e-9;\n\n/** A note with the pitch that immediately preceded it in the same sub-voice. */\nexport type PreparedNote = {\n pitch: number;\n prevPitch?: number;\n startBeat: number;\n endBeat: number;\n};\n\n/** One monophonic sub-voice of a track: ordered notes plus sounding spans. */\nexport type PreparedVoice = {\n /** The sub-voice's notes in time order, each with a stable id. */\n voice: VoiceNote[];\n /** The same notes as sounding spans, each carrying its predecessor's pitch. */\n sounding: PreparedNote[];\n};\n\n/** A track prepared for analysis: resolved metadata plus monophonic sub-voices. */\nexport type PreparedTrack = {\n name: string;\n role: TrackRole;\n /**\n * The track's notes partitioned into monophonic sub-voices. Voice analysis\n * assumes one note at a time, so a polyphonic track (e.g. a 'harmony' track\n * playing block chords) is split here; a monophonic track yields exactly one\n * sub-voice.\n */\n voices: PreparedVoice[];\n};\n\n/** Whether a sounding span `[start, end)` covers a beat. */\nexport function covers(note: PreparedNote, beat: number): boolean {\n return beat >= note.startBeat - EPS && beat < note.endBeat - EPS;\n}\n\n/**\n * Every sounding note of every track pooled into one flat list. Zero- and\n * negative-length notes never sound, so they are dropped here (matching the\n * chord-inference ingest in the timeline module).\n */\nexport function poolNotes(tracks: ArrangementTrack[]): NoteEvent[] {\n const notes: NoteEvent[] = [];\n for (const track of tracks) {\n for (const note of track.notes) {\n if (note.durationBeat > 0) {\n notes.push(note);\n }\n }\n }\n return notes;\n}\n\n/**\n * Split a track's ordered notes into monophonic sub-voices.\n *\n * Greedy lane assignment: each note joins the first sub-voice that is free at\n * its onset (its last note has ended), otherwise it opens a new sub-voice. A\n * monophonic track therefore stays a single sub-voice, while block chords fan\n * out into one sub-voice per simultaneous note, keeping every sub-voice's\n * note-to-note adjacency genuinely melodic.\n */\nfunction splitIntoSubVoices(ordered: VoiceNote[]): VoiceNote[][] {\n const lanes: VoiceNote[][] = [];\n for (const note of ordered) {\n const lane = lanes.find((candidate) => {\n const last = candidate[candidate.length - 1];\n return last !== undefined && last.startBeat + last.durationBeat <= note.startBeat + EPS;\n });\n if (lane) {\n lane.push(note);\n } else {\n lanes.push([note]);\n }\n }\n return lanes;\n}\n\n/**\n * Resolve each track's metadata and derive its monophonic sub-voices.\n *\n * Notes are sorted by onset, then pitch, so ordering is deterministic, and ids\n * are assigned in that order. Zero- and negative-length notes never sound and\n * are dropped at ingest. Each track is then partitioned into monophonic\n * sub-voices (see {@link splitIntoSubVoices}); the predecessor pitch used for\n * suspension and parallel detection is the previous note of the same sub-voice,\n * never a simultaneous chord member.\n */\nexport function prepareTracks(tracks: ArrangementTrack[]): PreparedTrack[] {\n let nextId = 0;\n return tracks.map((track, index) => {\n const ordered: VoiceNote[] = track.notes\n .filter((note) => note.durationBeat > 0)\n .sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch)\n .map((note) => ({ ...note, id: nextId++ }));\n const voices: PreparedVoice[] = splitIntoSubVoices(ordered).map((voice) => ({\n voice,\n sounding: voice.map((note, i) => {\n const prev = i > 0 ? voice[i - 1] : undefined;\n return {\n pitch: note.pitch,\n prevPitch: prev?.pitch,\n startBeat: note.startBeat,\n endBeat: note.startBeat + note.durationBeat,\n };\n }),\n }));\n return {\n name: track.name ?? `track ${index + 1}`,\n role: track.role ?? 'other',\n voices,\n };\n });\n}\n","/**\n * Arrangement tension analysis: a coarse harmonic-tension curve sampled at\n * regular beats across a whole multi-track piece, combining the sounding\n * chord's harmonic function, the dissonance of the sounding notes, and their\n * registral span into a single normalized reading.\n */\n\nimport { isStrongBeat, parseTimeSignature, type TimeSignature } from '../../core/meter/index.js';\nimport type { KeyScale } from '../../core/types.js';\nimport { chordPitchClasses } from '../../theory/chord/index.js';\nimport { evaluateSafety, NoteSafety, type SafetyProfile } from '../../theory/safety/index.js';\nimport { functionOf } from '../functional/index.js';\nimport { type ChordTimeline, chordTimelineFromNotes } from '../timeline/index.js';\nimport { covers, EPS, type PreparedTrack, poolNotes, prepareTracks } from './internal.js';\nimport type { ArrangementOptions, ArrangementTrack } from './tracks.js';\n\n/**\n * A tension reading sampled at a beat.\n *\n * @category Arrangement & Analysis\n */\nexport type TensionPoint = {\n beat: number;\n /** Combined tension in [0, 1]. */\n tension: number;\n};\n\n/** Tension contributed by the sounding chord's harmonic function. */\nconst FUNCTION_TENSION: Record<'tonic' | 'subdominant' | 'dominant', number> = {\n tonic: 0,\n subdominant: 0.5,\n dominant: 1,\n};\n\n/** Weight of the harmonic-function term in the combined tension score. */\nconst FUNCTION_WEIGHT = 0.5;\n/** Weight of the non-chord-tone / dissonance term. */\nconst DISSONANCE_WEIGHT = 0.35;\n/** Weight of the registral-span term. */\nconst SPAN_WEIGHT = 0.15;\n/** Pitch span, in semitones, that saturates the span term. */\nconst SPAN_SATURATION = 24;\n\n/** Reduce a pitch to a pitch class in [0, 11]. */\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/** Clamp a value into [0, 1]. */\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\n/**\n * Sample the harmonic tension of an arrangement at regular beats.\n *\n * At each sample beat the tension combines three normalized terms:\n * - the sounding chord's harmonic function (dominant `1`, subdominant `0.5`,\n * tonic or no chord `0`), weighted {@link FUNCTION_WEIGHT};\n * - the dissonance of the sounding notes — the larger of the share of sounding\n * pitches that are not chord tones and the share that {@link evaluateSafety}\n * rates {@link NoteSafety.Dissonant} — weighted {@link DISSONANCE_WEIGHT};\n * - the registral span of the sounding notes, saturating at\n * {@link SPAN_SATURATION} semitones, weighted {@link SPAN_WEIGHT}.\n *\n * The weighted sum is clamped to [0, 1]. The harmony is inferred from all tracks\n * pooled together, so the result is deterministic and self-contained.\n *\n * @param tracks The tracks to sample.\n * @param opts Analysis options plus an optional `step` (default one beat).\n * @returns One {@link TensionPoint} per sampled beat, in beat order.\n * @throws If `step` is not positive.\n * @example\n * ```ts\n * import { tensionCurve } from '@libraz/libcantus';\n * const notes = [{ pitch: 60, startBeat: 0, durationBeat: 4 }];\n * const curve = tensionCurve([{ notes }], { step: 1 });\n * curve; // one { beat, tension } sample per beat, in beat order\n * ```\n * @category Arrangement & Analysis\n */\nexport function tensionCurve(\n tracks: ArrangementTrack[],\n opts: ArrangementOptions & { step?: number } = {},\n): TensionPoint[] {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const profile: SafetyProfile = opts.profile ?? 'pop';\n const step = opts.step ?? 1;\n if (!(step > 0)) {\n throw new Error(`Invalid tension sampling step: ${step}`);\n }\n\n const pooled = poolNotes(tracks);\n const totalBeats = pooled.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);\n const { timeline, key } = chordTimelineFromNotes(pooled, {\n key: opts.key,\n ts,\n harmonicRhythm: opts.harmonicRhythm,\n });\n\n const prepared = prepareTracks(tracks);\n const points: TensionPoint[] = [];\n const sampleCount = Math.max(0, Math.ceil(totalBeats / step - EPS));\n for (let i = 0; i < sampleCount; i += 1) {\n const beat = i * step;\n points.push({ beat, tension: sampleTension(prepared, timeline, key, ts, profile, beat) });\n }\n return points;\n}\n\n/** All sounding notes across every track at a beat, tagged with their track. */\nfunction allSounding(prepared: PreparedTrack[], beat: number): { pitch: number; track: number }[] {\n const out: { pitch: number; track: number }[] = [];\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n for (const subVoice of track.voices) {\n for (const note of subVoice.sounding) {\n if (covers(note, beat)) {\n out.push({ pitch: note.pitch, track: t });\n }\n }\n }\n }\n return out;\n}\n\n/** Combine the harmonic, dissonance, and span terms at one sample beat. */\nfunction sampleTension(\n prepared: PreparedTrack[],\n timeline: ChordTimeline,\n key: KeyScale,\n ts: TimeSignature,\n profile: SafetyProfile,\n beat: number,\n): number {\n const sounding = allSounding(prepared, beat);\n if (sounding.length === 0) {\n return 0;\n }\n const chord = timeline.at(beat);\n const functionScore = chord ? FUNCTION_TENSION[functionOf(chord, key)] : 0;\n\n const chordPcs = chord ? new Set(chordPitchClasses(chord)) : null;\n const strongBeat = isStrongBeat(beat, ts);\n let nonChord = 0;\n let dissonant = 0;\n for (let i = 0; i < sounding.length; i += 1) {\n const voice = sounding[i];\n if (!voice) {\n continue;\n }\n // Non-chord-tone share only applies when a chord is sounding; at a timeline\n // gap there is no reference harmony, so vertical dissonance alone drives the\n // dissonance term (the chord function term is already 0 there).\n if (chordPcs && !chordPcs.has(pitchClass(voice.pitch))) {\n nonChord += 1;\n }\n const others = sounding.filter((_, j) => j !== i).map((s) => ({ pitch: s.pitch }));\n const result = evaluateSafety({\n profile,\n candidatePitch: voice.pitch,\n chord,\n key,\n otherVoices: others,\n strongBeat,\n });\n if (result.safety === NoteSafety.Dissonant) {\n dissonant += 1;\n }\n }\n const dissonanceScore = Math.max(nonChord, dissonant) / sounding.length;\n\n let low = Number.POSITIVE_INFINITY;\n let high = Number.NEGATIVE_INFINITY;\n for (const voice of sounding) {\n low = Math.min(low, voice.pitch);\n high = Math.max(high, voice.pitch);\n }\n const spanScore = Math.min(1, (high - low) / SPAN_SATURATION);\n\n return clamp01(\n FUNCTION_WEIGHT * functionScore + DISSONANCE_WEIGHT * dissonanceScore + SPAN_WEIGHT * spanScore,\n );\n}\n","import type { KeyScale, NoteEvent } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { chordPitchClasses, chordToneRole } from '../../theory/chord/index.js';\nimport {\n createsVerticalDissonance,\n isLeadingToneResolution,\n} from '../../theory/counterpoint/index.js';\nimport type { VoiceSnapshot } from '../../theory/safety/index.js';\n\n/**\n * A theory annotation attached to a note.\n *\n * @category Arrangement & Analysis\n */\nexport type TheoryLabel =\n | { kind: 'chordTone'; role: 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' }\n | { kind: 'tension'; degree: 9 | 11 | 13 }\n | { kind: 'avoid' }\n | { kind: 'passing' }\n | { kind: 'neighbor' }\n | { kind: 'suspension'; type: 'sus4-3' | 'sus7-6' | 'sus9-8' | 'sus2-3'; resolveTo: number }\n | { kind: 'anticipation' }\n | { kind: 'escape' }\n | { kind: 'needsResolution'; resolveTo: number }\n | { kind: 'leadingTone'; resolveTo: number };\n\n/**\n * A note with its theory labels and a short rationale.\n *\n * @category Arrangement & Analysis\n */\nexport type AnalyzedNote = {\n noteId: number;\n labels: TheoryLabel[];\n rationale?: string;\n};\n\n/**\n * A single note in a monophonic voice: a {@link NoteEvent} with a stable id.\n *\n * @category Arrangement & Analysis\n */\nexport type VoiceNote = NoteEvent & { id: number };\n\n/** Float tolerance for beat comparisons. */\nconst EPS = 1e-9;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction intervalAboveRoot(pitch: number, chord: Chord): number {\n return (((pitchClass(pitch) - pitchClass(chord.rootPc)) % 12) + 12) % 12;\n}\n\n/**\n * Interval class of a pitch above the actual sounding bass.\n *\n * Suspension figures (4-3, 7-6, 9-8) are named for the interval above the bass,\n * not the chord root, so this prefers the lowest pitch among the other sounding\n * voices when one lies below the note. Without a lower sounding voice it falls\n * back to the chord's bass pitch class (or root in root position).\n */\nfunction intervalAboveBass(pitch: number, others: VoiceSnapshot[], chord: Chord): number {\n let bass = Number.POSITIVE_INFINITY;\n for (const ov of others) {\n bass = Math.min(bass, ov.pitch);\n }\n if (Number.isFinite(bass) && bass < pitch) {\n return (((pitch - bass) % 12) + 12) % 12;\n }\n const ref = chord.bassPc ?? chord.rootPc;\n return (((pitchClass(pitch) - pitchClass(ref)) % 12) + 12) % 12;\n}\n\n/**\n * Map an interval class above the root to its extended-tension scale degree:\n * a flat/natural ninth (1 or 2) to 9, an eleventh (5 or 6) to 11, and a\n * thirteenth (8 or 9) to 13.\n */\nfunction tensionDegree(ic: number): 9 | 11 | 13 {\n if (ic === 1 || ic === 2) {\n return 9;\n }\n if (ic === 5 || ic === 6) {\n return 11;\n }\n return 13;\n}\n\nfunction isChordMember(pitch: number, chord: Chord | null): boolean {\n return chord ? chordPitchClasses(chord).includes(pitchClass(pitch)) : false;\n}\n\nfunction isStep(a: number, b: number): boolean {\n const d = Math.abs(a - b);\n return d === 1 || d === 2;\n}\n\n/**\n * Classify a suspension figure from the interval class above the sounding bass\n * (`ic`) and the resolution direction (`delta`, positive when resolving upward).\n */\nfunction suspensionType(ic: number, delta: number): TheoryLabel & { kind: 'suspension' } {\n let type: 'sus4-3' | 'sus7-6' | 'sus9-8' | 'sus2-3';\n if (delta > 0) {\n type = 'sus2-3';\n } else if (ic === 2) {\n type = 'sus9-8';\n } else if (ic === 10 || ic === 11) {\n type = 'sus7-6';\n } else {\n type = 'sus4-3';\n }\n return { kind: 'suspension', type, resolveTo: 0 };\n}\n\nfunction stepResolution(pitch: number, chord: Chord): number | undefined {\n for (let delta = 1; delta <= 2; delta += 1) {\n if (isChordMember(pitch - delta, chord)) {\n return pitch - delta;\n }\n }\n return undefined;\n}\n\n/**\n * Label every note of a voice with its theory roles.\n *\n * Each note is classified against the chord sounding at its beat. Chord tones\n * get a role label; non-chord tones are matched, in order, as suspensions\n * (prepared by an identical consonant pitch and resolving by step), passing\n * tones, neighbors, anticipations, and escape tones, then fall back to tension,\n * avoid, or an unresolved-dissonance label. Leading-tone resolutions are noted\n * additionally.\n *\n * The voice is expected to be monophonic (one note at a time). Notes sharing an\n * onset are treated as simultaneous cluster members, not melodic neighbors, so\n * they receive no melodic labels (suspension, passing, neighbor, anticipation,\n * escape) — only harmonic ones. Callers with truly polyphonic material should\n * split it into monophonic sub-voices first, as `analyzeArrangement` does.\n *\n * @param voice The monophonic voice, in time order.\n * @param chordAtBeat Chord sounding at a given beat, or null.\n * @param key Key context for leading-tone detection.\n * @param otherVoicesAtBeat Other sounding voices at a given beat.\n * @returns One annotation per input note.\n * @example\n * ```ts\n * import { analyzeVoice, makeChord, majorKey } from '@libraz/libcantus';\n * const voice = [\n * { id: 0, pitch: 60, startBeat: 0, durationBeat: 1 },\n * { id: 1, pitch: 62, startBeat: 1, durationBeat: 1 },\n * { id: 2, pitch: 64, startBeat: 2, durationBeat: 1 },\n * ];\n * const cMajor = makeChord(0, 'maj');\n * const labels = analyzeVoice(voice, () => cMajor, majorKey(0), () => []);\n * labels; // one AnalyzedNote per input note, in the same order\n * ```\n * @category Arrangement & Analysis\n */\nexport function analyzeVoice(\n voice: VoiceNote[],\n chordAtBeat: (beat: number) => Chord | null,\n key: KeyScale,\n otherVoicesAtBeat: (beat: number) => VoiceSnapshot[],\n): AnalyzedNote[] {\n const result: AnalyzedNote[] = [];\n\n for (let i = 0; i < voice.length; i += 1) {\n const note = voice[i];\n if (!note) {\n continue;\n }\n const prevNote = i > 0 ? voice[i - 1] : undefined;\n const nextNote = i + 1 < voice.length ? voice[i + 1] : undefined;\n // A neighboring note sharing this note's onset is a simultaneous cluster\n // member, not a melodic predecessor/successor; treating it as one would\n // fabricate passing/suspension figures, so it is dropped here.\n const prev =\n prevNote !== undefined && prevNote.startBeat < note.startBeat - EPS ? prevNote : undefined;\n const next =\n nextNote !== undefined && nextNote.startBeat > note.startBeat + EPS ? nextNote : undefined;\n const chord = chordAtBeat(note.startBeat);\n const labels: TheoryLabel[] = [];\n const member = isChordMember(note.pitch, chord);\n let handled = false;\n\n if (chord && member) {\n const role = chordToneRole(note.pitch, chord);\n if (role) {\n labels.push({ kind: 'chordTone', role });\n } else {\n const ic = intervalAboveRoot(note.pitch, chord);\n labels.push({ kind: 'tension', degree: tensionDegree(ic) });\n }\n handled = true;\n }\n\n if (!handled && chord && prev && next) {\n const prevChord = chordAtBeat(prev.startBeat);\n const prepared = prev.pitch === note.pitch && isChordMember(prev.pitch, prevChord);\n const resolves = isStep(next.pitch, note.pitch);\n const others = otherVoicesAtBeat(note.startBeat);\n const verticallyDissonant = others.some((ov) =>\n createsVerticalDissonance(note.pitch, ov.pitch, true),\n );\n if (prepared && verticallyDissonant && resolves) {\n const ic = intervalAboveBass(note.pitch, others, chord);\n const sus = suspensionType(ic, next.pitch - note.pitch);\n sus.resolveTo = next.pitch;\n labels.push(sus);\n handled = true;\n }\n }\n\n if (!handled && chord && prev && next) {\n const prevMember = isChordMember(prev.pitch, chordAtBeat(prev.startBeat));\n const nextMember = isChordMember(next.pitch, chordAtBeat(next.startBeat));\n const up = note.pitch - prev.pitch > 0;\n const contInto = next.pitch - note.pitch > 0;\n const sameDir = note.pitch !== prev.pitch && next.pitch !== note.pitch && up === contInto;\n if (\n prevMember &&\n nextMember &&\n !member &&\n isStep(note.pitch, prev.pitch) &&\n isStep(next.pitch, note.pitch) &&\n sameDir\n ) {\n labels.push({ kind: 'passing' });\n handled = true;\n }\n }\n\n if (\n !handled &&\n chord &&\n prev &&\n next &&\n !member &&\n prev.pitch === next.pitch &&\n isChordMember(prev.pitch, chordAtBeat(prev.startBeat)) &&\n isStep(note.pitch, prev.pitch)\n ) {\n labels.push({ kind: 'neighbor' });\n handled = true;\n }\n\n if (!handled && chord && next && !member && note.pitch === next.pitch) {\n const nextChord = chordAtBeat(next.startBeat);\n if (isChordMember(next.pitch, nextChord)) {\n labels.push({ kind: 'anticipation' });\n handled = true;\n }\n }\n\n if (!handled && chord && prev && next && !member) {\n const prevMember = isChordMember(prev.pitch, chordAtBeat(prev.startBeat));\n const nextMember = isChordMember(next.pitch, chordAtBeat(next.startBeat));\n const stepFromPrev = isStep(note.pitch, prev.pitch);\n const leapToNext = Math.abs(next.pitch - note.pitch) >= 3;\n const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;\n if (prevMember && nextMember && stepFromPrev && leapToNext && opposite) {\n labels.push({ kind: 'escape' });\n handled = true;\n }\n }\n\n if (!handled && chord && !member) {\n const ic = intervalAboveRoot(note.pitch, chord);\n const isTension = ic === 2 || ic === 5 || ic === 9;\n const avoid =\n (ic === 5 && chord.intervals.includes(4) && !chord.intervals.includes(5)) ||\n (ic === 11 && chord.intervals.includes(4) && chord.intervals.includes(10));\n if (avoid) {\n labels.push({ kind: 'avoid' });\n const resolveTo = stepResolution(note.pitch, chord);\n if (resolveTo !== undefined) {\n labels.push({ kind: 'needsResolution', resolveTo });\n }\n } else if (isTension) {\n labels.push({ kind: 'tension', degree: tensionDegree(ic) });\n } else {\n const resolveTo = stepResolution(note.pitch, chord);\n if (resolveTo !== undefined) {\n labels.push({ kind: 'needsResolution', resolveTo });\n }\n }\n }\n\n if (next && isLeadingToneResolution(note.pitch, next.pitch, key)) {\n labels.push({ kind: 'leadingTone', resolveTo: next.pitch });\n }\n\n result.push({ noteId: note.id, labels, rationale: describe(labels) });\n }\n\n return result;\n}\n\n/** Build a short rationale from a note's primary label. */\nfunction describe(labels: TheoryLabel[]): string {\n const primary = labels[0];\n if (!primary) {\n return 'Unclassified note';\n }\n switch (primary.kind) {\n case 'chordTone':\n return `Chord ${primary.role}`;\n case 'tension':\n return `${primary.degree}th tension`;\n case 'avoid':\n return 'Avoid note';\n case 'passing':\n return 'Passing tone between chord tones';\n case 'neighbor':\n return 'Neighbor tone';\n case 'suspension':\n return `Suspension (${primary.type})`;\n case 'anticipation':\n return 'Anticipation of the next chord';\n case 'escape':\n return 'Escape tone';\n case 'needsResolution':\n return 'Unresolved dissonance';\n case 'leadingTone':\n return 'Leading tone resolving to the tonic';\n }\n}\n","/**\n * Arrangement track-role analysis: a single harmony is inferred from every\n * track's notes pooled together, each track is then analysed against that shared\n * harmony, and notes that clash with the sounding chord are collected as\n * conflicts.\n */\n\nimport { isStrongBeat, parseTimeSignature, type TimeSignature } from '../../core/meter/index.js';\nimport type { KeyScale, NoteEvent } from '../../core/types.js';\nimport {\n evaluateSafety,\n NoteSafety,\n type SafetyProfile,\n type VoiceSnapshot,\n} from '../../theory/safety/index.js';\nimport {\n type CadenceHit,\n type ChordTimeline,\n chordTimelineFromNotes,\n detectCadences,\n} from '../timeline/index.js';\nimport { type AnalyzedNote, analyzeVoice, type VoiceNote } from '../voice/index.js';\nimport { covers, EPS, type PreparedTrack, poolNotes, prepareTracks } from './internal.js';\n\n/**\n * The musical role a track plays in the arrangement.\n *\n * @category Arrangement & Analysis\n */\nexport type TrackRole = 'melody' | 'harmony' | 'bass' | 'other';\n\n/**\n * One input track: its notes plus optional name and role.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementTrack = {\n name?: string;\n role?: TrackRole;\n notes: NoteEvent[];\n};\n\n/**\n * A track after analysis: its resolved name, role, and per-note annotations.\n *\n * @category Arrangement & Analysis\n */\nexport type TrackAnalysis = {\n name: string;\n role: TrackRole;\n /** One {@link AnalyzedNote} per note, labelled against the inferred chords. */\n notes: AnalyzedNote[];\n};\n\n/**\n * A note that clashes with the harmony sounding beneath it.\n *\n * @category Arrangement & Analysis\n */\nexport type Conflict = {\n beat: number;\n trackName: string;\n pitch: number;\n /** The clash severity: {@link NoteSafety.Warning} or {@link NoteSafety.Dissonant}. */\n safety: NoteSafety;\n /** {@link import('../safety/index.js').SafetyResult.reasons} bitmask. */\n reasons: number;\n rationale?: string;\n};\n\n/**\n * The full result of {@link analyzeArrangement}.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementAnalysis = {\n key: KeyScale;\n timeline: ChordTimeline;\n segmentConfidence: number[];\n cadences: CadenceHit[];\n tracks: TrackAnalysis[];\n /** Notes clashing with the sounding harmony, worst severity first. */\n conflicts: Conflict[];\n};\n\n/**\n * Options controlling {@link analyzeArrangement} and {@link tensionCurve}.\n *\n * @category Arrangement & Analysis\n */\nexport type ArrangementOptions = {\n /** Key context; inferred from the pooled notes when omitted. */\n key?: KeyScale;\n /**\n * Time signature; defaults to 4/4.\n *\n * @defaultValue `4/4`\n */\n ts?: TimeSignature;\n /**\n * Chord-slot length in beats; defaults to one bar of `ts`.\n *\n * @defaultValue one bar of `ts`\n */\n harmonicRhythm?: number;\n /**\n * Safety profile used for conflict detection; defaults to `pop`.\n *\n * @defaultValue `'pop'`\n */\n profile?: SafetyProfile;\n};\n\n/**\n * Sounding pitches of every sub-voice at a beat, excluding one sub-voice.\n *\n * Only the sub-voice under analysis is excluded — sibling sub-voices of the\n * same track are included, so dissonant clusters inside a single polyphonic\n * track are still detected.\n */\nfunction otherVoicesSounding(\n prepared: PreparedTrack[],\n excludeTrack: number,\n excludeVoice: number,\n beat: number,\n): VoiceSnapshot[] {\n const out: VoiceSnapshot[] = [];\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n for (let v = 0; v < track.voices.length; v += 1) {\n if (t === excludeTrack && v === excludeVoice) {\n continue;\n }\n const subVoice = track.voices[v];\n if (!subVoice) {\n continue;\n }\n for (const note of subVoice.sounding) {\n if (!covers(note, beat)) {\n continue;\n }\n const snap: VoiceSnapshot = { pitch: note.pitch };\n if (note.prevPitch !== undefined) {\n snap.prevPitch = note.prevPitch;\n }\n out.push(snap);\n }\n }\n }\n return out;\n}\n\n/**\n * The beats at which a note must be checked against the harmony: its onset,\n * plus the onset of every later chord segment the note sustains across. Each\n * crossed segment is visited exactly once (at its own start), so a boundary\n * beat is never evaluated twice for the same note.\n */\nfunction evaluationBeats(note: VoiceNote, timeline: ChordTimeline): number[] {\n const noteEnd = note.startBeat + note.durationBeat;\n const beats = [note.startBeat];\n for (const segment of timeline.segments) {\n if (segment.startBeat > note.startBeat + EPS && segment.startBeat < noteEnd - EPS) {\n beats.push(segment.startBeat);\n }\n }\n return beats;\n}\n\n/**\n * Analyse a whole arrangement against a single inferred harmony.\n *\n * The chord timeline and key are inferred from the pooled notes of every track\n * (see {@link chordTimelineFromNotes}); pooling all voices is robust even when\n * roles are absent or a track doubles the harmony, so it is preferred over\n * deriving the harmony from a subset. Zero- and negative-length notes never\n * sound, so they are dropped at ingest and appear in neither the annotations\n * nor the conflicts.\n *\n * Voice analysis assumes one monophonic voice at a time, so each track is\n * first partitioned into monophonic sub-voices (a polyphonic block-chord track\n * fans out into one sub-voice per simultaneous note; a monophonic track is\n * unaffected). Each sub-voice is labelled note-by-note against the harmony\n * with {@link analyzeVoice}, seeing every other sub-voice — including siblings\n * within the same track — as its accompaniment. Every note is then re-checked\n * with {@link evaluateSafety} at its onset and again at each chord change it\n * sustains across, so a held note that clashes with a later chord is caught:\n * evaluations that are not {@link NoteSafety.Safe} become conflicts, one per\n * clashing beat, sorted worst severity first and then by beat.\n *\n * @param tracks The tracks to analyse.\n * @param opts Analysis options; see {@link ArrangementOptions}.\n * @returns The inferred harmony, per-track annotations, cadences, and conflicts.\n * @example\n * ```ts\n * import { analyzeArrangement } from '@libraz/libcantus';\n * const melody = [\n * { pitch: 60, startBeat: 0, durationBeat: 2 },\n * { pitch: 67, startBeat: 2, durationBeat: 2 },\n * ];\n * const { key, conflicts } = analyzeArrangement([{ role: 'melody', notes: melody }]);\n * conflicts; // notes clashing with the inferred harmony, worst severity first\n * ```\n * @category Arrangement & Analysis\n */\nexport function analyzeArrangement(\n tracks: ArrangementTrack[],\n opts: ArrangementOptions = {},\n): ArrangementAnalysis {\n const ts = opts.ts ?? parseTimeSignature('4/4');\n const profile: SafetyProfile = opts.profile ?? 'pop';\n const pooled = poolNotes(tracks);\n\n const { timeline, key, segmentConfidence } = chordTimelineFromNotes(pooled, {\n key: opts.key,\n ts,\n harmonicRhythm: opts.harmonicRhythm,\n });\n const cadences = detectCadences(timeline, key);\n const prepared = prepareTracks(tracks);\n\n const trackAnalyses: TrackAnalysis[] = [];\n const conflicts: Conflict[] = [];\n\n for (let t = 0; t < prepared.length; t += 1) {\n const track = prepared[t];\n if (!track) {\n continue;\n }\n const notes: AnalyzedNote[] = [];\n for (let v = 0; v < track.voices.length; v += 1) {\n const subVoice = track.voices[v];\n if (!subVoice) {\n continue;\n }\n notes.push(\n ...analyzeVoice(subVoice.voice, timeline.at, key, (beat) =>\n otherVoicesSounding(prepared, t, v, beat),\n ),\n );\n\n for (const note of subVoice.voice) {\n for (const beat of evaluationBeats(note, timeline)) {\n const result = evaluateSafety({\n profile,\n candidatePitch: note.pitch,\n chord: timeline.at(beat),\n key,\n otherVoices: otherVoicesSounding(prepared, t, v, beat),\n strongBeat: isStrongBeat(beat, ts),\n });\n if (result.safety !== NoteSafety.Safe) {\n const conflict: Conflict = {\n beat,\n trackName: track.name,\n pitch: note.pitch,\n safety: result.safety,\n reasons: result.reasons,\n };\n if (result.rationale !== undefined) {\n conflict.rationale = result.rationale;\n }\n conflicts.push(conflict);\n }\n }\n }\n }\n // Sub-voice results interleave; restore the track's onset-then-pitch order.\n notes.sort((a, b) => a.noteId - b.noteId);\n trackAnalyses.push({ name: track.name, role: track.role, notes });\n }\n\n conflicts.sort((a, b) => b.safety - a.safety || a.beat - b.beat);\n\n return { key, timeline, segmentConfidence, cadences, tracks: trackAnalyses, conflicts };\n}\n","/**\n * Pitch spelling: letter-name notes, enharmonic-aware conversion, and spelled\n * intervals.\n *\n * The rest of the library works in pitch classes (0..11), which cannot tell a\n * G# from an Ab or an augmented fourth from a diminished fifth. This module adds\n * an explicit spelling layer — a note is a diatonic letter plus a chromatic\n * alteration — so interval quality (P/M/m/A/d) and enharmonic identity are\n * preserved.\n */\n\n/** Semitone offset of each natural letter above C: C D E F G A B. */\nconst LETTER_SEMITONES = [0, 2, 4, 5, 7, 9, 11] as const;\n\n/** Letter glyphs indexed by letter number (0 = C .. 6 = B). */\nconst LETTER_NAMES = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] as const;\n\n/**\n * A spelled note: a diatonic letter, a chromatic alteration, and an optional\n * octave.\n *\n * - `letter` is 0..6 for C..B.\n * - `alter` is the number of semitones of alteration: -2 double-flat, -1 flat,\n * 0 natural, +1 sharp, +2 double-sharp.\n * - `octave` follows scientific pitch notation (middle C = C4 = MIDI 60). When\n * absent, the note denotes a bare pitch class.\n *\n * @category Pitch & Intervals\n */\nexport type Note = {\n letter: number;\n alter: number;\n octave?: number;\n};\n\n/**\n * A spelled interval: a diatonic number, a quality label, and its semitone span.\n *\n * @category Pitch & Intervals\n */\nexport type SpelledInterval = {\n /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */\n number: number;\n /** Quality label: 'P', 'M', 'm', or repeated 'A'/'d' for (multiply) aug/dim. */\n quality: string;\n /** Signed semitone distance from the first note to the second. */\n semitones: number;\n};\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/** Reduce any integer to [0, 7). */\nfunction mod7(n: number): number {\n return ((n % 7) + 7) % 7;\n}\n\n/**\n * Parse scientific pitch notation into a {@link Note}.\n *\n * Accepts a letter (case-insensitive) followed by any number of same-direction\n * accidentals and an optional octave, e.g. `\"C\"`, `\"C#4\"`, `\"Bb\"`, `\"F##3\"`,\n * `\"Ebb2\"`. Both `#` and `x` (double-sharp) are accepted for sharps; `b` for\n * flats. Mixing sharps and flats (e.g. `\"C#b\"`) is rejected.\n *\n * @param text The note text.\n * @returns The parsed note.\n * @throws If the text is not a valid note.\n * @example\n * ```ts\n * import { parseNote, noteToMidi } from '@libraz/libcantus';\n * const n = parseNote('C#4');\n * noteToMidi(n); // 61\n * ```\n * @category Pitch & Intervals\n */\nexport function parseNote(text: string): Note {\n const match = /^([A-Ga-g])([#x]*|b*)(-?\\d+)?$/.exec(text.trim());\n if (!match) {\n throw new Error(`Invalid note: ${text}`);\n }\n const letterGlyph = (match[1] ?? '').toUpperCase();\n const letter = LETTER_NAMES.indexOf(letterGlyph as (typeof LETTER_NAMES)[number]);\n let alter = 0;\n for (const ch of match[2] ?? '') {\n if (ch === '#') {\n alter += 1;\n } else if (ch === 'x') {\n alter += 2;\n } else if (ch === 'b') {\n alter -= 1;\n }\n }\n const note: Note = { letter, alter };\n if (match[3] !== undefined) {\n note.octave = Number.parseInt(match[3], 10);\n }\n return note;\n}\n\n/** Render an alteration as accidental glyphs (`##`, `b`, empty for natural). */\nfunction formatAlter(alter: number): string {\n if (alter > 0) {\n return '#'.repeat(alter);\n }\n if (alter < 0) {\n return 'b'.repeat(-alter);\n }\n return '';\n}\n\n/**\n * Render a {@link Note} as scientific pitch notation.\n *\n * @param note The note to format.\n * @returns The note text, including the octave when present.\n * @example\n * ```ts\n * import { formatNote, parseNote } from '@libraz/libcantus';\n * formatNote(parseNote('C#4')); // 'C#4'\n * ```\n * @category Pitch & Intervals\n */\nexport function formatNote(note: Note): string {\n const glyph = LETTER_NAMES[mod7(note.letter)] ?? 'C';\n const octave = note.octave === undefined ? '' : String(note.octave);\n return `${glyph}${formatAlter(note.alter)}${octave}`;\n}\n\n/**\n * Pitch class (0..11) of a note, ignoring octave.\n *\n * @param note The note.\n * @returns The pitch class.\n * @example\n * ```ts\n * import { noteToPitchClass, parseNote } from '@libraz/libcantus';\n * noteToPitchClass(parseNote('Db')); // 1\n * ```\n * @category Pitch & Intervals\n */\nexport function noteToPitchClass(note: Note): number {\n const natural = LETTER_SEMITONES[mod7(note.letter)] ?? 0;\n return mod12(natural + note.alter);\n}\n\n/**\n * MIDI number of a note (middle C = C4 = 60).\n *\n * @param note The note; must carry an octave.\n * @returns The MIDI number.\n * @throws If the note has no octave.\n * @example\n * ```ts\n * import { noteToMidi, parseNote } from '@libraz/libcantus';\n * noteToMidi(parseNote('A4')); // 69\n * ```\n * @category Pitch & Intervals\n */\nexport function noteToMidi(note: Note): number {\n if (note.octave === undefined) {\n throw new Error('noteToMidi requires an octave');\n }\n const natural = LETTER_SEMITONES[mod7(note.letter)] ?? 0;\n return (note.octave + 1) * 12 + natural + note.alter;\n}\n\n/** Preferred spelling when naming a black key from a bare MIDI number. */\nconst SHARP_SPELLING: readonly [number, number][] = [\n [0, 0],\n [0, 1],\n [1, 0],\n [1, 1],\n [2, 0],\n [3, 0],\n [3, 1],\n [4, 0],\n [4, 1],\n [5, 0],\n [5, 1],\n [6, 0],\n];\n\nconst FLAT_SPELLING: readonly [number, number][] = [\n [0, 0],\n [1, -1],\n [1, 0],\n [2, -1],\n [2, 0],\n [3, 0],\n [4, -1],\n [4, 0],\n [5, -1],\n [5, 0],\n [6, -1],\n [6, 0],\n];\n\n/**\n * Name a MIDI number as a {@link Note}, choosing sharp or flat spelling.\n *\n * The input is rounded to the nearest integer but is not clamped to the MIDI\n * range 0..127: out-of-range values extrapolate linearly (e.g. `-1` -> `B-2`,\n * `128` -> `G#9`) and remain an exact inverse of {@link noteToMidi}.\n *\n * @param midi The MIDI number.\n * @param spelling Whether to prefer sharps or flats for black keys.\n * @returns The spelled note, with octave.\n * @example\n * ```ts\n * import { midiToNote, formatNote } from '@libraz/libcantus';\n * formatNote(midiToNote(61)); // 'C#4'\n * formatNote(midiToNote(61, 'flat')); // 'Db4'\n * ```\n * @category Pitch & Intervals\n */\nexport function midiToNote(midi: number, spelling: 'sharp' | 'flat' = 'sharp'): Note {\n const rounded = Math.round(midi);\n const pc = mod12(rounded);\n const octave = Math.floor(rounded / 12) - 1;\n const table = spelling === 'sharp' ? SHARP_SPELLING : FLAT_SPELLING;\n const entry = table[pc] ?? [0, 0];\n return { letter: entry[0], alter: entry[1], octave };\n}\n\n/** Reference semitone span of a perfect/major simple interval by diatonic number. */\nconst SIMPLE_REFERENCE = [0, 0, 2, 4, 5, 7, 9, 11] as const;\n\n/** Whether a simple diatonic number (1..7 within an octave) is a perfect kind. */\nfunction isPerfectNumber(simpleNumber: number): boolean {\n return simpleNumber === 1 || simpleNumber === 4 || simpleNumber === 5;\n}\n\n/** Quality label from a diatonic number and its actual semitone span. */\nfunction qualityFromSpan(numberValue: number, semitones: number): string {\n const octaves = Math.floor((numberValue - 1) / 7);\n const simple = numberValue - 7 * octaves;\n const reference = (SIMPLE_REFERENCE[simple] ?? 0) + 12 * octaves;\n const delta = semitones - reference;\n if (isPerfectNumber(simple)) {\n if (delta === 0) {\n return 'P';\n }\n return delta > 0 ? 'A'.repeat(delta) : 'd'.repeat(-delta);\n }\n if (delta === 0) {\n return 'M';\n }\n if (delta === -1) {\n return 'm';\n }\n return delta > 0 ? 'A'.repeat(delta) : 'd'.repeat(-delta - 1);\n}\n\n/** Diatonic ladder index of a note (letter + 7 * octave when octave-bearing). */\nfunction diatonicIndex(note: Note): number {\n return mod7(note.letter) + 7 * (note.octave ?? 0);\n}\n\n/**\n * The spelled interval from one note to another.\n *\n * When both notes carry octaves, the interval reflects their full signed\n * distance (so `C4 -> C5` is a perfect octave). When either lacks an octave the\n * interval is measured within a single ascending octave from `a` to `b`.\n *\n * @param a The lower/first note.\n * @param b The upper/second note.\n * @returns The diatonic number, quality, and semitone span.\n * @example\n * ```ts\n * import { spelledInterval, parseNote } from '@libraz/libcantus';\n * spelledInterval(parseNote('C4'), parseNote('G4'));\n * // { number: 5, quality: 'P', semitones: 7 }\n * ```\n * @category Pitch & Intervals\n */\nexport function spelledInterval(a: Note, b: Note): SpelledInterval {\n const octaved = a.octave !== undefined && b.octave !== undefined;\n let letterSteps: number;\n let semitones: number;\n if (octaved) {\n letterSteps = diatonicIndex(b) - diatonicIndex(a);\n // Signed pitch distance from a to b, so a note below a yields a negative span.\n semitones = noteToMidi(b) - noteToMidi(a);\n } else {\n letterSteps = mod7(b.letter - a.letter);\n let rawSemis = mod12(noteToPitchClass(b) - noteToPitchClass(a));\n // Lift the chromatic span into the octave nearest the diatonic reference so\n // wraparound intervals stay consistent with the diatonic number instead of\n // collapsing modulo 12. The correction is bidirectional: an upward wrap\n // (e.g. Ab -> G# = augmented seventh) adds an octave, while a same-letter or\n // downward chromatic step (e.g. E -> Eb, F# -> F, C -> Cb = descending\n // diminished/augmented unison) subtracts one so the sign follows pitch\n // direction instead of returning a garbage stack of augmentations.\n const reference = SIMPLE_REFERENCE[letterSteps + 1] ?? 0;\n if (reference - rawSemis > 6) {\n rawSemis += 12;\n } else if (rawSemis - reference > 6) {\n rawSemis -= 12;\n }\n semitones = rawSemis;\n }\n const absSteps = Math.abs(letterSteps);\n const number = absSteps + 1;\n // Quality comes from the absolute chromatic span; semitones keeps its sign.\n const quality = qualityFromSpan(number, Math.abs(semitones));\n return { number, quality, semitones };\n}\n","/**\n * Deterministic seeded pseudo-random number generation shared across the\n * generative modules (rhythm, drums, bass, groove, counter-melody). A single\n * mulberry32 core exposes the small set of samplers those modules need; given a\n * seed the stream is fully reproducible.\n */\n\n/**\n * A deterministic PRNG with the sampling helpers the generators need.\n *\n * @category Utilities\n */\nexport type Rng = {\n /** Next float in [0, 1). */\n next: () => number;\n /** True with probability `p`. */\n prob: (p: number) => boolean;\n /** Integer in the inclusive range [lo, hi]. */\n range: (lo: number, hi: number) => number;\n /** Float in [lo, hi). */\n float: (lo: number, hi: number) => number;\n};\n\n/**\n * Create a seeded PRNG (mulberry32) exposing the shared samplers.\n *\n * @param seed The 32-bit seed; the same seed always yields the same stream.\n * @returns The seeded generator.\n * @example\n * ```ts\n * import { createRng } from '@libraz/libcantus';\n * const rng = createRng(42);\n * rng.next(); // deterministic float in [0, 1)\n * rng.range(1, 6); // deterministic integer in [1, 6]\n * ```\n * @category Utilities\n */\nexport function createRng(seed: number): Rng {\n let state = seed >>> 0;\n const next = () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n return {\n next,\n prob: (p) => next() < p,\n range: (lo, hi) => lo + Math.floor(next() * (hi - lo + 1)),\n float: (lo, hi) => lo + next() * (hi - lo),\n };\n}\n","/**\n * Tuning and microtonality: frequency conversion, cents, arbitrary equal\n * temperaments (EDO), and just-intonation ratios.\n *\n * The rest of the library reasons in twelve-tone pitch classes, which is a\n * deliberate scope choice for tonal theory. This module is the escape hatch for\n * anyone who needs actual frequencies, cents, non-12 equal temperaments, or the\n * acoustic (just) tuning behind the tempered intervals.\n */\n\n/**\n * An equal-tempered tuning: a reference pitch and a number of equal divisions of\n * the octave. With `divisions === 12` a step index is an ordinary MIDI number.\n *\n * @category Pitch & Intervals\n */\nexport type Tuning = {\n /** Step index (MIDI number when `divisions` is 12) whose frequency is `refFreq`. */\n refStep: number;\n /** Frequency in Hz of `refStep`. */\n refFreq: number;\n /** Equal divisions of the octave (12 standard; e.g. 19 or 31 for microtonal). */\n divisions: number;\n};\n\n/**\n * Standard twelve-tone equal temperament, A4 (MIDI 69) = 440 Hz.\n *\n * @category Pitch & Intervals\n */\nexport const TWELVE_TET: Tuning = { refStep: 69, refFreq: 440, divisions: 12 };\n\n/**\n * Build an equal temperament with `n` divisions of the octave.\n *\n * @param n Divisions of the octave (e.g. 19, 24, 31).\n * @param refFreq Reference frequency in Hz (default 440).\n * @param refStep Step index of the reference (default 69).\n * @returns The tuning.\n * @example\n * ```ts\n * import { edo, frequencyOf } from '@libraz/libcantus';\n * const et19 = edo(19); // { refStep: 69, refFreq: 440, divisions: 19 }\n * frequencyOf(70, et19); // one 19-EDO step above A4\n * ```\n * @category Pitch & Intervals\n */\nexport function edo(n: number, refFreq = 440, refStep = 69): Tuning {\n return { refStep, refFreq, divisions: n };\n}\n\n/**\n * Frequency in Hz of a step index under a tuning.\n *\n * @param step Step index (a MIDI number under 12-EDO).\n * @param tuning The tuning (default 12-TET).\n * @returns The frequency in Hz.\n * @example\n * ```ts\n * import { frequencyOf } from '@libraz/libcantus';\n * frequencyOf(69); // 440 (A4 in 12-TET)\n * frequencyOf(60); // middle C in Hz\n * ```\n * @category Pitch & Intervals\n */\nexport function frequencyOf(step: number, tuning: Tuning = TWELVE_TET): number {\n return tuning.refFreq * 2 ** ((step - tuning.refStep) / tuning.divisions);\n}\n\n/**\n * Nearest step index to a frequency under a tuning (the inverse of\n * {@link frequencyOf}, rounded).\n *\n * @param freq Frequency in Hz.\n * @param tuning The tuning (default 12-TET).\n * @returns The nearest step index.\n * @category Pitch & Intervals\n */\nexport function nearestStep(freq: number, tuning: Tuning = TWELVE_TET): number {\n return Math.round(tuning.refStep + tuning.divisions * Math.log2(freq / tuning.refFreq));\n}\n\n/**\n * Interval in cents between two frequencies.\n *\n * @param a Lower/first frequency in Hz.\n * @param b Upper/second frequency in Hz.\n * @returns Cents from `a` to `b` (negative if `b` is lower).\n * @category Pitch & Intervals\n */\nexport function centsBetweenFreq(a: number, b: number): number {\n return 1200 * Math.log2(b / a);\n}\n\n/**\n * Cents spanned by a number of equal-temperament steps.\n *\n * @param steps Number of steps.\n * @param tuning The tuning (default 12-TET).\n * @returns The cents.\n * @category Pitch & Intervals\n */\nexport function centsOfSteps(steps: number, tuning: Tuning = TWELVE_TET): number {\n return (steps * 1200) / tuning.divisions;\n}\n\n/**\n * Cents of a frequency ratio, e.g. `ratioToCents(3, 2)` ≈ 701.955 for the just\n * perfect fifth.\n *\n * @param numerator Ratio numerator.\n * @param denominator Ratio denominator.\n * @returns The interval in cents.\n * @category Pitch & Intervals\n */\nexport function ratioToCents(numerator: number, denominator: number): number {\n return 1200 * Math.log2(numerator / denominator);\n}\n\n/**\n * Five-limit just-intonation ratios for the twelve interval classes above a\n * unison, indexed by semitone class (0..12).\n *\n * @category Pitch & Intervals\n */\nexport const JUST_RATIOS: Record<number, [number, number]> = {\n 0: [1, 1],\n 1: [16, 15],\n 2: [9, 8],\n 3: [6, 5],\n 4: [5, 4],\n 5: [4, 3],\n 6: [45, 32],\n 7: [3, 2],\n 8: [8, 5],\n 9: [5, 3],\n 10: [9, 5],\n 11: [15, 8],\n 12: [2, 1],\n};\n\n/**\n * Cents by which a five-limit just interval departs from its 12-TET tempering\n * (positive means the just interval is wider).\n *\n * @param semitoneClass Semitone class in [0, 12].\n * @returns The deviation in cents, or NaN if the class has no listed ratio.\n * @category Pitch & Intervals\n */\nexport function justDeviationCents(semitoneClass: number): number {\n const ratio = JUST_RATIOS[semitoneClass];\n if (!ratio) {\n return Number.NaN;\n }\n return ratioToCents(ratio[0], ratio[1]) - semitoneClass * 100;\n}\n","/**\n * Deterministic bass-line generation over a chord placement.\n *\n * Given a sequence of chord segments and a key, this builds a monophonic bass\n * line in a chosen low register. Several idiomatic styles are supported, from a\n * single held root per segment to a quarter-note walking line that leads by\n * step into each chord change. All pitches are kept in a narrow bass band and\n * consecutive notes move by small intervals; given a seed the output is fully\n * reproducible.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention.\n */\n\nimport { isStrongBeat, type TimeSignature } from '../../core/meter/index.js';\nimport { createRng } from '../../core/random/index.js';\nimport type { KeyScale, NoteEvent } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { nearestScaleTone } from '../../theory/scale/index.js';\n\n/**\n * A chord sounding over a half-open beat span `[startBeat, endBeat)`.\n *\n * @category Composition\n */\nexport type BassSegment = {\n startBeat: number;\n endBeat: number;\n chord: Chord;\n};\n\n/**\n * The bass-line idiom to generate.\n *\n * @category Composition\n */\nexport type BassStyle = 'root' | 'rootFifth' | 'pop' | 'walking' | 'arpeggio';\n\n/**\n * Options controlling {@link generateBassLine}.\n *\n * @category Composition\n */\nexport type BassLineOptions = {\n /** Chord placement to follow; need not be pre-sorted. */\n segments: BassSegment[];\n /** Key/scale context, used for diatonic approach tones in `walking`. */\n key: KeyScale;\n /**\n * Time signature; used for metric accents.\n *\n * @defaultValue `{ numerator: 4, denominator: 4 }`\n */\n ts?: TimeSignature;\n /**\n * Bass-line idiom.\n *\n * @defaultValue `'root'`\n */\n style?: BassStyle;\n /**\n * Target register as a base MIDI octave; roots land around `octave*12+12`.\n *\n * @defaultValue 2\n */\n octave?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\nconst DEFAULT_STYLE: BassStyle = 'root';\nconst DEFAULT_OCTAVE = 2;\n\n/** Velocity for notes on metrically strong positions. */\nconst STRONG_VELOCITY = 100;\n/** Velocity for notes on weak positions. */\nconst WEAK_VELOCITY = 80;\n/** Probability of a weak-beat pickup in the `pop` style. */\nconst PICKUP_PROB = 0.35;\n\nconst EPS = 1e-9;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * Place a pitch class as a MIDI note near an anchor, clamped to the bass band.\n *\n * The octave nearest the anchor is chosen first (so motion from the previous\n * note is minimal), then the result is shifted by whole octaves into the band\n * `[low, low + 12]` if it falls outside.\n */\nfunction placePc(pc: number, anchor: number, low: number): number {\n const high = low + 12;\n let midi = pc + 12 * Math.round((anchor - pc) / 12);\n while (midi < low) {\n midi += 12;\n }\n while (midi > high) {\n midi -= 12;\n }\n return midi;\n}\n\n/** Chord-tone pitch classes in stacked-thirds order, deduplicated. */\nfunction chordTonePcs(chord: Chord): number[] {\n const seen = new Set<number>();\n const pcs: number[] = [];\n for (const interval of chord.intervals) {\n const pc = pitchClass(chord.rootPc + interval);\n if (!seen.has(pc)) {\n seen.add(pc);\n pcs.push(pc);\n }\n }\n if (pcs.length === 0) {\n pcs.push(pitchClass(chord.rootPc));\n }\n return pcs;\n}\n\n/**\n * The chord's fifth pitch class.\n *\n * Uses the perfect fifth when present, otherwise the chord's actual altered\n * fifth (diminished = 6, augmented = 8 semitones above the root), so dim/aug/\n * m7b5 chords sound their real fifth rather than a repeated root. Falls back to\n * the root only when the chord has no fifth degree at all.\n */\nfunction fifthPcOf(chord: Chord): number {\n const fifths = new Set(chord.intervals.map((i) => pitchClass(i)));\n const chosen = fifths.has(7) ? 7 : fifths.has(6) ? 6 : fifths.has(8) ? 8 : undefined;\n return chosen === undefined ? pitchClass(chord.rootPc) : pitchClass(chord.rootPc + chosen);\n}\n\n/** The sounding bass pitch class of a chord: its slash bass, else its root. */\nfunction bassPcOf(chord: Chord): number {\n return pitchClass(chord.bassPc ?? chord.rootPc);\n}\n\n/** Integer quarter-note beat positions within `[start, end)`, at least one. */\nfunction beatPositions(start: number, end: number): number[] {\n const positions: number[] = [];\n for (let p = start; p < end - EPS; p += 1) {\n positions.push(p);\n }\n if (positions.length === 0) {\n positions.push(start);\n }\n return positions;\n}\n\ntype RawNote = { startBeat: number; pitch: number; velocity: number };\n\n/** Working state threaded through the per-segment builders. */\ntype BuildContext = {\n ts: TimeSignature;\n low: number;\n key: KeyScale;\n rng: ReturnType<typeof createRng>;\n notes: RawNote[];\n prevMidi: number;\n};\n\n/** Append a note for pitch class `pc` at `pos`, placed near the running anchor. */\nfunction emit(ctx: BuildContext, pos: number, pc: number, midiOverride?: number): number {\n const midi = midiOverride ?? placePc(pc, ctx.prevMidi, ctx.low);\n const velocity = isStrongBeat(pos, ctx.ts) ? STRONG_VELOCITY : WEAK_VELOCITY;\n ctx.notes.push({ startBeat: pos, pitch: midi, velocity });\n return midi;\n}\n\n/** One root note per segment. */\nfunction buildRoot(ctx: BuildContext, seg: BassSegment): void {\n ctx.prevMidi = emit(ctx, seg.startBeat, bassPcOf(seg.chord));\n}\n\n/** Root on the downbeat, fifth on the segment's midpoint. */\nfunction buildRootFifth(ctx: BuildContext, seg: BassSegment): void {\n ctx.prevMidi = emit(ctx, seg.startBeat, bassPcOf(seg.chord));\n const mid = (seg.startBeat + seg.endBeat) / 2;\n if (mid > seg.startBeat + EPS && mid < seg.endBeat - EPS) {\n ctx.prevMidi = emit(ctx, mid, fifthPcOf(seg.chord));\n }\n}\n\n/** Root on every strong beat, with occasional octave/fifth pickups on weak beats. */\nfunction buildPop(ctx: BuildContext, seg: BassSegment): void {\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n const rootPc = bassPcOf(seg.chord);\n let emitted = false;\n for (const pos of positions) {\n if (isStrongBeat(pos, ctx.ts)) {\n ctx.prevMidi = emit(ctx, pos, rootPc);\n emitted = true;\n } else if (ctx.rng.prob(PICKUP_PROB)) {\n if (ctx.rng.prob(0.5)) {\n // Octave pickup: the root dropped toward the bottom of the register,\n // clamped so it never falls below the declared band.\n const base = placePc(rootPc, ctx.prevMidi, ctx.low);\n emit(ctx, pos, rootPc, Math.max(ctx.low, base - 12));\n } else {\n ctx.prevMidi = emit(ctx, pos, fifthPcOf(seg.chord));\n }\n }\n }\n if (!emitted) {\n ctx.prevMidi = emit(ctx, seg.startBeat, rootPc);\n }\n}\n\n/** Cycle root -> third -> fifth (-> seventh) across the segment's beats. */\nfunction buildArpeggio(ctx: BuildContext, seg: BassSegment): void {\n const tones = chordTonePcs(seg.chord);\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n positions.forEach((pos, i) => {\n const pc = tones[i % tones.length] ?? bassPcOf(seg.chord);\n ctx.prevMidi = emit(ctx, pos, pc);\n });\n}\n\n/** A diatonic or chromatic neighbor of `target`, a step toward `from`. */\nfunction approachNote(ctx: BuildContext, target: number, from: number): number {\n const dir = from <= target ? -1 : 1;\n if (ctx.rng.prob(0.5)) {\n return target + dir; // chromatic semitone\n }\n const cand = nearestScaleTone(target + dir * 2, ctx.key);\n const step = Math.abs(cand - target);\n return step >= 1 && step <= 2 ? cand : target + dir;\n}\n\n/** A quarter-note line of chord tones that leads by step into each chord change. */\nfunction buildWalking(ctx: BuildContext, seg: BassSegment, next: BassSegment | undefined): void {\n const tones = chordTonePcs(seg.chord);\n const positions = beatPositions(seg.startBeat, seg.endBeat);\n const count = positions.length;\n positions.forEach((pos, i) => {\n if (i === 0) {\n ctx.prevMidi = emit(ctx, pos, bassPcOf(seg.chord));\n return;\n }\n if (next && count > 1 && i === count - 1) {\n const nextBass = placePc(bassPcOf(next.chord), ctx.prevMidi, ctx.low);\n const midi = approachNote(ctx, nextBass, ctx.prevMidi);\n ctx.prevMidi = emit(ctx, pos, pitchClass(midi), midi);\n return;\n }\n const pc = tones[i % tones.length] ?? bassPcOf(seg.chord);\n ctx.prevMidi = emit(ctx, pos, pc);\n });\n}\n\n/**\n * Generate a bass line following a chord placement.\n *\n * Each segment contributes notes in the chosen bass register per the selected\n * style; consecutive notes are kept within roughly a fifth. Every note's\n * duration extends to the next onset (the final note extends to the last\n * segment's end). Given a seed the output is fully reproducible.\n *\n * @param opts Segments, key, and generation options.\n * @returns Bass notes sorted by onset, non-overlapping.\n *\n * @example\n * ```ts\n * import { generateBassLine, makeChord, majorKey } from '@libraz/libcantus';\n * const segments = [\n * { startBeat: 0, endBeat: 4, chord: makeChord(0, 'maj') },\n * { startBeat: 4, endBeat: 8, chord: makeChord(7, 'maj') },\n * ];\n * const notes = generateBassLine({ segments, key: majorKey(0), style: 'walking' });\n * ```\n *\n * @category Composition\n */\nexport function generateBassLine(opts: BassLineOptions): NoteEvent[] {\n const segments = [...opts.segments].sort((a, b) => a.startBeat - b.startBeat);\n if (segments.length === 0) {\n return [];\n }\n\n const ts = opts.ts ?? DEFAULT_TS;\n const style = opts.style ?? DEFAULT_STYLE;\n const octave = opts.octave ?? DEFAULT_OCTAVE;\n const low = octave * 12 + 12;\n\n const ctx: BuildContext = {\n ts,\n low,\n key: opts.key,\n rng: createRng(opts.seed ?? 0),\n notes: [],\n prevMidi: low,\n };\n\n for (let s = 0; s < segments.length; s += 1) {\n const seg = segments[s];\n if (!seg) {\n continue;\n }\n switch (style) {\n case 'rootFifth':\n buildRootFifth(ctx, seg);\n break;\n case 'pop':\n buildPop(ctx, seg);\n break;\n case 'walking':\n buildWalking(ctx, seg, segments[s + 1]);\n break;\n case 'arpeggio':\n buildArpeggio(ctx, seg);\n break;\n default:\n buildRoot(ctx, seg);\n break;\n }\n }\n\n ctx.notes.sort((a, b) => a.startBeat - b.startBeat);\n const lastEnd = segments.reduce((m, seg) => Math.max(m, seg.endBeat), Number.NEGATIVE_INFINITY);\n\n const out: NoteEvent[] = [];\n for (let i = 0; i < ctx.notes.length; i += 1) {\n const note = ctx.notes[i];\n if (!note) {\n continue;\n }\n const nextStart = ctx.notes[i + 1]?.startBeat ?? lastEnd;\n const durationBeat = nextStart - note.startBeat;\n if (durationBeat <= EPS) {\n continue;\n }\n out.push({\n pitch: note.pitch,\n startBeat: note.startBeat,\n durationBeat,\n velocity: note.velocity,\n });\n }\n return out;\n}\n","import type { TimeSignature } from '../../core/meter/index.js';\nimport { isStrongBeat } from '../../core/meter/index.js';\nimport type { Rng } from '../../core/random/index.js';\nimport { createRng } from '../../core/random/index.js';\nimport type { KeyScale, NoteEvent } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { chordToneRole } from '../../theory/chord/index.js';\nimport { createsParallelPerfect, isForbiddenMelodicLeap } from '../../theory/counterpoint/index.js';\nimport type { VoiceSnapshot } from '../../theory/safety/index.js';\nimport { enumerateSafePitches } from '../../theory/safety/index.js';\nimport { nearestScaleTone } from '../../theory/scale/index.js';\n\n/**\n * Options controlling {@link generateCounterMelody}.\n *\n * @category Voicing & Counterpoint\n */\nexport type CounterMelodyOptions = {\n /** The lead line to write against, in ascending onset order. */\n melody: NoteEvent[];\n /** Chord sounding at an absolute beat position, or null when none applies. */\n chordAt: (beat: number) => Chord | null;\n /** Key/scale context for scale-tone decisions. */\n key: KeyScale;\n /**\n * Meter used for strong-beat decisions.\n *\n * @defaultValue 4/4\n */\n ts?: TimeSignature;\n /**\n * Which side of the melody the counter line occupies.\n *\n * @defaultValue 'below'\n */\n register?: 'above' | 'below';\n /**\n * Onset strategy: `'complement'` moves where the melody holds or rests and\n * reinforces some strong beats; `'follow'` mirrors melody onsets.\n *\n * @defaultValue 'complement'\n */\n rhythm?: 'complement' | 'follow';\n /**\n * Safety profile applied to candidate pitches.\n *\n * @defaultValue 'pop'\n */\n profile?: 'strict' | 'pop';\n /** Lowest MIDI pitch the counter line may use (default derived from `register`). */\n pitchLow?: number;\n /** Highest MIDI pitch the counter line may use (default derived from `register`). */\n pitchHigh?: number;\n /**\n * PRNG seed; the same seed always yields the same line.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/** Meter assumed when none is supplied. */\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\n\n/** Tolerance for beat-position comparisons. */\nconst EPS = 1e-9;\n\n/** Grid resolution, in quarter-note beats, scanned for complement onsets. */\nconst GRID_STEP = 0.5;\n\n/** Minimum spacing between counter onsets, keeping the line uncluttered. */\nconst MIN_ONSET_GAP = 1;\n\n/** Semitone offset of the counter register's centre from the melody's mean pitch. */\nconst REGISTER_OFFSET = 12;\n\n/** Half-width, in semitones, of the default counter register. */\nconst DEFAULT_HALF_RANGE = 10;\n\n/** Probability of moving on a whole beat while the melody sustains. */\nconst HOLD_ON_BEAT_PROB = 0.55;\n\n/** Probability of moving on an off-beat subdivision while the melody sustains. */\nconst HOLD_OFF_BEAT_PROB = 0.2;\n\n/** Probability of reinforcing a strong beat that the melody also attacks. */\nconst REINFORCE_PROB = 0.35;\n\n/** Velocity assumed for melody notes that carry none. */\nconst DEFAULT_MELODY_VELOCITY = 96;\n\n/** How far below the concurrent melody velocity the counter line sits. */\nconst VELOCITY_DROP = 16;\n\n/** Whether a beat position falls on a whole quarter-note beat. */\nfunction isWholeBeat(beat: number): boolean {\n return Math.abs(beat - Math.round(beat)) < EPS;\n}\n\n/** The melody note sounding at a beat (latest onset wins on overlaps). */\nfunction melodyNoteAt(melody: NoteEvent[], beat: number): NoteEvent | undefined {\n let found: NoteEvent | undefined;\n for (const note of melody) {\n if (note.startBeat - EPS <= beat && beat < note.startBeat + note.durationBeat - EPS) {\n if (!found || note.startBeat > found.startBeat) {\n found = note;\n }\n }\n }\n return found;\n}\n\n/** Whether any melody note attacks exactly at a beat. */\nfunction melodyAttacksAt(melody: NoteEvent[], beat: number): boolean {\n return melody.some((note) => Math.abs(note.startBeat - beat) < EPS);\n}\n\n/** Counter onsets mirroring the melody's own onsets, deduplicated and sorted. */\nfunction followOnsets(melody: NoteEvent[]): number[] {\n return [...new Set(melody.map((note) => note.startBeat))].sort((a, b) => a - b);\n}\n\n/**\n * Counter onsets complementing the melody: whole beats inside rests are always\n * taken, positions where the melody sustains are taken probabilistically, and\n * strong beats the melody also attacks are occasionally reinforced. A minimum\n * gap between accepted onsets keeps the line sparse.\n */\nfunction complementOnsets(\n melody: NoteEvent[],\n ts: TimeSignature,\n spanStart: number,\n spanEnd: number,\n rng: Rng,\n): number[] {\n const onsets: number[] = [];\n const gridStart = Math.floor(spanStart / GRID_STEP) * GRID_STEP;\n let last = Number.NEGATIVE_INFINITY;\n for (let beat = gridStart; beat < spanEnd - EPS; beat += GRID_STEP) {\n const attacked = melodyAttacksAt(melody, beat);\n const sounding = melodyNoteAt(melody, beat) !== undefined;\n let place = false;\n if (!attacked && !sounding) {\n place = isWholeBeat(beat);\n } else if (!attacked) {\n place = rng.prob(isWholeBeat(beat) ? HOLD_ON_BEAT_PROB : HOLD_OFF_BEAT_PROB);\n } else if (isStrongBeat(beat, ts)) {\n place = rng.prob(REINFORCE_PROB);\n }\n if (place && beat - last >= MIN_ONSET_GAP - EPS) {\n onsets.push(beat);\n last = beat;\n }\n }\n return onsets;\n}\n\n/**\n * Preference score for one candidate counter pitch. Rewards imperfect\n * consonance with the melody, chord-tone membership, contrary or oblique\n * motion, and stepwise movement; penalizes wide or forbidden leaps, weak-beat\n * clashes, and drifting from the register centre.\n */\nfunction scoreCandidate(\n pitch: number,\n melPitch: number | undefined,\n melPrev: number | undefined,\n prevPitch: number | undefined,\n chord: Chord | null,\n center: number,\n): number {\n let score = 0;\n if (melPitch !== undefined) {\n const ic = Math.abs(pitch - melPitch) % 12;\n if (ic === 3 || ic === 4 || ic === 8 || ic === 9) {\n score += 2; // imperfect consonance: thirds and sixths\n } else if (ic === 0 || ic === 7) {\n score += 0.5; // perfect consonance: allowed but less colourful\n } else if (ic === 1 || ic === 2 || ic === 6 || ic === 10 || ic === 11) {\n score -= 2; // dissonant even on weak beats\n }\n }\n if (chord && chordToneRole(pitch, chord) !== null) {\n score += 1;\n }\n if (prevPitch !== undefined) {\n const move = pitch - prevPitch;\n const dist = Math.abs(move);\n score -= dist * 0.3;\n if (dist > 0 && dist <= 2) {\n score += 1; // stepwise motion\n }\n if (isForbiddenMelodicLeap(prevPitch, pitch)) {\n score -= 6;\n }\n if (melPitch !== undefined && melPrev !== undefined) {\n const melMove = melPitch - melPrev;\n if ((move > 0 && melMove < 0) || (move < 0 && melMove > 0)) {\n score += 2; // contrary motion\n } else if (move === 0 || melMove === 0) {\n score += 1; // oblique motion\n } else {\n score -= 1; // similar motion\n }\n }\n }\n score -= Math.abs(pitch - center) * 0.02;\n return score;\n}\n\n/**\n * Last-resort pitch when no safe candidate survives filtering: the scale tone\n * nearest the previous pitch (or the register centre), pushed onto the correct\n * side of the sounding melody note.\n */\nfunction fallbackPitch(\n melPitch: number | undefined,\n prevPitch: number | undefined,\n center: number,\n register: 'above' | 'below',\n low: number,\n high: number,\n key: KeyScale,\n): number {\n let target = prevPitch ?? Math.round(center);\n if (melPitch !== undefined) {\n if (register === 'below' && target >= melPitch) {\n target = melPitch - 5;\n } else if (register === 'above' && target <= melPitch) {\n target = melPitch + 5;\n }\n }\n target = Math.min(Math.max(target, low), high);\n let pitch = nearestScaleTone(target, key);\n // Push onto the requested side of the melody, but only by whole octaves that\n // keep the pitch inside [low, high]; the declared range is a hard bound while\n // the register side is a soft preference. A final clamp guarantees the range.\n if (melPitch !== undefined) {\n while (register === 'below' && pitch >= melPitch && pitch - 12 >= low) {\n pitch -= 12;\n }\n while (register === 'above' && pitch <= melPitch && pitch + 12 <= high) {\n pitch += 12;\n }\n }\n return Math.min(Math.max(pitch, low), high);\n}\n\n/**\n * Generate a counter melody against a lead line.\n *\n * Onsets are chosen per `rhythm`: `'follow'` places one counter note on each\n * melody onset; `'complement'` fills melody rests and sustains and reinforces\n * an occasional strong beat, spaced at least a beat apart. Each onset's pitch\n * is picked from the safe pitches in the counter register (chord tones and\n * consonant tensions against the sounding melody note), rejecting candidates\n * that would form a parallel perfect interval with the melody or sit on the\n * wrong side of it, then scored to favour contrary or oblique motion, imperfect\n * consonance, and stepwise movement. Ties break toward the lower pitch, so a\n * given seed always yields the same line. Notes extend to the next counter\n * onset (the last to the melody's end) at a velocity slightly under the melody.\n *\n * @param opts The lead line, chord context callback, key, and generation knobs.\n * @returns The counter line as note events sorted by onset; `[]` for an empty melody.\n * @example\n * ```ts\n * import { generateCounterMelody, majorKey, parseChordSymbol } from '@libraz/libcantus';\n * const melody = [{ pitch: 72, startBeat: 0, durationBeat: 2 }];\n * const counter = generateCounterMelody({\n * melody,\n * chordAt: () => parseChordSymbol('C'),\n * key: majorKey(0),\n * }); // note events below the melody, in onset order\n * ```\n * @category Voicing & Counterpoint\n */\nexport function generateCounterMelody(opts: CounterMelodyOptions): NoteEvent[] {\n const melody = [...opts.melody].sort((a, b) => a.startBeat - b.startBeat);\n if (melody.length === 0) {\n return [];\n }\n const ts = opts.ts ?? DEFAULT_TS;\n const register = opts.register ?? 'below';\n const rhythm = opts.rhythm ?? 'complement';\n const profile = opts.profile ?? 'pop';\n const rng = createRng(opts.seed ?? 0);\n\n const spanStart = melody[0]?.startBeat ?? 0;\n const spanEnd = melody.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), spanStart);\n const meanPitch = melody.reduce((sum, n) => sum + n.pitch, 0) / melody.length;\n const defaultCenter =\n register === 'below' ? meanPitch - REGISTER_OFFSET : meanPitch + REGISTER_OFFSET;\n const low = opts.pitchLow ?? Math.round(defaultCenter) - DEFAULT_HALF_RANGE;\n const high = opts.pitchHigh ?? Math.round(defaultCenter) + DEFAULT_HALF_RANGE;\n const center = (low + high) / 2;\n\n const onsets =\n rhythm === 'follow'\n ? followOnsets(melody)\n : complementOnsets(melody, ts, spanStart, spanEnd, rng);\n\n const out: NoteEvent[] = [];\n let prevPitch: number | undefined;\n let prevOnset: number | undefined;\n for (const beat of onsets) {\n const melNote = melodyNoteAt(melody, beat);\n const melPitch = melNote?.pitch;\n const melPrev = prevOnset !== undefined ? melodyNoteAt(melody, prevOnset)?.pitch : undefined;\n const chord = opts.chordAt(beat);\n const otherVoices: VoiceSnapshot[] =\n melPitch !== undefined ? [{ pitch: melPitch, prevPitch: melPrev }] : [];\n\n const candidates = enumerateSafePitches(\n {\n profile,\n prevPitch,\n chord,\n key: opts.key,\n otherVoices,\n strongBeat: isStrongBeat(beat, ts),\n vocalLow: low,\n vocalHigh: high,\n },\n low,\n high,\n );\n\n let bestPitch: number | undefined;\n let bestScore = Number.NEGATIVE_INFINITY;\n for (const candidate of candidates) {\n if (melPitch !== undefined) {\n if (register === 'below' && candidate >= melPitch) {\n continue;\n }\n if (register === 'above' && candidate <= melPitch) {\n continue;\n }\n if (\n prevPitch !== undefined &&\n melPrev !== undefined &&\n // Parallel octaves are the perfect-class-zero case of this predicate,\n // so a single check covers both parallel fifths and octaves.\n createsParallelPerfect(prevPitch, candidate, melPrev, melPitch)\n ) {\n continue;\n }\n }\n const score = scoreCandidate(candidate, melPitch, melPrev, prevPitch, chord, center);\n const tie =\n Math.abs(score - bestScore) <= EPS && candidate < (bestPitch ?? Number.POSITIVE_INFINITY);\n if (score > bestScore + EPS || tie) {\n bestScore = score;\n bestPitch = candidate;\n }\n }\n\n const pitch =\n bestPitch ?? fallbackPitch(melPitch, prevPitch, center, register, low, high, opts.key);\n const velocity = Math.max(\n 1,\n Math.min(127, Math.round((melNote?.velocity ?? DEFAULT_MELODY_VELOCITY) - VELOCITY_DROP)),\n );\n out.push({ pitch, startBeat: beat, durationBeat: GRID_STEP, velocity });\n prevPitch = pitch;\n prevOnset = beat;\n }\n\n // Extend each note to the next counter onset; the last to the melody's end.\n for (let i = 0; i < out.length; i += 1) {\n const note = out[i];\n if (!note) {\n continue;\n }\n const next = out[i + 1];\n const end = next ? next.startBeat : Math.max(spanEnd, note.startBeat + GRID_STEP);\n note.durationBeat = end - note.startBeat;\n }\n return out;\n}\n","/** General MIDI percussion note numbers used across the drum engine. */\nexport const GM = {\n BD: 36,\n SD: 38,\n SIDESTICK: 37,\n HANDCLAP: 39,\n CHH: 42,\n FHH: 44,\n OHH: 46,\n CRASH: 49,\n RIDE: 51,\n TAMBOURINE: 54,\n TOM_H: 50,\n TOM_M: 47,\n TOM_L: 45,\n SHAKER: 82,\n} as const;\n\n/** One beat and one sixteenth expressed as fractions of a beat. */\nexport const EIGHTH = 0.5;\nexport const SIXTEENTH = 0.25;\n\n/** Internal drum style selected by the public groove style. */\nexport type DrumStyle =\n | 'sparse'\n | 'standard'\n | 'fourOnFloor'\n | 'upbeat'\n | 'rock'\n | 'synth'\n | 'trap'\n | 'latin';\n\n/** Groove feel controlling off-beat swing. */\nexport type Feel = 'straight' | 'swing' | 'shuffle';\n\n/** Reduced section set the engine reasons about. */\nexport type SectionType = 'intro' | 'a' | 'b' | 'chorus' | 'bridge' | 'outro';\n\n/** Backing density bucket derived from the public density knob. */\nexport type BackingDensity = 'thin' | 'normal' | 'thick';\n\n/** Section energy level, used to shape fills. */\nexport type SectionEnergy = 'low' | 'medium' | 'high' | 'peak';\n\n/** Ghost-note mood category for the density table. */\nexport enum MoodCategory {\n Calm = 0,\n Standard = 1,\n Energetic = 2,\n}\n\n/** Percussion mood category for the activation table. */\nexport enum PercMoodCategory {\n Calm = 0,\n Standard = 1,\n Energetic = 2,\n Idol = 3,\n RockDark = 4,\n}\n\n/** Public groove style identifiers. */\nexport type GrooveStyle =\n | 'standard'\n | 'funk'\n | 'shuffle'\n | 'bossa'\n | 'trap'\n | 'halftime'\n | 'breakbeat'\n | 'house'\n | 'synthpop';\n\n/** Public role identifiers gating which voices are present. */\nexport type DrumRole = 'full' | 'ambient' | 'minimal' | 'fxOnly';\n\n/** Public section identifiers. */\nexport type PublicSection = 'intro' | 'verse' | 'prechorus' | 'chorus' | 'bridge' | 'outro';\n\n/** Resolved internal parameters for a public groove style. */\nexport type StyleMapping = {\n style: DrumStyle;\n feel: Feel;\n ghostBoost: boolean;\n snareBeat3: boolean;\n};\n\nconst STYLE_MAP: Record<GrooveStyle, StyleMapping> = {\n // Standard pop pulse: kick on beats 1 and 3, backbeat snare on 2 and 4.\n standard: { style: 'standard', feel: 'straight', ghostBoost: false, snareBeat3: false },\n funk: { style: 'upbeat', feel: 'straight', ghostBoost: true, snareBeat3: false },\n shuffle: { style: 'standard', feel: 'shuffle', ghostBoost: false, snareBeat3: false },\n bossa: { style: 'latin', feel: 'straight', ghostBoost: false, snareBeat3: false },\n trap: { style: 'trap', feel: 'straight', ghostBoost: false, snareBeat3: true },\n halftime: { style: 'sparse', feel: 'straight', ghostBoost: false, snareBeat3: true },\n breakbeat: { style: 'rock', feel: 'straight', ghostBoost: false, snareBeat3: false },\n // Four-on-the-floor dance kick with idol-style auxiliary percussion.\n house: { style: 'fourOnFloor', feel: 'straight', ghostBoost: false, snareBeat3: false },\n // Synth-pop pulse with denser 16th hi-hats and busy kick syncopation.\n synthpop: { style: 'synth', feel: 'straight', ghostBoost: true, snareBeat3: false },\n};\n\n/** Resolve the internal style/feel parameters for a public groove style. */\nexport function mapStyle(style: GrooveStyle): StyleMapping {\n return STYLE_MAP[style];\n}\n\n/** Map a public section to the internal section type. */\nexport function mapSection(section: PublicSection): SectionType {\n switch (section) {\n case 'intro':\n return 'intro';\n case 'verse':\n return 'a';\n case 'prechorus':\n return 'b';\n case 'chorus':\n return 'chorus';\n case 'bridge':\n return 'bridge';\n case 'outro':\n return 'outro';\n }\n}\n\n/** Bucket the 0..1 density knob into a backing-density level. */\nexport function mapDensity(density: number): BackingDensity {\n if (density < 0.34) {\n return 'thin';\n }\n if (density < 0.67) {\n return 'normal';\n }\n return 'thick';\n}\n\n/** Swing amount (0..1) implied by a groove feel. */\nexport function feelSwingAmount(feel: Feel): number {\n if (feel === 'swing') {\n return 0.33;\n }\n if (feel === 'shuffle') {\n return 0.5;\n }\n return 0;\n}\n\n/** Ghost-note mood category derived from the internal style. */\nexport function ghostMoodCategory(style: DrumStyle): MoodCategory {\n if (style === 'sparse') {\n return MoodCategory.Calm;\n }\n if (style === 'trap' || style === 'upbeat') {\n return MoodCategory.Energetic;\n }\n return MoodCategory.Standard;\n}\n\n/** Percussion mood category derived from the internal style. */\nexport function percMoodCategory(style: DrumStyle): PercMoodCategory {\n switch (style) {\n case 'sparse':\n return PercMoodCategory.Calm;\n case 'upbeat':\n case 'latin':\n return PercMoodCategory.Energetic;\n case 'fourOnFloor':\n return PercMoodCategory.Idol;\n case 'trap':\n case 'rock':\n return PercMoodCategory.RockDark;\n default:\n return PercMoodCategory.Standard;\n }\n}\n\n/** Zero-based section index shared by the ghost and percussion tables. */\nexport function sectionIndex(section: SectionType): number {\n switch (section) {\n case 'intro':\n return 0;\n case 'a':\n return 1;\n case 'b':\n return 2;\n case 'chorus':\n return 3;\n case 'bridge':\n return 4;\n case 'outro':\n return 6;\n }\n}\n\n/** Section energy used to size fills. */\nexport function sectionEnergy(section: SectionType): SectionEnergy {\n switch (section) {\n case 'intro':\n case 'outro':\n return 'low';\n case 'a':\n case 'bridge':\n return 'medium';\n case 'b':\n return 'high';\n case 'chorus':\n return 'peak';\n }\n}\n\n/** Section velocity multiplier applied to the base drum velocity. */\nexport function sectionVelocityMultiplier(section: SectionType): number {\n switch (section) {\n case 'intro':\n case 'outro':\n return 0.8;\n case 'a':\n return 0.9;\n case 'b':\n return 1.0;\n case 'chorus':\n return 1.1;\n case 'bridge':\n return 0.85;\n }\n}\n\n/** Section density multiplier before backing-density scaling. */\nexport function sectionDensityMultiplier(section: SectionType): number {\n switch (section) {\n case 'intro':\n return 0.5;\n case 'a':\n return 0.7;\n case 'b':\n return 0.85;\n case 'chorus':\n return 1.0;\n case 'bridge':\n return 0.6;\n case 'outro':\n return 0.6;\n }\n}\n\n/** Base drum velocity for a section beat (downbeats accented). */\nexport function calculateVelocity(section: SectionType, beat: number): number {\n const base = 80;\n const beatAdj = beat === 0 ? 10 : beat === 2 ? 5 : 0;\n const velocity = (base + beatAdj) * sectionVelocityMultiplier(section);\n return clampVel(velocity);\n}\n\n/** Round and clamp a velocity into the valid MIDI range. */\nexport function clampVel(velocity: number): number {\n return Math.max(1, Math.min(127, Math.round(velocity)));\n}\n","import type { BackingDensity, SectionType } from './internal.js';\nimport { MoodCategory, sectionIndex } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Ghost-note position within a beat: the \"e\" (1st 16th) or \"a\" (3rd 16th). */\nexport type GhostPosition = 'e' | 'a';\n\n/** Ghost density level ordinal (0 = none, 3 = heavy). */\ntype GhostDensityLevel = 0 | 1 | 2 | 3;\n\n// Ghost density level per [section index][mood category].\nconst GHOST_DENSITY_TABLE: GhostDensityLevel[][] = [\n /* intro */ [0, 1, 1],\n /* a */ [0, 1, 2],\n /* b */ [1, 2, 2],\n /* chorus */ [1, 2, 3],\n /* bridge */ [1, 1, 2],\n /* interlude */ [0, 1, 1],\n /* outro */ [0, 1, 1],\n];\n\nfunction levelToProbability(level: GhostDensityLevel): number {\n switch (level) {\n case 0:\n return 0;\n case 1:\n return 0.15;\n case 2:\n return 0.3;\n case 3:\n return 0.45;\n }\n}\n\nfunction clampLevel(level: number): GhostDensityLevel {\n return Math.max(0, Math.min(3, level)) as GhostDensityLevel;\n}\n\nfunction adjustForBpm(level: GhostDensityLevel, bpm: number): GhostDensityLevel {\n if (bpm >= 160 && level !== 0) {\n return clampLevel(level - 1);\n }\n if (bpm <= 90 && level !== 3) {\n return clampLevel(level + 1);\n }\n return level;\n}\n\n/** Ghost-note trigger probability for a section, mood, density, and tempo. */\nexport function getGhostDensity(\n mood: MoodCategory,\n section: SectionType,\n backingDensity: BackingDensity,\n bpm: number,\n): number {\n const row = GHOST_DENSITY_TABLE[sectionIndex(section)] ?? GHOST_DENSITY_TABLE[1];\n const level = adjustForBpm((row?.[mood] ?? 0) as GhostDensityLevel, bpm);\n\n if (backingDensity === 'thin' && level !== 0) {\n return levelToProbability(clampLevel(level - 1));\n }\n if (backingDensity === 'thick' && level !== 3) {\n return levelToProbability(clampLevel(level + 1));\n }\n return levelToProbability(level);\n}\n\n/** Ghost-note velocity multiplier for a section and metric position. */\nexport function getGhostVelocity(\n section: SectionType,\n beatPosition: number,\n isAfterSnare: boolean,\n): number {\n let base = 0.4;\n const even = beatPosition % 2 === 0 ? 0.05 : 0;\n switch (section) {\n case 'a':\n base = 0.35 + even;\n break;\n case 'chorus':\n base = 0.5 + even;\n break;\n case 'bridge':\n base = 0.25 + even;\n break;\n case 'b':\n base = 0.4 + even;\n break;\n case 'intro':\n case 'outro':\n base = 0.38;\n break;\n }\n if (isAfterSnare) {\n base += 0.1;\n }\n return Math.max(0.25, Math.min(0.65, base));\n}\n\n/** Probability of a ghost at a specific 16th position (higher near the snare). */\nexport function getGhostProbabilityAtPosition(beat: number, sixteenthInBeat: number): number {\n const nearSnare =\n (beat === 0 && sixteenthInBeat === 3) ||\n (beat === 1 && sixteenthInBeat === 1) ||\n (beat === 2 && sixteenthInBeat === 3) ||\n (beat === 3 && sixteenthInBeat === 1);\n return nearSnare ? 0.6 : 0.25;\n}\n\n/** Choose which ghost positions a groove favours. */\nexport function selectGhostPositions(mood: MoodCategory, rng: DrumRng): GhostPosition[] {\n if (mood === MoodCategory.Energetic) {\n return ['e', 'a'];\n }\n if (mood === MoodCategory.Calm) {\n return rng.prob(0.5) ? ['e'] : [];\n }\n return ['e'];\n}\n","import type { DrumRole, DrumStyle, SectionType } from './internal.js';\nimport { GM } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Hi-hat subdivision level. */\nexport type HiHatLevel = 'quarter' | 'eighth' | 'sixteenth';\n\n/** Hi-hat articulation type. */\nexport type HiHatType = 'closed' | 'pedal' | 'open' | 'halfOpen' | 'ride';\n\n/** BPM at or above which 16th-note hi-hats become 8ths for playability. */\nexport const HH_16TH_BPM_THRESHOLD = 150;\n\nconst FHH_VEL_MIN = 45;\nconst FHH_VEL_MAX = 60;\n/** Velocity boost applied to dynamic open hi-hat accents. */\nexport const OHH_VEL_BOOST = 7;\n\n/** True unless the role suppresses timekeeping cymbals entirely. */\nexport function shouldPlayHiHat(role: DrumRole): boolean {\n return role !== 'fxOnly';\n}\n\n/** Preferred timekeeping instrument for a role. */\nexport function roleHiHatInstrument(role: DrumRole, useRide: boolean): number {\n if (role === 'ambient') {\n return GM.RIDE;\n }\n return useRide ? GM.RIDE : GM.CHH;\n}\n\nfunction sparser(level: HiHatLevel): HiHatLevel {\n if (level === 'sixteenth') {\n return 'eighth';\n }\n if (level === 'eighth') {\n return 'quarter';\n }\n return 'quarter';\n}\n\nfunction denser(level: HiHatLevel): HiHatLevel {\n if (level === 'quarter') {\n return 'eighth';\n }\n if (level === 'eighth') {\n return 'sixteenth';\n }\n return 'sixteenth';\n}\n\n/** Choose the hi-hat subdivision for a section/style/density/BPM. */\nexport function getHiHatLevel(\n section: SectionType,\n style: DrumStyle,\n backingDensity: 'thin' | 'normal' | 'thick',\n bpm: number,\n rng: DrumRng,\n): HiHatLevel {\n const allow16th = bpm < HH_16TH_BPM_THRESHOLD;\n let base: HiHatLevel = 'eighth';\n\n if (style === 'sparse') {\n base = section === 'chorus' ? 'eighth' : 'quarter';\n } else if (style === 'fourOnFloor') {\n if (allow16th && section === 'chorus' && rng.prob(0.25)) {\n return 'sixteenth';\n }\n return 'eighth';\n } else if (style === 'synth') {\n if (!allow16th) {\n return 'eighth';\n }\n if (section === 'a' && rng.prob(0.2)) {\n return 'eighth';\n }\n return 'sixteenth';\n } else if (style === 'trap') {\n return allow16th ? 'sixteenth' : 'eighth';\n } else if (style === 'latin') {\n if (allow16th && section === 'chorus' && rng.prob(0.3)) {\n return 'sixteenth';\n }\n return 'eighth';\n } else {\n switch (section) {\n case 'intro':\n base = 'quarter';\n break;\n case 'outro':\n base = 'eighth';\n break;\n case 'a':\n base = rng.prob(0.3) ? 'quarter' : 'eighth';\n break;\n case 'b':\n base = allow16th && rng.prob(0.25) ? 'sixteenth' : 'eighth';\n break;\n case 'chorus':\n base = allow16th && rng.prob(0.35) ? 'sixteenth' : 'eighth';\n break;\n case 'bridge':\n base = 'eighth';\n break;\n }\n }\n\n if (backingDensity === 'thin') {\n base = sparser(base);\n } else if (backingDensity === 'thick') {\n base = denser(base);\n }\n\n if (!allow16th && base === 'sixteenth') {\n base = 'eighth';\n }\n return base;\n}\n\n/** Metric velocity multiplier for a 16th position within a beat. */\nexport function hiHatVelocityMultiplier(sixteenth: number, rng: DrumRng): number {\n let baseValue: number;\n switch (sixteenth) {\n case 0:\n baseValue = 0.95;\n break;\n case 2:\n baseValue = 0.75;\n break;\n case 1:\n baseValue = 0.55;\n break;\n default:\n baseValue = 0.5;\n break;\n }\n return baseValue * rng.float(0.95, 1.05);\n}\n\n/** Bars between dynamic open hi-hat accents (0 disables them). */\nexport function openHiHatBarInterval(section: SectionType, style: DrumStyle): number {\n if (style === 'sparse') {\n return section === 'chorus' ? 4 : 0;\n }\n switch (section) {\n case 'intro':\n return style === 'fourOnFloor' ? 4 : 0;\n case 'a':\n return style === 'fourOnFloor' || style === 'upbeat' ? 2 : 4;\n case 'b':\n return 2;\n case 'chorus':\n return style === 'rock' || style === 'fourOnFloor' ? 1 : 2;\n case 'bridge':\n return 0;\n case 'outro':\n return 4;\n }\n}\n\n/** Beat that receives the dynamic open hi-hat within a bar. */\nexport function openHiHatBeat(section: SectionType, rng: DrumRng): number {\n if (section === 'chorus') {\n const choice = rng.range(0, 3);\n if (choice < 2) {\n return 3;\n }\n if (choice < 3) {\n return 1;\n }\n return 2;\n }\n return 3;\n}\n\n/** Whether the section uses an independent foot hi-hat pulse. */\nexport function shouldUseFootHiHat(section: SectionType, role: DrumRole): boolean {\n if (role === 'fxOnly') {\n return false;\n }\n switch (section) {\n case 'intro':\n case 'bridge':\n case 'outro':\n return true;\n default:\n return role === 'ambient' || role === 'minimal';\n }\n}\n\n/** Primary hi-hat articulation for a section. */\nexport function sectionHiHatType(section: SectionType, role: DrumRole): HiHatType {\n if (role === 'ambient') {\n return 'ride';\n }\n if (role === 'minimal') {\n return 'pedal';\n }\n switch (section) {\n case 'intro':\n case 'a':\n return 'pedal';\n case 'b':\n return 'closed';\n case 'chorus':\n return 'open';\n case 'bridge':\n return 'ride';\n case 'outro':\n return 'halfOpen';\n }\n}\n\n/** GM note for a hi-hat articulation. */\nexport function hiHatNote(type: HiHatType): number {\n switch (type) {\n case 'pedal':\n return GM.FHH;\n case 'open':\n return GM.OHH;\n case 'ride':\n return GM.RIDE;\n default:\n return GM.CHH;\n }\n}\n\n/** Velocity multiplier for a hi-hat articulation. */\nexport function hiHatTypeVelocityMultiplier(type: HiHatType): number {\n switch (type) {\n case 'halfOpen':\n return 0.75;\n case 'pedal':\n return 0.65;\n case 'open':\n return 1.0;\n case 'ride':\n return 0.9;\n default:\n return 0.85;\n }\n}\n\n/** Whether to accent with an open hi-hat at a given beat. */\nexport function shouldAddOpenHHAccent(\n section: SectionType,\n beat: number,\n bar: number,\n rng: DrumRng,\n): boolean {\n if (section !== 'chorus' && section !== 'b') {\n return false;\n }\n if (section === 'chorus') {\n if (beat === 1 || beat === 3) {\n return rng.prob(0.6);\n }\n return false;\n }\n if (beat === 3 && bar % 2 === 1) {\n return rng.prob(0.4);\n }\n return false;\n}\n\n/** Foot hi-hat velocity with slight humanization. */\nexport function footHiHatVelocity(rng: DrumRng): number {\n return rng.range(FHH_VEL_MIN, FHH_VEL_MAX);\n}\n\n/** Whether the section uses a ride cymbal instead of hi-hats. */\nexport function shouldUseRideForSection(section: SectionType, style: DrumStyle): boolean {\n if (style === 'rock' && section === 'chorus') {\n return true;\n }\n if (style === 'sparse') {\n return false;\n }\n return section === 'bridge';\n}\n\n/** Whether a bridge beat is carried by a cross-stick instead of the hi-hat. */\nexport function shouldUseBridgeCrossStick(section: SectionType, beat: number): boolean {\n return section === 'bridge' && (beat === 1 || beat === 3);\n}\n","import type { Feel } from './internal.js';\n\nconst SIXTEENTH = 0.25;\nconst EIGHTH = 0.5;\nconst HALF_16TH = 0.125;\n/** Delay of an off-beat 16th at full swing (triplet minus straight), in beats. */\nconst DELTA_16 = 1 / 3 - 1 / 4; // 0.08333...\n/** Delay of an off-beat 8th at full swing, in beats. */\nconst DELTA_8 = (2 / 3 - 1 / 2) / 2 + (2 / 3 - 1 / 2) / 2; // 0.16667...\n\n/** Grid resolution for swing quantization. */\nexport type SwingResolution = 'eighth' | 'sixteenth';\n\n/** Effective swing after applying the groove feel to a base swing amount. */\nexport function effectiveSwing(feel: Feel, swingAmount: number): number {\n if (feel === 'straight') {\n return 0;\n }\n if (feel === 'shuffle') {\n return Math.min(1, swingAmount * 1.5);\n }\n return swingAmount;\n}\n\n/**\n * Push an off-beat position toward its triplet placement.\n *\n * On-beat positions are returned unchanged; off-beat 8ths and 16ths are delayed\n * proportionally to the swing amount.\n *\n * @param startBeat Absolute position in beats.\n * @param swing Swing amount in [0, 1] (already feel-adjusted).\n * @param resolution Whether to swing the 16th or only the 8th grid.\n * @returns The swung position in beats.\n */\nexport function quantizeSwing(\n startBeat: number,\n swing: number,\n resolution: SwingResolution,\n): number {\n const clamped = Math.max(0, Math.min(1, swing));\n if (clamped <= 0) {\n return startBeat;\n }\n const base = Math.floor(startBeat);\n const offset = startBeat - base;\n\n if (resolution === 'sixteenth') {\n if (offset >= HALF_16TH && offset < SIXTEENTH + HALF_16TH) {\n return base + SIXTEENTH + DELTA_16 * clamped;\n }\n if (offset >= SIXTEENTH + HALF_16TH && offset < EIGHTH + HALF_16TH) {\n return base + EIGHTH + DELTA_8 * clamped;\n }\n if (offset >= EIGHTH + HALF_16TH && offset < 3 * SIXTEENTH + HALF_16TH) {\n // The \"a\" 16th is the midpoint of the compressed second half of the beat\n // (between the swung \"and\" and the next downbeat), mirroring the \"e\" 16th\n // in the first half. Because DELTA_8 = 2 * DELTA_16, that midpoint reduces\n // to a single DELTA_16 delay off the straight position, so the \"a\" never\n // overshoots the downbeat and needs no clamp. At the default shuffle feel\n // (swing 0.75) this lands near 0.8125 rather than the doubly-swung 0.9375.\n return base + 3 * SIXTEENTH + DELTA_16 * clamped;\n }\n return startBeat;\n }\n\n if (offset >= SIXTEENTH && offset < 3 * SIXTEENTH) {\n return base + EIGHTH + DELTA_8 * clamped;\n }\n return startBeat;\n}\n","import {\n getGhostDensity,\n getGhostProbabilityAtPosition,\n getGhostVelocity,\n selectGhostPositions,\n} from './ghost.js';\nimport {\n footHiHatVelocity,\n type HiHatLevel,\n hiHatNote,\n hiHatTypeVelocityMultiplier,\n hiHatVelocityMultiplier,\n OHH_VEL_BOOST,\n roleHiHatInstrument,\n sectionHiHatType,\n shouldAddOpenHHAccent,\n shouldPlayHiHat,\n shouldUseBridgeCrossStick,\n} from './hihat.js';\nimport type { HitList } from './hit.js';\nimport type { BackingDensity, DrumRole, DrumStyle, Feel, SectionType } from './internal.js';\nimport { EIGHTH, GM, type MoodCategory, SIXTEENTH } from './internal.js';\nimport type { KickPattern } from './kick.js';\nimport type { DrumRng } from './rng.js';\nimport { effectiveSwing, quantizeSwing } from './swing.js';\n\n/** Per-section drum state shared across the bars of a section. */\nexport type SectionCtx = {\n style: DrumStyle;\n feel: Feel;\n densityMult: number;\n backingDensity: BackingDensity;\n hhLevel: HiHatLevel;\n useGhostNotes: boolean;\n ghostBoost: boolean;\n useRide: boolean;\n useFootHh: boolean;\n role: DrumRole;\n ghostMood: MoodCategory;\n snareBeat3: boolean;\n};\n\n/** Per-beat context passed to every beat processor. */\nexport type BeatCtx = {\n track: HitList;\n beatTick: number;\n beat: number;\n velocity: number;\n section: SectionType;\n bpm: number;\n bar: number;\n sectionBars: number;\n inPrechorusLift: boolean;\n swingAmount: number;\n barHasOpenHh: boolean;\n openHhBeat: number;\n rng: DrumRng;\n};\n\nfunction swing16(tick: number, feel: Feel, swingAmount: number): number {\n return quantizeSwing(tick, effectiveSwing(feel, swingAmount), 'sixteenth');\n}\n\nfunction hatSwingFactor(style: DrumStyle): number {\n if (style === 'trap') {\n return 0;\n }\n if (style === 'latin') {\n return 0.35;\n }\n return 0.5;\n}\n\n/** Emit the kick for one beat. */\nexport function generateKickForBeat(ctx: BeatCtx, sec: SectionCtx, kick: KickPattern): void {\n if (ctx.inPrechorusLift) {\n return;\n }\n const on = [kick.beat1, kick.beat2, kick.beat3, kick.beat4][ctx.beat] ?? false;\n const and = [kick.beat1and, kick.beat2and, kick.beat3and, kick.beat4and][ctx.beat] ?? false;\n\n if (on) {\n ctx.track.add(GM.BD, ctx.beatTick, EIGHTH, ctx.velocity);\n }\n if (and) {\n const andTick = swing16(ctx.beatTick + EIGHTH, sec.feel, ctx.swingAmount);\n ctx.track.add(GM.BD, andTick, EIGHTH, ctx.velocity * 0.85);\n }\n}\n\n/** Emit the backbeat snare (or side-stick) for one beat. */\nexport function generateSnareForBeat(ctx: BeatCtx, sec: SectionCtx, isIntroFirst: boolean): void {\n if (ctx.inPrechorusLift) {\n return;\n }\n const snareOn = sec.snareBeat3 ? ctx.beat === 2 : ctx.beat === 1 || ctx.beat === 3;\n if (!snareOn || isIntroFirst) {\n return;\n }\n if (sec.useRide && shouldUseBridgeCrossStick(ctx.section, ctx.beat)) {\n return;\n }\n\n const backbeatVel = Math.min(127, ctx.velocity + 16);\n const promoteSparseChorus =\n sec.style === 'sparse' && ctx.section === 'chorus' && sec.role === 'full';\n\n if (promoteSparseChorus) {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, backbeatVel);\n } else if (sec.style === 'sparse' || sec.role === 'ambient') {\n if (sec.role !== 'fxOnly' && sec.role !== 'minimal') {\n ctx.track.add(GM.SIDESTICK, ctx.beatTick, EIGHTH, ctx.velocity * 0.8);\n }\n } else {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, backbeatVel);\n }\n}\n\n/** Emit ghost snares at the \"e\"/\"a\" 16ths of beats 1 and 3. */\nexport function generateGhostNotesForBeat(ctx: BeatCtx, sec: SectionCtx): void {\n if (ctx.beat !== 0 && ctx.beat !== 2) {\n return;\n }\n const positions = selectGhostPositions(sec.ghostMood, ctx.rng);\n let ghostProb = getGhostDensity(sec.ghostMood, ctx.section, sec.backingDensity, ctx.bpm);\n if (sec.ghostBoost) {\n ghostProb = Math.min(1, ghostProb * 1.4);\n }\n\n for (const pos of positions) {\n const sixteenthInBeat = pos === 'e' ? 1 : 3;\n const posProb = getGhostProbabilityAtPosition(ctx.beat, sixteenthInBeat);\n if (!ctx.rng.prob(ghostProb * posProb)) {\n continue;\n }\n const variation = ctx.rng.float(0.85, 1.15);\n const ghostBase = getGhostVelocity(ctx.section, ctx.beat / 2, false);\n let ghostVel = ctx.velocity * ghostBase * variation;\n if (pos === 'a') {\n ghostVel *= 0.9;\n }\n const offset = pos === 'e' ? SIXTEENTH : 3 * SIXTEENTH;\n const tick = swing16(ctx.beatTick + offset, sec.feel, ctx.swingAmount);\n ctx.track.add(GM.SD, tick, SIXTEENTH, ghostVel);\n }\n}\n\n/** Emit the pre-chorus lift buildup for one beat. */\nexport function generatePreChorusBuildup(\n ctx: BeatCtx,\n sec: SectionCtx,\n isSectionLastBar: boolean,\n): void {\n if (sec.style === 'sparse') {\n if (isSectionLastBar && ctx.beat === 3) {\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, Math.max(45, ctx.velocity * 0.75));\n ctx.track.add(GM.CRASH, ctx.beatTick + EIGHTH + SIXTEENTH, SIXTEENTH, ctx.velocity * 0.9);\n }\n return;\n }\n const barsInLift = 2;\n const barInLift = ctx.bar - (ctx.sectionBars - barsInLift);\n const progress = (barInLift * 4 + ctx.beat) / (barsInLift * 4);\n const buildupVel = ctx.velocity * (0.5 + 0.5 * progress);\n ctx.track.add(GM.SD, ctx.beatTick, EIGHTH, buildupVel);\n ctx.track.add(GM.SD, ctx.beatTick + EIGHTH, EIGHTH, buildupVel * 0.85);\n if (isSectionLastBar && ctx.beat === 3) {\n ctx.track.add(GM.CRASH, ctx.beatTick + EIGHTH + SIXTEENTH, SIXTEENTH, ctx.velocity * 1.1);\n }\n}\n\n/** Emit the timekeeping hi-hat (or ride/foot) for one beat. */\nexport function generateHiHatForBeat(ctx: BeatCtx, sec: SectionCtx): void {\n if (!shouldPlayHiHat(sec.role)) {\n if (sec.useFootHh && (ctx.beat === 0 || ctx.beat === 2)) {\n ctx.track.add(GM.FHH, ctx.beatTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n return;\n }\n\n const crossStick = sec.useRide && shouldUseBridgeCrossStick(ctx.section, ctx.beat);\n const hhInstrument = crossStick ? GM.SIDESTICK : roleHiHatInstrument(sec.role, sec.useRide);\n const hhType = sectionHiHatType(ctx.section, sec.role);\n const typeMult = hiHatTypeVelocityMultiplier(hhType);\n const isDynamicOpen = ctx.barHasOpenHh && ctx.beat === ctx.openHhBeat;\n const dm = sec.densityMult;\n\n if (sec.hhLevel === 'quarter') {\n const introRest = ctx.section === 'intro' && ctx.beat !== 0;\n if (!introRest) {\n if (isDynamicOpen) {\n ctx.track.add(\n GM.OHH,\n ctx.beatTick,\n EIGHTH,\n ctx.velocity * dm * 0.75 * typeMult + OHH_VEL_BOOST,\n );\n } else {\n ctx.track.add(\n hhInstrument,\n ctx.beatTick,\n EIGHTH,\n Math.max(20, ctx.velocity * dm * 0.75 * typeMult),\n );\n }\n } else if (sec.useFootHh) {\n ctx.track.add(GM.FHH, ctx.beatTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n return;\n }\n\n if (sec.hhLevel === 'eighth') {\n for (let eighth = 0; eighth < 2; eighth += 1) {\n let hhTick = ctx.beatTick + eighth * EIGHTH;\n if (eighth === 1) {\n hhTick = swing16(hhTick, sec.feel, ctx.swingAmount);\n }\n if (ctx.section === 'intro' && eighth === 1) {\n if (sec.useFootHh && ctx.beat % 2 === 0) {\n ctx.track.add(GM.FHH, hhTick, EIGHTH, footHiHatVelocity(ctx.rng));\n }\n continue;\n }\n const hhVel = Math.max(20, ctx.velocity * dm * typeMult * (eighth === 0 ? 0.9 : 0.65));\n if (isDynamicOpen && eighth === 0) {\n ctx.track.add(GM.OHH, hhTick, EIGHTH, hhVel + OHH_VEL_BOOST);\n continue;\n }\n let useOpen = false;\n if (sec.style === 'fourOnFloor' && eighth === 1) {\n const openProb = Math.max(0.15, Math.min(0.8, 45 / ctx.bpm));\n useOpen = (ctx.beat === 1 || ctx.beat === 3) && ctx.rng.prob(openProb);\n } else if (eighth === 0) {\n useOpen = shouldAddOpenHHAccent(ctx.section, ctx.beat, ctx.bar, ctx.rng);\n }\n if (useOpen) {\n ctx.track.add(hiHatNote('open'), hhTick, EIGHTH, Math.max(20, hhVel * 1.1));\n } else {\n ctx.track.add(hhInstrument, hhTick, EIGHTH / 2, hhVel);\n }\n }\n return;\n }\n\n for (let sixteenth = 0; sixteenth < 4; sixteenth += 1) {\n let hhTick = ctx.beatTick + sixteenth * SIXTEENTH;\n if (sixteenth === 1 || sixteenth === 3) {\n const swung = effectiveSwing(sec.feel, ctx.swingAmount) * hatSwingFactor(sec.style);\n hhTick = quantizeSwing(hhTick, swung, 'sixteenth');\n }\n const metricVel = hiHatVelocityMultiplier(sixteenth, ctx.rng);\n const hhVel = Math.max(20, ctx.velocity * dm * typeMult * metricVel);\n if (isDynamicOpen && sixteenth === 0) {\n ctx.track.add(GM.OHH, hhTick, SIXTEENTH, hhVel + OHH_VEL_BOOST);\n continue;\n }\n if (ctx.beat === 3 && sixteenth === 3) {\n const openProb = Math.max(0.1, Math.min(0.4, 30 / ctx.bpm));\n if (ctx.rng.prob(openProb)) {\n ctx.track.add(GM.OHH, hhTick, SIXTEENTH, Math.max(20, hhVel * 1.2));\n continue;\n }\n }\n ctx.track.add(hhInstrument, hhTick, SIXTEENTH / 2, hhVel);\n }\n}\n","/**\n * Generate a euclidean onset pattern (Bjorklund's algorithm), distributing\n * `pulses` as evenly as possible across `steps`, then rotating.\n *\n * @param pulses Number of onsets, clamped to [0, steps].\n * @param steps Total steps (>= 1).\n * @param rotation Steps to rotate onsets toward later positions.\n * @returns One boolean per step; true marks an onset.\n */\nexport function euclideanRhythm(pulses: number, steps: number, rotation = 0): boolean[] {\n if (steps < 1) {\n return [];\n }\n const p = Math.max(0, Math.min(pulses, steps));\n const base = bjorklund(p, steps);\n const shift = ((rotation % steps) + steps) % steps;\n if (shift === 0) {\n return base;\n }\n return base.map((_, i) => base[(i - shift + steps) % steps] ?? false);\n}\n\n/** True when the 16-step bitmask has an onset at `step`. */\nexport function hasHit(mask: number, step: number): boolean {\n return ((mask >> step) & 1) === 1;\n}\n\n/** Convert a euclidean boolean pattern to a 16-step bitmask (LSB = step 0). */\nexport function patternToMask(pattern: boolean[]): number {\n let mask = 0;\n for (let i = 0; i < pattern.length; i += 1) {\n if (pattern[i]) {\n mask |= 1 << i;\n }\n }\n return mask;\n}\n\nfunction bjorklund(pulses: number, steps: number): boolean[] {\n if (pulses === 0) {\n return Array.from({ length: steps }, () => false);\n }\n if (pulses >= steps) {\n return Array.from({ length: steps }, () => true);\n }\n let head: boolean[][] = Array.from({ length: pulses }, () => [true]);\n let remainder: boolean[][] = Array.from({ length: steps - pulses }, () => [false]);\n while (remainder.length > 1) {\n const count = Math.min(head.length, remainder.length);\n const next: boolean[][] = [];\n for (let i = 0; i < count; i += 1) {\n next.push([...(head[i] ?? []), ...(remainder[i] ?? [])]);\n }\n remainder = head.length > count ? head.slice(count) : remainder.slice(count);\n head = next;\n }\n return [...head.flat(), ...remainder.flat()];\n}\n","import type { HitList } from './hit.js';\nimport type { DrumStyle, SectionEnergy, SectionType } from './internal.js';\nimport { EIGHTH, GM, SIXTEENTH } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** The thirteen fill archetypes for section transitions. */\nexport type FillType =\n | 'snareRoll'\n | 'tomDescend'\n | 'tomAscend'\n | 'snareTomCombo'\n | 'simpleCrash'\n | 'linearFill'\n | 'ghostToAccent'\n | 'bdSnareAlternate'\n | 'hiHatChoke'\n | 'tomShuffle'\n | 'breakdownFill'\n | 'flamsAndDrags'\n | 'halfTimeFill';\n\n/** Beat at which a fill begins, widening with section energy. */\nexport function getFillStartBeat(energy: SectionEnergy): number {\n switch (energy) {\n case 'low':\n return 3;\n case 'medium':\n return 2;\n case 'high':\n case 'peak':\n return 0;\n }\n}\n\n/**\n * Pick a fill archetype for a section transition.\n *\n * The transition-specific archetypes (into a chorus, out of an intro) are\n * checked before the generic energy fills so every variation stays reachable;\n * with `from === to` the caller effectively asks for a within-section fill.\n *\n * @param from Section the fill leaves.\n * @param to Section the fill leads into.\n * @param style Internal drum style.\n * @param nextEnergy Energy of the section the fill leads into.\n * @param rng Deterministic PRNG.\n */\nexport function selectFillType(\n from: SectionType,\n to: SectionType,\n style: DrumStyle,\n nextEnergy: SectionEnergy,\n rng: DrumRng,\n): FillType {\n if (style === 'sparse') {\n return rng.range(0, 1) === 0 ? 'simpleCrash' : 'breakdownFill';\n }\n\n const toChorus = to === 'chorus';\n const fromIntro = from === 'intro';\n const highEnergy = style === 'rock' || style === 'fourOnFloor';\n\n // Dropping into a low-energy section: keep the phrase end gentle.\n if (nextEnergy === 'low') {\n switch (rng.range(0, 2)) {\n case 0:\n return 'simpleCrash';\n case 1:\n return 'breakdownFill';\n default:\n return 'halfTimeFill';\n }\n }\n\n // Big lead-ins to a chorus take precedence over the generic energy fills.\n if (toChorus) {\n const choice = rng.range(0, 7);\n if (highEnergy) {\n switch (choice) {\n case 0:\n case 1:\n return 'tomDescend';\n case 2:\n return 'snareRoll';\n case 3:\n return 'linearFill';\n case 4:\n return 'bdSnareAlternate';\n case 5:\n return 'flamsAndDrags';\n case 6:\n return 'tomShuffle';\n default:\n return 'ghostToAccent';\n }\n }\n switch (choice) {\n case 0:\n case 1:\n return 'snareTomCombo';\n case 2:\n return 'tomDescend';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'hiHatChoke';\n case 5:\n return 'linearFill';\n default:\n return 'snareRoll';\n }\n }\n\n // Leaving the intro: lighter, building character.\n if (fromIntro) {\n switch (rng.range(0, 5)) {\n case 0:\n case 1:\n return 'snareRoll';\n case 2:\n return 'simpleCrash';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'breakdownFill';\n default:\n return 'halfTimeFill';\n }\n }\n\n // Generic medium/high/peak fills, split by style energy.\n const choice = rng.range(0, 7);\n if (highEnergy) {\n switch (choice) {\n case 0:\n return 'tomDescend';\n case 1:\n return 'snareRoll';\n case 2:\n return 'tomAscend';\n case 3:\n return 'snareTomCombo';\n case 4:\n return 'linearFill';\n case 5:\n return 'bdSnareAlternate';\n case 6:\n return 'flamsAndDrags';\n default:\n return 'tomShuffle';\n }\n }\n\n switch (choice) {\n case 0:\n case 1:\n return 'snareRoll';\n case 2:\n return 'snareTomCombo';\n case 3:\n return 'ghostToAccent';\n case 4:\n return 'hiHatChoke';\n case 5:\n return 'halfTimeFill';\n default:\n return 'breakdownFill';\n }\n}\n\n/**\n * Emit a fill for a single beat of the fill bar.\n *\n * @param track Hit accumulator.\n * @param beatTick Absolute beat position of this beat.\n * @param beat Beat index within the bar (0-3).\n * @param fillType Selected fill archetype.\n * @param velocity Base velocity for the beat.\n */\nexport function generateFill(\n track: HitList,\n beatTick: number,\n beat: number,\n fillType: FillType,\n velocity: number,\n): void {\n const fillVel = velocity * 0.9;\n const accentVel = velocity * 0.95;\n const S = SIXTEENTH;\n const E = EIGHTH;\n\n if (beat === 0) {\n track.add(GM.BD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, E, fillVel - 5);\n return;\n }\n if (beat === 1) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_H, beatTick + E, E, fillVel - 3);\n return;\n }\n\n switch (fillType) {\n case 'snareRoll':\n if (beat === 2) {\n for (let i = 0; i < 4; i += 1) {\n track.add(GM.SD, beatTick + i * S, S, fillVel * (0.6 + 0.1 * i));\n }\n } else {\n for (let i = 0; i < 3; i += 1) {\n track.add(GM.SD, beatTick + i * S, S, fillVel * (0.7 + 0.1 * i));\n }\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'tomDescend':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_H, beatTick + E, E, fillVel - 5);\n } else {\n track.add(GM.TOM_H, beatTick, S, fillVel);\n track.add(GM.TOM_M, beatTick + S, S, fillVel - 3);\n track.add(GM.TOM_M, beatTick + E, S, fillVel - 5);\n track.add(GM.TOM_L, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'tomAscend':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.TOM_L, beatTick + E, E, fillVel - 5);\n } else {\n track.add(GM.TOM_L, beatTick, S, fillVel);\n track.add(GM.TOM_M, beatTick + S, S, fillVel + 3);\n track.add(GM.TOM_M, beatTick + E, S, fillVel + 5);\n track.add(GM.TOM_H, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'snareTomCombo':\n if (beat === 2) {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, S, fillVel - 5);\n track.add(GM.TOM_H, beatTick + E + S, S, fillVel);\n } else {\n track.add(GM.TOM_M, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel - 3);\n track.add(GM.TOM_L, beatTick + E, S, fillVel + 2);\n track.add(GM.BD, beatTick + E + S, S, accentVel);\n }\n break;\n\n case 'simpleCrash':\n if (beat === 3) {\n track.add(GM.BD, beatTick + E + S, S, accentVel);\n track.add(GM.CRASH, beatTick + E + S, E, accentVel);\n }\n break;\n\n case 'linearFill':\n if (beat === 2) {\n track.add(GM.BD, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel);\n track.add(GM.TOM_H, beatTick + 2 * S, S, fillVel);\n track.add(GM.TOM_M, beatTick + 3 * S, S, fillVel);\n } else {\n track.add(GM.TOM_L, beatTick, S, fillVel + 3);\n track.add(GM.SD, beatTick + S, S, fillVel + 5);\n track.add(GM.BD, beatTick + 2 * S, S, fillVel + 7);\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'ghostToAccent':\n if (beat === 2) {\n const ghost = fillVel * 0.4;\n track.add(GM.SD, beatTick, S, ghost);\n track.add(GM.SD, beatTick + S, S, ghost + 10);\n track.add(GM.SD, beatTick + 2 * S, S, ghost + 20);\n track.add(GM.SD, beatTick + 3 * S, S, ghost + 30);\n } else {\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, E, accentVel);\n }\n break;\n\n case 'bdSnareAlternate':\n if (beat === 2) {\n track.add(GM.BD, beatTick, S, fillVel);\n track.add(GM.SD, beatTick + S, S, fillVel);\n track.add(GM.BD, beatTick + 2 * S, S, fillVel + 3);\n track.add(GM.SD, beatTick + 3 * S, S, fillVel + 3);\n } else {\n track.add(GM.BD, beatTick, S, fillVel + 5);\n track.add(GM.SD, beatTick + S, S, fillVel + 5);\n track.add(GM.BD, beatTick + 2 * S, S, accentVel);\n track.add(GM.SD, beatTick + 3 * S, S, accentVel);\n }\n break;\n\n case 'hiHatChoke':\n if (beat === 2) {\n track.add(GM.OHH, beatTick, E, fillVel);\n track.add(GM.OHH, beatTick + E, E, fillVel + 5);\n } else {\n track.add(GM.OHH, beatTick, S, fillVel + 8);\n track.add(GM.CHH, beatTick + S, S, accentVel);\n track.add(GM.SD, beatTick + E, E, accentVel);\n }\n break;\n\n case 'tomShuffle':\n if (beat === 2) {\n track.add(GM.TOM_H, beatTick, E, fillVel);\n track.add(GM.TOM_M, beatTick + E + S / 2, S, fillVel - 5);\n } else {\n track.add(GM.TOM_M, beatTick, E, fillVel);\n track.add(GM.TOM_L, beatTick + E + S / 2, S, fillVel + 5);\n }\n break;\n\n case 'breakdownFill':\n if (beat === 3) {\n track.add(GM.SD, beatTick + E, S, accentVel);\n }\n break;\n\n case 'flamsAndDrags':\n if (beat === 2) {\n track.add(GM.SD, beatTick - S / 4, S / 4, fillVel * 0.5);\n track.add(GM.SD, beatTick, E, fillVel);\n track.add(GM.SD, beatTick + E, S / 2, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S / 2, S / 2, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S, E, fillVel);\n } else {\n track.add(GM.SD, beatTick - S / 4, S / 4, fillVel * 0.5);\n track.add(GM.SD, beatTick, 1, accentVel);\n }\n break;\n\n case 'halfTimeFill':\n if (beat === 2) {\n track.add(GM.SD, beatTick, 1, accentVel);\n track.add(GM.BD, beatTick, 1, fillVel);\n } else if (beat === 3) {\n // At low energy the fill spans only beat 3, so this branch keeps the\n // phrase end from going silent: a broad half-time backbeat snare with a\n // light pickup into the next section.\n track.add(GM.SD, beatTick, EIGHTH, accentVel);\n track.add(GM.SD, beatTick + E, S, fillVel * 0.6);\n track.add(GM.SD, beatTick + E + S, S, accentVel);\n }\n break;\n }\n}\n","import { clampVel, GM } from './internal.js';\n\n/** A single percussion onset. */\nexport type DrumHit = {\n pitch: number;\n startBeat: number;\n durationBeat: number;\n velocity: number;\n};\n\n/** Accumulator for drum onsets with velocity clamping and simple lookups. */\nexport class HitList {\n readonly hits: DrumHit[] = [];\n\n /** Append a hit, clamping velocity and dropping non-positive positions. */\n add(pitch: number, startBeat: number, durationBeat: number, velocity: number): void {\n this.hits.push({\n pitch,\n startBeat: Math.max(0, startBeat),\n durationBeat,\n velocity: clampVel(velocity),\n });\n }\n\n /** True when a crash already sits within a 16th of `startBeat`. */\n hasCrashNear(startBeat: number): boolean {\n return this.hits.some(\n (h) => h.pitch === GM.CRASH && h.startBeat >= startBeat && h.startBeat < startBeat + 0.25,\n );\n }\n}\n","import { hasHit } from './euclid.js';\nimport type { DrumStyle, SectionType } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Kick presence flags across the eight 8th-note slots of a bar. */\nexport type KickPattern = {\n beat1: boolean;\n beat1and: boolean;\n beat2: boolean;\n beat2and: boolean;\n beat3: boolean;\n beat3and: boolean;\n beat4: boolean;\n beat4and: boolean;\n};\n\nconst EMPTY: KickPattern = {\n beat1: false,\n beat1and: false,\n beat2: false,\n beat2and: false,\n beat3: false,\n beat3and: false,\n beat4: false,\n beat4and: false,\n};\n\n/**\n * Whether a pre-chorus bar sits in the two-bar lift into the chorus.\n *\n * @param section Current section.\n * @param bar Bar index within the section.\n * @param sectionBars Total bars in the section.\n * @param nextIsChorus Whether the following section is a chorus.\n */\nexport function isInPreChorusLift(\n section: SectionType,\n bar: number,\n sectionBars: number,\n nextIsChorus: boolean,\n): boolean {\n if (section !== 'b' || !nextIsChorus || sectionBars < 3) {\n return false;\n }\n return bar >= sectionBars - 2;\n}\n\n/** Convert a 16-step euclidean bitmask into an 8th-slot kick pattern. */\nexport function euclideanToKickPattern(mask: number): KickPattern {\n const slot = (step: number) => hasHit(mask, step) || hasHit(mask, (step + 15) % 16);\n return {\n beat1: slot(0),\n beat1and: slot(2),\n beat2: slot(4),\n beat2and: slot(6),\n beat3: slot(8),\n beat3and: slot(10),\n beat4: slot(12),\n beat4and: slot(14),\n };\n}\n\n/**\n * Build a section- and style-aware kick pattern.\n *\n * @param section Current section.\n * @param style Internal drum style.\n * @param bar Bar index (drives variation for a few styles).\n * @param rng Deterministic PRNG for probabilistic accents.\n */\nexport function getKickPattern(\n section: SectionType,\n style: DrumStyle,\n bar: number,\n rng: DrumRng,\n): KickPattern {\n const p: KickPattern = { ...EMPTY };\n\n if (section === 'outro') {\n p.beat1 = true;\n p.beat3 = true;\n return p;\n }\n\n switch (style) {\n case 'sparse':\n p.beat1 = true;\n if (section === 'chorus' && bar % 2 === 1) {\n p.beat3 = true;\n }\n break;\n\n case 'fourOnFloor':\n p.beat1 = p.beat2 = p.beat3 = p.beat4 = true;\n if (section === 'chorus' && rng.prob(0.2)) {\n p.beat2and = true;\n }\n break;\n\n case 'upbeat':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b' || section === 'chorus') {\n p.beat2and = rng.prob(0.7);\n }\n if (section === 'chorus') {\n p.beat4and = rng.prob(0.6);\n }\n break;\n\n case 'rock':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'chorus') {\n p.beat2and = rng.prob(0.65);\n p.beat4and = rng.prob(0.4);\n } else if (section === 'b') {\n p.beat2and = rng.prob(0.3);\n }\n break;\n\n case 'synth':\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b' || section === 'chorus') {\n p.beat2and = rng.prob(0.75);\n }\n if (section === 'chorus') {\n p.beat4and = rng.prob(0.65);\n }\n break;\n\n case 'trap':\n p.beat1 = true;\n p.beat2and = rng.prob(0.8);\n p.beat3 = rng.prob(0.3);\n p.beat4and = rng.prob(0.7);\n break;\n\n case 'latin':\n p.beat1 = true;\n p.beat2and = true;\n p.beat3 = true;\n p.beat4and = rng.prob(0.5);\n break;\n\n default:\n p.beat1 = true;\n p.beat3 = true;\n if (section === 'b') {\n p.beat2and = rng.prob(0.5);\n } else if (section === 'chorus') {\n p.beat2and = rng.prob(0.55);\n p.beat4and = rng.prob(0.35);\n }\n break;\n }\n\n return p;\n}\n","import { HH_16TH_BPM_THRESHOLD } from './hihat.js';\nimport type { HitList } from './hit.js';\nimport type { DrumRole, SectionType } from './internal.js';\nimport { EIGHTH, GM, PercMoodCategory, SIXTEENTH, sectionIndex } from './internal.js';\nimport type { DrumRng } from './rng.js';\n\n/** Enabled auxiliary percussion voices for a section. */\nexport type PercussionConfig = {\n tambourine: boolean;\n shaker: boolean;\n handclap: boolean;\n shaker16th: boolean;\n};\n\ntype PercActivation = [tambourine: boolean, shaker: boolean, handclap: boolean];\n\n// Percussion activation per [mood category][section index]. Columns:\n// intro, a, b, chorus, bridge, interlude, outro, chant, mixbreak.\nconst F: PercActivation = [false, false, false];\nconst PERC_TABLE: PercActivation[][] = [\n /* calm */ [F, F, F, F, F, F, F, F, F],\n /* std */ [F, F, [false, true, false], [true, false, true], F, F, F, F, [true, false, true]],\n /* ener */ [\n F,\n [false, true, false],\n [false, true, false],\n [true, true, true],\n F,\n F,\n F,\n F,\n [true, true, true],\n ],\n /* idol */ [\n F,\n [false, true, false],\n [false, true, false],\n [true, true, true],\n F,\n F,\n F,\n F,\n [true, true, true],\n ],\n /* rock */ [F, F, F, [false, false, true], F, F, F, F, [false, false, true]],\n];\n\n/** Resolve which auxiliary percussion voices play for a section. */\nexport function getPercussionConfig(\n mood: PercMoodCategory,\n section: SectionType,\n): PercussionConfig {\n const row = PERC_TABLE[mood] ?? PERC_TABLE[PercMoodCategory.Standard];\n const act = row?.[sectionIndex(section)] ?? F;\n return {\n tambourine: act[0],\n shaker: act[1],\n handclap: act[2],\n shaker16th: act[1],\n };\n}\n\n/** Emit one bar of auxiliary percussion (tambourine/shaker/handclap). */\nexport function generateAuxPercussionForBar(\n track: HitList,\n barStart: number,\n config: PercussionConfig,\n role: DrumRole,\n densityMult: number,\n rng: DrumRng,\n bpm: number,\n): void {\n if (role === 'minimal' || role === 'fxOnly') {\n return;\n }\n\n if (config.tambourine) {\n for (let beat = 1; beat <= 3; beat += 2) {\n const raw = 70 * densityMult * rng.float(0.9, 1.1);\n track.add(GM.TAMBOURINE, barStart + beat, EIGHTH, Math.max(40, Math.min(90, raw)));\n }\n }\n\n if (config.shaker) {\n const use16th = config.shaker16th && bpm < HH_16TH_BPM_THRESHOLD;\n if (use16th) {\n const velCurve = [0.75, 0.45, 0.6, 0.45];\n for (let beat = 0; beat < 4; beat += 1) {\n for (let sub = 0; sub < 4; sub += 1) {\n const raw = 80 * (velCurve[sub] ?? 0.5) * densityMult * rng.float(0.9, 1.1);\n track.add(\n GM.SHAKER,\n barStart + beat + sub * SIXTEENTH,\n SIXTEENTH,\n Math.max(25, Math.min(85, raw)),\n );\n }\n }\n } else {\n const velCurve = [0.75, 0.55];\n for (let beat = 0; beat < 4; beat += 1) {\n for (let sub = 0; sub < 2; sub += 1) {\n const raw = 80 * (velCurve[sub] ?? 0.6) * densityMult * rng.float(0.9, 1.1);\n track.add(\n GM.SHAKER,\n barStart + beat + sub * EIGHTH,\n EIGHTH,\n Math.max(25, Math.min(85, raw)),\n );\n }\n }\n }\n }\n\n if (config.handclap) {\n for (let beat = 1; beat <= 3; beat += 2) {\n const raw = 85 * densityMult * rng.float(0.9, 1.1);\n track.add(GM.HANDCLAP, barStart + beat, EIGHTH, Math.max(50, Math.min(100, raw)));\n }\n }\n}\n","import {\n type BeatCtx,\n generateGhostNotesForBeat,\n generateHiHatForBeat,\n generateKickForBeat,\n generatePreChorusBuildup,\n generateSnareForBeat,\n type SectionCtx,\n} from './beat.js';\nimport { euclideanRhythm, patternToMask } from './euclid.js';\nimport { type FillType, generateFill, getFillStartBeat, selectFillType } from './fills.js';\nimport {\n footHiHatVelocity,\n getHiHatLevel,\n openHiHatBarInterval,\n openHiHatBeat,\n shouldPlayHiHat,\n shouldUseFootHiHat,\n shouldUseRideForSection,\n} from './hihat.js';\nimport { type DrumHit, HitList } from './hit.js';\nimport {\n calculateVelocity,\n type DrumRole,\n type Feel,\n feelSwingAmount,\n GM,\n type GrooveStyle,\n ghostMoodCategory,\n mapDensity,\n mapSection,\n mapStyle,\n type PublicSection,\n percMoodCategory,\n sectionDensityMultiplier,\n sectionEnergy,\n} from './internal.js';\nimport {\n euclideanToKickPattern,\n getKickPattern,\n isInPreChorusLift,\n type KickPattern,\n} from './kick.js';\nimport { generateAuxPercussionForBar, getPercussionConfig } from './percussion.js';\nimport { createRng } from './rng.js';\n\n/**\n * A single drum onset emitted by {@link generateDrums}.\n *\n * @category Composition\n */\nexport type { DrumHit } from './hit.js';\n\n/**\n * Groove feel (the swing/straight rhythmic character) for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type GrooveFeel = Feel;\n\n/**\n * Drum voicing role and groove style identifiers for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type { DrumRole, GrooveStyle } from './internal.js';\n\n/**\n * Public section identifiers for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type Section = PublicSection;\n\n/**\n * A Euclidean (Bjorklund) kick pattern for {@link generateDrums}.\n *\n * @category Composition\n */\nexport type EuclideanKick = {\n /** Number of kick onsets, clamped to `[0, steps]`. */\n pulses: number;\n /**\n * Total steps in the bar (1..16).\n *\n * @defaultValue 16\n */\n steps?: number;\n /**\n * Steps to rotate the onsets toward later positions.\n *\n * @defaultValue 0\n */\n rotation?: number;\n};\n\n/**\n * Options controlling {@link generateDrums}.\n *\n * @category Composition\n */\nexport type DrumsOptions = {\n bars: number;\n bpm: number;\n style: GrooveStyle;\n section: Section;\n density: number;\n /**\n * Replace the final bar with a fill.\n *\n * @defaultValue false\n */\n fills?: boolean;\n feel?: GrooveFeel;\n /**\n * Voicing role; `'fxOnly'` suppresses the main kick/snare/ghost/fill voices.\n *\n * @defaultValue `'full'`\n */\n role?: DrumRole;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n /**\n * Section the final-bar fill leads into. Shapes which fill archetype is\n * chosen (into-chorus and out-of-intro fills differ from generic ones).\n * Defaults to `section`, i.e. a within-section fill.\n */\n nextSection?: Section;\n /**\n * When set, the kick follows this Euclidean rhythm instead of the\n * style/section pattern, giving direct access to evenly spread onsets.\n */\n euclideanKick?: EuclideanKick;\n};\n\n/**\n * Generate a drum performance as a flat list of onsets.\n *\n * Every voice (kick, snare, ghost snares, closed/open/foot hi-hats, ride, toms,\n * crash, and auxiliary percussion) is emitted as a {@link DrumHit} distinguished\n * by its General MIDI pitch. Groove style selects an internal style and feel;\n * `density` sets the backing-density level; `section` shapes kick, hi-hat, ghost,\n * and percussion density. 16th-note hi-hats drop to 8ths at or above 150 BPM.\n * When `fills` is true the final bar is replaced with a fill whose archetype is\n * shaped by `nextSection`; a fill that would emit nothing on its beat falls back\n * to the normal groove so the phrase end is never silent. `euclideanKick`\n * overrides the kick with an evenly-spread Euclidean pattern. Output is fully\n * determined by the options plus `seed`.\n *\n * @param opts Generation options.\n * @returns Percussion onsets in bar order.\n *\n * @example\n * ```ts\n * import { generateDrums } from '@libraz/libcantus';\n * const hits = generateDrums({ bars: 4, bpm: 120, style: 'standard', section: 'chorus', density: 0.6, fills: true });\n * // Fully determined by the options plus seed (defaults to 0).\n * ```\n *\n * @category Composition\n */\nexport function generateDrums(opts: DrumsOptions): DrumHit[] {\n const track = new HitList();\n const rng = createRng(opts.seed ?? 0);\n const mapping = mapStyle(opts.style);\n const style = mapping.style;\n const feel: Feel = opts.feel ?? mapping.feel;\n const role: DrumRole = opts.role ?? 'full';\n // fxOnly leaves only fx/aux voices: the main kick, snare, ghost, and fill\n // voices are suppressed just as timekeeping hi-hats already are.\n const playMainVoices = role !== 'fxOnly';\n const section = mapSection(opts.section);\n const backingDensity = mapDensity(opts.density);\n const swingAmount = feelSwingAmount(feel);\n\n let densityMult = sectionDensityMultiplier(section);\n if (backingDensity === 'thin') {\n densityMult *= 0.75;\n } else if (backingDensity === 'thick') {\n densityMult *= 1.15;\n }\n\n const sec: SectionCtx = {\n style,\n feel,\n densityMult,\n backingDensity,\n hhLevel: getHiHatLevel(section, style, backingDensity, opts.bpm, rng),\n useGhostNotes:\n (section === 'b' || section === 'chorus' || section === 'bridge') && style !== 'sparse',\n ghostBoost: mapping.ghostBoost,\n useRide: shouldUseRideForSection(section, style),\n useFootHh: shouldUseFootHiHat(section, role),\n role,\n ghostMood: ghostMoodCategory(style),\n snareBeat3: mapping.snareBeat3,\n };\n\n const ohhBarInterval = openHiHatBarInterval(section, style);\n const energy = sectionEnergy(section);\n const fillStartBeat = getFillStartBeat(energy);\n const percMood = percMoodCategory(style);\n\n // The final-bar fill is shaped by the section it leads into. When no next\n // section is given the fill is treated as within-section (from === to).\n const nextSection = opts.nextSection ? mapSection(opts.nextSection) : section;\n const nextEnergy = sectionEnergy(nextSection);\n\n const euclidKick: KickPattern | undefined = opts.euclideanKick\n ? euclideanToKickPattern(\n patternToMask(\n euclideanRhythm(\n opts.euclideanKick.pulses,\n opts.euclideanKick.steps ?? 16,\n opts.euclideanKick.rotation ?? 0,\n ),\n ),\n )\n : undefined;\n\n const reuseSectionKick = (section === 'b' || section === 'chorus') && style !== 'sparse';\n let sectionKick: KickPattern | undefined;\n\n for (let bar = 0; bar < opts.bars; bar += 1) {\n const barStart = bar * 4;\n const isLastBar = bar === opts.bars - 1;\n\n if (bar === 0 && section === 'chorus') {\n track.add(GM.CRASH, barStart, 0.5, 100 * densityMult);\n }\n\n let barHasOpenHh = false;\n let openHhBeatIndex = 3;\n if (ohhBarInterval > 0 && bar % ohhBarInterval === ohhBarInterval - 1) {\n openHhBeatIndex = openHiHatBeat(section, rng);\n barHasOpenHh = !track.hasCrashNear(barStart + openHhBeatIndex);\n }\n\n let kick: KickPattern;\n if (euclidKick) {\n kick = euclidKick;\n } else if (reuseSectionKick) {\n sectionKick ??= getKickPattern(section, style, 0, rng);\n kick = sectionKick;\n } else {\n kick = getKickPattern(section, style, bar, rng);\n }\n\n const inLift = isInPreChorusLift(section, bar, opts.bars, section === 'b');\n let currentFill: FillType = 'snareRoll';\n\n for (let beat = 0; beat < 4; beat += 1) {\n const beatTick = barStart + beat;\n const velocity = calculateVelocity(section, beat);\n\n if (opts.fills && isLastBar && !inLift && beat >= fillStartBeat) {\n if (beat === fillStartBeat) {\n currentFill = selectFillType(section, nextSection, style, nextEnergy, rng);\n }\n if (playMainVoices) {\n const before = track.hits.length;\n generateFill(track, beatTick, beat, currentFill, velocity);\n if (track.hits.length > before) {\n continue;\n }\n // Safety net: an archetype that contributes nothing on this beat would\n // leave a silent phrase end, so fall through to the normal groove.\n } else {\n // fxOnly deliberately emits no main voices on the fill beats.\n continue;\n }\n }\n\n const ctx: BeatCtx = {\n track,\n beatTick,\n beat,\n velocity,\n section,\n bpm: opts.bpm,\n bar,\n sectionBars: opts.bars,\n inPrechorusLift: inLift,\n swingAmount,\n barHasOpenHh,\n openHhBeat: openHhBeatIndex,\n rng,\n };\n\n if (playMainVoices) {\n if (inLift) {\n generatePreChorusBuildup(ctx, sec, isLastBar);\n }\n generateKickForBeat(ctx, sec, kick);\n generateSnareForBeat(ctx, sec, section === 'intro' && bar === 0);\n if (sec.useGhostNotes && !inLift) {\n generateGhostNotesForBeat(ctx, sec);\n }\n }\n generateHiHatForBeat(ctx, sec);\n }\n\n if (sec.useFootHh && shouldPlayHiHat(role)) {\n for (let fhhBeat = 0; fhhBeat < 4; fhhBeat += 2) {\n const fhhTick = barStart + fhhBeat;\n const occupied = track.hits.some((h) => h.pitch === GM.FHH && h.startBeat === fhhTick);\n if (!occupied) {\n track.add(GM.FHH, fhhTick, 0.5, footHiHatVelocity(rng));\n }\n }\n }\n\n generateAuxPercussionForBar(\n track,\n barStart,\n getPercussionConfig(percMood, section),\n role,\n densityMult,\n rng,\n opts.bpm,\n );\n }\n\n return track.hits;\n}\n","/**\n * Groove and humanization: nudging quantized note events toward a more human\n * feel, and capturing/replaying the timing-and-velocity \"feel\" of a\n * performance as a reusable groove template.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention. Randomness, where used, always goes through the\n * seeded PRNG from the `random` module so results are fully reproducible.\n */\n\nimport {\n beatsPerBar,\n formatTimeSignature,\n metricWeight,\n type TimeSignature,\n} from '../../core/meter/index.js';\nimport { createRng } from '../../core/random/index.js';\nimport type { NoteEvent } from '../../core/types.js';\n\n/**\n * Options controlling {@link humanize}.\n *\n * @category Rhythm & Meter\n */\nexport type HumanizeOptions = {\n /**\n * Time signature used to derive metric accents.\n *\n * @defaultValue 4/4\n */\n ts?: TimeSignature;\n /**\n * Maximum timing jitter in quarter-note beats, applied as ±this value.\n *\n * @defaultValue 0.02\n */\n timing?: number;\n /**\n * Maximum velocity jitter (MIDI units), applied as ±this value.\n *\n * @defaultValue 8\n */\n velocity?: number;\n /**\n * How much louder strong beats get relative to weak ones, in MIDI velocity units.\n *\n * @defaultValue 12\n */\n accent?: number;\n /**\n * Velocity assumed for events with no `velocity` of their own.\n *\n * @defaultValue 80\n */\n baseVelocity?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/** Default time signature for {@link humanize} when none is given. */\nconst DEFAULT_TS: TimeSignature = { numerator: 4, denominator: 4 };\nconst DEFAULT_TIMING = 0.02;\nconst DEFAULT_VELOCITY_JITTER = 8;\nconst DEFAULT_ACCENT = 12;\nconst DEFAULT_BASE_VELOCITY = 80;\nconst MAX_METRIC_WEIGHT = 3;\nconst MIN_VELOCITY = 1;\nconst MAX_VELOCITY = 127;\n\n/**\n * Humanize a sequence of note events by nudging their timing and velocity\n * with small, deterministic (seeded) randomness plus a metric-accent shape:\n * events on strong beats (see {@link metricWeight}) come out louder on\n * average than events on weak ones.\n *\n * Each returned event is a copy; `startBeat` is jittered within\n * `[-timing, +timing]` beats and clamped to be non-negative, and `velocity`\n * is the event's own velocity (or `baseVelocity` if it has none) plus an\n * accent term scaled by the event's metric weight plus a jitter within\n * `[-velocity, +velocity]`, clamped to `[1, 127]` and rounded. The metric\n * weight is computed from each event's original (pre-jitter) `startBeat`.\n * `pitch` and `durationBeat` pass through unchanged, and the output keeps the\n * input order.\n *\n * @param events The events to humanize.\n * @param opts Humanization options.\n * @returns Humanized copies of `events`, in input order.\n * @example\n * ```ts\n * import { humanize } from '@libraz/libcantus';\n * const events = [{ pitch: 60, startBeat: 0, durationBeat: 1, velocity: 80 }];\n * humanize(events, { seed: 1, timing: 0.03 }); // copies with jittered timing and accented velocity\n * ```\n * @category Rhythm & Meter\n */\nexport function humanize(events: NoteEvent[], opts: HumanizeOptions = {}): NoteEvent[] {\n const ts = opts.ts ?? DEFAULT_TS;\n const timing = opts.timing ?? DEFAULT_TIMING;\n const velocityJitter = opts.velocity ?? DEFAULT_VELOCITY_JITTER;\n const accent = opts.accent ?? DEFAULT_ACCENT;\n const baseVelocity = opts.baseVelocity ?? DEFAULT_BASE_VELOCITY;\n const rng = createRng(opts.seed ?? 0);\n\n return events.map((event) => {\n const timingOffset = rng.float(-timing, timing);\n const startBeat = Math.max(0, event.startBeat + timingOffset);\n\n const weight = metricWeight(event.startBeat, ts);\n const accentBoost = (weight / MAX_METRIC_WEIGHT) * accent;\n const velocityOffset = rng.float(-velocityJitter, velocityJitter);\n const rawVelocity = (event.velocity ?? baseVelocity) + accentBoost + velocityOffset;\n const velocity = Math.min(MAX_VELOCITY, Math.max(MIN_VELOCITY, Math.round(rawVelocity)));\n\n return {\n pitch: event.pitch,\n startBeat,\n durationBeat: event.durationBeat,\n velocity,\n };\n });\n}\n\n/**\n * The recorded feel at a single grid slot: an average timing deviation and velocity.\n *\n * @category Rhythm & Meter\n */\nexport type GrooveSlot = {\n /** Average `actualStartBeat - quantizedBeat` (in quarter-note beats) for events landing on this slot. */\n timingOffset: number;\n /**\n * Average velocity of events landing on this slot, or `null` if no event\n * with a velocity did. `null` (not 0) is the \"unrecorded\" sentinel so that a\n * genuine velocity of 0 is preserved and applied like any other value.\n */\n velocity: number | null;\n};\n\n/**\n * A per-bar grid of timing and velocity deviations captured from a performance.\n *\n * @category Rhythm & Meter\n */\nexport type GrooveTemplate = {\n /** Grid resolution: equal grid steps per quarter-note beat. */\n subdivision: number;\n /** Number of grid slots per bar (`beatsPerBar(ts) * subdivision`). */\n slotsPerBar: number;\n /** One entry per grid slot, in slot-index order (slot 0 is the downbeat). */\n slots: GrooveSlot[];\n /**\n * The time signature the template was extracted under. {@link applyGrooveTemplate}\n * requires the apply-time meter to match this so the per-bar grid lines up\n * instead of silently drifting. Optional for backward compatibility with\n * templates constructed without it (in which case no check is performed).\n */\n ts?: TimeSignature;\n};\n\n/**\n * Quantize a beat position to the nearest grid slot at the given subdivision,\n * within the bar that contains it.\n *\n * @param beat Absolute position in quarter-note beats.\n * @param barBeats Bar length in quarter-note beats.\n * @param subdivision Grid steps per quarter-note beat.\n * @param slotsPerBar Number of grid slots per bar.\n * @returns The quantized absolute beat and its 0-based slot index within the bar.\n */\nfunction quantizeToGrid(\n beat: number,\n barBeats: number,\n subdivision: number,\n slotsPerBar: number,\n): { quantizedBeat: number; slotIndex: number } {\n const barIndex = Math.floor(beat / barBeats);\n const modBeat = beat - barIndex * barBeats;\n let slotIndex = Math.round(modBeat * subdivision);\n let effectiveBarIndex = barIndex;\n // Rounding the last slot in a bar up to the grid step count means it\n // actually lands on the next bar's downbeat.\n if (slotIndex >= slotsPerBar) {\n slotIndex = 0;\n effectiveBarIndex += 1;\n }\n return {\n quantizedBeat: effectiveBarIndex * barBeats + slotIndex / subdivision,\n slotIndex,\n };\n}\n\n/**\n * Extract a groove template from a set of note events: for each grid slot,\n * the average timing deviation from the quantized grid and the average\n * velocity of events landing on it. Slots with no velocity-carrying event\n * record `velocity: null` (the \"unrecorded\" sentinel); empty slots default to\n * `{ timingOffset: 0, velocity: null }`. The time signature is stored on the\n * template so {@link applyGrooveTemplate} can verify the meter matches.\n *\n * @param events The (typically \"groovy\", human-played) events to analyze.\n * @param ts The time signature, used to compute the bar length.\n * @param subdivision Grid resolution: equal grid steps per quarter-note beat.\n * @returns The extracted groove template.\n * @category Rhythm & Meter\n */\nexport function extractGrooveTemplate(\n events: NoteEvent[],\n ts: TimeSignature,\n subdivision: number,\n): GrooveTemplate {\n const barBeats = beatsPerBar(ts);\n const slotsPerBar = Math.round(barBeats * subdivision);\n const offsetSums = new Array<number>(slotsPerBar).fill(0);\n const velocitySums = new Array<number>(slotsPerBar).fill(0);\n const counts = new Array<number>(slotsPerBar).fill(0);\n const velocityCounts = new Array<number>(slotsPerBar).fill(0);\n\n for (const event of events) {\n const { quantizedBeat, slotIndex } = quantizeToGrid(\n event.startBeat,\n barBeats,\n subdivision,\n slotsPerBar,\n );\n offsetSums[slotIndex] = (offsetSums[slotIndex] ?? 0) + (event.startBeat - quantizedBeat);\n counts[slotIndex] = (counts[slotIndex] ?? 0) + 1;\n // Only events that carry a velocity contribute to the velocity average, so a\n // velocity-less event does not pull the slot's recorded velocity toward zero.\n if (event.velocity !== undefined) {\n velocitySums[slotIndex] = (velocitySums[slotIndex] ?? 0) + event.velocity;\n velocityCounts[slotIndex] = (velocityCounts[slotIndex] ?? 0) + 1;\n }\n }\n\n const slots: GrooveSlot[] = [];\n for (let i = 0; i < slotsPerBar; i += 1) {\n const count = counts[i] ?? 0;\n if (count === 0) {\n slots.push({ timingOffset: 0, velocity: null });\n continue;\n }\n const velocityCount = velocityCounts[i] ?? 0;\n slots.push({\n timingOffset: (offsetSums[i] ?? 0) / count,\n velocity: velocityCount > 0 ? (velocitySums[i] ?? 0) / velocityCount : null,\n });\n }\n\n return { subdivision, slotsPerBar, slots, ts };\n}\n\n/**\n * Apply a groove template to a set of (typically quantized) note events: each\n * event is snapped to its grid slot and then offset by that slot's recorded\n * timing deviation, pushing stiff timing toward the template's feel.\n * Velocity is set to the slot's recorded average when it recorded one (a\n * non-`null` velocity, including a genuine 0); otherwise the event's own\n * velocity is left untouched.\n *\n * If the template carries a time signature (see {@link GrooveTemplate.ts}) it\n * must match `ts`, since a differing bar length would misalign the per-bar\n * grid and drift the feel; a mismatch throws rather than corrupting timing\n * silently.\n *\n * @param events The events to reshape.\n * @param template The groove template, from {@link extractGrooveTemplate}.\n * @param ts The time signature, used to compute the bar length.\n * @returns Reshaped copies of `events`, in input order.\n * @throws If `template.ts` is set and does not match `ts`.\n * @example\n * ```ts\n * import { extractGrooveTemplate, applyGrooveTemplate, parseTimeSignature } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * // Learn the feel from a loosely played performance...\n * const groovy = [\n * { pitch: 36, startBeat: 0.02, durationBeat: 1, velocity: 100 },\n * { pitch: 38, startBeat: 1.06, durationBeat: 1, velocity: 70 },\n * ];\n * const template = extractGrooveTemplate(groovy, ts, 4);\n * // ...then impose it on stiff, quantized events.\n * const quantized = [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 80 }];\n * applyGrooveTemplate(quantized, template, ts); // events nudged toward the captured feel\n * ```\n * @category Rhythm & Meter\n */\nexport function applyGrooveTemplate(\n events: NoteEvent[],\n template: GrooveTemplate,\n ts: TimeSignature,\n): NoteEvent[] {\n if (\n template.ts &&\n (template.ts.numerator !== ts.numerator || template.ts.denominator !== ts.denominator)\n ) {\n throw new Error(\n `Groove template meter ${formatTimeSignature(template.ts)} does not match ` +\n `apply-time meter ${formatTimeSignature(ts)}`,\n );\n }\n const barBeats = beatsPerBar(ts);\n return events.map((event) => {\n const { quantizedBeat, slotIndex } = quantizeToGrid(\n event.startBeat,\n barBeats,\n template.subdivision,\n template.slotsPerBar,\n );\n const slot = template.slots[slotIndex];\n const startBeat = quantizedBeat + (slot?.timingOffset ?? 0);\n const velocity =\n slot && slot.velocity !== null && slot.velocity !== undefined\n ? Math.round(slot.velocity)\n : event.velocity;\n\n return {\n pitch: event.pitch,\n startBeat,\n durationBeat: event.durationBeat,\n velocity,\n };\n });\n}\n","import type { Chord } from '../chord/index.js';\n\n/**\n * Harmonic role a pitch plays within a chord.\n *\n * @category Functional Harmony\n */\nexport type HarmonyRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh' | 'tension' | 'doubling';\n\n/**\n * How firmly a pitch is locked to the chord's identity.\n *\n * - `identity`: moving it produces a different chord (the root).\n * - `quality`: moving it flips the chord quality (the third).\n * - `voicing`: it can move freely without changing chord identity or quality.\n *\n * @category Functional Harmony\n */\nexport type LockLevel = 'identity' | 'quality' | 'voicing';\n\n/**\n * A pitch's role, lock level, and owning chord.\n *\n * @category Functional Harmony\n */\nexport type VoicedRole = {\n role: HarmonyRole;\n lock: LockLevel;\n belongsToChordId: number;\n};\n\n/**\n * Classify a pitch's harmonic role and lock level within a chord.\n *\n * The role comes from the pitch's interval class above the chord root: root (0),\n * third (3/4), fifth (6/7/8), seventh (10/11), and 9/11/13 tensions (2/5/9, and\n * the flat ninth 1). The root locks the chord identity, the third locks its\n * quality, and everything else is free voicing. In a suspended chord (a chord\n * whose intervals include a 4th (5) or 2nd (2) but no third), the suspended tone\n * takes the third's place as the quality-defining tone and is locked to\n * `quality`, since moving it changes the chord. Detecting an octave doubling\n * requires the surrounding voicing, which this single-pitch query does not carry,\n * so `doubling` is part of the type but not returned here.\n *\n * @param pitch MIDI pitch or bare pitch class.\n * @param chord The chord providing the root reference.\n * @param chordId Identifier stored on the result (defaults to 0).\n * @returns The pitch's role, lock level, and owning chord id.\n * @example\n * ```ts\n * import { roleOf, makeChord } from '@libraz/libcantus';\n * roleOf(64, makeChord(0, 'maj')); // E over C major\n * // { role: 'third', lock: 'quality', belongsToChordId: 0 }\n * ```\n * @category Functional Harmony\n */\nexport function roleOf(pitch: number, chord: Chord, chordId = 0): VoicedRole {\n const interval = (((Math.trunc(pitch) - chord.rootPc) % 12) + 12) % 12;\n const tones = new Set(chord.intervals.map((i) => ((i % 12) + 12) % 12));\n const hasHigherSeventh = tones.has(10) || tones.has(11);\n const hasThird = tones.has(3) || tones.has(4);\n const isSuspendedTone =\n !hasThird && ((interval === 5 && tones.has(5)) || (interval === 2 && tones.has(2)));\n let role: HarmonyRole;\n let lock: LockLevel;\n if (interval === 0) {\n role = 'root';\n lock = 'identity';\n } else if (isSuspendedTone) {\n role = 'third'; // suspended tone occupies the third's quality-defining slot\n lock = 'quality';\n } else if (interval === 3 || interval === 4) {\n role = 'third';\n lock = 'quality';\n } else if (interval === 6 || interval === 7 || interval === 8) {\n role = 'fifth';\n lock = 'voicing';\n } else if (interval === 9 && tones.has(3) && tones.has(6) && !hasHigherSeventh) {\n role = 'seventh'; // diminished seventh\n lock = 'voicing';\n } else if (interval === 9 && tones.has(9) && !hasHigherSeventh) {\n role = 'sixth';\n lock = 'voicing';\n } else if (interval === 10 || interval === 11) {\n role = 'seventh';\n lock = 'voicing';\n } else {\n role = 'tension';\n lock = 'voicing';\n }\n return { role, lock, belongsToChordId: chordId };\n}\n","import type { TimeSignature } from '../../core/meter/index.js';\nimport { isStrongBeat } from '../../core/meter/index.js';\nimport type { KeyScale, NoteEvent } from '../../core/types.js';\nimport type { Chord, ChordQuality } from '../../theory/chord/index.js';\nimport { chordPitchClasses, diatonicTriad, makeChord } from '../../theory/chord/index.js';\nimport type { HarmonyRole } from '../../theory/harmony/index.js';\nimport { roleOf } from '../../theory/harmony/index.js';\nimport {\n isScaleTone,\n majorKey,\n minorKey,\n NATURAL_MINOR_MASK,\n scaleTonesInDegreeOrder,\n} from '../../theory/scale/index.js';\nimport type { ChordSpan } from '../progression/index.js';\n\n/**\n * A melody note supplied to the harmonizer: a {@link NoteEvent}.\n *\n * @category Reharmonization\n */\nexport type MelodyNote = NoteEvent;\n\n/**\n * Options controlling {@link harmonizeMelody}.\n *\n * @category Reharmonization\n */\nexport type HarmonizeOptions = {\n melody: MelodyNote[];\n key: KeyScale | 'infer';\n harmonicRhythm: number;\n reharmonize: 'diatonic' | 'secondaryDominant' | 'borrowed';\n placement: { transposeSearch: boolean; octaveSearch: boolean };\n /**\n * Seed for the deterministic tie-break perturbation.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\n/**\n * The chosen transpose, key, chord path, and per-note roles.\n *\n * @category Reharmonization\n */\nexport type HarmonizeResult = {\n transposeSemitones: number;\n key: KeyScale;\n chords: ChordSpan[];\n melodyRoles: { noteIndex: number; role: HarmonyRole }[];\n};\n\ntype Candidate = {\n rootPc: number;\n quality: ChordQuality;\n degree?: number;\n secondaryDominant: boolean;\n targetDegree?: number;\n base: number;\n};\n\ntype Segment = { startBeat: number; endBeat: number; noteIndices: number[] };\n\nconst FALLBACK: Candidate = { rootPc: 0, quality: 'maj', secondaryDominant: false, base: 0 };\n\n/** Default meter used to weight metric accents when none is supplied. */\nconst DEFAULT_METER: TimeSignature = { numerator: 4, denominator: 4 };\n\n/** Comfortable melodic range (MIDI) and the per-semitone cost of leaving it. */\nconst COMFORT_LOW = 55;\nconst COMFORT_HIGH = 79;\nconst TESSITURA_WEIGHT = 0.001;\n\n/**\n * Magnitude of the seed-driven per-candidate perturbation. Kept far below the\n * smallest real cost difference (transition/emission terms are on the order of\n * 0.3 and up), so it can only decide between candidates or paths whose costs are\n * otherwise exactly equal. The seed therefore breaks ties deterministically and\n * never overrides melody fit or functional flow.\n */\nconst TIE_BREAK_JITTER = 1e-6;\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * Estimate the best-fit key from a melody's pitch-class weighting.\n *\n * Both major and natural-minor tonics are scored, so a minor melody is\n * recognized as its own minor key rather than being folded into the relative\n * major (which shares identical pitch-class content). Each in-scale note adds\n * its duration weight; notes matching the candidate tonic add a further\n * half-weight, and that tonic emphasis is what separates a minor key from its\n * relative major. For minor candidates the raised leading tone (the\n * harmonic-minor seventh) also counts as in-scale, so cadential leading tones do\n * not penalize the true minor key. Ties are broken toward the earlier candidate,\n * and major is scored before minor at each tonic.\n */\nfunction inferKey(melody: MelodyNote[]): KeyScale {\n let best: KeyScale = majorKey(0);\n let bestScore = Number.NEGATIVE_INFINITY;\n const candidates: KeyScale[] = [];\n for (let tonic = 0; tonic < 12; tonic += 1) {\n candidates.push(majorKey(tonic), minorKey(tonic));\n }\n for (const key of candidates) {\n const tonic = pitchClass(key.rootPc);\n const isMinor = key.modeMask12 === NATURAL_MINOR_MASK;\n const leadingTone = (tonic + 11) % 12;\n let score = 0;\n for (const n of melody) {\n const w = Math.max(0.25, n.durationBeat);\n const pc = pitchClass(n.pitch);\n if (isScaleTone(n.pitch, key) || (isMinor && pc === leadingTone)) {\n score += w;\n }\n if (pc === tonic) {\n score += 0.5 * w;\n }\n }\n if (score > bestScore) {\n bestScore = score;\n best = key;\n }\n }\n return best;\n}\n\n/** Enumerate candidate chords for the key, gated by reharmonization strength. */\nfunction buildCandidates(key: KeyScale, reharmonize: HarmonizeOptions['reharmonize']): Candidate[] {\n const tones = scaleTonesInDegreeOrder(key);\n const candidates: Candidate[] = tones.map((rootPc, degree) => ({\n rootPc,\n quality: diatonicTriad(degree, key).quality,\n degree,\n secondaryDominant: false,\n base: 0,\n }));\n\n const tonic = tones[0] ?? 0;\n if (reharmonize !== 'diatonic') {\n for (const target of [1, 3, 4, 5]) {\n const targetRoot = tones[target] ?? 0;\n candidates.push({\n rootPc: (targetRoot + 7) % 12,\n quality: 'dom7',\n secondaryDominant: true,\n targetDegree: target,\n base: 1.5,\n });\n }\n }\n\n if (reharmonize === 'borrowed') {\n candidates.push({\n rootPc: (tonic + 10) % 12,\n quality: 'maj',\n secondaryDominant: false,\n base: 2,\n }); // bVII\n candidates.push({\n rootPc: (tonic + 8) % 12,\n quality: 'maj',\n secondaryDominant: false,\n base: 2,\n }); // bVI\n candidates.push({\n rootPc: (tonic + 5) % 12,\n quality: 'min',\n secondaryDominant: false,\n base: 2,\n }); // iv\n }\n\n return candidates;\n}\n\n/**\n * Melody-fit cost of a candidate over a segment's notes.\n *\n * Each note is weighted by the portion of its duration that overlaps the\n * segment, so a note sustained across a boundary contributes to every segment\n * it sounds in rather than only the one it starts in.\n */\nfunction emissionCost(seg: Segment, cand: Candidate, melody: MelodyNote[], key: KeyScale): number {\n const pcs = chordPitchClasses(makeChord(cand.rootPc, cand.quality));\n let cost = cand.base;\n for (const idx of seg.noteIndices) {\n const note = melody[idx];\n if (!note) {\n continue;\n }\n const overlapStart = Math.max(note.startBeat, seg.startBeat);\n const overlap = Math.min(note.startBeat + note.durationBeat, seg.endBeat) - overlapStart;\n if (overlap <= 0) {\n continue;\n }\n const w = Math.max(0.25, overlap);\n if (pcs.includes(pitchClass(note.pitch))) {\n continue;\n }\n const strong = isStrongBeat(overlapStart, DEFAULT_METER);\n cost += (strong ? 10 : 2) * w;\n if (!isScaleTone(note.pitch, key)) {\n cost += w;\n }\n }\n return cost;\n}\n\n/**\n * Register cost of a placed melody: a small penalty for notes pushed outside a\n * comfortable range. Kept far below emission/transition costs so it only breaks\n * ties between otherwise-equal octave placements.\n */\nfunction tessituraCost(melody: MelodyNote[]): number {\n let cost = 0;\n for (const n of melody) {\n if (n.pitch < COMFORT_LOW) {\n cost += (COMFORT_LOW - n.pitch) * TESSITURA_WEIGHT;\n } else if (n.pitch > COMFORT_HIGH) {\n cost += (n.pitch - COMFORT_HIGH) * TESSITURA_WEIGHT;\n }\n }\n return cost;\n}\n\n/** Functional-flow cost of moving from one candidate chord to the next. */\nfunction transitionCost(prev: Candidate, cur: Candidate, tonicPc: number): number {\n let cost = 0;\n if ((prev.rootPc - cur.rootPc + 12) % 12 === 7) {\n cost -= 2; // descending-fifth root motion\n }\n if (\n prev.rootPc === (tonicPc + 7) % 12 &&\n (prev.quality === 'maj' || prev.quality === 'dom7') &&\n cur.rootPc === tonicPc\n ) {\n cost -= 3; // V -> I\n }\n if (prev.secondaryDominant) {\n cost += cur.degree === prev.targetDegree ? -3 : 2;\n }\n const dist = Math.min((prev.rootPc - cur.rootPc + 12) % 12, (cur.rootPc - prev.rootPc + 12) % 12);\n cost += dist * 0.3;\n return cost;\n}\n\n/** Run one Viterbi harmonization pass over a fixed melody and key. */\nfunction harmonizeOnce(\n melody: MelodyNote[],\n key: KeyScale,\n candidates: Candidate[],\n segments: Segment[],\n jitter: number[],\n): { cost: number; path: number[] } {\n const tonicPc = pitchClass(key.rootPc);\n const n = candidates.length;\n const candAt = (i: number): Candidate => candidates[i] ?? FALLBACK;\n const seg0 = segments[0];\n\n let dp = candidates.map(\n (c, ci) => (seg0 ? emissionCost(seg0, c, melody, key) : 0) + (jitter[ci] ?? 0),\n );\n const back: number[][] = [];\n\n for (let s = 1; s < segments.length; s += 1) {\n const seg = segments[s];\n if (!seg) {\n continue;\n }\n const next: number[] = [];\n const ptr: number[] = [];\n for (let c = 0; c < n; c += 1) {\n let best = Number.POSITIVE_INFINITY;\n let bestPrev = 0;\n for (let p = 0; p < n; p += 1) {\n const cost =\n (dp[p] ?? Number.POSITIVE_INFINITY) + transitionCost(candAt(p), candAt(c), tonicPc);\n if (cost < best) {\n best = cost;\n bestPrev = p;\n }\n }\n next[c] = best + emissionCost(seg, candAt(c), melody, key) + (jitter[c] ?? 0);\n ptr[c] = bestPrev;\n }\n dp = next;\n back.push(ptr);\n }\n\n let bestCost = Number.POSITIVE_INFINITY;\n let bestEnd = 0;\n for (let c = 0; c < n; c += 1) {\n const cadence = candAt(c).rootPc === tonicPc ? -2 : 0;\n const total = (dp[c] ?? Number.POSITIVE_INFINITY) + cadence;\n if (total < bestCost) {\n bestCost = total;\n bestEnd = c;\n }\n }\n\n const path: number[] = new Array<number>(segments.length).fill(bestEnd);\n for (let s = segments.length - 2; s >= 0; s -= 1) {\n const ptr = back[s];\n const nextIdx = path[s + 1] ?? bestEnd;\n path[s] = ptr ? (ptr[nextIdx] ?? bestEnd) : bestEnd;\n }\n return { cost: bestCost, path };\n}\n\n/**\n * Harmonize a melody with a min-cost chord progression.\n *\n * The melody is segmented by `harmonicRhythm`; each segment is scored against\n * diatonic (and, per `reharmonize`, secondary-dominant and borrowed) candidate\n * chords by melody fit, and a Viterbi search picks the lowest-cost path using a\n * functional-flow transition cost. When `placement.transposeSearch`/`octaveSearch`\n * is set, the whole melody is transposed across a range and the best\n * `(transpose, progression)` pair is returned; a small tessitura cost breaks\n * ties toward placements that keep the melody in a comfortable register.\n *\n * The `seed` drives a deterministic tie-break only: it perturbs candidates by a\n * magnitude far below any real cost difference (see {@link TIE_BREAK_JITTER}),\n * so it can decide between chords or paths of otherwise-equal cost but never\n * overrides melody fit or functional flow. For a well-determined melody the\n * result is identical across seeds; the same seed always yields the same result.\n *\n * @param opts Melody, key (or `'infer'`), harmonic rhythm, reharmonization\n * strength, height-search flags, and seed.\n * @returns The chosen transpose, key, chord path, and per-note roles.\n * @example\n * ```ts\n * import { harmonizeMelody, majorKey } from '@libraz/libcantus';\n * const result = harmonizeMelody({\n * melody: [\n * { pitch: 60, startBeat: 0, durationBeat: 1 },\n * { pitch: 64, startBeat: 1, durationBeat: 1 },\n * ],\n * key: majorKey(0),\n * harmonicRhythm: 1,\n * reharmonize: 'diatonic',\n * placement: { transposeSearch: false, octaveSearch: false },\n * });\n * result.chords; // one ChordSpan per harmonic-rhythm segment\n * ```\n * @category Reharmonization\n */\nexport function harmonizeMelody(opts: HarmonizeOptions): HarmonizeResult {\n const key = opts.key === 'infer' ? inferKey(opts.melody) : opts.key;\n const candidates = buildCandidates(key, opts.reharmonize);\n const candAt = (i: number): Candidate => candidates[i] ?? FALLBACK;\n const rng = mulberry32(opts.seed ?? 0);\n const jitter = candidates.map(() => rng() * TIE_BREAK_JITTER);\n\n const melodyEnd = opts.melody.reduce((m, n) => Math.max(m, n.startBeat + n.durationBeat), 0);\n const hr = Math.max(0.25, opts.harmonicRhythm);\n const segCount = Math.max(1, Math.ceil(melodyEnd / hr));\n const segments: Segment[] = [];\n for (let s = 0; s < segCount; s += 1) {\n const startBeat = s * hr;\n const endBeat = startBeat + hr;\n const noteIndices = opts.melody\n .map((n, i) => ({ n, i }))\n .filter(({ n }) => n.startBeat < endBeat && n.startBeat + n.durationBeat > startBeat)\n .map(({ i }) => i);\n segments.push({ startBeat, endBeat, noteIndices });\n }\n\n const transposes: number[] = [0];\n if (opts.placement.transposeSearch) {\n for (let s = -6; s <= 6; s += 1) {\n if (s !== 0) {\n transposes.push(s);\n }\n }\n }\n if (opts.placement.octaveSearch) {\n for (const o of [-12, 12]) {\n if (!transposes.includes(o)) {\n transposes.push(o);\n }\n }\n }\n\n let bestCost = Number.POSITIVE_INFINITY;\n let bestTs = 0;\n let bestPath: number[] = [];\n let bestMelody = opts.melody;\n for (const ts of transposes) {\n const shifted = opts.melody.map((n) => ({ ...n, pitch: n.pitch + ts }));\n const { cost, path } = harmonizeOnce(shifted, key, candidates, segments, jitter);\n const total = cost + tessituraCost(shifted);\n if (total < bestCost) {\n bestCost = total;\n bestTs = ts;\n bestPath = path;\n bestMelody = shifted;\n }\n }\n\n const chords: ChordSpan[] = bestPath.map((ci, s) => {\n const cand = candAt(ci);\n const chord: ChordSpan = {\n rootPc: cand.rootPc,\n quality: cand.quality,\n startBeat: segments[s]?.startBeat ?? s * hr,\n };\n if (cand.degree !== undefined) {\n chord.degree = cand.degree;\n }\n if (cand.secondaryDominant) {\n chord.secondaryDominant = true;\n }\n return chord;\n });\n\n const melodyRoles = bestMelody.map((note, noteIndex) => {\n const segIdx = Math.min(segments.length - 1, Math.max(0, Math.floor(note.startBeat / hr)));\n const cand = candAt(bestPath[segIdx] ?? 0);\n const chord: Chord = makeChord(cand.rootPc, cand.quality);\n return { noteIndex, role: roleOf(note.pitch, chord).role };\n });\n\n return { transposeSemitones: bestTs, key, chords, melodyRoles };\n}\n","import type { ChordTimeline } from '../../analyze/timeline/index.js';\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../../theory/chord/index.js';\nimport { chordPitchClasses } from '../../theory/chord/index.js';\nimport { isScaleTone, nearestScaleTone } from '../../theory/scale/index.js';\n\n/**\n * A transformation applicable to a motif cell.\n *\n * @category Composition\n */\nexport type MotifTransform =\n | 'transposeDiatonic'\n | 'transposeChromatic'\n | 'invert'\n | 'retrograde'\n | 'augment'\n | 'diminish'\n | 'sequence';\n\n/**\n * A single note within a motif cell.\n *\n * @category Composition\n */\nexport type MotifNote = {\n pitch: number;\n startBeat: number;\n durationBeat: number;\n};\n\n/**\n * A short melodic cell.\n *\n * @category Composition\n */\nexport type MotifCell = {\n notes: MotifNote[];\n};\n\n/**\n * Melodic contour shape for {@link generateMotif}.\n *\n * @category Composition\n */\nexport type MotifContour = 'arch' | 'ascending' | 'descending' | 'wave';\n\n/**\n * Options controlling {@link generateMotif}.\n *\n * @category Composition\n */\nexport type MotifOptions = {\n key: KeyScale;\n chord?: Chord | null;\n bars: number;\n /**\n * Melodic contour shape the line follows.\n *\n * @defaultValue `'arch'`\n */\n contour?: MotifContour;\n /**\n * Probability in [0, 1] that a note is nudged by a single diatonic step. The\n * nudge direction is balanced (up or down with equal odds), so it adds\n * variety without biasing the line off its contour. Default 0, which\n * reproduces the requested contour exactly (no drift, tails return to tonic).\n *\n * @defaultValue 0\n */\n jitter?: number;\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nfunction pitchClass(pitch: number): number {\n return ((Math.trunc(pitch) % 12) + 12) % 12;\n}\n\n/**\n * Smallest span, in beats, treated as a distinct tile step. A positive but\n * near-zero cell span is clamped to this so tiling cannot stall.\n */\nconst MIN_TILE_SPAN = 1 / 256;\n\n/** Nearest in-scale pitch strictly above `pitch`. */\nfunction upScaleTone(pitch: number, key: KeyScale): number {\n for (let d = 1; d <= 12; d += 1) {\n if (isScaleTone(pitch + d, key)) {\n return pitch + d;\n }\n }\n return pitch + 12;\n}\n\n/** Nearest in-scale pitch strictly below `pitch`. */\nfunction downScaleTone(pitch: number, key: KeyScale): number {\n for (let d = 1; d <= 12; d += 1) {\n if (isScaleTone(pitch - d, key)) {\n return pitch - d;\n }\n }\n return pitch - 12;\n}\n\n/** Shift a pitch by a number of diatonic scale degrees. */\nfunction stepDiatonic(pitch: number, degrees: number, key: KeyScale): number {\n let p = nearestScaleTone(pitch, key);\n const steps = Math.abs(Math.trunc(degrees));\n for (let i = 0; i < steps; i += 1) {\n p = degrees >= 0 ? upScaleTone(p, key) : downScaleTone(p, key);\n }\n return p;\n}\n\n/** Nearest chord tone to `pitch`, preferring the lower pitch on a tie. */\nfunction nearestChordTone(pitch: number, chord: Chord): number {\n const pcs = chordPitchClasses(chord);\n for (let d = 0; d <= 12; d += 1) {\n if (pcs.includes(pitchClass(pitch - d))) {\n return pitch - d;\n }\n if (pcs.includes(pitchClass(pitch + d))) {\n return pitch + d;\n }\n }\n return pitch;\n}\n\n/** Earliest onset in a cell; the time origin for timing transforms. */\nfunction cellOrigin(notes: MotifNote[]): number {\n return notes.length === 0 ? 0 : Math.min(...notes.map((n) => n.startBeat));\n}\n\n/** Total beat span covered by a cell (from first onset to last offset). */\nfunction cellSpan(cell: MotifCell): number {\n if (cell.notes.length === 0) {\n return 0;\n }\n const start = cellOrigin(cell.notes);\n const end = Math.max(...cell.notes.map((n) => n.startBeat + n.durationBeat));\n return end - start;\n}\n\nfunction clone(cell: MotifCell): MotifCell {\n return { notes: cell.notes.map((n) => ({ ...n })) };\n}\n\n/** Deterministic 32-bit PRNG in [0, 1). */\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Diatonic scale-degree offsets shaping a contour of `count` notes. */\nfunction contourOffsets(contour: MotifContour, count: number): number[] {\n const offsets: number[] = [];\n for (let i = 0; i < count; i += 1) {\n switch (contour) {\n case 'ascending':\n offsets.push(i);\n break;\n case 'descending':\n offsets.push(-i);\n break;\n case 'arch':\n // Symmetric rise-and-fall: a palindrome that starts and ends on the\n // tonic (offset 0) for both odd and even lengths.\n offsets.push(Math.min(i, count - 1 - i));\n break;\n case 'wave':\n offsets.push([0, 1, 0, -1][i % 4] ?? 0);\n break;\n }\n }\n return offsets;\n}\n\n/**\n * Generate a short seed motif over `bars`.\n *\n * The melody follows the requested contour in diatonic steps from the tonic,\n * snapped to the key. When a chord is supplied, notes landing on bar downbeats\n * are pulled to the nearest chord tone. An optional `jitter` adds balanced\n * per-note variation without biasing the contour; it is off by default, so the\n * contour is reproduced exactly. Output is deterministic for a given seed.\n *\n * @param opts Key, optional chord, length, contour, jitter, and seed.\n * @returns The generated motif cell.\n *\n * @example\n * ```ts\n * import { generateMotif, majorKey } from '@libraz/libcantus';\n * const cell = generateMotif({ key: majorKey(0), bars: 2, contour: 'arch' });\n * // cell.notes is a deterministic MotifCell (seed defaults to 0)\n * ```\n *\n * @category Composition\n */\nexport function generateMotif(opts: MotifOptions): MotifCell {\n const contour = opts.contour ?? 'arch';\n const bars = Math.max(1, Math.trunc(opts.bars));\n const totalBeats = bars * 4;\n const noteCount = Math.max(3, bars * 2);\n const beatsPerNote = totalBeats / noteCount;\n const rng = mulberry32(opts.seed ?? 0);\n const jitterProb = Math.min(1, Math.max(0, opts.jitter ?? 0));\n const tonic = pitchClass(opts.key.rootPc) + 60;\n const offsets = contourOffsets(contour, noteCount);\n\n const notes: MotifNote[] = [];\n for (let i = 0; i < noteCount; i += 1) {\n // Opt-in, direction-balanced jitter: disabled by default so the contour is\n // preserved exactly. When enabled it nudges up or down with equal odds,\n // avoiding the upward bias that used to drift arch/wave tails off the tonic.\n let jitter = 0;\n if (jitterProb > 0 && rng() < jitterProb) {\n jitter = rng() < 0.5 ? 1 : -1;\n }\n let pitch = stepDiatonic(tonic, (offsets[i] ?? 0) + jitter, opts.key);\n const startBeat = i * beatsPerNote;\n if (opts.chord && startBeat % 4 === 0) {\n pitch = nearestChordTone(pitch, opts.chord);\n }\n notes.push({ pitch, startBeat, durationBeat: beatsPerNote });\n }\n return { notes };\n}\n\n/**\n * Apply a transformation to a motif cell.\n *\n * `invert` reflects pitches about the first note (chromatic, self-inverse);\n * `retrograde` mirrors onsets about the cell span, preserving rests (self-inverse);\n * `augment`/`diminish` scale time by `amount ?? 2` and its reciprocal;\n * `transposeChromatic` adds `amount` semitones; `transposeDiatonic` shifts by\n * `amount` scale degrees when a `key` is given, or — with no `key` — falls back\n * to a chromatic shift of `amount` semitones; `sequence` appends a shifted copy\n * (by `amount` diatonic degrees with a `key`, or by `amount` semitones without\n * one, since it delegates to `transposeDiatonic`).\n *\n * @param cell The cell to transform.\n * @param t The transformation.\n * @param amount Optional parameter (semitones, degrees, or time factor).\n * @param key Key context for the diatonic transforms; without it,\n * `transposeDiatonic` and `sequence` shift chromatically by semitones.\n * @returns The transformed cell.\n *\n * @example\n * ```ts\n * import { generateMotif, transformMotif, majorKey } from '@libraz/libcantus';\n * const cell = generateMotif({ key: majorKey(0), bars: 1 });\n * const inverted = transformMotif(cell, 'invert');\n * ```\n *\n * @category Composition\n */\nexport function transformMotif(\n cell: MotifCell,\n t: MotifTransform,\n amount?: number,\n key?: KeyScale,\n): MotifCell {\n const notes = cell.notes;\n switch (t) {\n case 'transposeChromatic': {\n const semis = amount ?? 0;\n return { notes: notes.map((n) => ({ ...n, pitch: n.pitch + semis })) };\n }\n case 'transposeDiatonic': {\n const degrees = amount ?? 1;\n return {\n notes: notes.map((n) => ({\n ...n,\n // With a key, shift by scale degrees; without one, fall back to a\n // chromatic shift of `degrees` semitones.\n pitch: key ? stepDiatonic(n.pitch, degrees, key) : n.pitch + degrees,\n })),\n };\n }\n case 'invert': {\n const pivot = notes[0]?.pitch ?? 0;\n return { notes: notes.map((n) => ({ ...n, pitch: 2 * pivot - n.pitch })) };\n }\n case 'retrograde': {\n if (notes.length === 0) {\n return { notes: [] };\n }\n const start = cellOrigin(notes);\n const end = Math.max(...notes.map((n) => n.startBeat + n.durationBeat));\n return {\n notes: notes.map((n) => ({\n pitch: n.pitch,\n startBeat: start + (end - (n.startBeat + n.durationBeat)),\n durationBeat: n.durationBeat,\n })),\n };\n }\n case 'augment':\n return scaleTime(cell, amount ?? 2);\n case 'diminish':\n return scaleTime(cell, 1 / (amount ?? 2));\n case 'sequence': {\n const degrees = amount ?? 2;\n const span = cellSpan(cell);\n // Delegates to transposeDiatonic: a diatonic shift when `key` is given,\n // otherwise a chromatic shift of `degrees` semitones.\n const copy = transformMotif(cell, 'transposeDiatonic', degrees, key);\n const shifted = copy.notes.map((n) => ({ ...n, startBeat: n.startBeat + span }));\n return { notes: [...clone(cell).notes, ...shifted] };\n }\n }\n}\n\n/** Scale a cell's timing about its origin by `factor`. */\nfunction scaleTime(cell: MotifCell, factor: number): MotifCell {\n const origin = cellOrigin(cell.notes);\n return {\n notes: cell.notes.map((n) => ({\n pitch: n.pitch,\n startBeat: origin + (n.startBeat - origin) * factor,\n durationBeat: n.durationBeat * factor,\n })),\n };\n}\n\n/**\n * Lay a motif across `bars` and snap it to a chord timeline.\n *\n * The cell is tiled back-to-back to fill the requested span; each note is then\n * pulled to the nearest chord tone of the segment sounding at its onset, so the\n * developed line spells the underlying harmony.\n *\n * @param cell The source motif.\n * @param timeline Chord segments to snap against.\n * @param key Key context (used to keep snapped pitches sensible).\n * @param bars Number of four-beat bars to fill.\n * @returns The developed, harmony-aware cell.\n *\n * @example\n * ```ts\n * import { chordTimelineFromChords, developMotif, generateMotif, majorKey } from '@libraz/libcantus';\n * const key = majorKey(0);\n * const timeline = chordTimelineFromChords([{ rootPc: 0, quality: 'maj', startBeat: 0 }], 8);\n * const developed = developMotif(generateMotif({ key, bars: 1 }), timeline, key, 2);\n * ```\n *\n * @category Composition\n */\nexport function developMotif(\n cell: MotifCell,\n timeline: ChordTimeline,\n key: KeyScale,\n bars: number,\n): MotifCell {\n const span = cellSpan(cell);\n const totalBeats = Math.max(1, Math.trunc(bars)) * 4;\n const origin = cellOrigin(cell.notes);\n const out: MotifNote[] = [];\n\n if (span <= 0) {\n return clone(cell);\n }\n\n // Clamp a degenerate near-zero span so the tile count stays finite, and step\n // the offset multiplicatively so rounding error cannot accumulate over tiles.\n const tileSpan = Math.max(span, MIN_TILE_SPAN);\n const tileCount = Math.ceil(totalBeats / tileSpan);\n for (let k = 0; k < tileCount; k += 1) {\n const offset = k * tileSpan;\n for (const n of cell.notes) {\n const startBeat = offset + (n.startBeat - origin);\n if (startBeat >= totalBeats) {\n continue;\n }\n const chord = timeline.at(startBeat);\n let pitch = n.pitch;\n if (chord) {\n const isMember = chordPitchClasses(chord).includes(pitchClass(pitch));\n pitch = isMember ? pitch : nearestChordTone(pitch, chord);\n } else {\n pitch = nearestScaleTone(pitch, key);\n }\n out.push({ pitch, startBeat, durationBeat: n.durationBeat });\n }\n }\n return { notes: out };\n}\n","import type { KeyScale } from '../../core/types.js';\nimport type { ChordQuality, ChordSpan } from '../../theory/chord/index.js';\nimport { diatonicTriad } from '../../theory/chord/index.js';\nimport { scaleTonesInDegreeOrder } from '../../theory/scale/index.js';\n\nexport type { ChordSpan } from '../../theory/chord/index.js';\n\n/**\n * Broad production style a progression preset suits.\n *\n * @category Composition\n */\nexport type ProgStyle = 'minimal' | 'dance' | 'idol' | 'rock';\n\n/**\n * Harmonic-function role of a progression as a whole.\n *\n * @category Composition\n */\nexport type ProgFunction = 'loop' | 'tensionBuild' | 'cadenceStrong' | 'stable';\n\n/**\n * A named chord-progression preset expressed in scale degrees.\n *\n * @category Composition\n */\nexport type ProgressionPreset = {\n id: string;\n name: string;\n degrees: number[];\n functional: ProgFunction;\n styles: ProgStyle[];\n};\n\n/**\n * Options controlling {@link generateProgression}.\n *\n * @category Composition\n */\nexport type ProgressionOptions = {\n key: KeyScale;\n style: ProgStyle;\n bars: number;\n presetId?: string;\n ext?: ChordQuality | 'auto';\n reharmonize?: boolean;\n /**\n * Seed for the deterministic preset choice and reharmonization.\n *\n * @defaultValue 0\n */\n seed?: number;\n};\n\nconst PRESETS: ProgressionPreset[] = [\n {\n id: 'fourChordPop',\n name: 'Four Chord Pop',\n degrees: [0, 4, 5, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'pop1',\n name: 'Pop 1',\n degrees: [0, 5, 3, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'axis',\n name: 'Axis',\n degrees: [5, 3, 0, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol', 'rock'],\n },\n {\n id: 'pop2',\n name: 'Pop 2',\n degrees: [3, 0, 4, 5],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'classic',\n name: 'Classic',\n degrees: [0, 3, 4, 0],\n functional: 'cadenceStrong',\n styles: ['dance', 'idol', 'rock'],\n },\n {\n id: 'pop3',\n name: 'Pop 3',\n degrees: [0, 3, 5, 4],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'royalRoad',\n name: 'Royal Road',\n degrees: [3, 4, 2, 5],\n functional: 'tensionBuild',\n styles: ['dance', 'idol'],\n },\n {\n id: 'minor1',\n name: 'Minor 1',\n degrees: [5, 4, 3, 4],\n functional: 'tensionBuild',\n styles: ['idol', 'rock'],\n },\n {\n id: 'minor2',\n name: 'Minor 2',\n degrees: [5, 3, 4, 0],\n functional: 'tensionBuild',\n styles: ['idol', 'rock'],\n },\n {\n id: 'pop4',\n name: 'Pop 4',\n degrees: [0, 4, 2, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'pop5',\n name: 'Pop 5',\n degrees: [0, 2, 3, 4],\n functional: 'stable',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'rock1',\n name: 'Rock 1',\n degrees: [0, 10, 3, 0],\n functional: 'tensionBuild',\n styles: ['rock'],\n },\n {\n id: 'rock2',\n name: 'Rock 2',\n degrees: [0, 3, 10, 0],\n functional: 'tensionBuild',\n styles: ['rock'],\n },\n {\n id: 'extended4',\n name: 'Extended 4',\n degrees: [0, 4, 5, 2],\n functional: 'stable',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'minor3',\n name: 'Minor 3',\n degrees: [5, 0, 4, 3],\n functional: 'loop',\n styles: ['dance', 'idol'],\n },\n {\n id: 'aeolianPop',\n name: 'Aeolian Pop',\n degrees: [5, 8, 10, 0],\n functional: 'tensionBuild',\n styles: ['minimal', 'dance', 'idol', 'rock'],\n },\n {\n id: 'animeHighEnergy1',\n name: 'Anime High Energy 1',\n degrees: [5, 2, 3, 0],\n functional: 'loop',\n styles: ['dance', 'idol'],\n },\n {\n id: 'jazzPop',\n name: 'Jazz Pop',\n degrees: [1, 4, 0, 5],\n functional: 'cadenceStrong',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'animeHighEnergy2',\n name: 'Anime High Energy 2',\n degrees: [5, 1, 4, 0],\n functional: 'cadenceStrong',\n styles: ['dance', 'idol'],\n },\n {\n id: 'cityPop',\n name: 'City Pop',\n degrees: [0, 5, 1, 4],\n functional: 'stable',\n styles: ['minimal', 'dance'],\n },\n {\n id: 'extended5',\n name: 'Extended 5',\n degrees: [0, 4, 5, 2, 3],\n functional: 'loop',\n styles: ['minimal', 'dance', 'idol'],\n },\n {\n id: 'neapolitanPop',\n name: 'Neapolitan Pop',\n degrees: [5, 12, 13, 4, 0],\n functional: 'cadenceStrong',\n styles: ['minimal', 'dance', 'idol'],\n },\n];\n\n/** Chromatic semitone offset from the tonic for borrowed (non-diatonic) degrees. */\nconst BORROWED_OFFSET: Record<number, number> = {\n 8: 8, // bVI\n 10: 10, // bVII\n 11: 3, // bIII\n 12: 5, // iv\n 13: 1, // bII\n 14: 6, // #IV\n};\n\n/**\n * All built-in progression presets.\n *\n * @category Composition\n */\nexport function progressions(): ProgressionPreset[] {\n return PRESETS.map((p) => ({ ...p, degrees: [...p.degrees], styles: [...p.styles] }));\n}\n\n/**\n * Presets whose style list includes the given style.\n *\n * @category Composition\n */\nexport function progressionsByStyle(style: ProgStyle): ProgressionPreset[] {\n return progressions().filter((p) => p.styles.includes(style));\n}\n\n/** Deterministic 32-bit PRNG producing a float in [0, 1). */\nfunction mulberry32(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let t = state;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Root pitch class of a scale degree in the given key, including borrowed degrees. */\nfunction degreeToRootPc(degree: number, key: KeyScale): number {\n if (degree >= 0 && degree <= 6) {\n const tones = scaleTonesInDegreeOrder(key);\n return tones.length > 0 ? (tones[degree % tones.length] ?? key.rootPc % 12) : key.rootPc % 12;\n }\n const offset = BORROWED_OFFSET[degree] ?? 0;\n return ((((key.rootPc % 12) + offset) % 12) + 12) % 12;\n}\n\n/**\n * Diatonic (or borrowed) triad quality of a degree in the given key.\n *\n * Diatonic degrees (0-6) take their scale-correct triad quality, so non-major\n * keys yield diatonic chords. Borrowed degrees keep their fixed chromatic\n * qualities (`#IV` diminished, `iv` minor, the rest major).\n */\nfunction autoQuality(degree: number, key: KeyScale): ChordQuality {\n if (degree >= 0 && degree <= 6) {\n return diatonicTriad(degree, key).quality;\n }\n if (degree === 14) {\n return 'dim';\n }\n if (degree === 12) {\n return 'min';\n }\n return 'maj';\n}\n\n/**\n * Generate a chord progression laid out one chord per bar.\n *\n * A preset is chosen by `presetId` when given, otherwise deterministically from\n * the presets matching `style`, seeded by `seed`. An unknown `presetId` is a\n * caller error and throws rather than silently falling back to a random preset.\n * The preset's degrees cycle to\n * fill `bars`; each bar is four beats, so `startBeat` is `barIndex * 4`. Chord\n * roots come from the key's diatonic scale-degree mapping. When `ext` is\n * omitted or `'auto'`, each chord takes its diatonic triad quality; otherwise\n * `ext` is forced on every chord. When `reharmonize` is set, some chords are\n * deterministically replaced with the secondary dominant (V7) of the following\n * chord, flagged with `secondaryDominant`.\n *\n * @param opts Generation options.\n * @returns One chord per bar in timeline order.\n * @throws If `presetId` is given but does not match any built-in preset.\n *\n * @example\n * ```ts\n * import { generateProgression, majorKey } from '@libraz/libcantus';\n * const chords = generateProgression({ key: majorKey(0), style: 'dance', bars: 4 });\n * // Deterministic for a given seed (defaults to 0); one ChordSpan per bar.\n * ```\n *\n * @category Composition\n */\nexport function generateProgression(opts: ProgressionOptions): ChordSpan[] {\n const seed = opts.seed ?? 0;\n let preset: ProgressionPreset | undefined;\n if (opts.presetId !== undefined) {\n preset = PRESETS.find((p) => p.id === opts.presetId);\n if (preset === undefined) {\n throw new Error(`Unknown progression preset: ${opts.presetId}`);\n }\n }\n if (preset === undefined) {\n const pool = PRESETS.filter((p) => p.styles.includes(opts.style));\n const candidates = pool.length > 0 ? pool : PRESETS;\n const rng = mulberry32(seed);\n const index = Math.floor(rng() * candidates.length) % candidates.length;\n preset = candidates[index] ?? PRESETS[0];\n }\n const degrees = preset?.degrees ?? [0];\n const chords: ChordSpan[] = [];\n for (let bar = 0; bar < opts.bars; bar += 1) {\n const degree = degrees[bar % degrees.length] ?? 0;\n const quality =\n opts.ext !== undefined && opts.ext !== 'auto' ? opts.ext : autoQuality(degree, opts.key);\n const chord: ChordSpan = {\n rootPc: degreeToRootPc(degree, opts.key),\n quality,\n startBeat: bar * 4,\n degree: degree >= 0 && degree <= 6 ? degree : undefined,\n };\n chords.push(chord);\n }\n\n if (opts.reharmonize) {\n const tonicPc = (((opts.key.rootPc % 12) + 12) % 12) as number;\n const rrng = mulberry32((seed ^ 0x9e3779b9) >>> 0);\n for (let i = 0; i < chords.length - 1; i += 1) {\n const cur = chords[i];\n const next = chords[i + 1];\n if (!cur || !next) {\n continue;\n }\n const domRoot = (next.rootPc + 7) % 12;\n const targetsTonic = (next.rootPc - tonicPc + 12) % 12 === 0;\n const alreadySecondary = cur.rootPc === domRoot && cur.quality === 'dom7';\n // A secondary dominant inserted at i-1 resolves onto this chord; replacing\n // it here would orphan that dominant.\n const isResolutionTarget = chords[i - 1]?.secondaryDominant === true;\n if (targetsTonic || alreadySecondary || isResolutionTarget) {\n continue;\n }\n if (rrng() < 0.5) {\n chords[i] = {\n rootPc: domRoot,\n quality: 'dom7',\n startBeat: cur.startBeat,\n secondaryDominant: true,\n };\n }\n }\n }\n\n return chords;\n}\n","/**\n * Reharmonization: chord substitution, modal-interchange palettes, and negative\n * harmony. These transforms take an existing chord (or a key) and propose\n * alternative harmonies that preserve a chosen relationship — a shared function,\n * a common tone, a tonicizing dominant, or a reflection across the key axis.\n *\n * Roots are pitch classes (0..11); no spelled key signature is required.\n */\n\nimport { detectChordBest } from '../../analyze/detect/index.js';\nimport {\n type BorrowedSource,\n borrowedSource,\n chordToRoman,\n functionOf,\n type HarmonicFunction,\n isDiatonic,\n parallelKey,\n} from '../../analyze/functional/index.js';\nimport type { KeyScale } from '../../core/types.js';\nimport {\n type Chord,\n type ChordQuality,\n chordPitchClasses,\n diatonicTriad,\n makeChord,\n} from '../../theory/chord/index.js';\nimport { scaleTonesInDegreeOrder } from '../../theory/scale/index.js';\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/**\n * The kind of substitution relationship a candidate realizes.\n *\n * @category Reharmonization\n */\nexport type SubstitutionType =\n | 'tritone'\n | 'relative'\n | 'borrowed'\n | 'chromatic-mediant'\n | 'secondary-dominant';\n\n/**\n * A proposed chord substitution with its relationship, numeral, and function.\n *\n * @category Reharmonization\n */\nexport type Substitution = {\n chord: Chord;\n type: SubstitutionType;\n roman: string;\n function: HarmonicFunction;\n};\n\n/**\n * Options controlling which substitutions {@link substituteChord} returns.\n *\n * @category Reharmonization\n */\nexport type SubstituteOptions = {\n /**\n * Melody pitch classes that must remain chord tones. When given, only\n * substitutions whose pitch classes contain every listed pitch class are\n * kept, so the melody stays consonant against the new harmony.\n */\n melodyPcs?: number[];\n};\n\n/** Whether the chord's template carries a given interval (mod 12). */\nfunction hasInterval(chord: Chord, semitone: number): boolean {\n return chord.intervals.some((iv) => mod12(iv) === semitone);\n}\n\n/** Whether a chord is a dominant type: a major third with a minor seventh. */\nfunction isDominantType(chord: Chord): boolean {\n return hasInterval(chord, 4) && hasInterval(chord, 10);\n}\n\n/**\n * A chord that can be tonicized: it has a perfect fifth and a third but is not\n * itself a dominant seventh (which is an unstable, tonicizing sonority rather\n * than a stable target).\n */\nfunction isStableTarget(chord: Chord): boolean {\n const hasFifth = hasInterval(chord, 7);\n const hasThird = hasInterval(chord, 3) || hasInterval(chord, 4);\n return hasFifth && hasThird && !isDominantType(chord);\n}\n\n/** The triad pitch classes (root, third, fifth) implied by a chord's template. */\nfunction triadPitchClasses(chord: Chord): number[] {\n const third = hasInterval(chord, 4) ? 4 : hasInterval(chord, 3) ? 3 : 4;\n const fifth = hasInterval(chord, 8) ? 8 : hasInterval(chord, 6) ? 6 : 7;\n return [mod12(chord.rootPc), mod12(chord.rootPc + third), mod12(chord.rootPc + fifth)];\n}\n\n/** Count the pitch classes shared between two pitch-class sets. */\nfunction commonToneCount(a: number[], b: number[]): number {\n const set = new Set(b);\n return a.filter((pc) => set.has(pc)).length;\n}\n\n/** The diatonic triads of a key, one per scale degree. */\nfunction diatonicTriadsOf(key: KeyScale): Chord[] {\n const degrees = scaleTonesInDegreeOrder(key).length;\n const triads: Chord[] = [];\n for (let degree = 0; degree < degrees; degree += 1) {\n triads.push(diatonicTriad(degree, key));\n }\n return triads;\n}\n\n/** Whether two chords share the same root pitch class and quality. */\nfunction sameChord(a: Chord, b: Chord): boolean {\n return mod12(a.rootPc) === mod12(b.rootPc) && a.quality === b.quality;\n}\n\n/** Root offsets (semitones) that form a third above or below a root. */\nconst THIRD_OFFSETS = [3, 4, 8, 9] as const;\n\n/**\n * Propose substitutions for a chord within a key.\n *\n * Candidates are generated by several relationships and deduplicated against the\n * original chord and each other:\n *\n * - `tritone`: for a dominant-type chord, the dominant seventh a tritone away.\n * - `secondary-dominant`: for a stable target, the dominant seventh a fifth\n * above its root (tonicizing it).\n * - `relative`: a diatonic triad a third away that shares two common tones.\n * - `borrowed`: a triad from the parallel mode with the same harmonic function.\n * - `chromatic-mediant`: a major/minor triad a third away sharing one common\n * tone.\n *\n * Each result carries its Roman numeral and harmonic function in `key`. When\n * `opts.melodyPcs` is given, only substitutions whose pitch classes contain all\n * of those pitch classes are returned.\n *\n * @param chord The chord to reharmonize.\n * @param key The prevailing key.\n * @param opts Optional melody-preservation constraint.\n * @returns The deduplicated substitution candidates.\n * @example\n * ```ts\n * import { substituteChord, makeChord, majorKey } from '@libraz/libcantus';\n * const subs = substituteChord(makeChord(7, 'dom7'), majorKey(0));\n * // includes the tritone sub Db7 (rootPc 1, quality 'dom7')\n * ```\n * @category Reharmonization\n */\nexport function substituteChord(\n chord: Chord,\n key: KeyScale,\n opts?: SubstituteOptions,\n): Substitution[] {\n const original = triadPitchClasses(chord);\n const candidates: { chord: Chord; type: SubstitutionType }[] = [];\n\n // Tritone substitution: only for dominant-type chords.\n if (isDominantType(chord)) {\n candidates.push({ chord: makeChord(mod12(chord.rootPc + 6), 'dom7'), type: 'tritone' });\n }\n\n // Secondary dominant: the V7 tonicizing a stable target.\n if (isStableTarget(chord)) {\n candidates.push({\n chord: makeChord(mod12(chord.rootPc + 7), 'dom7'),\n type: 'secondary-dominant',\n });\n }\n\n // Relative: a diatonic triad a third away sharing two common tones.\n for (const triad of diatonicTriadsOf(key)) {\n const offset = mod12(triad.rootPc - chord.rootPc);\n if (\n (THIRD_OFFSETS as readonly number[]).includes(offset) &&\n commonToneCount(original, chordPitchClasses(triad)) === 2\n ) {\n candidates.push({ chord: triad, type: 'relative' });\n }\n }\n\n // Borrowed: a parallel-mode triad sharing the original's harmonic function.\n const targetFunction = functionOf(chord, key);\n for (const triad of diatonicTriadsOf(parallelKey(key))) {\n if (functionOf(triad, key) === targetFunction && !isDiatonic(triad, key)) {\n candidates.push({ chord: triad, type: 'borrowed' });\n }\n }\n\n // Chromatic mediants: major/minor triads a third away sharing one common tone.\n for (const offset of THIRD_OFFSETS) {\n for (const quality of ['maj', 'min'] as const) {\n const mediant = makeChord(mod12(chord.rootPc + offset), quality);\n if (\n commonToneCount(original, chordPitchClasses(mediant)) === 1 &&\n !isDiatonic(mediant, key)\n ) {\n candidates.push({ chord: mediant, type: 'chromatic-mediant' });\n }\n }\n }\n\n const melodyPcs = opts?.melodyPcs?.map(mod12);\n const seen = new Set<string>();\n const results: Substitution[] = [];\n for (const candidate of candidates) {\n if (sameChord(candidate.chord, chord)) {\n continue;\n }\n const dedupeKey = `${mod12(candidate.chord.rootPc)}:${candidate.chord.quality}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n if (melodyPcs !== undefined) {\n const pcs = new Set(chordPitchClasses(candidate.chord));\n if (!melodyPcs.every((pc) => pcs.has(pc))) {\n continue;\n }\n }\n results.push({\n chord: candidate.chord,\n type: candidate.type,\n roman: chordToRoman(candidate.chord, key),\n function: functionOf(candidate.chord, key),\n });\n }\n return results;\n}\n\n/**\n * A borrowed chord in the modal-interchange palette of a key.\n *\n * @category Reharmonization\n */\nexport type BorrowedChord = {\n chord: Chord;\n roman: string;\n source: BorrowedSource;\n};\n\n/**\n * The modal-interchange palette of a key.\n *\n * Lists the diatonic triads of the {@link parallelKey} that are not diatonic to\n * `key` (the classic borrowed chords such as `iv`, `bVI`, and `bVII` in a major\n * key), plus the Neapolitan (a major triad on the flat second degree). Each\n * carries its Roman numeral and {@link borrowedSource} relative to `key`.\n *\n * @param key The prevailing key.\n * @returns The borrowed-chord palette.\n * @category Reharmonization\n */\nexport function modalInterchangePalette(key: KeyScale): BorrowedChord[] {\n const palette: BorrowedChord[] = [];\n const seen = new Set<string>();\n const add = (chord: Chord) => {\n const dedupeKey = `${mod12(chord.rootPc)}:${chord.quality}`;\n if (seen.has(dedupeKey)) {\n return;\n }\n seen.add(dedupeKey);\n palette.push({\n chord,\n roman: chordToRoman(chord, key),\n source: borrowedSource(chord, key),\n });\n };\n\n for (const triad of diatonicTriadsOf(parallelKey(key))) {\n if (!isDiatonic(triad, key)) {\n add(triad);\n }\n }\n // The Neapolitan (major triad on b2) sits outside both parallel modes, so it\n // is added explicitly — unless b2 is already diatonic (e.g. in a Phrygian key,\n // where it is a native chord rather than a borrowing).\n const neapolitan = makeChord(mod12(key.rootPc + 1), 'maj');\n if (!isDiatonic(neapolitan, key)) {\n add(neapolitan);\n }\n return palette;\n}\n\n/**\n * Reflect a chord across the tonic–dominant axis of a key (negative harmony).\n *\n * Every pitch class `p` maps to `(2*T + 7 - p) mod 12`, where `T` is the key\n * tonic — the reflection that swaps the tonic with the dominant. The mirrored\n * pitch classes (including the bass, if set) are reassembled into a chord by\n * {@link detectChordBest}; when no chord is recognized, the mirrored root and\n * the original quality are used as a fallback.\n *\n * @param chord The chord to reflect.\n * @param key The prevailing key.\n * @returns The negative-harmony counterpart of the chord.\n * @example\n * ```ts\n * import { negativeHarmonyMirror, makeChord, majorKey } from '@libraz/libcantus';\n * negativeHarmonyMirror(makeChord(7, 'maj'), majorKey(0));\n * // G major reflected across C's axis => F minor (rootPc 5, quality 'min')\n * ```\n * @category Reharmonization\n */\nexport function negativeHarmonyMirror(chord: Chord, key: KeyScale): Chord {\n const tonic = mod12(key.rootPc);\n const mirror = (p: number) => mod12(2 * tonic + 7 - p);\n const pcs = chordPitchClasses(chord).map(mirror);\n const bassPc = chord.bassPc !== undefined ? mirror(chord.bassPc) : undefined;\n // Place the mirrored bass an octave below so it is recognized as the lowest\n // note and preserved through detection.\n const pitches = bassPc !== undefined ? [bassPc - 12, ...pcs] : pcs;\n const detected = detectChordBest(pitches);\n if (detected) {\n // Without an input bass the mirrored tones are octave-less, so detection may\n // read the lowest pitch class as a slash bass and report a spurious\n // inversion. Restore the recognized chord to root position in that case.\n if (bassPc === undefined && detected.bassPc !== undefined) {\n return makeChord(detected.rootPc, detected.quality);\n }\n return detected;\n }\n const quality: ChordQuality = chord.quality;\n return makeChord(mirror(chord.rootPc), quality, bassPc);\n}\n","/**\n * Deterministic rhythm generation over a metric grid.\n *\n * Builds a fixed-resolution grid across one or more bars of a time signature\n * and decides, per grid slot, whether it becomes a note onset. Onset\n * probability follows the metric-accent hierarchy from the `meter` module, so\n * strong positions (downbeats, secondary pulses) are favored over weak\n * off-pulse subdivisions. Given a seed the output is fully reproducible.\n *\n * Positions and durations are measured in quarter-note beats, matching the\n * library-wide convention.\n */\n\nimport { beatsPerBar, metricWeight, type TimeSignature } from '../../core/meter/index.js';\nimport { createRng } from '../../core/random/index.js';\n\n/**\n * A single rhythmic note: an onset position and how long it sounds.\n *\n * @category Rhythm & Meter\n */\nexport type RhythmEvent = {\n /** Onset position in quarter-note beats, absolute from the start of the span. */\n position: number;\n /** Duration in quarter-note beats, extending to the next onset. */\n duration: number;\n};\n\n/**\n * Options controlling {@link generateRhythm}.\n *\n * @category Rhythm & Meter\n */\nexport type RhythmOptions = {\n /**\n * Seed for the deterministic PRNG.\n *\n * @defaultValue 0\n */\n seed?: number;\n /**\n * Number of bars to generate.\n *\n * @defaultValue 1\n */\n bars?: number;\n /**\n * Grid resolution as the number of equal grid steps per quarter-note beat.\n * The default of 2 yields an eighth-note grid; 4 yields a sixteenth-note\n * grid, 3 an eighth-note triplet grid, and so on.\n *\n * @defaultValue 2\n */\n subdivision?: number;\n /**\n * Overall onset density in [0, 1]. Scales the per-slot onset probability, so\n * higher values fill more grid slots. Values outside [0, 1] are clamped into\n * range.\n *\n * @defaultValue 0.5\n */\n density?: number;\n};\n\nconst DEFAULT_SUBDIVISION = 2;\nconst DEFAULT_DENSITY = 0.5;\nconst DEFAULT_BARS = 1;\n\n/**\n * Map a metric weight (0–3 from {@link metricWeight}) to a base onset\n * probability before density scaling. Strong positions are much more likely to\n * carry an onset than weak ones; the curve is intentionally small and explicit\n * so its behavior is easy to inspect and test.\n *\n * @param weight The metric weight, 0 (off-pulse) to 3 (downbeat).\n * @returns A base onset probability in [0, 1].\n * @category Rhythm & Meter\n */\nexport function onsetWeightCurve(weight: number): number {\n switch (weight) {\n case 3:\n return 1;\n case 2:\n return 0.8;\n case 1:\n return 0.55;\n default:\n return 0.25;\n }\n}\n\n/**\n * Generate a deterministic rhythmic pattern over `bars` bars of a time\n * signature. A grid is built at the chosen subdivision; each slot becomes an\n * onset with a probability derived from its metric weight scaled by `density`\n * and sampled from the seeded PRNG. Every bar's downbeat is always an onset, so\n * a pattern of any length has a reliable pulse independent of the seed. Each\n * event's duration extends to the next onset, and the last event extends to the\n * end of the span. `density` is clamped to [0, 1].\n *\n * @param ts The time signature.\n * @param opts Generation options.\n * @returns Onset events sorted by position, non-overlapping, covering the span.\n * @example\n * ```ts\n * import { parseTimeSignature, generateRhythm } from '@libraz/libcantus';\n * const ts = parseTimeSignature('4/4');\n * generateRhythm(ts, { seed: 42, density: 0.6 }); // onset events over one bar\n * ```\n * @category Rhythm & Meter\n */\nexport function generateRhythm(ts: TimeSignature, opts: RhythmOptions = {}): RhythmEvent[] {\n const seed = opts.seed ?? 0;\n const bars = opts.bars ?? DEFAULT_BARS;\n const subdivision = opts.subdivision ?? DEFAULT_SUBDIVISION;\n const density = Math.min(1, Math.max(0, opts.density ?? DEFAULT_DENSITY));\n\n const barBeats = beatsPerBar(ts);\n const spanBeats = barBeats * bars;\n const step = 1 / subdivision;\n const slotCount = Math.round(spanBeats * subdivision);\n const slotsPerBar = Math.round(barBeats * subdivision);\n const rng = createRng(seed);\n\n const positions: number[] = [];\n for (let i = 0; i < slotCount; i += 1) {\n const position = i * step;\n // Force every bar's downbeat so the pulse is reliable regardless of seed.\n if (i % slotsPerBar === 0) {\n positions.push(position);\n continue;\n }\n const weight = metricWeight(position, ts);\n const probability = onsetWeightCurve(weight) * density;\n if (rng.prob(probability)) {\n positions.push(position);\n }\n }\n\n const events: RhythmEvent[] = [];\n for (let i = 0; i < positions.length; i += 1) {\n const position = positions[i] ?? 0;\n const nextPosition = positions[i + 1] ?? spanBeats;\n events.push({ position, duration: nextPosition - position });\n }\n return events;\n}\n\n/**\n * Onset density of a generated pattern: the mean number of onsets per bar.\n *\n * @param events Events from {@link generateRhythm}.\n * @param ts The time signature.\n * @returns The onset count divided by the number of bars the events span.\n * @category Rhythm & Meter\n */\nexport function rhythmDensity(events: RhythmEvent[], ts: TimeSignature): number {\n if (events.length === 0) {\n return 0;\n }\n const last = events[events.length - 1];\n const spanBeats = (last?.position ?? 0) + (last?.duration ?? 0);\n const bars = spanBeats / beatsPerBar(ts);\n return bars > 0 ? events.length / bars : 0;\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport { NAMED_SCALES } from '../scale/index.js';\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Count the set bits (scale tones) in a 12-bit mode mask. */\nfunction popcount12(mask: number): number {\n let count = 0;\n for (let n = 0; n < 12; n += 1) {\n count += (mask >> n) & 1;\n }\n return count;\n}\n\n/** Test whether a pitch class belongs to a mode mask rooted on `scaleRootPc`. */\nfunction maskHasPitchClass(mask: number, scaleRootPc: number, pc: number): boolean {\n const offset = pitchClass(pc - scaleRootPc);\n return ((mask >> offset) & 1) === 1;\n}\n\n/**\n * Test whether every chord pitch class is contained in a scale.\n *\n * @param chordPcs The chord's pitch classes (0..11).\n * @param scaleMask The scale's 12-bit mode mask.\n * @param scaleRootPc The pitch class the mask is rooted on.\n * @returns True if the scale is a superset of the chord.\n *\n * @category Scales\n */\nexport function scaleMatchesChord(\n chordPcs: number[],\n scaleMask: number,\n scaleRootPc: number,\n): boolean {\n for (const pc of chordPcs) {\n if (!maskHasPitchClass(scaleMask, scaleRootPc, pc)) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * A named scale rooted on a pitch class that fits over a chord.\n *\n * @category Scales\n */\nexport type ChordScaleMatch = {\n name: string;\n rootPc: number;\n};\n\n/**\n * Scale names whose mask duplicates another {@link NAMED_SCALES} entry\n * (major/ionian, naturalMinor/aeolian). Chord-scale analysis conventionally\n * speaks in mode names, so these aliases are skipped and only the modal name\n * is reported.\n */\nconst ALIASED_SCALE_NAMES = new Set(['major', 'naturalMinor']);\n\n/** Number of tones in a heptatonic (seven-note) scale. */\nconst HEPTATONIC_SIZE = 7;\n\n/**\n * List the scales that fit over a chord, best fit first.\n *\n * Only the chord root is considered as the scale root, matching the\n * conventional chord-scale relationship. Every entry of {@link NAMED_SCALES}\n * whose pitch-class set is a superset of the chord's is returned once per\n * distinct pitch-class set (aliased masks such as major/ionian report only the\n * modal name), ranked by fewest extra scale tones beyond the chord, then by\n * scale size (heptatonic before larger scales), then by scale name. For bare\n * triads and smaller chords, heptatonic scales rank before pentatonics and\n * other sizes: a pentatonic adds no modal color over a triad, so the seven-note\n * modes are the more useful answer. The chromatic scale is only returned as a\n * fallback when no other scale contains the chord.\n *\n * @param chord The chord to fit scales over.\n * @returns The matching scales rooted on the chord root, best fit first.\n *\n * @example\n * ```ts\n * import { makeChord, chordScales } from '@libraz/libcantus';\n * const scales = chordScales(makeChord(0, 'maj7'));\n * // scales for Cmaj7, best fit first; each is { name, rootPc: 0 }\n * ```\n *\n * @category Scales\n */\nexport function chordScales(chord: Chord): ChordScaleMatch[] {\n const chordPcs = chordPitchClasses(chord);\n const rootPc = pitchClass(chord.rootPc);\n const ranked: { name: string; extra: number; size: number }[] = [];\n const seenMasks = new Set<number>();\n for (const name of Object.keys(NAMED_SCALES)) {\n if (name === 'chromatic' || ALIASED_SCALE_NAMES.has(name)) {\n continue;\n }\n const mask = NAMED_SCALES[name];\n if (mask === undefined || seenMasks.has(mask)) {\n continue;\n }\n seenMasks.add(mask);\n if (scaleMatchesChord(chordPcs, mask, rootPc)) {\n const size = popcount12(mask);\n ranked.push({ name, extra: size - chordPcs.length, size });\n }\n }\n if (ranked.length === 0) {\n // No diatonic-style scale contains the chord; fall back to the chromatic\n // scale, which trivially contains every pitch class.\n if (NAMED_SCALES.chromatic !== undefined) {\n return [{ name: 'chromatic', rootPc }];\n }\n return [];\n }\n const preferHeptatonic = chordPcs.length <= 3;\n ranked.sort((a, b) => {\n if (preferHeptatonic && (a.size === HEPTATONIC_SIZE) !== (b.size === HEPTATONIC_SIZE)) {\n return a.size === HEPTATONIC_SIZE ? -1 : 1;\n }\n if (a.extra !== b.extra) {\n return a.extra - b.extra;\n }\n if (a.size !== b.size) {\n return a.size - b.size;\n }\n return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;\n });\n return ranked.map((entry) => ({ name: entry.name, rootPc }));\n}\n\n/**\n * List a scale's avoid notes over a chord.\n *\n * An avoid note is a non-chord scale tone that lies a semitone directly above a\n * chord tone; sounding it against the chord clashes. The scale is rooted on the\n * chord root. If the scale does not contain the chord, no avoid notes exist.\n *\n * @param chord The chord providing the chord tones.\n * @param scaleName A key of {@link NAMED_SCALES}.\n * @returns The avoid-note pitch classes, sorted ascending in [0, 11].\n *\n * @category Scales\n */\nexport function avoidNotes(chord: Chord, scaleName: string): number[] {\n const mask = NAMED_SCALES[scaleName];\n if (mask === undefined) {\n return [];\n }\n const rootPc = pitchClass(chord.rootPc);\n const chordPcs = chordPitchClasses(chord);\n if (!scaleMatchesChord(chordPcs, mask, rootPc)) {\n return [];\n }\n const chordSet = new Set(chordPcs);\n const avoid: number[] = [];\n for (let pc = 0; pc < 12; pc += 1) {\n if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc)) {\n continue;\n }\n if (chordSet.has(pitchClass(pc - 1))) {\n avoid.push(pc);\n }\n }\n return avoid.sort((a, b) => a - b);\n}\n\n/**\n * List a scale's available tensions over a chord.\n *\n * Available tensions are scale tones that are neither chord tones nor avoid\n * notes, i.e. the usable color tones (typically the 9/11/13 region). The scale\n * is rooted on the chord root. If the scale does not contain the chord, there\n * are no available tensions.\n *\n * @param chord The chord providing the chord tones.\n * @param scaleName A key of {@link NAMED_SCALES}.\n * @returns The available-tension pitch classes, sorted ascending in [0, 11].\n *\n * @example\n * ```ts\n * import { makeChord, availableTensions } from '@libraz/libcantus';\n * availableTensions(makeChord(0, 'maj7'), 'ionian'); // [2, 9] — color tones over Cmaj7\n * ```\n *\n * @category Scales\n */\nexport function availableTensions(chord: Chord, scaleName: string): number[] {\n const mask = NAMED_SCALES[scaleName];\n if (mask === undefined) {\n return [];\n }\n const rootPc = pitchClass(chord.rootPc);\n const chordPcs = chordPitchClasses(chord);\n if (!scaleMatchesChord(chordPcs, mask, rootPc)) {\n return [];\n }\n const chordSet = new Set(chordPcs);\n const avoidSet = new Set(avoidNotes(chord, scaleName));\n const tensions: number[] = [];\n for (let pc = 0; pc < 12; pc += 1) {\n if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc) || avoidSet.has(pc)) {\n continue;\n }\n tensions.push(pc);\n }\n return tensions.sort((a, b) => a - b);\n}\n\n/**\n * A scale fit over a chord together with its avoid notes and tensions.\n *\n * @category Scales\n */\nexport type ChordScaleReportEntry = {\n name: string;\n rootPc: number;\n avoid: number[];\n tensions: number[];\n};\n\n/**\n * Report the best-fitting scales for a chord with their avoid notes and tensions.\n *\n * Combines {@link chordScales}, {@link avoidNotes}, and {@link availableTensions}\n * into a single ergonomic result, ordered best fit first.\n *\n * @param chord The chord to analyze.\n * @param limit Optional maximum number of scales to report; all by default.\n * @returns One entry per reported scale, best fit first.\n *\n * @category Scales\n */\nexport function chordScaleReport(chord: Chord, limit?: number): ChordScaleReportEntry[] {\n const matches = chordScales(chord);\n const chosen = limit === undefined ? matches : matches.slice(0, Math.max(0, limit));\n return chosen.map((match) => ({\n name: match.name,\n rootPc: match.rootPc,\n avoid: avoidNotes(chord, match.name),\n tensions: availableTensions(chord, match.name),\n }));\n}\n\n/**\n * A chord paired with the scale chosen for it by {@link scalesForChanges}.\n *\n * @category Scales\n */\nexport type ScaleChoice = {\n chord: Chord;\n scale: ChordScaleMatch;\n};\n\n/**\n * Small per-candidate penalty added in {@link scalesForChanges} so that, among\n * choices of otherwise-equal transition cost, the tighter best-fit scale wins.\n */\nconst RANK_PENALTY = 0.01;\n\n/** Build the pitch-class set of a named scale rooted on `rootPc`. */\nfunction scalePitchClassSet(name: string, rootPc: number): Set<number> {\n const mask = NAMED_SCALES[name];\n const pcs = new Set<number>();\n if (mask === undefined) {\n return pcs;\n }\n for (let n = 0; n < 12; n += 1) {\n if (((mask >> n) & 1) === 1) {\n pcs.add(pitchClass(rootPc + n));\n }\n }\n return pcs;\n}\n\n/** Count pitch classes that belong to exactly one of two sets. */\nfunction symmetricDifferenceSize(a: Set<number>, b: Set<number>): number {\n let count = 0;\n for (const pc of a) {\n if (!b.has(pc)) {\n count += 1;\n }\n }\n for (const pc of b) {\n if (!a.has(pc)) {\n count += 1;\n }\n }\n return count;\n}\n\n/**\n * Choose one scale per chord across a progression, favoring continuity.\n *\n * Each chord's {@link chordScales} candidates form a stage in a Viterbi-style\n * dynamic program. The transition cost between adjacent choices is the number\n * of pitch classes that differ between their pitch-class sets (the symmetric\n * difference), plus a small penalty for straying from a chord's best-fit scale\n * so that ties break toward the tighter fit. The minimum-total-cost path is\n * returned, one {@link ScaleChoice} per input chord in the original order.\n *\n * @param chords The chord sequence to choose scales for.\n * @returns One scale choice per chord, in input order.\n *\n * @category Scales\n */\nexport function scalesForChanges(chords: Chord[]): ScaleChoice[] {\n if (chords.length === 0) {\n return [];\n }\n const candidateLists = chords.map((chord) => chordScales(chord));\n const pcSets = candidateLists.map((candidates) =>\n candidates.map((match) => scalePitchClassSet(match.name, match.rootPc)),\n );\n\n const first = candidateLists[0] ?? [];\n const dp: number[][] = [first.map((_, j) => j * RANK_PENALTY)];\n const back: number[][] = [first.map(() => -1)];\n\n for (let i = 1; i < candidateLists.length; i += 1) {\n const candidates = candidateLists[i] ?? [];\n const prevCosts = dp[i - 1] ?? [];\n const prevSets = pcSets[i - 1] ?? [];\n const curSets = pcSets[i] ?? [];\n const stageCosts: number[] = [];\n const stageBack: number[] = [];\n for (let j = 0; j < candidates.length; j += 1) {\n let bestCost = Number.POSITIVE_INFINITY;\n let bestPrev = -1;\n for (let k = 0; k < prevCosts.length; k += 1) {\n const transition = symmetricDifferenceSize(\n prevSets[k] ?? new Set(),\n curSets[j] ?? new Set(),\n );\n const cost = (prevCosts[k] ?? 0) + transition;\n if (cost < bestCost) {\n bestCost = cost;\n bestPrev = k;\n }\n }\n stageCosts.push(bestCost + j * RANK_PENALTY);\n stageBack.push(bestPrev);\n }\n dp.push(stageCosts);\n back.push(stageBack);\n }\n\n const lastCosts = dp[dp.length - 1] ?? [];\n let bestFinal = 0;\n for (let j = 1; j < lastCosts.length; j += 1) {\n if ((lastCosts[j] ?? Number.POSITIVE_INFINITY) < (lastCosts[bestFinal] ?? 0)) {\n bestFinal = j;\n }\n }\n\n const chosenIndices: number[] = new Array(candidateLists.length);\n let current = bestFinal;\n for (let i = candidateLists.length - 1; i >= 0; i -= 1) {\n chosenIndices[i] = current;\n current = back[i]?.[current] ?? -1;\n }\n\n return chords.map((chord, i) => {\n const candidates = candidateLists[i] ?? [];\n const scale = candidates[chosenIndices[i] ?? 0] ?? { name: 'chromatic', rootPc: chord.rootPc };\n return { chord, scale };\n });\n}\n","/**\n * Spelling: derive letter-name notes for scales and chords from a spelled tonic.\n *\n * The theory core works in pitch classes, which cannot choose between (say) a\n * G# and an Ab. Given a spelled tonic, this module assigns diatonic letters to\n * scale degrees and chord tones so a C major scale spells as C D E F G A B and\n * A harmonic minor spells its seventh as G#.\n */\n\nimport type { Note } from '../../core/pitch/index.js';\nimport { formatNote } from '../../core/pitch/index.js';\nimport type { KeyScale } from '../../core/types.js';\nimport type { Chord } from '../chord/index.js';\nimport { scaleTonesInDegreeOrder } from '../scale/index.js';\n\n/** Semitone offset of each natural letter above C: C D E F G A B. */\nconst LETTER_SEMITONES = [0, 2, 4, 5, 7, 9, 11] as const;\n\n/**\n * Conventional degree assignment for each chromatic offset above the tonic.\n *\n * The letter is derived from the tonic's letter plus `degreeOffset` (so the\n * spelling follows the key's diatonic letters), and the accidental is recomputed\n * for that letter. This covers the flat-side alterations (b2, b3, b6, b7), the\n * raised fourth (#4), and the raised degrees of a minor key: the raised sixth\n * (#6) and the raised leading tone (#7). The latter two keep sharp-side minor\n * keys spelling their raised degrees with the key-correct letter (e.g. F# minor\n * spells its leading tone E#, not F).\n *\n * The `alter` field is illustrative only; `spellPitchClass` recomputes the\n * accidental from the chosen letter.\n */\nconst CHROMATIC_SPELLING: Record<number, { degreeOffset: number; alter: number }> = {\n 1: { degreeOffset: 1, alter: -1 }, // b2\n 3: { degreeOffset: 2, alter: -1 }, // b3\n 6: { degreeOffset: 3, alter: 1 }, // #4\n 8: { degreeOffset: 5, alter: -1 }, // b6\n 9: { degreeOffset: 5, alter: 1 }, // #6 (raised sixth of a minor key)\n 10: { degreeOffset: 6, alter: -1 }, // b7\n 11: { degreeOffset: 6, alter: 1 }, // #7 (raised leading tone of a minor key)\n};\n\nfunction mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\nfunction mod7(n: number): number {\n return ((n % 7) + 7) % 7;\n}\n\n/** Natural pitch class of a letter (0 = C .. 6 = B). */\nfunction naturalPc(letter: number): number {\n return LETTER_SEMITONES[mod7(letter)] ?? 0;\n}\n\n/** Shortest signed alteration (in [-6, 6]) taking a letter's natural pc to `pc`. */\nfunction alterFor(letter: number, pc: number): number {\n let d = mod12(pc - naturalPc(letter));\n if (d > 6) {\n d -= 12;\n }\n return d;\n}\n\n/** Whether the key's scale is a seven-note (heptatonic) scale. */\nfunction isHeptatonic(key: KeyScale): boolean {\n return scaleTonesInDegreeOrder(key).length === 7;\n}\n\n/**\n * Spell a single pitch class relative to a spelled tonic and key.\n *\n * Diatonic pitch classes take the scale's letter for their degree; the common\n * chromatic tones (b2, b3, #4, b6, b7) and a minor key's raised degrees (#6, #7)\n * take their conventional, key-correct accidental spelling; anything else falls\n * back to a sharp spelling of the nearest natural.\n *\n * @param pc The pitch class to spell.\n * @param tonic The spelled tonic (its letter anchors the spelling).\n * @param key The key/scale.\n * @returns The spelled note (without octave).\n * @category Pitch & Intervals\n */\nexport function spellPitchClass(pc: number, tonic: Note, key: KeyScale): Note {\n const tonicPc = mod12(naturalPc(tonic.letter) + tonic.alter);\n const offset = mod12(pc - tonicPc);\n const tones = scaleTonesInDegreeOrder(key);\n\n if (isHeptatonic(key)) {\n const degree = tones.indexOf(mod12(pc));\n if (degree >= 0) {\n const letter = mod7(tonic.letter + degree);\n return { letter, alter: alterFor(letter, pc) };\n }\n const chromatic = CHROMATIC_SPELLING[offset];\n if (chromatic) {\n const letter = mod7(tonic.letter + chromatic.degreeOffset);\n return { letter, alter: alterFor(letter, pc) };\n }\n }\n\n // Fallback: name the pitch class from the nearest natural, preferring a sharp.\n for (let letter = 0; letter < 7; letter += 1) {\n if (naturalPc(letter) === mod12(pc)) {\n return { letter, alter: 0 };\n }\n }\n const belowLetter = mod7([0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6][mod12(pc)] ?? 0);\n return { letter: belowLetter, alter: alterFor(belowLetter, pc) };\n}\n\n/**\n * Spell every pitch class of a scale, in ascending scale-degree order.\n *\n * Correct for heptatonic scales (each degree gets the next letter). Non-standard\n * scales are spelled tone-by-tone with a sharp preference.\n *\n * @param tonic The spelled tonic.\n * @param key The key/scale.\n * @returns Spelled notes, one per scale degree.\n * @example\n * ```ts\n * import { spellScale, noteNames, parseNote, majorKey } from '@libraz/libcantus';\n * noteNames(spellScale(parseNote('C'), majorKey(0)));\n * // ['C', 'D', 'E', 'F', 'G', 'A', 'B']\n * ```\n * @category Pitch & Intervals\n */\nexport function spellScale(tonic: Note, key: KeyScale): Note[] {\n return scaleTonesInDegreeOrder(key).map((pc) => spellPitchClass(pc, tonic, key));\n}\n\n/**\n * Spell an arbitrary list of pitch classes relative to a key.\n *\n * @param pcs The pitch classes.\n * @param tonic The spelled tonic.\n * @param key The key/scale.\n * @returns Spelled notes, in input order.\n * @category Pitch & Intervals\n */\nexport function spellPitchClasses(pcs: number[], tonic: Note, key: KeyScale): Note[] {\n return pcs.map((pc) => spellPitchClass(pc, tonic, key));\n}\n\n/**\n * Spell a chord's tones, in the chord's own (tertian) order, relative to a key.\n *\n * Diatonic chords spell exactly (e.g. G7 in C major -> G B D F). Chromatic chord\n * tones take their conventional spelling; enharmonically ambiguous altered\n * tensions may be spelled by the general convention rather than by chord\n * function.\n *\n * @param chord The chord.\n * @param tonic The spelled tonic of the key.\n * @param key The key/scale.\n * @returns Spelled chord tones, root first.\n * @example\n * ```ts\n * import { spellChord, noteNames, parseNote, majorKey, makeChord } from '@libraz/libcantus';\n * // G7 in C major\n * noteNames(spellChord(makeChord(7, 'dom7'), parseNote('C'), majorKey(0)));\n * // ['G', 'B', 'D', 'F']\n * ```\n * @category Pitch & Intervals\n */\nexport function spellChord(chord: Chord, tonic: Note, key: KeyScale): Note[] {\n return chord.intervals.map((interval) =>\n spellPitchClass(mod12(chord.rootPc + interval), tonic, key),\n );\n}\n\n/**\n * Convenience: render spelled notes as letter-name strings.\n *\n * @param notes The notes.\n * @returns Their formatted names.\n * @category Pitch & Intervals\n */\nexport function noteNames(notes: Note[]): string[] {\n return notes.map(formatNote);\n}\n","/**\n * Lead-sheet chord symbol parsing and formatting.\n *\n * Bridges the informal `<root><quality>[/<bass>]` notation musicians write\n * (`Cmaj7`, `F#m7b5`, `Bb7`, `C/G`) and the library's structured {@link Chord}\n * type, so callers can accept/emit plain text at the edges of the API.\n */\n\nimport {\n formatNote,\n midiToNote,\n type Note,\n noteToPitchClass,\n parseNote,\n} from '../../core/pitch/index.js';\nimport { type Chord, type ChordQuality, makeChord, type PitchSpelling } from '../chord/index.js';\n\n/**\n * Matches a chord root: a letter A-G (case-insensitive, like {@link parseNote})\n * with an optional single-direction accidental.\n */\nconst ROOT_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?/;\n\n/** Matches a bare note usable as a slash-chord bass (no octave). */\nconst BASS_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?$/;\n\n/** Recognized quality suffixes, keyed by their exact lead-sheet spelling. */\nconst QUALITY_MAP: Record<string, ChordQuality> = {\n '': 'maj',\n m: 'min',\n min: 'min',\n '-': 'min',\n dim: 'dim',\n '°': 'dim',\n aug: 'aug',\n '+': 'aug',\n maj7: 'maj7',\n M7: 'maj7',\n Δ: 'maj7',\n Δ7: 'maj7',\n m7: 'min7',\n min7: 'min7',\n '-7': 'min7',\n '7': 'dom7',\n dim7: 'dim7',\n '°7': 'dim7',\n m7b5: 'm7b5',\n ø: 'm7b5',\n ø7: 'm7b5',\n min7b5: 'm7b5',\n mMaj7: 'minMaj7',\n mM7: 'minMaj7',\n minMaj7: 'minMaj7',\n aug7: 'aug7',\n '+7': 'aug7',\n '7#5': 'aug7',\n augMaj7: 'augMaj7',\n augM7: 'augMaj7',\n '+maj7': 'augMaj7',\n '+M7': 'augMaj7',\n majb5: 'majb5',\n 'maj(b5)': 'majb5',\n '(b5)': 'majb5',\n '6': '6',\n m6: 'min6',\n min6: 'min6',\n '6/9': '6/9',\n '69': '6/9',\n sus2: 'sus2',\n sus: 'sus4',\n sus4: 'sus4',\n add9: 'add9',\n add11: 'add11',\n maj9: 'maj9',\n M9: 'maj9',\n m9: 'min9',\n min9: 'min9',\n '9': 'dom9',\n '7b9': '7b9',\n '7#9': '7#9',\n '7#11': '7#11',\n '7b13': '7b13',\n '11': '11',\n '13': '13',\n '5': '5',\n};\n\n/** Canonical lead-sheet suffix emitted for each chord quality when formatting. */\nconst CANONICAL_SUFFIX: Record<ChordQuality, string> = {\n maj: '',\n min: 'm',\n dim: 'dim',\n aug: 'aug',\n maj7: 'maj7',\n min7: 'm7',\n dom7: '7',\n dim7: 'dim7',\n m7b5: 'm7b5',\n minMaj7: 'mMaj7',\n aug7: 'aug7',\n augMaj7: 'augMaj7',\n majb5: 'maj(b5)',\n '6': '6',\n min6: 'm6',\n '6/9': '6/9',\n sus2: 'sus2',\n sus4: 'sus4',\n add9: 'add9',\n add11: 'add11',\n maj9: 'maj9',\n min9: 'm9',\n dom9: '9',\n '7b9': '7b9',\n '7#9': '7#9',\n '7#11': '7#11',\n '7b13': '7b13',\n '11': '11',\n '13': '13',\n '5': '5',\n};\n\n/** Reduce a value to a pitch class in [0, 11]. */\nfunction pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/** Build a chord and record the parsed spellings as enharmonic hints. */\nfunction makeSpelledChord(root: Note, quality: ChordQuality, bass?: Note): Chord {\n const chord = makeChord(\n noteToPitchClass(root),\n quality,\n bass === undefined ? undefined : noteToPitchClass(bass),\n );\n chord.rootSpelling = { letter: root.letter, alter: root.alter };\n if (bass !== undefined) {\n chord.bassSpelling = { letter: bass.letter, alter: bass.alter };\n }\n return chord;\n}\n\n/**\n * Parse a lead-sheet chord symbol into a {@link Chord}.\n *\n * Accepts `<root><quality>[/<bass>]`, e.g. `Cmaj7`, `F#m7b5`, `Bb7`, `C/G`,\n * `C6/9`, `C6/9/E`. Root and bass letters are case-insensitive, matching\n * {@link parseNote}. A `/` is ambiguous between a slash bass and the `6/9`\n * quality; the text splits at the last `/` whose right-hand side is a valid\n * bare note preceded by a recognized quality, so `6/9` (with or without a\n * further slash bass) parses as a quality.\n *\n * The parsed chord carries the root/bass spellings as enharmonic hints\n * (`rootSpelling`/`bassSpelling`) so {@link formatChordSymbol} can reproduce\n * flat spellings such as `Bbmaj7` instead of respelling them with sharps.\n *\n * @param text The chord symbol text.\n * @returns The parsed chord.\n * @throws If the root or quality is not recognized.\n * @example\n * ```ts\n * import { parseChordSymbol, formatChordSymbol } from '@libraz/libcantus';\n * const c = parseChordSymbol('Bbmaj7');\n * formatChordSymbol(c); // 'Bbmaj7' — flat spelling is preserved on round-trip\n * ```\n * @category Chords\n */\nexport function parseChordSymbol(text: string): Chord {\n const trimmed = text.trim();\n const rootMatch = ROOT_RE.exec(trimmed);\n if (!rootMatch) {\n throw new Error(`Invalid chord symbol: ${text}`);\n }\n const rootToken = rootMatch[0];\n const rootNote = parseNote(rootToken);\n const rest = trimmed.slice(rootToken.length);\n\n // Split at the last '/' so the '6/9' quality's own slash never masks a\n // trailing slash bass (e.g. 'C6/9/E').\n const slashIndex = rest.lastIndexOf('/');\n if (slashIndex !== -1) {\n const before = rest.slice(0, slashIndex);\n const after = rest.slice(slashIndex + 1);\n const beforeQuality = QUALITY_MAP[before];\n if (beforeQuality !== undefined && BASS_RE.test(after)) {\n return makeSpelledChord(rootNote, beforeQuality, parseNote(after));\n }\n }\n\n const quality = QUALITY_MAP[rest];\n if (quality === undefined) {\n throw new Error(`Unrecognized chord quality: ${text}`);\n }\n return makeSpelledChord(rootNote, quality);\n}\n\n/**\n * Name a pitch class, preferring a spelling hint when it is still valid.\n *\n * A hint is used only when no explicit sharp/flat preference was given and the\n * hint still resolves to `pc` (a stale hint left over after transposition is\n * ignored). Otherwise the pitch class is respelled from the requested table.\n */\nfunction pitchClassName(pc: number, hint: PitchSpelling | undefined, flats?: boolean): string {\n if (flats === undefined && hint !== undefined && noteToPitchClass(hint) === pc) {\n return formatNote(hint);\n }\n const note = midiToNote(60 + pc, flats ? 'flat' : 'sharp');\n return formatNote({ letter: note.letter, alter: note.alter });\n}\n\n/**\n * Format a {@link Chord} as a lead-sheet chord symbol.\n *\n * The inverse of {@link parseChordSymbol}: each quality maps to one canonical\n * suffix spelling, and a slash bass is appended only when it differs from the\n * root. When the chord carries `rootSpelling`/`bassSpelling` hints (as chords\n * from {@link parseChordSymbol} do) and no explicit `flats` preference is\n * given, the hints are reused so flat symbols round-trip unchanged.\n *\n * @param chord The chord to format.\n * @param opts Formatting options.\n * @param opts.flats Prefer flat spellings over sharps for altered roots/basses;\n * passing either `true` or `false` overrides any spelling hints.\n * @returns The chord symbol text.\n * @example\n * ```ts\n * import { makeChord, formatChordSymbol } from '@libraz/libcantus';\n * formatChordSymbol(makeChord(0, 'min7')); // 'Cm7'\n * ```\n * @category Chords\n */\nexport function formatChordSymbol(chord: Chord, opts?: { flats?: boolean }): string {\n const rootPc = pitchClass(chord.rootPc);\n const rootName = pitchClassName(rootPc, chord.rootSpelling, opts?.flats);\n const suffix = CANONICAL_SUFFIX[chord.quality];\n let symbol = `${rootName}${suffix}`;\n if (chord.bassPc !== undefined && pitchClass(chord.bassPc) !== rootPc) {\n symbol += `/${pitchClassName(pitchClass(chord.bassPc), chord.bassSpelling, opts?.flats)}`;\n }\n return symbol;\n}\n\n/**\n * Transpose a chord symbol by a number of semitones.\n *\n * @param text The chord symbol text.\n * @param semitones Signed semitone offset to apply to the root and bass.\n * @param opts Formatting options for the result; see {@link formatChordSymbol}.\n * @returns The transposed chord symbol text.\n * @throws If `text` does not parse as a chord symbol.\n * @example\n * ```ts\n * import { transposeChordSymbol } from '@libraz/libcantus';\n * transposeChordSymbol('C/G', 2); // 'D/A'\n * ```\n * @category Chords\n */\nexport function transposeChordSymbol(\n text: string,\n semitones: number,\n opts?: { flats?: boolean },\n): string {\n const chord = parseChordSymbol(text);\n const transposed: Chord = { ...chord, rootPc: pitchClass(chord.rootPc + semitones) };\n if (chord.bassPc !== undefined) {\n transposed.bassPc = pitchClass(chord.bassPc + semitones);\n }\n return formatChordSymbol(transposed, opts);\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordPitchClasses } from '../chord/index.js';\nimport {\n createsParallelPerfect,\n createsVoiceCrossing,\n createsVoiceOverlap,\n exceedsSpacing,\n} from '../counterpoint/index.js';\nimport type { VoiceRange } from './satb.js';\n\n/** Default maximum spacing between adjacent upper voices (one octave). */\nexport const DEFAULT_MAX_SPACING = 12;\n\n/** Score penalty per counterpoint violation between consecutive voicings. */\nexport const VIOLATION_PENALTY = 1000;\n/** Score penalty per chord tone absent from a voicing. */\nconst MISSING_TONE_PENALTY = 500;\n/** Score penalty per doubled tone that is neither the root nor the fifth. */\nconst POOR_DOUBLING_PENALTY = 4;\n/** Hard cap on candidate voicings evaluated per chord, keeping the search bounded. */\nconst MAX_CANDIDATES = 4000;\n\n/** Reduce a value to a pitch class in [0, 11]. */\nexport function pitchClass(value: number): number {\n return ((Math.trunc(value) % 12) + 12) % 12;\n}\n\n/**\n * All MIDI pitches of a pitch class inside an inclusive range, ordered from the\n * centre of the range outward (ties break toward the lower pitch). Enumerating\n * centre-outward keeps the candidate set balanced around the register when it\n * is truncated at {@link MAX_CANDIDATES}, instead of skewing to the low octaves\n * that a plain ascending scan would visit first.\n */\nfunction pitchesForPc(pc: number, range: VoiceRange): number[] {\n const result: number[] = [];\n for (let midi = Math.ceil(range.min); midi <= range.max; midi += 1) {\n if (pitchClass(midi) === pc) {\n result.push(midi);\n }\n }\n const center = (range.min + range.max) / 2;\n return result.sort((a, b) => {\n const da = Math.abs(a - center);\n const db = Math.abs(b - center);\n return da === db ? a - b : da - db;\n });\n}\n\n/**\n * Enumerate candidate voicings for a chord: the bass takes the chord's bass\n * (or root) pitch class at each available octave, and each upper voice takes\n * any chord pitch class within its range. Candidates are built in ascending\n * voice order and pruned to exclude voice crossings and over-wide adjacent\n * spacing (the bass–tenor pair is allowed an extra octave, per convention).\n * Enumeration is deterministic and capped at {@link MAX_CANDIDATES}.\n */\nexport function enumerateVoicings(\n chord: Chord,\n ranges: VoiceRange[],\n maxSpacing: number,\n): number[][] {\n const chordPcs = chordPitchClasses(chord);\n const bassPc = pitchClass(chord.bassPc ?? chord.rootPc);\n const results: number[][] = [];\n const current: number[] = [];\n const build = (voice: number): void => {\n if (results.length >= MAX_CANDIDATES) {\n return;\n }\n if (voice === ranges.length) {\n results.push([...current]);\n return;\n }\n const range = ranges[voice];\n if (range === undefined) {\n return;\n }\n const pcs = voice === 0 ? [bassPc] : chordPcs;\n const prev = current[voice - 1];\n for (const pc of pcs) {\n for (const pitch of pitchesForPc(pc, range)) {\n if (prev !== undefined) {\n if (pitch < prev) {\n continue; // would cross below the next lower voice\n }\n const spacingLimit = voice === 1 ? maxSpacing + 12 : maxSpacing;\n if (pitch - prev > spacingLimit) {\n continue;\n }\n }\n current.push(pitch);\n build(voice + 1);\n current.pop();\n }\n }\n };\n build(0);\n return results;\n}\n\n/**\n * Structural quality penalty of a single voicing: heavily penalize missing\n * chord tones, mildly penalize doubling anything other than the root or fifth.\n */\nexport function structuralPenalty(pitches: number[], chord: Chord): number {\n const counts = new Map<number, number>();\n for (const pitch of pitches) {\n const pc = pitchClass(pitch);\n counts.set(pc, (counts.get(pc) ?? 0) + 1);\n }\n let penalty = 0;\n for (const pc of chordPitchClasses(chord)) {\n if (!counts.has(pc)) {\n penalty += MISSING_TONE_PENALTY;\n }\n }\n const rootPc = pitchClass(chord.rootPc);\n const fifthPc = pitchClass(chord.rootPc + 7);\n for (const [pc, count] of counts) {\n if (count > 1 && pc !== rootPc && pc !== fifthPc) {\n penalty += (count - 1) * POOR_DOUBLING_PENALTY;\n }\n }\n return penalty;\n}\n\n/**\n * Count counterpoint violations between two consecutive voicings of equal\n * length: parallel perfects (fifths and octaves alike, since octaves are the\n * perfect-class-zero case of {@link createsParallelPerfect}) on every voice\n * pair, voice crossings in the new voicing, and — on adjacent pairs — voice\n * overlaps and over-wide spacing between upper voices.\n */\nexport function violationCount(prev: number[], cur: number[], maxSpacing: number): number {\n let count = 0;\n for (let lower = 0; lower < cur.length; lower += 1) {\n for (let upper = lower + 1; upper < cur.length; upper += 1) {\n const prevLower = prev[lower];\n const prevUpper = prev[upper];\n const curLower = cur[lower];\n const curUpper = cur[upper];\n if (\n prevLower === undefined ||\n prevUpper === undefined ||\n curLower === undefined ||\n curUpper === undefined\n ) {\n continue;\n }\n if (createsParallelPerfect(prevUpper, curUpper, prevLower, curLower)) {\n count += 1;\n }\n if (createsVoiceCrossing(curUpper, curLower)) {\n count += 1;\n }\n if (upper === lower + 1) {\n if (createsVoiceOverlap(prevUpper, curUpper, prevLower, curLower)) {\n count += 1;\n }\n if (lower > 0 && exceedsSpacing(curUpper, curLower, maxSpacing)) {\n count += 1;\n }\n }\n }\n }\n return count;\n}\n","import type { Chord } from '../chord/index.js';\nimport {\n DEFAULT_MAX_SPACING,\n enumerateVoicings,\n structuralPenalty,\n VIOLATION_PENALTY,\n violationCount,\n} from './internal.js';\nimport { voiceLeadingCost } from './leading.js';\n\n/**\n * An inclusive MIDI pitch range for a single voice.\n *\n * @category Voicing & Counterpoint\n */\nexport type VoiceRange = {\n min: number;\n max: number;\n};\n\n/**\n * Default four-voice SATB ranges, ascending (index 0 = lowest):\n * bass E2–C4 (40–60), tenor C3–G4 (48–67), alto G3–D5 (55–74),\n * soprano C4–G5 (60–79).\n *\n * @category Voicing & Counterpoint\n */\nexport const SATB_RANGES: readonly VoiceRange[] = [\n { min: 40, max: 60 },\n { min: 48, max: 67 },\n { min: 55, max: 74 },\n { min: 60, max: 79 },\n];\n\n/**\n * Options controlling {@link voiceChord} and {@link voiceProgression}.\n *\n * @category Voicing & Counterpoint\n */\nexport type VoicingOptions = {\n /**\n * Number of voices to realize. Ignored when `ranges` is given.\n *\n * @defaultValue 4\n */\n voices?: number;\n /** Explicit per-voice ranges, ascending (index 0 = lowest). Takes precedence over `voices`. */\n ranges?: VoiceRange[];\n /**\n * Maximum spacing in semitones between adjacent upper voices.\n *\n * @defaultValue 12\n */\n maxSpacing?: number;\n};\n\n/** Overall pitch floor/ceiling used when deriving ranges for arbitrary voice counts. */\nconst DERIVED_LOW = 40;\nconst DERIVED_HIGH = 79;\n/** Span of each derived per-voice range in semitones. */\nconst DERIVED_SPAN = 19;\n\n/**\n * Resolve the per-voice ranges implied by the options: explicit `ranges` win,\n * four voices use {@link SATB_RANGES}, and other counts get evenly spaced\n * ranges spanning roughly the bass-to-soprano compass.\n */\nexport function resolveRanges(opts?: VoicingOptions): VoiceRange[] {\n if (opts?.ranges !== undefined) {\n if (opts.ranges.length === 0) {\n throw new Error('ranges must contain at least one voice range');\n }\n return opts.ranges.map((range) => ({ ...range }));\n }\n const voices = opts?.voices ?? 4;\n if (voices < 1) {\n throw new Error('voices must be at least 1');\n }\n if (voices === 4) {\n return SATB_RANGES.map((range) => ({ ...range }));\n }\n if (voices === 1) {\n return [{ min: DERIVED_LOW, max: DERIVED_HIGH }];\n }\n const ranges: VoiceRange[] = [];\n for (let i = 0; i < voices; i += 1) {\n const min = Math.round(\n DERIVED_LOW + (i * (DERIVED_HIGH - DERIVED_SPAN - DERIVED_LOW)) / (voices - 1),\n );\n ranges.push({ min, max: min + DERIVED_SPAN });\n }\n return ranges;\n}\n\n/**\n * Realize a single chord as one MIDI pitch per voice, ascending (index 0 =\n * lowest). The bass voice takes the chord's `bassPc` when set, otherwise the\n * root; upper voices take chord pitch classes, doubling the root or fifth as\n * needed to fill all voices. The result stays inside each voice's range, keeps\n * adjacent upper voices within `maxSpacing`, avoids voice crossing, and is\n * deterministic: a compact close-position voicing centered in the ranges.\n *\n * @param chord The chord to voice.\n * @param opts Voicing options; defaults to four voices in {@link SATB_RANGES}.\n * @returns MIDI pitches, ascending, one per voice.\n * @throws If no voicing fits the given ranges.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceChord } from '@libraz/libcantus';\n * const chord = parseChordSymbol('Cmaj7');\n * voiceChord(chord); // four ascending MIDI pitches within the SATB ranges\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceChord(chord: Chord, opts?: VoicingOptions): number[] {\n const ranges = resolveRanges(opts);\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n let score = structuralPenalty(candidate, chord);\n for (let i = 0; i < candidate.length; i += 1) {\n const pitch = candidate[i];\n const range = ranges[i];\n if (pitch === undefined || range === undefined) {\n continue;\n }\n // Prefer pitches near the middle of each voice's range for a centered,\n // compact default voicing.\n score += Math.abs(pitch - (range.min + range.max) / 2);\n }\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n return best;\n}\n\n/**\n * Voice a chord progression with smooth voice leading. The first chord is\n * voiced with {@link voiceChord}; each subsequent chord picks, from a bounded\n * deterministic candidate set, the voicing minimizing the voice-leading cost\n * from the previous voicing plus a large penalty per counterpoint violation\n * (parallel perfects/octaves, voice crossing, voice overlap, and over-wide\n * upper-voice spacing).\n *\n * @param chords The chords to voice in order.\n * @param opts Voicing options; defaults to four voices in {@link SATB_RANGES}.\n * @returns One voicing per chord, each ascending with one MIDI pitch per voice.\n * @throws If any chord admits no voicing within the given ranges.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceProgression } from '@libraz/libcantus';\n * const chords = ['C', 'Am', 'F', 'G'].map((s) => parseChordSymbol(s));\n * voiceProgression(chords); // one four-voice voicing per chord, smoothly led\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceProgression(chords: Chord[], opts?: VoicingOptions): number[][] {\n const ranges = resolveRanges(opts);\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const result: number[][] = [];\n let prev: number[] | undefined;\n for (const chord of chords) {\n if (prev === undefined) {\n prev = voiceChord(chord, opts);\n result.push(prev);\n continue;\n }\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const score =\n structuralPenalty(candidate, chord) +\n voiceLeadingCost(prev, candidate) +\n VIOLATION_PENALTY * violationCount(prev, candidate, maxSpacing);\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n result.push(best);\n prev = best;\n }\n return result;\n}\n","import type { Chord } from '../chord/index.js';\nimport { createsHiddenParallelPerfect } from '../counterpoint/index.js';\nimport {\n DEFAULT_MAX_SPACING,\n enumerateVoicings,\n structuralPenalty,\n VIOLATION_PENALTY,\n violationCount,\n} from './internal.js';\nimport type { VoicingOptions } from './satb.js';\nimport { resolveRanges } from './satb.js';\n\n/**\n * Moderate penalty for a hidden/direct perfect fifth or octave reached on the\n * outer-voice (bass–soprano) pair. Unlike a true parallel perfect it is\n * discouraged rather than forbidden, so the weight sits alongside voice-leading\n * motion rather than the hard {@link VIOLATION_PENALTY}.\n */\nconst HIDDEN_PERFECT_PENALTY = 6;\n\n/**\n * Total voice-leading cost between two voicings: the sum of absolute semitone\n * motion across voices, plus a moderate {@link HIDDEN_PERFECT_PENALTY} when the\n * outer-voice (bass–soprano) pair reaches a hidden/direct perfect fifth or\n * octave by similar motion. The arrays must be the same length; when they\n * differ the voicings are not comparable and the cost is `Infinity`.\n *\n * @param from The previous voicing, one MIDI pitch per voice.\n * @param to The next voicing, one MIDI pitch per voice.\n * @returns The summed absolute motion (plus any hidden-perfect penalty), or\n * `Infinity` when lengths differ.\n * @category Voicing & Counterpoint\n */\nexport function voiceLeadingCost(from: number[], to: number[]): number {\n if (from.length !== to.length) {\n return Number.POSITIVE_INFINITY;\n }\n let total = 0;\n for (let i = 0; i < from.length; i += 1) {\n const a = from[i];\n const b = to[i];\n if (a === undefined || b === undefined) {\n continue;\n }\n total += Math.abs(b - a);\n }\n // Discourage hidden/direct perfects between the outermost voices, where they\n // are most audible. True parallels are handled (and forbidden) elsewhere.\n if (from.length >= 2) {\n const bassPrev = from[0];\n const bassCur = to[0];\n const sopPrev = from[from.length - 1];\n const sopCur = to[to.length - 1];\n if (\n bassPrev !== undefined &&\n bassCur !== undefined &&\n sopPrev !== undefined &&\n sopCur !== undefined &&\n createsHiddenParallelPerfect(bassPrev, bassCur, sopPrev, sopCur)\n ) {\n total += HIDDEN_PERFECT_PENALTY;\n }\n }\n return total;\n}\n\n/**\n * Voice a single chord to follow smoothly from an arbitrary current voicing.\n *\n * Candidate voicings of `chord` are enumerated within ranges taken from `opts`,\n * or — when neither `voices` nor `ranges` is given — from a one-octave window\n * around each pitch of `current` (so the result matches `current`'s voice\n * count). Each candidate is scored by structural quality, voice-leading motion\n * from `current`, and a large penalty per counterpoint violation; the lowest\n * scoring candidate is returned, ascending.\n *\n * @param current The current voicing to lead from, ascending (index 0 = lowest).\n * @param chord The next chord to voice.\n * @param opts Voicing options; when omitted, ranges follow `current`'s span.\n * @returns The chosen voicing, ascending with one MIDI pitch per voice.\n * @throws If no voicing fits the derived ranges.\n * @category Voicing & Counterpoint\n */\nexport function nextVoicing(current: number[], chord: Chord, opts?: VoicingOptions): number[] {\n const ranges =\n opts?.ranges !== undefined || opts?.voices !== undefined\n ? resolveRanges(opts)\n : current.map((pitch) => {\n // Window one octave around each current pitch, clamped so extreme-low\n // or extreme-high input can never yield MIDI outside [0, 127].\n const centre = Math.min(127, Math.max(0, pitch));\n return { min: Math.max(0, centre - 12), max: Math.min(127, centre + 12) };\n });\n const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;\n const candidates = enumerateVoicings(chord, ranges, maxSpacing);\n let best: number[] | undefined;\n let bestScore = Number.POSITIVE_INFINITY;\n for (const candidate of candidates) {\n const score =\n structuralPenalty(candidate, chord) +\n voiceLeadingCost(current, candidate) +\n VIOLATION_PENALTY * violationCount(current, candidate, maxSpacing);\n if (score < bestScore) {\n bestScore = score;\n best = candidate;\n }\n }\n if (best === undefined) {\n throw new Error('no voicing satisfies the given ranges');\n }\n return best;\n}\n","import type { Chord } from '../chord/index.js';\nimport { chordToneRole } from '../chord/index.js';\nimport { pitchClass } from './internal.js';\n\n/**\n * A tertian voicing style for {@link voiceChordStyled}.\n *\n * - `close`: the plain close-position tertian stack.\n * - `drop2`: the second voice from the top dropped an octave (drop-2 voicing).\n * - `drop3`: the third voice from the top dropped an octave (drop-3 voicing).\n * - `shell`: root plus guide tones (third and seventh) for seventh chords, or\n * root/third/fifth for triads; the fifth and tensions are omitted.\n * - `rootless`: the root omitted, keeping third/fifth/seventh and tensions\n * (a typical left-hand jazz voicing).\n *\n * @category Voicing & Counterpoint\n */\nexport type VoicingStyle = 'close' | 'drop2' | 'drop3' | 'shell' | 'rootless';\n\n/**\n * Options controlling {@link voiceChordStyled}.\n *\n * @category Voicing & Counterpoint\n */\nexport type StyledVoicingOptions = {\n /**\n * Voicing style to build.\n *\n * @defaultValue 'close'\n */\n style?: VoicingStyle;\n /** Constrain the highest voice to this pitch class (0..11) when given. */\n topNote?: number;\n /**\n * Base octave for the close stack; the stack begins near `12 * octave`.\n *\n * @defaultValue 4\n */\n octave?: number;\n /**\n * Omit the root regardless of style (relevant for jazz voicings).\n *\n * @defaultValue false\n */\n rootless?: boolean;\n};\n\n/** Default base octave for a styled close-position stack. */\nconst DEFAULT_STYLE_OCTAVE = 4;\n\n/** Return the pitch classes of a list in order, without duplicates. */\nfunction dedupePcs(pcs: number[]): number[] {\n const seen = new Set<number>();\n const result: number[] = [];\n for (const pc of pcs) {\n if (!seen.has(pc)) {\n seen.add(pc);\n result.push(pc);\n }\n }\n return result;\n}\n\n/** The lowest MIDI pitch of a pitch class at or above a floor. */\nfunction lowestPitchAtOrAbove(pc: number, floor: number): number {\n return floor + ((((pc - pitchClass(floor)) % 12) + 12) % 12);\n}\n\n/** The pitch class in `pcs` whose circular distance to `target` is smallest. */\nfunction nearestPc(target: number, pcs: number[]): number {\n let best = pcs[0] ?? target;\n let bestDist = 12;\n for (const pc of pcs) {\n const dist = Math.min((((pc - target) % 12) + 12) % 12, (((target - pc) % 12) + 12) % 12);\n if (dist < bestDist) {\n bestDist = dist;\n best = pc;\n }\n }\n return best;\n}\n\n/**\n * Realize a single chord as an explicit tertian voicing in a chosen style,\n * independent of the SATB range search used by {@link voiceChord}.\n *\n * The chord tones are stacked in close position from the bass (`bassPc`, else\n * `rootPc`) in the given scientific-pitch `octave` upward (octave 4 starts the\n * bass near C4 = MIDI 60, matching {@link midiToNote} and the bass module).\n * When `topNote` is given the stack is rotated so the highest voice's pitch\n * class equals that note (or the nearest chord tone). The chosen\n * {@link VoicingStyle} then transforms the stack, and the result is returned as\n * ascending MIDI pitches (index 0 = lowest).\n *\n * @param chord The chord to voice.\n * @param opts Styled voicing options; defaults to a close voicing at octave 4.\n * @returns MIDI pitches, ascending, one per retained voice.\n * @example\n * ```ts\n * import { parseChordSymbol, voiceChordStyled } from '@libraz/libcantus';\n * const chord = parseChordSymbol('Dm7');\n * voiceChordStyled(chord, { style: 'drop2' }); // ascending MIDI pitches, drop-2 voicing\n * ```\n * @category Voicing & Counterpoint\n */\nexport function voiceChordStyled(chord: Chord, opts?: StyledVoicingOptions): number[] {\n const style = opts?.style ?? 'close';\n const base = 12 * ((opts?.octave ?? DEFAULT_STYLE_OCTAVE) + 1);\n const rootPc = pitchClass(chord.rootPc);\n const bassPc = pitchClass(chord.bassPc ?? chord.rootPc);\n const omitRoot = style === 'rootless' || opts?.rootless === true;\n\n // Tertian chord tones in order, with the bass tone rotated to the bottom.\n let order = dedupePcs(chord.intervals.map((interval) => pitchClass(chord.rootPc + interval)));\n const bassIndex = order.indexOf(bassPc);\n if (bassIndex > 0) {\n order = [...order.slice(bassIndex), ...order.slice(0, bassIndex)];\n } else if (bassIndex < 0) {\n order = [bassPc, ...order];\n }\n\n if (style === 'shell') {\n const roles = order.map((pc) => chordToneRole(pc, chord));\n // The guide tone is the seventh when present; on a sixth chord the sixth\n // stands in for it, and otherwise the voicing falls back to the fifth.\n const guide = roles.includes('seventh')\n ? 'seventh'\n : roles.includes('sixth')\n ? 'sixth'\n : 'fifth';\n order = order.filter((_pc, i) => {\n const role = roles[i];\n return role === 'root' || role === 'third' || role === guide;\n });\n }\n\n if (omitRoot) {\n order = order.filter((pc) => pc !== rootPc);\n }\n\n if (order.length === 0) {\n return [];\n }\n\n if (opts?.topNote !== undefined) {\n const target = order.includes(pitchClass(opts.topNote))\n ? pitchClass(opts.topNote)\n : nearestPc(pitchClass(opts.topNote), order);\n const targetIndex = order.indexOf(target);\n order = [...order.slice(targetIndex + 1), ...order.slice(0, targetIndex + 1)];\n }\n\n // Stack the ordered pitch classes upward in close position.\n const stack: number[] = [];\n let prev: number | undefined;\n for (const pc of order) {\n if (prev === undefined) {\n prev = lowestPitchAtOrAbove(pc, base);\n } else {\n let delta = (((pc - pitchClass(prev)) % 12) + 12) % 12;\n if (delta === 0) {\n delta = 12;\n }\n prev += delta;\n }\n stack.push(prev);\n }\n\n if (style === 'drop2' && stack.length >= 2) {\n stack[stack.length - 2] = (stack[stack.length - 2] ?? 0) - 12;\n } else if (style === 'drop3' && stack.length >= 3) {\n stack[stack.length - 3] = (stack[stack.length - 3] ?? 0) - 12;\n }\n\n return stack.sort((a, b) => a - b);\n}\n","import { midiToNote, type Note as NoteData } from '../core/pitch/index.js';\n\n/** Reduce any integer to a pitch class in [0, 11]. */\nexport function mod12(n: number): number {\n return ((n % 12) + 12) % 12;\n}\n\n/** Spell a bare pitch class as an octave-less note with a sharp/flat preference. */\nexport function spellPitchClassBare(pc: number, spelling: 'sharp' | 'flat'): NoteData {\n const spelled = midiToNote(60 + mod12(pc), spelling);\n return { letter: spelled.letter, alter: spelled.alter };\n}\n","import {\n formatNote,\n midiToNote,\n type Note as NoteData,\n noteToMidi,\n noteToPitchClass,\n parseNote,\n type SpelledInterval,\n spelledInterval,\n} from '../core/pitch/index.js';\nimport { spellPitchClassBare } from './shared.js';\n\n/** Defensive copy of a plain note. */\nfunction copyNote(data: NoteData): NoteData {\n const copy: NoteData = { letter: data.letter, alter: data.alter };\n if (data.octave !== undefined) {\n copy.octave = data.octave;\n }\n return copy;\n}\n\n/**\n * An immutable spelled note: a diatonic letter plus a chromatic alteration and\n * an optional octave. Wraps the plain note object and delegates to the pitch\n * module; every transformation returns a new instance.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.of('C4').transpose(7).name; // 'G4'\n * ```\n */\nexport class Note {\n readonly #data: NoteData;\n\n /**\n * Wrap a plain note object.\n *\n * @param data The spelled note; it is copied, never retained or mutated.\n */\n constructor(data: NoteData) {\n this.#data = copyNote(data);\n }\n\n /**\n * Parse scientific pitch notation (e.g. `'C#4'`, `'Bb'`, `'F##3'`).\n *\n * @param name The note text.\n * @returns The parsed note.\n * @throws If the text is not a valid note.\n */\n static of(name: string): Note {\n return new Note(parseNote(name));\n }\n\n /**\n * Name a MIDI number (middle C = C4 = 60) as a note.\n *\n * @param midi The MIDI number.\n * @param spelling Whether to prefer sharps or flats for black keys.\n * @returns The spelled note, with octave.\n */\n static fromMidi(midi: number, spelling: 'sharp' | 'flat' = 'sharp'): Note {\n return new Note(midiToNote(midi, spelling));\n }\n\n /**\n * Wrap an existing plain note object.\n *\n * @param data The plain note.\n * @returns The wrapped note.\n */\n static fromData(data: NoteData): Note {\n return new Note(data);\n }\n\n /** The note rendered as scientific pitch notation, e.g. `'G4'` or `'Bb'`. */\n get name(): string {\n return formatNote(this.#data);\n }\n\n /** The pitch class (0..11), ignoring octave. */\n get pitchClass(): number {\n return noteToPitchClass(this.#data);\n }\n\n /**\n * The MIDI number (middle C = C4 = 60).\n *\n * @throws If the note has no octave and therefore no fixed pitch.\n */\n get midi(): number {\n if (this.#data.octave === undefined) {\n throw new Error(`note ${this.name} has no octave, so it has no MIDI number`);\n }\n return noteToMidi(this.#data);\n }\n\n /** The diatonic letter number: 0..6 for C..B. */\n get letter(): number {\n return this.#data.letter;\n }\n\n /** The chromatic alteration in semitones: -1 flat, 0 natural, +1 sharp, ... */\n get alter(): number {\n return this.#data.alter;\n }\n\n /** The octave (scientific pitch notation), or undefined for a bare pitch class. */\n get octave(): number | undefined {\n return this.#data.octave;\n }\n\n /** A copy of the underlying plain note object. */\n get data(): NoteData {\n return copyNote(this.#data);\n }\n\n /**\n * Transpose by a signed number of semitones.\n *\n * When the note carries an octave the transposition happens in MIDI space and\n * the result is spelled with a sharp preference. An octave-less note stays\n * octave-less: only its pitch class is moved. Transposing by zero is the\n * identity: the original spelling is preserved (no enharmonic respelling).\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed note.\n */\n transpose(semitones: number): Note {\n if (semitones === 0) {\n return new Note(this.#data);\n }\n if (this.#data.octave !== undefined) {\n return Note.fromMidi(this.midi + semitones);\n }\n return new Note(spellPitchClassBare(this.pitchClass + semitones, 'sharp'));\n }\n\n /**\n * The spelled interval from this note to another.\n *\n * @param other The second note.\n * @returns The diatonic number, quality, and semitone span.\n */\n intervalTo(other: Note): SpelledInterval {\n return spelledInterval(this.#data, other.#data);\n }\n\n /**\n * Whether another note has the same letter, alteration, and octave.\n *\n * @param other The note to compare.\n * @returns True if the spellings are identical.\n */\n equals(other: Note): boolean {\n return (\n this.#data.letter === other.#data.letter &&\n this.#data.alter === other.#data.alter &&\n this.#data.octave === other.#data.octave\n );\n }\n\n /**\n * The plain note data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(note)` from collapsing to `{}`.\n *\n * @returns A copy of the underlying plain note object.\n */\n toJSON(): NoteData {\n return this.data;\n }\n}\n","import {\n type Cadence,\n type ChordAnalysis,\n detectCadence,\n type HarmonicFunction,\n} from '../analyze/functional/index.js';\nimport type { Note as NoteData } from '../core/pitch/index.js';\nimport type { KeyScale } from '../core/types.js';\nimport type { Chord as ChordData } from '../theory/chord/index.js';\nimport { type VoicingOptions, voiceProgression } from '../theory/voicing/index.js';\nimport type { Chord } from './chord.js';\nimport type { Key } from './key.js';\n\n/**\n * An immutable ordered sequence of chords, optionally carrying a {@link Key}\n * context shared by its analysis methods.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const key = Key.major('C');\n * key.chord(1).progressionTo(key.chord(4), key.chord(0)).roman();\n * // ['ii', 'V', 'I']\n * ```\n */\nexport class Progression {\n readonly #chords: readonly Chord[];\n readonly #key: Key | undefined;\n\n /**\n * Wrap a chord sequence.\n *\n * @param chords The chords in order; the array is copied.\n * @param key Optional key context for analysis methods.\n */\n constructor(chords: readonly Chord[], key?: Key) {\n this.#chords = [...chords];\n this.#key = key;\n }\n\n /** A copy of the chord sequence. */\n get chords(): readonly Chord[] {\n return [...this.#chords];\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /** The number of chords. */\n get length(): number {\n return this.#chords.length;\n }\n\n /**\n * A copy of this progression with a chord appended.\n *\n * @param chord The chord to append.\n * @returns The new progression.\n */\n add(chord: Chord): Progression {\n return new Progression([...this.#chords, chord], this.#key);\n }\n\n /**\n * A copy of this progression carrying the given key context.\n *\n * @param key The key context to attach.\n * @returns The new progression.\n */\n withKey(key: Key): Progression {\n return new Progression(this.#chords, key);\n }\n\n /**\n * Voice the progression with smooth voice leading.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns One ascending voicing (MIDI pitches) per chord.\n * @throws If any chord admits no voicing within the given ranges.\n */\n voice(opts?: VoicingOptions): number[][] {\n return voiceProgression(\n this.#chords.map((chord) => chord.data),\n opts,\n );\n }\n\n /**\n * The Roman numeral of each chord in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns One numeral per chord.\n * @throws If no key is given and none is carried.\n */\n roman(key?: Key): string[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.roman(resolved));\n }\n\n /**\n * The harmonic function of each chord in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns One function per chord.\n * @throws If no key is given and none is carried.\n */\n functions(key?: Key): HarmonicFunction[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.function(resolved));\n }\n\n /**\n * Analyze every chord and classify the closing cadence.\n *\n * The cadence is detected on the final chord pair and is null when the\n * progression has fewer than two chords.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns Per-chord analyses and the closing cadence.\n * @throws If no key is given and none is carried.\n */\n analyze(key?: Key): { chords: ChordAnalysis[]; cadence: Cadence } {\n const resolved = this.#resolveKey(key);\n const chords = this.#chords.map((chord) => chord.analyze(resolved));\n const from = this.#chords[this.#chords.length - 2];\n const to = this.#chords[this.#chords.length - 1];\n const cadence =\n from !== undefined && to !== undefined\n ? detectCadence(from.data, to.data, resolved.scale)\n : null;\n return { chords, cadence };\n }\n\n /**\n * The plain progression data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(progression)` from collapsing to `{}`. The chords are\n * emitted as plain data and the carried key, when present, as its own data.\n *\n * @returns The chord data sequence and the carried key, if any.\n */\n toJSON(): { chords: ChordData[]; key: { scale: KeyScale; tonic: NoteData } | undefined } {\n return {\n chords: this.#chords.map((chord) => chord.data),\n key: this.#key?.toJSON(),\n };\n }\n\n /** Resolve the key for an analysis method: explicit first, then carried. */\n #resolveKey(key?: Key): Key {\n const resolved = key ?? this.#key;\n if (resolved === undefined) {\n throw new Error('progression has no key context; pass a Key or attach one with withKey()');\n }\n return resolved;\n }\n}\n","import { detectChord, detectChordBest } from '../analyze/detect/index.js';\nimport {\n analyzeChord,\n type BorrowedSource,\n borrowedSource,\n type ChordAnalysis,\n chordToRoman,\n functionOf,\n type HarmonicFunction,\n isBorrowedChord,\n} from '../analyze/functional/index.js';\nimport { negativeHarmonyMirror } from '../generate/reharmony/index.js';\nimport {\n type Chord as ChordData,\n type ChordQuality,\n chordPitchClasses,\n makeChord,\n} from '../theory/chord/index.js';\nimport {\n availableTensions,\n avoidNotes,\n type ChordScaleMatch,\n chordScales,\n} from '../theory/chordscale/index.js';\nimport { spellChord } from '../theory/spelling/index.js';\nimport { formatChordSymbol, parseChordSymbol } from '../theory/symbol/index.js';\nimport {\n type StyledVoicingOptions,\n type VoicingOptions,\n voiceChord,\n voiceChordStyled,\n} from '../theory/voicing/index.js';\nimport type { Key } from './key.js';\nimport { Note } from './note.js';\nimport { Progression } from './progression.js';\nimport { mod12 } from './shared.js';\n\n/**\n * Defensive copy of a plain chord.\n *\n * Any enharmonic spelling hints (`rootSpelling`/`bassSpelling`, populated by\n * `parseChordSymbol`) are carried through so a flat-named chord round-trips\n * through the class API; a hint that no longer matches its pitch class is\n * simply ignored by the formatter.\n */\nfunction copyChord(data: ChordData): ChordData {\n const copy: ChordData = {\n rootPc: data.rootPc,\n quality: data.quality,\n intervals: [...data.intervals],\n };\n if (data.bassPc !== undefined) {\n copy.bassPc = data.bassPc;\n }\n if (data.rootSpelling !== undefined) {\n copy.rootSpelling = { letter: data.rootSpelling.letter, alter: data.rootSpelling.alter };\n }\n if (data.bassSpelling !== undefined) {\n copy.bassSpelling = { letter: data.bassSpelling.letter, alter: data.bassSpelling.alter };\n }\n return copy;\n}\n\n/**\n * An immutable chord: a root pitch class, quality, interval template, and\n * optional slash bass, optionally carrying a {@link Key} context. Analysis\n * methods (`roman`, `function`, `analyze`, ...) use an explicitly passed key\n * first and fall back to the carried context.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').invert(1).symbol(); // 'Cmaj7/E' (third in the bass)\n * ```\n */\nexport class Chord {\n readonly #data: ChordData;\n readonly #key: Key | undefined;\n\n /**\n * Wrap a plain chord object.\n *\n * @param data The chord; it is copied, never retained or mutated.\n * @param key Optional key context for analysis methods.\n */\n constructor(data: ChordData, key?: Key) {\n this.#data = copyChord(data);\n this.#key = key;\n }\n\n /**\n * Build a chord from a root and quality.\n *\n * @param root Root as a note name (e.g. `'Eb'`) or a pitch class.\n * @param quality The chord quality.\n * @param bass Optional slash-chord bass pitch class.\n * @returns The chord (without key context).\n */\n static of(root: string | number, quality: ChordQuality, bass?: number): Chord {\n const rootPc = typeof root === 'string' ? Note.of(root).pitchClass : root;\n return new Chord(makeChord(rootPc, quality, bass));\n }\n\n /**\n * Wrap an existing plain chord object.\n *\n * @param data The plain chord.\n * @returns The wrapped chord (without key context).\n */\n static from(data: ChordData): Chord {\n return new Chord(data);\n }\n\n /**\n * Parse a lead-sheet chord symbol (e.g. `'Cmaj7'`, `'F#m7b5'`, `'C/G'`).\n *\n * @param symbol The chord symbol.\n * @returns The chord (without key context).\n * @throws If the root or quality is not recognized.\n */\n static parse(symbol: string): Chord {\n return new Chord(parseChordSymbol(symbol));\n }\n\n /**\n * Identify the chords matching a set of pitches, best interpretation first.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns Ranked chord interpretations (may be empty).\n */\n static detect(pitches: number[]): Chord[] {\n return detectChord(pitches).map(\n (match) => new Chord(makeChord(match.rootPc, match.quality, match.bassPc)),\n );\n }\n\n /**\n * The single best chord interpretation of a pitch set.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @returns The top-ranked chord, or null when nothing matches.\n */\n static detectBest(pitches: number[]): Chord | null {\n const best = detectChordBest(pitches);\n return best === null ? null : new Chord(best);\n }\n\n /** The root pitch class (0..11). */\n get rootPc(): number {\n return this.#data.rootPc;\n }\n\n /** The chord quality. */\n get quality(): ChordQuality {\n return this.#data.quality;\n }\n\n /** A copy of the semitone offsets above the root. */\n get intervals(): number[] {\n return [...this.#data.intervals];\n }\n\n /** The slash-chord bass pitch class, or undefined in root position. */\n get bassPc(): number | undefined {\n return this.#data.bassPc;\n }\n\n /** A copy of the underlying plain chord object. */\n get data(): ChordData {\n return copyChord(this.#data);\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /**\n * A copy of this chord carrying the given key context.\n *\n * @param key The key context to attach.\n * @returns The new chord.\n */\n withKey(key: Key): Chord {\n return new Chord(this.#data, key);\n }\n\n /**\n * The chord's sorted, deduplicated pitch classes.\n *\n * @returns Pitch classes ascending in [0, 11].\n */\n pitchClasses(): number[] {\n return chordPitchClasses(this.#data);\n }\n\n /**\n * The chord's Roman numeral in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The Roman numeral string.\n * @throws If no key is given and none is carried.\n */\n roman(key?: Key): string {\n return chordToRoman(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The chord's harmonic function (tonic / subdominant / dominant) in a key.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The harmonic function.\n * @throws If no key is given and none is carried.\n */\n function(key?: Key): HarmonicFunction {\n return functionOf(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * Full functional analysis: function, borrowing, and Roman numeral.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The chord analysis.\n * @throws If no key is given and none is carried.\n */\n analyze(key?: Key): ChordAnalysis {\n return analyzeChord(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * Whether the chord is borrowed from the parallel mode (modal interchange).\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns True if the chord is borrowed.\n * @throws If no key is given and none is carried.\n */\n isBorrowed(key?: Key): boolean {\n return isBorrowedChord(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The origin of a non-diatonic chord (parallel mode or Neapolitan), or null.\n *\n * @param key Key to analyze in; falls back to the carried context.\n * @returns The borrowing source, or null.\n * @throws If no key is given and none is carried.\n */\n borrowedSource(key?: Key): BorrowedSource {\n return borrowedSource(this.#data, this.#resolveKey(key).scale);\n }\n\n /**\n * The chord rendered as a lead-sheet symbol (e.g. `'Cmaj7'`, `'F#m7'`, `'C/G'`).\n *\n * @param opts Set `flats: true` to spell the root/bass with flats.\n * @returns The chord symbol.\n */\n symbol(opts?: { flats?: boolean }): string {\n return formatChordSymbol(this.#data, opts);\n }\n\n /**\n * Realize the chord as one MIDI pitch per voice, ascending.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns MIDI pitches, ascending, one per voice.\n * @throws If no voicing fits the given ranges.\n */\n voice(opts?: VoicingOptions): number[] {\n return voiceChord(this.#data, opts);\n }\n\n /**\n * Realize the chord as a single styled voicing (`close`, `drop2`, `drop3`,\n * `shell`, or `rootless`), optionally constraining the top voice.\n *\n * @param opts Styled-voicing options; defaults to a close-position voicing.\n * @returns MIDI pitches, ascending.\n */\n styledVoicing(opts?: StyledVoicingOptions): number[] {\n return voiceChordStyled(this.#data, opts);\n }\n\n /**\n * The negative-harmony mirror of the chord about the key's tonic–dominant\n * axis (major becomes minor and vice versa).\n *\n * @param key Key providing the reflection axis; falls back to the carried\n * context.\n * @returns The mirrored chord, keeping any key context.\n * @throws If no key is given and none is carried.\n */\n negativeHarmony(key?: Key): Chord {\n const resolved = this.#resolveKey(key);\n // Retain the key that anchored the reflection (explicit first, then carried)\n // so a later no-arg analysis method still has a key context.\n return new Chord(negativeHarmonyMirror(this.#data, resolved.scale), key ?? this.#key);\n }\n\n /**\n * The n-th inversion: a copy whose bass is the chord tone `n` steps above the\n * root in the interval template (`invert(1)` puts the third in the bass).\n * `n` wraps around the template length; negative values count backwards.\n *\n * `invert(0)` (and any `n` that wraps to it) is root position, so it carries\n * no slash bass and equals the original chord.\n *\n * @param n The inversion number.\n * @returns The inverted chord, keeping any key context.\n * @throws If the chord has no intervals.\n */\n invert(n: number): Chord {\n const intervals = this.#data.intervals;\n const length = intervals.length;\n if (length === 0) {\n throw new Error('cannot invert a chord with no intervals');\n }\n const index = ((n % length) + length) % length;\n const data = copyChord(this.#data);\n if (index === 0) {\n delete data.bassPc;\n } else {\n data.bassPc = mod12(this.#data.rootPc + (intervals[index] ?? 0));\n }\n return new Chord(data, this.#key);\n }\n\n /**\n * The named scales that fit over this chord, best fit first, rooted on the\n * chord root.\n *\n * @returns The matching scales.\n */\n scales(): ChordScaleMatch[] {\n return chordScales(this.#data);\n }\n\n /**\n * The available tensions (usable non-chord, non-avoid scale tones) of a\n * scale over this chord.\n *\n * @param scaleName A named scale, rooted on the chord root.\n * @returns Tension pitch classes, ascending in [0, 11].\n */\n tensions(scaleName: string): number[] {\n return availableTensions(this.#data, scaleName);\n }\n\n /**\n * The avoid notes (scale tones a semitone above a chord tone) of a scale\n * over this chord.\n *\n * @param scaleName A named scale, rooted on the chord root.\n * @returns Avoid-note pitch classes, ascending in [0, 11].\n */\n avoidNotes(scaleName: string): number[] {\n return avoidNotes(this.#data, scaleName);\n }\n\n /**\n * Spell the chord tones with letter names, root first, in the key's spelling.\n *\n * @param key Key providing the spelled tonic; falls back to the carried\n * context.\n * @returns Spelled octave-less notes in the chord's own (tertian) order.\n * @throws If no key is given and none is carried.\n */\n spell(key?: Key): Note[] {\n const resolved = this.#resolveKey(key);\n return spellChord(this.#data, resolved.tonic.data, resolved.scale).map(\n (note) => new Note(note),\n );\n }\n\n /**\n * Start a progression with this chord followed by others, carrying this\n * chord's key context (if any).\n *\n * @param others The chords following this one.\n * @returns The progression.\n */\n progressionTo(...others: Chord[]): Progression {\n return new Progression([this, ...others], this.#key);\n }\n\n /**\n * Whether another chord has the same root, quality, intervals, and bass.\n * Key context is not compared.\n *\n * @param other The chord to compare.\n * @returns True if the chord data is identical.\n */\n equals(other: Chord): boolean {\n const a = this.#data;\n const b = other.#data;\n return (\n a.rootPc === b.rootPc &&\n a.quality === b.quality &&\n a.bassPc === b.bassPc &&\n a.intervals.length === b.intervals.length &&\n a.intervals.every((interval, i) => interval === b.intervals[i])\n );\n }\n\n /**\n * The plain chord data, for JSON serialization.\n *\n * @returns A copy of the underlying plain chord object.\n */\n toJSON(): ChordData {\n return this.data;\n }\n\n /** Resolve the key for an analysis method: explicit first, then carried. */\n #resolveKey(key?: Key): Key {\n const resolved = key ?? this.#key;\n if (resolved === undefined) {\n throw new Error('chord has no key context; pass a Key or attach one with withKey()');\n }\n return resolved;\n }\n}\n","import type { SpelledInterval } from '../core/pitch/index.js';\nimport type { Note } from './note.js';\n\n/**\n * An immutable spelled interval value: a diatonic number, a quality label, and\n * a signed semitone span. A thin convenience wrapper over the pitch module's\n * plain interval result.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Interval, Note } from '@libraz/libcantus';\n * Interval.between(Note.of('C4'), Note.of('G4')).name; // 'P5'\n * ```\n */\nexport class Interval {\n readonly #number: number;\n readonly #quality: string;\n readonly #semitones: number;\n\n private constructor(numberValue: number, quality: string, semitones: number) {\n this.#number = numberValue;\n this.#quality = quality;\n this.#semitones = semitones;\n }\n\n /**\n * The spelled interval between two notes.\n *\n * @param a The first note.\n * @param b The second note.\n * @returns The interval from `a` to `b`.\n */\n static between(a: Note, b: Note): Interval {\n const spelled = a.intervalTo(b);\n return new Interval(spelled.number, spelled.quality, spelled.semitones);\n }\n\n /**\n * Build an interval from explicit components.\n *\n * @param numberValue Diatonic size: 1 = unison, 2 = second, ... 8 = octave.\n * @param quality Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`.\n * @param semitones Signed semitone span.\n * @returns The interval.\n */\n static of(numberValue: number, quality: string, semitones: number): Interval {\n return new Interval(numberValue, quality, semitones);\n }\n\n /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */\n get number(): number {\n return this.#number;\n }\n\n /** Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`. */\n get quality(): string {\n return this.#quality;\n }\n\n /** Signed semitone span. */\n get semitones(): number {\n return this.#semitones;\n }\n\n /** A readable label composed of quality and number, e.g. `'P5'` or `'M3'`. */\n get name(): string {\n return `${this.#quality}${this.#number}`;\n }\n\n /**\n * The plain interval data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(interval)` from collapsing to `{}`.\n *\n * @returns The diatonic number, quality, and semitone span.\n */\n toJSON(): SpelledInterval {\n return { number: this.#number, quality: this.#quality, semitones: this.#semitones };\n }\n}\n","import { isMinorKey, romanToChord } from '../analyze/functional/index.js';\nimport type { Note as NoteData } from '../core/pitch/index.js';\nimport type { KeyScale } from '../core/types.js';\nimport {\n type ChordQuality,\n chordFromDegree,\n diatonicSeventh,\n diatonicTriad,\n} from '../theory/chord/index.js';\nimport {\n isScaleTone,\n majorKey,\n minorKey,\n scaleByName,\n scaleTonesInDegreeOrder,\n} from '../theory/scale/index.js';\nimport { spellScale } from '../theory/spelling/index.js';\nimport { Chord } from './chord.js';\nimport { Note } from './note.js';\nimport { mod12, spellPitchClassBare } from './shared.js';\n\n/** Resolve a string or numeric key root into a spelled tonic note. */\nfunction resolveTonic(root: string | number, spelling: 'sharp' | 'flat'): Note {\n return typeof root === 'string' ? Note.of(root) : new Note(spellPitchClassBare(root, spelling));\n}\n\n/** Total accidentals a spelled tonic produces across a key's whole scale. */\nfunction accidentalLoad(tonic: NoteData, scale: KeyScale): number {\n return spellScale(tonic, scale).reduce((sum, note) => sum + Math.abs(note.alter), 0);\n}\n\n/**\n * Choose the tonic spelling (sharp- or flat-side) that spells `scale` with the\n * fewest accidentals, so a numeric root never yields a double-flat/double-sharp\n * scale (e.g. pitch class 6 minor spells as F# minor, not Gb minor with Bbb).\n */\nfunction bestTonicForScale(rootPc: number, scale: KeyScale): Note {\n const sharp = spellPitchClassBare(rootPc, 'sharp');\n const flat = spellPitchClassBare(rootPc, 'flat');\n if (sharp.letter === flat.letter && sharp.alter === flat.alter) {\n return new Note(sharp);\n }\n return accidentalLoad(flat, scale) <= accidentalLoad(sharp, scale)\n ? new Note(flat)\n : new Note(sharp);\n}\n\n/**\n * An immutable key/scale: a `KeyScale` (root pitch class plus mode mask) paired\n * with a spelled tonic that anchors letter-name spelling. Acts as the factory\n * for key-aware chords.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').chord(4).symbol(); // 'G' (the diatonic triad on scale degree 4)\n * ```\n */\nexport class Key {\n readonly #scale: KeyScale;\n readonly #tonic: Note;\n\n /**\n * Wrap a key/scale and its spelled tonic.\n *\n * @param scale The key/scale; its root is normalized to a pitch class.\n * @param tonic The spelled tonic anchoring letter-name spelling.\n */\n constructor(scale: KeyScale, tonic: Note) {\n this.#scale = { rootPc: mod12(scale.rootPc), modeMask12: scale.modeMask12 };\n this.#tonic = tonic;\n }\n\n /**\n * A major key.\n *\n * @param root Tonic as a note name (e.g. `'Eb'`) or a pitch class; a numeric\n * root is spelled with whichever accidental side yields the fewest\n * accidentals across the scale.\n * @returns The major key.\n */\n static major(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.of(root);\n return new Key(majorKey(tonic.pitchClass), tonic);\n }\n const scale = majorKey(root);\n return new Key(scale, bestTonicForScale(root, scale));\n }\n\n /**\n * A natural-minor key.\n *\n * @param root Tonic as a note name or a pitch class; a numeric root is\n * spelled with whichever accidental side yields the fewest accidentals\n * across the scale.\n * @returns The minor key.\n */\n static minor(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.of(root);\n return new Key(minorKey(tonic.pitchClass), tonic);\n }\n const scale = minorKey(root);\n return new Key(scale, bestTonicForScale(root, scale));\n }\n\n /**\n * A key on a named scale (e.g. `'dorian'`, `'harmonicMinor'`).\n *\n * @param name The scale name, a key of the scale module's named-scale table.\n * @param root Tonic as a note name or a pitch class.\n * @returns The key.\n * @throws If the name is not a known scale.\n */\n static named(name: string, root: string | number): Key {\n const tonic = resolveTonic(root, 'sharp');\n return new Key(scaleByName(name, tonic.pitchClass), tonic);\n }\n\n /**\n * Wrap an existing `KeyScale`, synthesizing a spelled tonic when none is\n * given (flat-preferred for minor-third scales, sharp-preferred otherwise).\n *\n * @param scale The key/scale to wrap.\n * @param tonic Optional spelled tonic.\n * @returns The key.\n */\n static of(scale: KeyScale, tonic?: Note): Key {\n const spelled =\n tonic ?? new Note(spellPitchClassBare(scale.rootPc, isMinorKey(scale) ? 'flat' : 'sharp'));\n return new Key(scale, spelled);\n }\n\n /** A copy of the underlying plain `KeyScale`. */\n get scale(): KeyScale {\n return { rootPc: this.#scale.rootPc, modeMask12: this.#scale.modeMask12 };\n }\n\n /** The spelled tonic. */\n get tonic(): Note {\n return this.#tonic;\n }\n\n /** The tonic pitch class (0..11). */\n get rootPc(): number {\n return this.#scale.rootPc;\n }\n\n /** Whether the scale has a minor third and no major third. */\n get isMinor(): boolean {\n return isMinorKey(this.#scale);\n }\n\n /**\n * The scale's pitch classes in ascending scale-degree order (degree 0 first).\n *\n * @returns One pitch class per scale degree.\n */\n pitchClasses(): number[] {\n return scaleTonesInDegreeOrder(this.#scale);\n }\n\n /**\n * The spelled scale, one note per degree (e.g. C D E F G A B for C major).\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n notes(): Note[] {\n return spellScale(this.#tonic.data, this.#scale).map((note) => new Note(note));\n }\n\n /**\n * Alias of {@link Key.notes}.\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n spell(): Note[] {\n return this.notes();\n }\n\n /**\n * The spelled scale as letter-name strings.\n *\n * @returns One name per scale degree.\n */\n noteNames(): string[] {\n return this.notes().map((note) => note.name);\n }\n\n /**\n * Build a chord on a scale degree, carrying this key as context.\n *\n * With an explicit quality the quality's interval template is attached to the\n * degree's diatonic root; without one the scale-correct diatonic triad is\n * stacked (e.g. a diminished triad on the leading tone of a major key).\n *\n * @param degree 0-based scale degree of the chord root.\n * @param quality Optional chord quality.\n * @returns The chord, with this key attached.\n */\n chord(degree: number, quality?: ChordQuality): Chord {\n const data =\n quality === undefined\n ? diatonicTriad(degree, this.#scale)\n : chordFromDegree(degree, quality, this.#scale);\n return new Chord(data, this);\n }\n\n /**\n * The diatonic triad on a scale degree, carrying this key as context.\n *\n * @param degree 0-based scale degree of the chord root.\n * @returns The triad, with this key attached.\n */\n diatonicTriad(degree: number): Chord {\n return new Chord(diatonicTriad(degree, this.#scale), this);\n }\n\n /**\n * The diatonic seventh chord on a scale degree, carrying this key as context.\n *\n * @param degree 0-based scale degree of the chord root.\n * @returns The seventh chord, with this key attached.\n */\n diatonicSeventh(degree: number): Chord {\n return new Chord(diatonicSeventh(degree, this.#scale), this);\n }\n\n /**\n * Build the chord denoted by a Roman numeral in this key (including applied\n * chords such as `'V7/V'`), carrying this key as context.\n *\n * @param text The Roman numeral.\n * @returns The chord, with this key attached.\n * @throws If the numeral is not valid.\n */\n roman(text: string): Chord {\n return new Chord(romanToChord(text, this.#scale), this);\n }\n\n /**\n * Whether a pitch belongs to the scale.\n *\n * @param x A MIDI pitch, bare pitch class, or note.\n * @returns True if the pitch class is a scale tone.\n */\n contains(x: number | Note): boolean {\n return isScaleTone(typeof x === 'number' ? x : x.pitchClass, this.#scale);\n }\n\n /**\n * The plain key data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(key)` from collapsing to `{}`. The result pairs the\n * `KeyScale` with the spelled tonic, enough to reconstruct the key via\n * {@link Key.of}.\n *\n * @returns The key/scale and its spelled tonic.\n */\n toJSON(): { scale: KeyScale; tonic: NoteData } {\n return { scale: this.scale, tonic: this.#tonic.data };\n }\n}\n"],"mappings":"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","names":["pitchClass","IntervalQuality","pitchClass","NoteSafety","ReasonFlag","pitchClass","degreeNumber","hasMajorThird","pitchClass","EPS","pitchClass","EPS","pitchClass","EPS","EPS","pitchClass","intervalAboveRoot","isChordMember","stepResolution","describe","EPS","mod12","EPS","pitchClass","DEFAULT_TS","EPS","SIXTEENTH","EIGHTH","choice","DEFAULT_TS","pitchClass","pitchClass","mulberry32","mulberry32","mod12","sameChord","pitchClass","LETTER_SEMITONES","mod12","mod7","pitchClass","pitchClass","pitchClass","mod12","mod12","mod12"]}