@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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/generate/harmonize/index.ts","../src/generate/motif/index.ts","../src/generate/progression/index.ts","../src/generate/rhythm/index.ts"],"sourcesContent":["/**\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 { 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 * 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"],"mappings":"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","names":["DEFAULT_TS","EPS","SIXTEENTH","EIGHTH","choice","DEFAULT_TS","pitchClass","pitchClass","mulberry32","mulberry32"]}
@@ -0,0 +1,41 @@
1
+ // src/theory/harmony/index.ts
2
+ function roleOf(pitch, chord, chordId = 0) {
3
+ const interval = ((Math.trunc(pitch) - chord.rootPc) % 12 + 12) % 12;
4
+ const tones = new Set(chord.intervals.map((i) => (i % 12 + 12) % 12));
5
+ const hasHigherSeventh = tones.has(10) || tones.has(11);
6
+ const hasThird = tones.has(3) || tones.has(4);
7
+ const isSuspendedTone = !hasThird && (interval === 5 && tones.has(5) || interval === 2 && tones.has(2));
8
+ let role;
9
+ let lock;
10
+ if (interval === 0) {
11
+ role = "root";
12
+ lock = "identity";
13
+ } else if (isSuspendedTone) {
14
+ role = "third";
15
+ lock = "quality";
16
+ } else if (interval === 3 || interval === 4) {
17
+ role = "third";
18
+ lock = "quality";
19
+ } else if (interval === 6 || interval === 7 || interval === 8) {
20
+ role = "fifth";
21
+ lock = "voicing";
22
+ } else if (interval === 9 && tones.has(3) && tones.has(6) && !hasHigherSeventh) {
23
+ role = "seventh";
24
+ lock = "voicing";
25
+ } else if (interval === 9 && tones.has(9) && !hasHigherSeventh) {
26
+ role = "sixth";
27
+ lock = "voicing";
28
+ } else if (interval === 10 || interval === 11) {
29
+ role = "seventh";
30
+ lock = "voicing";
31
+ } else {
32
+ role = "tension";
33
+ lock = "voicing";
34
+ }
35
+ return { role, lock, belongsToChordId: chordId };
36
+ }
37
+
38
+ export {
39
+ roleOf
40
+ };
41
+ //# sourceMappingURL=chunk-SDM3VJJ5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theory/harmony/index.ts"],"sourcesContent":["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"],"mappings":";AAwDO,SAAS,OAAO,OAAe,OAAc,UAAU,GAAe;AAC3E,QAAM,aAAc,KAAK,MAAM,KAAK,IAAI,MAAM,UAAU,KAAM,MAAM;AACpE,QAAM,QAAQ,IAAI,IAAI,MAAM,UAAU,IAAI,CAAC,OAAQ,IAAI,KAAM,MAAM,EAAE,CAAC;AACtE,QAAM,mBAAmB,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE;AACtD,QAAM,WAAW,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC;AAC5C,QAAM,kBACJ,CAAC,aAAc,aAAa,KAAK,MAAM,IAAI,CAAC,KAAO,aAAa,KAAK,MAAM,IAAI,CAAC;AAClF,MAAI;AACJ,MAAI;AACJ,MAAI,aAAa,GAAG;AAClB,WAAO;AACP,WAAO;AAAA,EACT,WAAW,iBAAiB;AAC1B,WAAO;AACP,WAAO;AAAA,EACT,WAAW,aAAa,KAAK,aAAa,GAAG;AAC3C,WAAO;AACP,WAAO;AAAA,EACT,WAAW,aAAa,KAAK,aAAa,KAAK,aAAa,GAAG;AAC7D,WAAO;AACP,WAAO;AAAA,EACT,WAAW,aAAa,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB;AAC9E,WAAO;AACP,WAAO;AAAA,EACT,WAAW,aAAa,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB;AAC9D,WAAO;AACP,WAAO;AAAA,EACT,WAAW,aAAa,MAAM,aAAa,IAAI;AAC7C,WAAO;AACP,WAAO;AAAA,EACT,OAAO;AACL,WAAO;AACP,WAAO;AAAA,EACT;AACA,SAAO,EAAE,MAAM,MAAM,kBAAkB,QAAQ;AACjD;","names":[]}