@libraz/libcantus 0.9.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +61 -261
  2. package/README_ja.md +115 -0
  3. package/dist/analyze/index.cjs +54 -7
  4. package/dist/analyze/index.cjs.map +1 -1
  5. package/dist/analyze/index.d.cts +213 -456
  6. package/dist/analyze/index.d.ts +213 -456
  7. package/dist/analyze/index.js +56 -9
  8. package/dist/chunk-3JXCW6DX.cjs +3220 -0
  9. package/dist/chunk-3JXCW6DX.cjs.map +1 -0
  10. package/dist/chunk-4A2RMUCC.js +7647 -0
  11. package/dist/chunk-4A2RMUCC.js.map +1 -0
  12. package/dist/chunk-6XPTBE7Y.cjs +49 -0
  13. package/dist/chunk-6XPTBE7Y.cjs.map +1 -0
  14. package/dist/chunk-AFM2ULJH.cjs +5121 -0
  15. package/dist/chunk-AFM2ULJH.cjs.map +1 -0
  16. package/dist/chunk-E3F4AHAH.cjs +690 -0
  17. package/dist/chunk-E3F4AHAH.cjs.map +1 -0
  18. package/dist/chunk-ELCTZUJJ.js +379 -0
  19. package/dist/chunk-ELCTZUJJ.js.map +1 -0
  20. package/dist/chunk-FVSI36UV.js +690 -0
  21. package/dist/chunk-FVSI36UV.js.map +1 -0
  22. package/dist/chunk-GEDTJHAC.cjs +1 -0
  23. package/dist/chunk-GEDTJHAC.cjs.map +1 -0
  24. package/dist/chunk-GOZG57ER.js +3220 -0
  25. package/dist/chunk-GOZG57ER.js.map +1 -0
  26. package/dist/chunk-H3VORETI.js +2243 -0
  27. package/dist/chunk-H3VORETI.js.map +1 -0
  28. package/dist/chunk-H42UHPYW.js +1577 -0
  29. package/dist/chunk-H42UHPYW.js.map +1 -0
  30. package/dist/chunk-HFPS7JFD.js +1 -0
  31. package/dist/chunk-INHVXP6Z.js +3053 -0
  32. package/dist/chunk-INHVXP6Z.js.map +1 -0
  33. package/dist/chunk-K4ZJUGF4.cjs +379 -0
  34. package/dist/chunk-K4ZJUGF4.cjs.map +1 -0
  35. package/dist/chunk-KNJEKLKV.js +49 -0
  36. package/dist/chunk-KNJEKLKV.js.map +1 -0
  37. package/dist/chunk-M4CWTJWJ.cjs +7647 -0
  38. package/dist/chunk-M4CWTJWJ.cjs.map +1 -0
  39. package/dist/chunk-MXO72PLY.cjs +211 -0
  40. package/dist/chunk-MXO72PLY.cjs.map +1 -0
  41. package/dist/chunk-NLEU4QSE.cjs +360 -0
  42. package/dist/chunk-NLEU4QSE.cjs.map +1 -0
  43. package/dist/chunk-OE6WK2Y2.cjs +1577 -0
  44. package/dist/chunk-OE6WK2Y2.cjs.map +1 -0
  45. package/dist/chunk-Q2WGKJNN.cjs +1064 -0
  46. package/dist/chunk-Q2WGKJNN.cjs.map +1 -0
  47. package/dist/chunk-QYQQ5J6E.js +1 -0
  48. package/dist/chunk-QYQQ5J6E.js.map +1 -0
  49. package/dist/chunk-RHIJ3S4I.cjs +1 -0
  50. package/dist/chunk-RHIJ3S4I.cjs.map +1 -0
  51. package/dist/chunk-TTCLJX6D.js +211 -0
  52. package/dist/chunk-TTCLJX6D.js.map +1 -0
  53. package/dist/chunk-UADYAYAT.cjs +3053 -0
  54. package/dist/chunk-UADYAYAT.cjs.map +1 -0
  55. package/dist/chunk-VOHZB45S.js +5121 -0
  56. package/dist/chunk-VOHZB45S.js.map +1 -0
  57. package/dist/chunk-VTI6FOLB.js +1064 -0
  58. package/dist/chunk-VTI6FOLB.js.map +1 -0
  59. package/dist/chunk-WWURE4XT.cjs +2243 -0
  60. package/dist/chunk-WWURE4XT.cjs.map +1 -0
  61. package/dist/chunk-YH3BIKHH.js +360 -0
  62. package/dist/chunk-YH3BIKHH.js.map +1 -0
  63. package/dist/core/index.cjs +103 -6
  64. package/dist/core/index.cjs.map +1 -1
  65. package/dist/core/index.d.cts +96 -345
  66. package/dist/core/index.d.ts +96 -345
  67. package/dist/core/index.js +104 -7
  68. package/dist/generate/index.cjs +89 -10
  69. package/dist/generate/index.cjs.map +1 -1
  70. package/dist/generate/index.d.cts +437 -1095
  71. package/dist/generate/index.d.ts +437 -1095
  72. package/dist/generate/index.js +94 -15
  73. package/dist/index-9wcMhG73.d.ts +1095 -0
  74. package/dist/{index-D6b6na69.d.cts → index-B4o55NDr.d.cts} +13 -9
  75. package/dist/index-B9MNZboQ.d.cts +770 -0
  76. package/dist/index-B9MNZboQ.d.ts +770 -0
  77. package/dist/index-BGFW-8P2.d.cts +2307 -0
  78. package/dist/index-BO6xE9YU.d.cts +1804 -0
  79. package/dist/index-BkGmlyI3.d.cts +470 -0
  80. package/dist/index-CCNJRG-P.d.cts +1095 -0
  81. package/dist/index-CGpRv5sl.d.cts +643 -0
  82. package/dist/index-C_8o--VE.d.cts +1242 -0
  83. package/dist/index-CgHqxdps.d.ts +2307 -0
  84. package/dist/index-Chbst3Jx.d.ts +1343 -0
  85. package/dist/index-Cj49F892.d.ts +470 -0
  86. package/dist/{index-tSQh-xwY.d.ts → index-CunYKLiu.d.ts} +13 -9
  87. package/dist/index-D57QRbVn.d.ts +1804 -0
  88. package/dist/index-DInQqT8Q.d.cts +66 -0
  89. package/dist/index-DInQqT8Q.d.ts +66 -0
  90. package/dist/index-Dzr13q3d.d.cts +1343 -0
  91. package/dist/index-G1uwGGWQ.d.ts +643 -0
  92. package/dist/index-szBv3496.d.ts +1242 -0
  93. package/dist/index.cjs +358 -15
  94. package/dist/index.cjs.map +1 -1
  95. package/dist/index.d.cts +17 -15
  96. package/dist/index.d.ts +17 -15
  97. package/dist/index.js +407 -64
  98. package/dist/masks-DYbE485J.d.cts +445 -0
  99. package/dist/masks-DYbE485J.d.ts +445 -0
  100. package/dist/model/index.cjs +39 -7
  101. package/dist/model/index.cjs.map +1 -1
  102. package/dist/model/index.d.cts +4685 -243
  103. package/dist/model/index.d.ts +4685 -243
  104. package/dist/model/index.js +40 -8
  105. package/dist/positional-Cptlj-xs.d.ts +287 -0
  106. package/dist/positional-DvH_sd8u.d.cts +287 -0
  107. package/dist/theory/index.cjs +101 -7
  108. package/dist/theory/index.cjs.map +1 -1
  109. package/dist/theory/index.d.cts +513 -173
  110. package/dist/theory/index.d.ts +513 -173
  111. package/dist/theory/index.js +118 -24
  112. package/package.json +16 -11
  113. package/dist/chunk-36N73KZ3.cjs +0 -246
  114. package/dist/chunk-36N73KZ3.cjs.map +0 -1
  115. package/dist/chunk-4HLLZPXT.cjs +0 -3077
  116. package/dist/chunk-4HLLZPXT.cjs.map +0 -1
  117. package/dist/chunk-7MGZ7D62.cjs +0 -498
  118. package/dist/chunk-7MGZ7D62.cjs.map +0 -1
  119. package/dist/chunk-7NKDPF74.js +0 -3077
  120. package/dist/chunk-7NKDPF74.js.map +0 -1
  121. package/dist/chunk-CAN76NCU.cjs +0 -679
  122. package/dist/chunk-CAN76NCU.cjs.map +0 -1
  123. package/dist/chunk-D2FAJBYL.js +0 -479
  124. package/dist/chunk-D2FAJBYL.js.map +0 -1
  125. package/dist/chunk-EHVEBWM5.js +0 -1449
  126. package/dist/chunk-EHVEBWM5.js.map +0 -1
  127. package/dist/chunk-FCANXBAT.cjs +0 -30
  128. package/dist/chunk-FCANXBAT.cjs.map +0 -1
  129. package/dist/chunk-FNDWXRRI.cjs +0 -479
  130. package/dist/chunk-FNDWXRRI.cjs.map +0 -1
  131. package/dist/chunk-GQSGS2N4.js +0 -173
  132. package/dist/chunk-GQSGS2N4.js.map +0 -1
  133. package/dist/chunk-HKGYCQ34.js +0 -53
  134. package/dist/chunk-HKGYCQ34.js.map +0 -1
  135. package/dist/chunk-I24MV65U.js +0 -106
  136. package/dist/chunk-I24MV65U.js.map +0 -1
  137. package/dist/chunk-KMHOICIY.js +0 -679
  138. package/dist/chunk-KMHOICIY.js.map +0 -1
  139. package/dist/chunk-LW53AHQU.cjs +0 -1117
  140. package/dist/chunk-LW53AHQU.cjs.map +0 -1
  141. package/dist/chunk-N6IHQUOX.js +0 -1
  142. package/dist/chunk-NKIBQ6PT.js +0 -30
  143. package/dist/chunk-NKIBQ6PT.js.map +0 -1
  144. package/dist/chunk-NP4NA2FB.cjs +0 -106
  145. package/dist/chunk-NP4NA2FB.cjs.map +0 -1
  146. package/dist/chunk-NVE34YGZ.cjs +0 -1449
  147. package/dist/chunk-NVE34YGZ.cjs.map +0 -1
  148. package/dist/chunk-NYYWMV2C.js +0 -327
  149. package/dist/chunk-NYYWMV2C.js.map +0 -1
  150. package/dist/chunk-Q2XUP227.js +0 -845
  151. package/dist/chunk-Q2XUP227.js.map +0 -1
  152. package/dist/chunk-Q6OP4U43.cjs +0 -327
  153. package/dist/chunk-Q6OP4U43.cjs.map +0 -1
  154. package/dist/chunk-RC6GBMCD.cjs +0 -845
  155. package/dist/chunk-RC6GBMCD.cjs.map +0 -1
  156. package/dist/chunk-RK35RIN7.js +0 -1117
  157. package/dist/chunk-RK35RIN7.js.map +0 -1
  158. package/dist/chunk-RUMU3UA6.cjs +0 -53
  159. package/dist/chunk-RUMU3UA6.cjs.map +0 -1
  160. package/dist/chunk-T64C7ZD7.cjs +0 -1
  161. package/dist/chunk-T64C7ZD7.cjs.map +0 -1
  162. package/dist/chunk-XEBG3G53.js +0 -498
  163. package/dist/chunk-XEBG3G53.js.map +0 -1
  164. package/dist/chunk-YLEMGEFH.js +0 -246
  165. package/dist/chunk-YLEMGEFH.js.map +0 -1
  166. package/dist/chunk-ZEJR4TKL.cjs +0 -173
  167. package/dist/chunk-ZEJR4TKL.cjs.map +0 -1
  168. package/dist/function-BtiZb9i9.d.ts +0 -208
  169. package/dist/function-DNugAOrt.d.cts +0 -208
  170. package/dist/index-6VR8-kit.d.ts +0 -143
  171. package/dist/index-70p168VM.d.ts +0 -192
  172. package/dist/index-Be74mcon.d.cts +0 -152
  173. package/dist/index-BtXT6UQ0.d.cts +0 -192
  174. package/dist/index-C5UBbQ4G.d.ts +0 -152
  175. package/dist/index-C83mZI1P.d.ts +0 -242
  176. package/dist/index-DXd9JikN.d.cts +0 -246
  177. package/dist/index-DXd9JikN.d.ts +0 -246
  178. package/dist/index-OG65ocOr.d.cts +0 -272
  179. package/dist/index-OG65ocOr.d.ts +0 -272
  180. package/dist/index-tJhkmQgE.d.cts +0 -143
  181. package/dist/index-y_ak9_Hi.d.cts +0 -242
  182. package/dist/styled-DIRkk9Uz.d.ts +0 -506
  183. package/dist/styled-DJbkJQfj.d.cts +0 -506
  184. package/dist/types-BN6_Q9Kl.d.cts +0 -39
  185. package/dist/types-BN6_Q9Kl.d.ts +0 -39
  186. /package/dist/{chunk-N6IHQUOX.js.map → chunk-HFPS7JFD.js.map} +0 -0
package/README.md CHANGED
@@ -1,315 +1,115 @@
1
1
  # @libraz/libcantus
2
2
 
3
- Pure-TypeScript toolkit for working with music: name notes and chords, analyze
4
- harmony, recognize what you're hearing, voice and reharmonize progressions, and
5
- generate parts (bass, countermelody, drums, rhythm) — all with no runtime
6
- dependencies.
3
+ Pure-TypeScript music theory for MIDI note events. Build and spell chords, inspect harmony, analyze keys and form, and generate parts from the same data model. The package has no runtime dependencies.
7
4
 
8
5
  [![CI](https://img.shields.io/github/actions/workflow/status/libraz/libcantus/ci.yml?branch=main&label=CI)](https://github.com/libraz/libcantus/actions)
9
6
  [![npm](https://img.shields.io/npm/v/@libraz/libcantus)](https://www.npmjs.com/package/@libraz/libcantus)
10
7
  [![codecov](https://codecov.io/gh/libraz/libcantus/branch/main/graph/badge.svg)](https://codecov.io/gh/libraz/libcantus)
11
8
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/libraz/libcantus/blob/main/LICENSE)
12
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
13
- [![Node.js](https://img.shields.io/badge/Node.js-22.x-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
14
11
  [![docs](https://img.shields.io/badge/docs-API%20reference-b5892e)](https://libraz.github.io/libcantus/)
15
12
 
16
- ## What can you do with it?
17
-
18
- - **Name and move notes** — parse `C4`, transpose it, convert to/from MIDI, spell
19
- intervals with correct enharmonics (`F#` vs `Gb`).
20
- - **Build chords and progressions** — from scale degrees, Roman numerals
21
- (`V7/V`), or lead-sheet symbols (`Cmaj7`, `F#m7b5`, `C/G`).
22
- - **Analyze harmony** — Roman-numeral analysis, harmonic function, cadence
23
- detection, and borrowed / modal-interchange chords.
24
- - **Recognize what you hear** — notes in, chord or key out (the inverse of the
25
- builders).
26
- - **Reharmonize** — tritone subs, chromatic mediants, negative harmony, modal
27
- interchange palettes.
28
- - **Voice chords** — smooth 4-voice (SATB) leading, plus drop-2/3, shell, and
29
- rootless comping styles.
30
- - **Generate parts** — bass lines, countermelodies, drums, rhythms, motifs, and
31
- whole progressions; deterministic for a given seed.
32
- - **Arrange from a DAW / MIDI file** — feed raw multi-track notes, recover the
33
- harmony, get a whole-piece analysis (with per-note conflicts), and generate the
34
- missing parts against it.
35
- - **Work with pitch as sound** — frequencies, cents, EDO, and just intonation.
36
-
37
- The musical **values** — notes, chords, keys, progressions — come in two
38
- interchangeable styles: a **fluent, immutable class API** (`Note`, `Chord`,
39
- `Key`, `Progression`) that reads like music theory, and the underlying
40
- **tree-shakeable pure functions**. Operations over **collections and timelines**
41
- (part generation and whole-arrangement analysis) work on arrays of note events,
42
- so — like `rhythm`, `drums`, and `detectKey` — they are exposed as functions.
13
+ ## What it does
43
14
 
44
- ## Install
45
-
46
- ```sh
47
- yarn add @libraz/libcantus
48
- ```
49
-
50
- ## Subpath imports
51
-
52
- The package root exports everything. To pull in a single layer, import its
53
- subpath instead:
54
-
55
- ```ts
56
- import { Chord, Key, Note } from '@libraz/libcantus/model'; // class API
57
- import { majorKey, makeChord } from '@libraz/libcantus/theory'; // scales, chords
58
- import { generateDrums, generateProgression } from '@libraz/libcantus/generate';
59
- import { analyzeArrangement, detectKey } from '@libraz/libcantus/analyze';
60
- import { parseNote, edo } from '@libraz/libcantus/core'; // pitch, meter, tuning
61
- ```
62
-
63
- The layers are `core`, `theory`, `analyze`, `generate`, and `model`.
64
-
65
- ## Quick start
66
-
67
- The class API chains immutably and carries key context, so analysis needs no
68
- repetition:
69
-
70
- ```ts
71
- import { Chord, Key, Note } from '@libraz/libcantus';
72
-
73
- const c = Key.major('C');
74
-
75
- c.chord(4, 'dom7').pitchClasses(); // [2, 5, 7, 11] (G7)
76
- c.roman('V7/V').voice(); // [ ...SATB MIDI ] (secondary dominant, voiced)
77
- Note.of('C4').transpose(7).name; // 'G4'
78
-
79
- // A ii–V–I, built and analyzed in one line:
80
- c.chord(1, 'min').progressionTo(c.chord(4, 'dom7'), c.chord(0, 'maj')).analyze();
81
- // { chords: [...functional analysis...], cadence: 'authentic' }
82
-
83
- Chord.detect([60, 64, 67])[0].quality; // 'maj'
84
- ```
85
-
86
- Every class wraps a plain object (`Chord.data`, `Note.data`) and delegates to the
87
- pure functions, so the two styles interoperate freely. The same task with the
88
- functional API:
15
+ It sits between software that already holds notes or chord symbols — a DAW project, a MIDI parser, a practice tool — and what those notes mean harmonically. Give it note events and it recovers the harmony; give it that harmony back and it writes parts against it:
89
16
 
90
17
  ```ts
91
- import { chordFromDegree, chordPitchClasses, classifyInterval, majorKey } from '@libraz/libcantus';
92
-
93
- const cMajor = majorKey(0);
94
-
95
- classifyInterval(7); // IntervalQuality.PerfectConsonance
96
- chordPitchClasses(chordFromDegree(4, 'dom7', cMajor)); // [2, 5, 7, 11] (G7)
97
- ```
18
+ import { Composer, Score } from '@libraz/libcantus';
98
19
 
99
- ## Name and move notes
20
+ // Four bars of block chords, as a DAW would hand them over:
21
+ const harmony = [[48, 60, 64, 67], [41, 60, 65, 69], [43, 59, 62, 65], [48, 60, 64, 67]].flatMap(
22
+ (pitches, bar) => pitches.map((pitch) => ({ pitch, startBeat: bar * 4, durationBeat: 4 })),
23
+ );
100
24
 
101
- Parse and format notes, convert to MIDI, and spell intervals so enharmonics the
102
- pitch-class layer can't tell apart come out right:
25
+ const chords = Score.of(harmony).timeline();
26
+ chords.roman().map((entry) => entry.roman); // ['I', 'IV', 'V7', 'I']
27
+ chords.cadences().at(-1)?.cadence.type; // 'authentic'
103
28
 
104
- ```ts
105
- import { Interval, Note } from '@libraz/libcantus';
106
-
107
- Note.of('C4').transpose(7).name; // 'G4'
108
- Note.of('C4').midi; // 60
109
- Interval.between(Note.of('C4'), Note.of('F#4')).name; // 'A4' (augmented fourth)
110
- Interval.between(Note.of('C4'), Note.of('Gb4')).name; // 'd5' (diminished fifth)
29
+ // A walking bass over the harmony that was just recovered:
30
+ Composer.of({ key: chords.key, bpm: 120, seed: 1 }).bass(chords, { style: 'walking' }).notes;
31
+ // 16 notes: [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 100 }, ...]
111
32
  ```
112
33
 
113
- ## Keys and scales
114
-
115
- A `KeyScale` is a root pitch class plus a 12-bit `modeMask12` (bit `n` set means
116
- pitch class `(rootPc + n) % 12` is in the scale). `majorKey`, `minorKey`, and
117
- `scaleByName` cover the modes, pentatonics, blues, whole-tone, and octatonic
118
- scales; `MAJOR_MASK` / `NATURAL_MINOR_MASK` let you define custom keys.
119
-
120
- `nearestScaleTone` snaps a pitch to the closest in-scale MIDI pitch (preferring
121
- the lower on a tie) — handy when constraining generated notes to a key.
122
-
123
- ## Build chords and progressions
34
+ Chord boundaries are searched for rather than assumed, and so is the key, so a piece that modulates is not read against the key it started in.
124
35
 
125
- From scale degrees, Roman numerals, or lead-sheet symbols — and back again:
36
+ What each layer covers:
126
37
 
127
- ```ts
128
- import { Chord, Key } from '@libraz/libcantus';
129
-
130
- const c = Key.major('C');
38
+ - **[Pitch and notation](docs/en/pitch-and-notation.md)** — spelled notes and intervals, MIDI conversion, note names read and written in English, German, Japanese, Italian or fixed-do, and line spelling solved as one path instead of note by note. Every text parser has a non-throwing sibling (`tryParseNote`, `tryParseInterval`, `tryParseChordSymbol`, `tryParseKeyName`, `tryParseTimeSignature`, and `tryParse` on `Note`, `Interval`, `Key`, `Chord` and `Meter`), so a text field needs no `try`/`catch` per keystroke.
39
+ - **[Harmony](docs/en/harmony.md)** — chords as structured values, scales including modes, pentatonics and the `WORLD_SCALES` set, Roman numerals and function, voicing, figured bass, and the part-writing and species-counterpoint checkers that report a violation with the voice it happened in and the reason.
40
+ - **[Analysis](docs/en/analysis.md)** — chord and key detection over note events, timelines and cadences, prolongational reduction, phrases, sections, hypermeter, motifs, and arrangement reports.
41
+ - **[Generation](docs/en/generation.md)** — progressions, motifs, rhythms, drums, bass and counter-melody, all drawing on one `GenerationContext`: a project seed, three additive complexity dials (rhythmic, harmonic, ornament), a separate difficulty ceiling, the tempo, and the instrument each part is written for. Same context, same output.
42
+ - **[Time and arrangement](docs/en/time-and-arrangement.md)** — meter, tempo, positions in bars and beats, and analysis across several tracks at once.
43
+ - **[Class API](docs/en/api-reference.md)** — the same theory as one immutable class per thing the library works with, `Score`, `Timeline` and `Composer` included, each a thin skin over the functions above. Reach for a function or a class as it suits the call site; the answers are the same.
131
44
 
132
- c.roman('V7/V').symbol(); // 'D7' (a secondary dominant)
133
- c.chord(4, 'dom7').roman(); // 'V7'
134
- Chord.parse('F#m7b5').pitchClasses(); // [0, 4, 6, 9]
135
- ```
45
+ Answers say why they were reached. `analyzeChord`, `detectCadence` and `explainRoman` carry a `rationale`, `detectKey` attaches one on request, and each can report the readings it turned down as `alternatives`. Where the input cannot settle a question, the field comes back `null` rather than a plausible guess — grading a cadence perfect or imperfect needs a voicing, because only a voicing says what is in the soprano.
136
46
 
137
- Chord vocabulary spans triads through thirteenths — `dim7`, `m7b5`, `minMaj7`,
138
- `aug7`, sixths, and altered dominants included.
47
+ Spelling is kept wherever it decides the answer. A diminished fifth and an augmented fourth are the same distance in pitch classes but not the same interval, so the counterpoint and part-writing checkers take spelled notes rather than numbers.
139
48
 
140
- Or generate a progression from a style preset (a collection-level operation, so
141
- it stays functional):
49
+ Seven worked guides start from the data an application already has: [DAW workflow](docs/en/use-cases/daw-workflow.md), [piece analysis](docs/en/use-cases/piece-analysis.md), [modulation report](docs/en/use-cases/modulation-report.md), [harmony exercise checker](docs/en/use-cases/harmony-exercise-checker.md), [generative arrangement](docs/en/use-cases/generative-arrangement.md), [chord chart import](docs/en/use-cases/chord-chart-import.md), and [part preparation](docs/en/use-cases/part-preparation.md).
142
50
 
143
- ```ts
144
- import { generateProgression, majorKey } from '@libraz/libcantus';
51
+ ## What it doesn't do
145
52
 
146
- // One chord per bar, secondary dominants inserted where they fit:
147
- generateProgression({ key: majorKey(0), style: 'idol', bars: 8, reharmonize: true, seed: 1 });
148
- ```
53
+ - **No I/O, notation or audio.** No MIDI file reader or writer, no score rendering, no audio analysis, no playback. Bring your own parser and hand it note events. If that layer is what you need, [libsonare](https://github.com/libraz/libsonare) covers audio analysis, mastering, synthesis and SMF I/O; the two share no code and neither requires the other.
54
+ - **No microtonal analysis.** Frequencies, cents, equal divisions of the octave and just-intonation ratios live in `core`, but everything above the pitch layer runs on twelve pitch classes. Music organised in smaller steps than a semitone is out of reach, which is also why the maqāmāt built on half-flat degrees are left out of `WORLD_SCALES` rather than rounded to a twelve-tone neighbour.
55
+ - **No modal systems.** `WORLD_SCALES` records the pitch material a tradition names — a thāt, a maqām's set, a Japanese pentatonic — and not the system built on it: ascent and descent forms, the notes a phrase leans on, and the phrase grammar have no place in a mask.
56
+ - **No assumption that the material is tonal.** Roman numerals and functional harmony presuppose the common practice, and `supportsFunctionalHarmony` says whether a named scale admits that reading at all — `'dorian'` does, `'miyakoBushi'` does not.
57
+ - **No corpus.** Nothing is bundled to run statistics over.
58
+ - **Known gaps in functional harmony.** `functionOf` answers from a chord and a key alone, so a cadential six-four reads there as an inverted tonic; the dominant reading of it belongs to the layers that see time, and `detectCadence` gives it when the chord before the dominant is passed as `approach`.
149
59
 
150
- ## Analyze harmony
60
+ ## Requirements
151
61
 
152
- Turn chords into Roman-numeral analysis with function, cadences, and modal
153
- interchange — in major and minor, respecting inversions:
154
-
155
- ```ts
156
- import { Chord, Key } from '@libraz/libcantus';
157
-
158
- // A minor iv in a major key reads as a borrowed subdominant:
159
- Chord.of('F', 'min').analyze(Key.major('C'));
160
- // { function: 'subdominant', borrowed: true, source: 'parallelMinor', roman: 'iv' }
161
- ```
62
+ Node.js >= 22.
162
63
 
163
- ## Recognize what you hear
164
-
165
- Notes in, chord or key out — the inverse of the builders:
166
-
167
- ```ts
168
- import { Chord, detectKey } from '@libraz/libcantus';
169
-
170
- Chord.detect([60, 64, 67])[0].symbol(); // 'C'
171
- Chord.detectBest([60, 63, 67, 70])?.symbol(); // 'Cm7'
172
- detectKey([0, 0, 0, 4, 7])[0]; // C major, best fit (key ranking stays functional)
173
- ```
174
-
175
- ## Spell chords and scales
176
-
177
- A `Key` carries a spelled tonic, so the pitch-class core produces letter names,
178
- correct in major and minor:
179
-
180
- ```ts
181
- import { Chord, Key } from '@libraz/libcantus';
182
-
183
- Key.named('harmonicMinor', 'A').noteNames(); // ['A', 'B', 'C', 'D', 'E', 'F', 'G#']
184
- Key.minor('E').noteNames(); // ['E', 'F#', 'G', 'A', 'B', 'C', 'D']
185
-
186
- // Chords spell in a key's context too:
187
- Key.major('C').chord(4, 'dom7').spell().map((n) => n.name); // ['G', 'B', 'D', 'F']
188
- ```
189
-
190
- ## Reharmonize
191
-
192
- Reflect a chord through negative harmony on the class, or list substitution
193
- candidates — tritone, relative, borrowed, and chromatic-mediant subs, plus
194
- modal-interchange palettes — with the functions:
195
-
196
- ```ts
197
- import { Chord, Key, majorKey, parseChordSymbol, substituteChord } from '@libraz/libcantus';
198
-
199
- Key.major('C').chord(4, 'dom7').negativeHarmony().symbol(); // 'Dm7b5'
200
-
201
- // Substitution/palette search returns lists, so it stays functional:
202
- substituteChord(parseChordSymbol('G7'), majorKey(0));
203
- // [{ chord: Db7, type: 'tritone', ... }, ...]
204
- ```
205
-
206
- ## Choose scales and tensions
207
-
208
- Find scales compatible with a chord and its available tensions and avoid notes
209
- on the class; get a continuity-optimized scale choice across a whole set of
210
- changes with `scalesForChanges`:
211
-
212
- ```ts
213
- import { Chord } from '@libraz/libcantus';
64
+ ## Install
214
65
 
215
- Chord.of('C', 'dom7').scales()[0]; // { name: 'mixolydian', rootPc: 0 }
216
- Chord.of('C', 'maj7').tensions('ionian'); // [2, 9] (9 and 13; the 11 is an avoid note)
66
+ ```sh
67
+ yarn add @libraz/libcantus
217
68
  ```
218
69
 
219
- ## Voice chords
70
+ ## Quick start
220
71
 
221
- Realize a progression into smooth 4-voice (SATB) MIDI voicings with minimal
222
- motion, or voice a single chord in a comping style (drop-2/3, shell, rootless):
72
+ The theory lives in tree-shakeable pure functions. On top of them sits an immutable class API — one class per thing the library works with, from a single `Note`, `Interval` or `Chord` up to the `Score`, `Timeline`, `Arrangement` and `Composer` that carry a whole piece — that reads the way theory is spoken:
223
73
 
224
74
  ```ts
225
75
  import { Chord, Key } from '@libraz/libcantus';
226
76
 
227
- const c = Key.major('C');
77
+ const key = Key.major('C');
78
+ const dominant = key.chord(5, 'dom7');
228
79
 
229
- // A whole progression, voiced with minimal motion:
230
- c.chord(0, 'maj').progressionTo(c.chord(5, 'maj'), c.chord(4, 'dom7'), c.chord(0, 'maj')).voice();
231
- // [[...], [...], [...], [...]] (one ascending pitch per voice)
232
-
233
- // A single chord in a shell comping voicing:
234
- Chord.of('C', 'maj7').styledVoicing({ style: 'shell' }); // root, third, seventh
80
+ dominant.symbol(); // 'G7'
81
+ dominant.analyze(key).roman; // 'V7'
82
+ Chord.parse('C7(b9,#11)').pitchClasses(); // [0, 1, 4, 6, 7, 10]
235
83
  ```
236
84
 
237
- `voiceLeadingCost` and `nextVoicing` let you steer the leading, and the
238
- `counterpoint` predicates (parallel/hidden perfects, spacing, voice crossing,
239
- leading-tone resolution, …) let you validate it.
85
+ The functions are the library; every class is a thin skin over them. A class wraps a plain object it exposes as `.data`, and the functions return data a class can be built from, so neither side is a walled garden and the two give the same answers. What a class adds is holding a value together with its context, so a chain of calls does not restate the same facts: a `Score` carries its notes with their meter, tempo, and key, and a `Composer` carries the key, tempo, and seed one piece is written under.
240
86
 
241
- ## Generate parts
87
+ ## Import paths
242
88
 
243
- Seeded, deterministic generators for melody and accompaniment:
89
+ The package root exports everything. To pull in a single layer, import its subpath instead:
244
90
 
245
91
  ```ts
246
- import {
247
- generateBassLine, generateCounterMelody, generateDrums, generateRhythm,
248
- generateMotif, majorKey, parseTimeSignature,
249
- } from '@libraz/libcantus';
250
-
251
- generateRhythm(parseTimeSignature('4/4'), { seed: 1, density: 0.5 }); // strong-beat-weighted onsets
252
- const motif = generateMotif({ key: majorKey(0), bars: 2, contour: 'arch', seed: 1 });
253
- motif.notes.length > 0; // true — a deterministic short melodic cell
254
- ```
255
-
256
- `humanize`, `extractGrooveTemplate`, and `applyGrooveTemplate` add a meter-aware
257
- feel — or capture the feel of one performance and transplant it onto another.
258
-
259
- ## Arrange from a DAW or MIDI file
260
-
261
- The arrangement layer takes raw multi-track `NoteEvent`s, recovers the harmony,
262
- then analyses and generates against it:
263
-
264
- ```ts
265
- import {
266
- analyzeArrangement, chordTimelineFromNotes, generateBassLine, generateCounterMelody,
267
- } from '@libraz/libcantus';
268
-
269
- // Infer a chord progression (and the key) from played notes:
270
- const { timeline, key } = chordTimelineFromNotes(melodyAndChordNotes);
271
-
272
- // Whole-piece analysis: inferred chords, cadences, per-note theory labels, and
273
- // notes that clash with the sounding harmony (with reasons and suggestions):
274
- const report = analyzeArrangement([
275
- { role: 'melody', notes: melodyNotes },
276
- { role: 'harmony', notes: chordNotes },
277
- ]);
278
- report.conflicts; // [{ beat, trackName, pitch, safety, reasons, rationale }, ...]
279
-
280
- // Generate the missing parts from the recovered timeline:
281
- generateBassLine({ segments: timeline.segments, key, style: 'walking', seed: 1 });
282
- generateCounterMelody({ melody: melodyNotes, timeline, key, register: 'below' });
92
+ import { parseNote, edo } from '@libraz/libcantus/core'; // pitch, meter, tempo, tuning
93
+ import { majorKey, makeChord } from '@libraz/libcantus/theory'; // scales, chords, voicing, rules
94
+ import { analyzeArrangement, detectKey } from '@libraz/libcantus/analyze';
95
+ import { generateDrums, generateProgression } from '@libraz/libcantus/generate';
96
+ import { Chord, Key, Note } from '@libraz/libcantus/model'; // class API
283
97
  ```
284
98
 
285
- `harmonizeMelody` goes the other way — given a bare melody, it searches for the
286
- best key, transpose, and chord path (with optional reharmonization) to harmonize
287
- it.
99
+ Both ESM and CommonJS builds ship for every path.
288
100
 
289
- Note events shared across the arrangement and generation modules use one type,
290
- `NoteEvent` (`{ pitch, startBeat, durationBeat, velocity? }`, MIDI pitch in
291
- quarter-note beats). Seeded generators (`bass`, `groove`, `countermelody`,
292
- `rhythm`, `drums`, `motif`, `progression`) are deterministic for a given seed.
101
+ ## Documentation
293
102
 
294
- ## Work with pitch as sound
103
+ Start here: [Introduction](docs/en/introduction.md), [Getting started](docs/en/getting-started.md), [Use cases](docs/en/use-cases/index.md).
295
104
 
296
- Frequencies, cents, EDO, and just intonation — for tuning, microtonality, and
297
- analysis:
105
+ Domain guides: [Pitch and notation](docs/en/pitch-and-notation.md), [Scales and modes](docs/en/scales-and-modes.md), [Harmony](docs/en/harmony.md), [Key relations and modulation](docs/en/key-relations-and-modulation.md), [Voicing](docs/en/voicing.md), [Counterpoint and part-writing](docs/en/counterpoint-and-part-writing.md), [Time and arrangement](docs/en/time-and-arrangement.md), [Analysis](docs/en/analysis.md), [Melody and motifs](docs/en/melody-and-motifs.md), [Rhythm and groove](docs/en/rhythm-and-groove.md), [Generation](docs/en/generation.md), [Reharmonization](docs/en/reharmonization.md), [Instruments and playability](docs/en/instruments-and-playability.md), [Tuning and frequency](docs/en/tuning-and-frequency.md).
298
106
 
299
- ```ts
300
- import { frequencyOf, edo, justDeviationCents } from '@libraz/libcantus';
301
- ```
107
+ Cross-cutting: [Determinism and seeding](docs/en/determinism-and-seeding.md), [Errors and validation](docs/en/errors-and-validation.md), [Performance](docs/en/performance.md), [Interoperability](docs/en/interoperability.md).
302
108
 
303
- Meter helpers (`TimeSignature`, `parseTimeSignature`, `beatsPerBar`,
304
- `metricWeight`, `isStrongBeat`, `tuplet`) cover simple and compound meters and
305
- back the accent-aware generators.
306
-
307
- ## Documentation
109
+ Reference: [API reference](docs/en/api-reference.md), [Glossary](docs/en/glossary.md), [Questions and limitations](docs/en/faq.md).
308
110
 
309
- Full API reference — every export with signatures, categorized by domain and
310
- with runnable examples — is generated from the source and published at
311
- **[libraz.github.io/libcantus](https://libraz.github.io/libcantus/)**.
111
+ Every `ts` example in these guides is executed by the test suite, and an expected value written as a trailing comment is checked against what the call returns. The generated TypeDoc reference is written to `docs/api` and is separate from the hand-authored guides.
312
112
 
313
113
  ## License
314
114
 
315
- Apache-2.0
115
+ [@libraz/libcantus](https://github.com/libraz/libcantus) is released under the [Apache License 2.0](LICENSE).
package/README_ja.md ADDED
@@ -0,0 +1,115 @@
1
+ # @libraz/libcantus
2
+
3
+ MIDI ノートイベントを扱う、TypeScript 製の音楽理論ライブラリです。コードの組み立てと綴り、和声とキーの解析、曲の形式の読み取り、パート生成を同じデータモデルで行えます。実行時依存はありません。
4
+
5
+ [![CI](https://img.shields.io/github/actions/workflow/status/libraz/libcantus/ci.yml?branch=main&label=CI)](https://github.com/libraz/libcantus/actions)
6
+ [![npm](https://img.shields.io/npm/v/@libraz/libcantus)](https://www.npmjs.com/package/@libraz/libcantus)
7
+ [![codecov](https://codecov.io/gh/libraz/libcantus/branch/main/graph/badge.svg)](https://codecov.io/gh/libraz/libcantus)
8
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/libraz/libcantus/blob/main/LICENSE)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
11
+ [![docs](https://img.shields.io/badge/docs-API%20reference-b5892e)](https://libraz.github.io/libcantus/)
12
+
13
+ ## できること
14
+
15
+ すでにノートやコード記号を持っているソフトウェア(DAW のプロジェクト、MIDI パーサー、練習支援ツールなど)と、その音が和声的に何を意味するかとの間を埋めます。ノートイベントを渡せば和声が求まり、その和声を渡せばそれに沿ったパートが書けます。
16
+
17
+ ```ts
18
+ import { Composer, Score } from '@libraz/libcantus';
19
+
20
+ // DAW から渡ってくる形の、4 小節のブロックコード:
21
+ const harmony = [[48, 60, 64, 67], [41, 60, 65, 69], [43, 59, 62, 65], [48, 60, 64, 67]].flatMap(
22
+ (pitches, bar) => pitches.map((pitch) => ({ pitch, startBeat: bar * 4, durationBeat: 4 })),
23
+ );
24
+
25
+ const chords = Score.of(harmony).timeline();
26
+ chords.roman().map((entry) => entry.roman); // ['I', 'IV', 'V7', 'I']
27
+ chords.cadences().at(-1)?.cadence.type; // 'authentic'
28
+
29
+ // 求まった和声の上に、ウォーキングベースを書く:
30
+ Composer.of({ key: chords.key, bpm: 120, seed: 1 }).bass(chords, { style: 'walking' }).notes;
31
+ // 16 音: [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 100 }, ...]
32
+ ```
33
+
34
+ コードの境界は決め打ちせずに探索し、キーも同様に探します。転調する曲を、冒頭のキーのまま読み続けることはありません。
35
+
36
+ 各レイヤーが受け持つ範囲は次のとおりです。
37
+
38
+ - **[音高と記譜](docs/ja/pitch-and-notation.md)** — 綴りを保った音名と音程、MIDI 変換、英語・ドイツ語・日本語・イタリア語・固定ドでの読み書き、そして 1 音ずつではなく声部全体を 1 本の経路として解く綴り付け。テキストのパーサーにはいずれも例外を投げない対 (`tryParseNote`、`tryParseInterval`、`tryParseChordSymbol`、`tryParseKeyName`、`tryParseTimeSignature`、および `Note`・`Interval`・`Key`・`Chord`・`Meter` の `tryParse`) があるので、入力欄の 1 打鍵ごとに `try`/`catch` を書く必要はありません。
39
+ - **[和声](docs/ja/harmony.md)** — 構造を持つ値としてのコード、教会旋法やペンタトニックに加えて `WORLD_SCALES` を含むスケール、ローマ数字と和声機能、ヴォイシング、数字付き低音、そして違反した声部と理由まで返す声部書法・種目対位法のチェッカー。
40
+ - **[解析](docs/ja/analysis.md)** — ノートイベントからのコード・キー検出、タイムラインとカデンツ、和声的な還元、フレーズ、セクション、ハイパーメーター、モチーフ、アレンジ全体のレポート。
41
+ - **[生成](docs/ja/generation.md)** — プログレッション、モチーフ、リズム、ドラム、ベース、対旋律。いずれも 1 つの `GenerationContext` を参照します。プロジェクトのシード、加算的な 3 つの複雑さのダイヤル(リズム・和声・装飾)、それとは別枠の難易度の上限、テンポ、各パートの対象楽器がそこに入ります。同じコンテキストからは同じ結果が出ます。
42
+ - **[時間とアレンジ](docs/ja/time-and-arrangement.md)** — 拍子、テンポ、小節と拍による位置、複数トラックをまたぐ解析。
43
+ - **[クラス API](docs/ja/api-reference.md)** — 同じ理論を、ライブラリが扱う対象ごとの不変クラスとして提供します。`Score`、`Timeline`、`Composer` も含め、いずれも上記の関数の薄い外皮です。呼び出し側の都合で関数とクラスのどちらを使ってもよく、返る答えは同じです。
44
+
45
+ 答えには、そう読んだ理由が付きます。`analyzeChord`、`detectCadence`、`explainRoman` は `rationale` を必ず返し、`detectKey` は要求があれば付けます。いずれも、退けた解釈を `alternatives` として報告できます。渡された情報だけでは決まらない場合、それらしい答えを作らずに `null` を返します。カデンツが完全か不完全かはヴォイシングがなければ決まりません。ソプラノに何があるかはヴォイシングだけが答えられるからです。
46
+
47
+ 答えを左右する場面では、綴りの情報を落としません。減 5 度と増 4 度はピッチクラス上の距離が同じでも同じ音程ではないので、声部書法と対位法のチェッカーは数値ではなく綴られた音を受け取ります。
48
+
49
+ アプリケーションが手元に持っているデータから始まるガイドが 7 本あります。[DAW との連携](docs/ja/use-cases/daw-workflow.md)、[曲の解析](docs/ja/use-cases/piece-analysis.md)、[転調レポート](docs/ja/use-cases/modulation-report.md)、[和声課題のチェック](docs/ja/use-cases/harmony-exercise-checker.md)、[生成によるアレンジ](docs/ja/use-cases/generative-arrangement.md)、[コード譜の取り込み](docs/ja/use-cases/chord-chart-import.md)、[パートの準備](docs/ja/use-cases/part-preparation.md)です。
50
+
51
+ ## やらないこと
52
+
53
+ - **入出力・記譜・音声を扱いません。** MIDI ファイルの読み書き、楽譜の描画、音声解析、再生はありません。パーサーは各自で用意し、ノートイベントとして渡してください。その層こそが必要なら、[libsonare](https://github.com/libraz/libsonare) が音声解析、マスタリング、合成、SMF 入出力を扱います。両者はコードを共有せず、どちらも相手を必要としません。
54
+ - **微分音の解析はしません。** 周波数、セント、オクターブの等分割、純正律の比は `core` にありますが、音高より上の層はすべて 12 のピッチクラスで動きます。半音より細かい単位で組み立てられた音楽は範囲外です。半フラットの音度を持つマカームを 12 音の近い音で代用せず `WORLD_SCALES` から外しているのも、同じ理由です。
55
+ - **旋法体系そのものは扱いません。** `WORLD_SCALES` が収録するのは、thāt やマカーム、日本の音階といった伝統が名を与えた音組織であって、その上に立つ体系ではありません。上行形と下行形、フレーズが寄りかかる音、旋律型の文法は、マスクには入りません。
56
+ - **調性を前提にしません。** ローマ数字と機能和声は西洋の慣習を前提とします。その読み方が適用できるスケールかどうかは `supportsFunctionalHarmony` が答えます(`'dorian'` は真、`'miyakoBushi'` は偽)。
57
+ - **コーパスは持ちません。** 統計を取るためのデータは同梱していません。
58
+ - **機能和声には既知の穴があります。** `functionOf` は和音と調だけから答えるため、終止四六の和音はその層では主和音の転回として読まれます。属和音としての読みは時間軸を見る層のものであり、属和音の前の和音を `approach` として渡したときに `detectCadence` がそれを示します。
59
+
60
+ ## 要件
61
+
62
+ Node.js >= 22。
63
+
64
+ ## インストール
65
+
66
+ ```sh
67
+ yarn add @libraz/libcantus
68
+ ```
69
+
70
+ ## 最初の例
71
+
72
+ 理論の本体はツリーシェイク可能な純粋関数にあります。その上に、理論を語るときの言い方に近い不変のクラス API が乗っています。ライブラリが扱う対象ごとに1つのクラスがあり、単体の `Note`、`Interval`、`Chord` から、曲全体を受け持つ `Score`、`Timeline`、`Arrangement`、`Composer` までが揃います。
73
+
74
+ ```ts
75
+ import { Chord, Key } from '@libraz/libcantus';
76
+
77
+ const key = Key.major('C');
78
+ const dominant = key.chord(5, 'dom7');
79
+
80
+ dominant.symbol(); // 'G7'
81
+ dominant.analyze(key).roman; // 'V7'
82
+ Chord.parse('C7(b9,#11)').pitchClasses(); // [0, 1, 4, 6, 7, 10]
83
+ ```
84
+
85
+ 本体は関数で、クラスはいずれもその薄い外皮です。クラスは `.data` でプレーンな値を公開し、関数が返したデータからクラスを作れます。どちらかが閉じた世界になることはなく、返す答えも同じです。クラスが足すのは、値とその文脈をひとまとめに保持することです。呼び出しを連ねるときに同じ事実を書き直さずに済みます。`Score` は音符と拍子・テンポ・調をまとめて持ち、`Composer` は 1 曲を書くときの調・テンポ・シードを持ちます。
86
+
87
+ ## インポートパス
88
+
89
+ ルートからすべてを export しています。1 つのレイヤーだけを取り込みたい場合は、サブパスを使ってください。
90
+
91
+ ```ts
92
+ import { parseNote, edo } from '@libraz/libcantus/core'; // 音高、拍子、テンポ、音律
93
+ import { majorKey, makeChord } from '@libraz/libcantus/theory'; // スケール、コード、ヴォイシング、規則
94
+ import { analyzeArrangement, detectKey } from '@libraz/libcantus/analyze';
95
+ import { generateDrums, generateProgression } from '@libraz/libcantus/generate';
96
+ import { Chord, Key, Note } from '@libraz/libcantus/model'; // クラス API
97
+ ```
98
+
99
+ いずれのパスにも ESM と CommonJS の両方のビルドがあります。
100
+
101
+ ## ドキュメント
102
+
103
+ 最初に読むページ: [概要](docs/ja/introduction.md)、[使い始める](docs/ja/getting-started.md)、[ユースケース](docs/ja/use-cases/index.md)。
104
+
105
+ 各領域のガイド: [音高と記譜](docs/ja/pitch-and-notation.md)、[スケールとモード](docs/ja/scales-and-modes.md)、[和声](docs/ja/harmony.md)、[調関係と転調](docs/ja/key-relations-and-modulation.md)、[ボイシング](docs/ja/voicing.md)、[対位法と和声課題](docs/ja/counterpoint-and-part-writing.md)、[時間とアレンジ](docs/ja/time-and-arrangement.md)、[解析](docs/ja/analysis.md)、[旋律とモチーフ](docs/ja/melody-and-motifs.md)、[リズムとグルーヴ](docs/ja/rhythm-and-groove.md)、[生成](docs/ja/generation.md)、[リハーモナイズ](docs/ja/reharmonization.md)、[楽器と演奏可能性](docs/ja/instruments-and-playability.md)、[音律と周波数](docs/ja/tuning-and-frequency.md)。
106
+
107
+ 横断的な話題: [決定性とシード](docs/ja/determinism-and-seeding.md)、[エラーと検証](docs/ja/errors-and-validation.md)、[パフォーマンス](docs/ja/performance.md)、[相互運用](docs/ja/interoperability.md)。
108
+
109
+ リファレンス: [API リファレンス](docs/ja/api-reference.md)、[用語集](docs/ja/glossary.md)、[FAQ と制限](docs/ja/faq.md)。
110
+
111
+ これらのガイドの `ts` の例はすべてテストスイートで実行され、末尾コメントに書いた期待値は実際の返り値と照合されます。生成される TypeDoc のリファレンスは `docs/api` に出力され、手書きガイドとは分かれています。
112
+
113
+ ## ライセンス
114
+
115
+ [@libraz/libcantus](https://github.com/libraz/libcantus) は [Apache License 2.0](LICENSE) で提供します。
@@ -1,5 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
+ var _chunkMXO72PLYcjs = require('../chunk-MXO72PLY.cjs');
3
4
 
4
5
 
5
6
 
@@ -7,8 +8,6 @@
7
8
 
8
9
 
9
10
 
10
- var _chunkRC6GBMCDcjs = require('../chunk-RC6GBMCD.cjs');
11
- require('../chunk-36N73KZ3.cjs');
12
11
 
13
12
 
14
13
 
@@ -26,12 +25,9 @@ require('../chunk-36N73KZ3.cjs');
26
25
 
27
26
 
28
27
 
29
- var _chunkCAN76NCUcjs = require('../chunk-CAN76NCU.cjs');
28
+ var _chunk3JXCW6DXcjs = require('../chunk-3JXCW6DX.cjs');
30
29
 
31
30
 
32
- var _chunkQ6OP4U43cjs = require('../chunk-Q6OP4U43.cjs');
33
- require('../chunk-FNDWXRRI.cjs');
34
- require('../chunk-7MGZ7D62.cjs');
35
31
 
36
32
 
37
33
 
@@ -54,9 +50,60 @@ require('../chunk-7MGZ7D62.cjs');
54
50
 
55
51
 
56
52
 
53
+ var _chunkOE6WK2Y2cjs = require('../chunk-OE6WK2Y2.cjs');
54
+ require('../chunk-K4ZJUGF4.cjs');
57
55
 
58
56
 
57
+ var _chunkUADYAYATcjs = require('../chunk-UADYAYAT.cjs');
58
+ require('../chunk-Q2WGKJNN.cjs');
59
59
 
60
60
 
61
- exports.NoteSafety = _chunkQ6OP4U43cjs.NoteSafety; exports.analyzeArrangement = _chunkRC6GBMCDcjs.analyzeArrangement; exports.analyzeChord = _chunkCAN76NCUcjs.analyzeChord; exports.analyzeVoice = _chunkRC6GBMCDcjs.analyzeVoice; exports.borrowedSource = _chunkCAN76NCUcjs.borrowedSource; exports.chordTimelineFromChords = _chunkRC6GBMCDcjs.chordTimelineFromChords; exports.chordTimelineFromNotes = _chunkRC6GBMCDcjs.chordTimelineFromNotes; exports.chordToRoman = _chunkCAN76NCUcjs.chordToRoman; exports.detectCadence = _chunkCAN76NCUcjs.detectCadence; exports.detectCadences = _chunkRC6GBMCDcjs.detectCadences; exports.detectChord = _chunkCAN76NCUcjs.detectChord; exports.detectChordBest = _chunkCAN76NCUcjs.detectChordBest; exports.detectKey = _chunkCAN76NCUcjs.detectKey; exports.detectKeyBest = _chunkCAN76NCUcjs.detectKeyBest; exports.detectKeyFromNotes = _chunkCAN76NCUcjs.detectKeyFromNotes; exports.functionOf = _chunkCAN76NCUcjs.functionOf; exports.isBorrowedChord = _chunkCAN76NCUcjs.isBorrowedChord; exports.isDiatonic = _chunkCAN76NCUcjs.isDiatonic; exports.isMinorKey = _chunkCAN76NCUcjs.isMinorKey; exports.parallelKey = _chunkCAN76NCUcjs.parallelKey; exports.romanToChord = _chunkCAN76NCUcjs.romanToChord; exports.secondaryDominant = _chunkCAN76NCUcjs.secondaryDominant; exports.tensionCurve = _chunkRC6GBMCDcjs.tensionCurve; exports.tensionCurveFrom = _chunkRC6GBMCDcjs.tensionCurveFrom; exports.toVoiceNotes = _chunkRC6GBMCDcjs.toVoiceNotes;
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+ exports.MODAL_SCALE_NAMES = _chunkOE6WK2Y2cjs.MODAL_SCALE_NAMES; exports.NoteSafety = _chunkUADYAYATcjs.NoteSafety; exports.analyzeArrangement = _chunk3JXCW6DXcjs.analyzeArrangement; exports.analyzeChord = _chunkOE6WK2Y2cjs.analyzeChord; exports.analyzeVoice = _chunk3JXCW6DXcjs.analyzeVoice; exports.augmentedSixthChord = _chunkOE6WK2Y2cjs.augmentedSixthChord; exports.augmentedSixthFromPitchClasses = _chunkOE6WK2Y2cjs.augmentedSixthFromPitchClasses; exports.augmentedSixthKind = _chunkOE6WK2Y2cjs.augmentedSixthKind; exports.borrowedSource = _chunkOE6WK2Y2cjs.borrowedSource; exports.chordTimelineFromChords = _chunk3JXCW6DXcjs.chordTimelineFromChords; exports.chordTimelineFromNotes = _chunk3JXCW6DXcjs.chordTimelineFromNotes; exports.chordToRoman = _chunkOE6WK2Y2cjs.chordToRoman; exports.compareMelodies = _chunk3JXCW6DXcjs.compareMelodies; exports.createArrangementSession = _chunk3JXCW6DXcjs.createArrangementSession; exports.detectCadence = _chunkOE6WK2Y2cjs.detectCadence; exports.detectCadences = _chunk3JXCW6DXcjs.detectCadences; exports.detectChord = _chunkOE6WK2Y2cjs.detectChord; exports.detectChordBest = _chunkOE6WK2Y2cjs.detectChordBest; exports.detectKey = _chunkOE6WK2Y2cjs.detectKey; exports.detectKeyBest = _chunkOE6WK2Y2cjs.detectKeyBest; exports.detectKeyFromNotes = _chunkOE6WK2Y2cjs.detectKeyFromNotes; exports.detectModulations = _chunk3JXCW6DXcjs.detectModulations; exports.explainRoman = _chunkOE6WK2Y2cjs.explainRoman; exports.extractMotifs = _chunk3JXCW6DXcjs.extractMotifs; exports.functionOf = _chunkOE6WK2Y2cjs.functionOf; exports.hypermeter = _chunk3JXCW6DXcjs.hypermeter; exports.isBorrowedChord = _chunkOE6WK2Y2cjs.isBorrowedChord; exports.isDiatonic = _chunkOE6WK2Y2cjs.isDiatonic; exports.isMinorKey = _chunkOE6WK2Y2cjs.isMinorKey; exports.keyTimelineFromNotes = _chunk3JXCW6DXcjs.keyTimelineFromNotes; exports.melodicContour = _chunk3JXCW6DXcjs.melodicContour; exports.melodicSimilarity = _chunk3JXCW6DXcjs.melodicSimilarity; exports.motifFromNotes = _chunk3JXCW6DXcjs.motifFromNotes; exports.phrasesFromTimeline = _chunk3JXCW6DXcjs.phrasesFromTimeline; exports.pivotChords = _chunkOE6WK2Y2cjs.pivotChords; exports.prevailingKeyOf = _chunk3JXCW6DXcjs.prevailingKeyOf; exports.reduceProgression = _chunk3JXCW6DXcjs.reduceProgression; exports.relateMotifs = _chunk3JXCW6DXcjs.relateMotifs; exports.romanToChord = _chunkOE6WK2Y2cjs.romanToChord; exports.secondaryDominant = _chunkOE6WK2Y2cjs.secondaryDominant; exports.secondaryDominantOf = _chunkOE6WK2Y2cjs.secondaryDominantOf; exports.sectionsFromNotes = _chunk3JXCW6DXcjs.sectionsFromNotes; exports.spellAugmentedSixth = _chunkOE6WK2Y2cjs.spellAugmentedSixth; exports.spellLine = _chunkMXO72PLYcjs.spellLine; exports.structuralCadences = _chunk3JXCW6DXcjs.structuralCadences; exports.tensionCurve = _chunk3JXCW6DXcjs.tensionCurve; exports.tensionCurveFrom = _chunk3JXCW6DXcjs.tensionCurveFrom; exports.toVoiceNotes = _chunk3JXCW6DXcjs.toVoiceNotes;
62
109
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/libcantus/libcantus/dist/analyze/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,g7CAAC","file":"/home/runner/work/libcantus/libcantus/dist/analyze/index.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/libcantus/libcantus/dist/analyze/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,23FAAC","file":"/home/runner/work/libcantus/libcantus/dist/analyze/index.cjs"}