@libraz/libcantus 1.0.0 → 1.1.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.
- package/README.md +27 -65
- package/README_ja.md +28 -66
- package/dist/analyze/index.cjs +11 -7
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +79 -144
- package/dist/analyze/index.d.ts +79 -144
- package/dist/analyze/index.js +20 -16
- package/dist/{chunk-TTCLJX6D.js → chunk-57WB2EDF.js} +10 -8
- package/dist/chunk-57WB2EDF.js.map +1 -0
- package/dist/chunk-5JJ6EHEZ.cjs +457 -0
- package/dist/chunk-5JJ6EHEZ.cjs.map +1 -0
- package/dist/{chunk-AFM2ULJH.cjs → chunk-5KW7DNCJ.cjs} +1567 -1067
- package/dist/chunk-5KW7DNCJ.cjs.map +1 -0
- package/dist/chunk-7GOKQJTQ.js +145 -0
- package/dist/chunk-7GOKQJTQ.js.map +1 -0
- package/dist/{chunk-H3VORETI.js → chunk-AWEMD747.js} +487 -592
- package/dist/chunk-AWEMD747.js.map +1 -0
- package/dist/{chunk-4A2RMUCC.js → chunk-DKICR7AN.js} +1216 -611
- package/dist/chunk-DKICR7AN.js.map +1 -0
- package/dist/{chunk-INHVXP6Z.js → chunk-FPBZFNCD.js} +1159 -415
- package/dist/chunk-FPBZFNCD.js.map +1 -0
- package/dist/{chunk-M4CWTJWJ.cjs → chunk-GDKE6RQW.cjs} +1453 -848
- package/dist/chunk-GDKE6RQW.cjs.map +1 -0
- package/dist/chunk-H66ARFU5.js +363 -0
- package/dist/chunk-H66ARFU5.js.map +1 -0
- package/dist/{chunk-YH3BIKHH.js → chunk-HOHFYGKW.js} +146 -49
- package/dist/chunk-HOHFYGKW.js.map +1 -0
- package/dist/chunk-HSY2VQXZ.js +2272 -0
- package/dist/chunk-HSY2VQXZ.js.map +1 -0
- package/dist/{chunk-E3F4AHAH.cjs → chunk-J772DL3B.cjs} +221 -134
- package/dist/chunk-J772DL3B.cjs.map +1 -0
- package/dist/chunk-K6OZXIR6.js +1 -0
- package/dist/{chunk-VTI6FOLB.js → chunk-PQL7E5F6.js} +709 -133
- package/dist/chunk-PQL7E5F6.js.map +1 -0
- package/dist/chunk-Q6R3QAZD.cjs +3329 -0
- package/dist/chunk-Q6R3QAZD.cjs.map +1 -0
- package/dist/{chunk-MXO72PLY.cjs → chunk-QCXYKSZS.cjs} +21 -19
- package/dist/chunk-QCXYKSZS.cjs.map +1 -0
- package/dist/{chunk-VOHZB45S.js → chunk-R5VUXQMP.js} +1321 -821
- package/dist/chunk-R5VUXQMP.js.map +1 -0
- package/dist/chunk-R7B5N2JK.cjs +363 -0
- package/dist/chunk-R7B5N2JK.cjs.map +1 -0
- package/dist/{chunk-WWURE4XT.cjs → chunk-RVS4G4MR.cjs} +624 -729
- package/dist/chunk-RVS4G4MR.cjs.map +1 -0
- package/dist/chunk-TT6PKMPR.cjs +145 -0
- package/dist/chunk-TT6PKMPR.cjs.map +1 -0
- package/dist/chunk-UGLFDG7L.cjs +1 -0
- package/dist/chunk-UGLFDG7L.cjs.map +1 -0
- package/dist/chunk-VLE5R7PF.js +3329 -0
- package/dist/chunk-VLE5R7PF.js.map +1 -0
- package/dist/{chunk-FVSI36UV.js → chunk-X6RJAHII.js} +197 -110
- package/dist/chunk-X6RJAHII.js.map +1 -0
- package/dist/{chunk-Q2WGKJNN.cjs → chunk-XKSO2V5I.cjs} +699 -123
- package/dist/chunk-XKSO2V5I.cjs.map +1 -0
- package/dist/chunk-XVMJO3QF.cjs +2272 -0
- package/dist/chunk-XVMJO3QF.cjs.map +1 -0
- package/dist/{chunk-UADYAYAT.cjs → chunk-YPB3A3EY.cjs} +1309 -565
- package/dist/chunk-YPB3A3EY.cjs.map +1 -0
- package/dist/{index-C_8o--VE.d.cts → coerce-CJlgULrQ.d.cts} +210 -199
- package/dist/{index-szBv3496.d.ts → coerce-wwdELNYS.d.ts} +210 -199
- package/dist/core/index.cjs +9 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +122 -108
- package/dist/core/index.d.ts +122 -108
- package/dist/core/index.js +32 -28
- package/dist/generate/index.cjs +8 -8
- package/dist/generate/index.d.cts +168 -84
- package/dist/generate/index.d.ts +168 -84
- package/dist/generate/index.js +7 -7
- package/dist/{index-CGpRv5sl.d.cts → index-9eoQs2C1.d.ts} +34 -19
- package/dist/{index-Dzr13q3d.d.cts → index-B3WCj_Hm.d.cts} +135 -58
- package/dist/{index-BO6xE9YU.d.cts → index-BUtIf2go.d.ts} +460 -254
- package/dist/{index-CCNJRG-P.d.cts → index-BaoKVVhE.d.cts} +293 -56
- package/dist/{index-Chbst3Jx.d.ts → index-BpWOhkkE.d.ts} +135 -58
- package/dist/{index-BGFW-8P2.d.cts → index-BzLNkmA7.d.cts} +196 -114
- package/dist/{index-CunYKLiu.d.ts → index-CBCP84rv.d.cts} +1 -1
- package/dist/{index-BkGmlyI3.d.cts → index-Ci3xyows.d.ts} +60 -23
- package/dist/{index-9wcMhG73.d.ts → index-CnHQgqNh.d.ts} +293 -56
- package/dist/{index-B4o55NDr.d.cts → index-CnIdP4EZ.d.ts} +1 -1
- package/dist/{index-B9MNZboQ.d.ts → index-Cy15oTvh.d.cts} +52 -22
- package/dist/{index-B9MNZboQ.d.cts → index-Cy15oTvh.d.ts} +52 -22
- package/dist/{index-D57QRbVn.d.ts → index-DTsKaPaC.d.cts} +460 -254
- package/dist/{index-Cj49F892.d.ts → index-D_hzxD8w.d.cts} +60 -23
- package/dist/{index-CgHqxdps.d.ts → index-DpC-mDlV.d.ts} +196 -114
- package/dist/{index-G1uwGGWQ.d.ts → index-cHvbYgJI.d.cts} +34 -19
- package/dist/index.cjs +42 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +82 -54
- package/dist/{masks-DYbE485J.d.ts → masks-C8TWLFIi.d.cts} +49 -2
- package/dist/{masks-DYbE485J.d.cts → masks-O73Rhj5d.d.ts} +49 -2
- package/dist/model/index.cjs +19 -12
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +502 -181
- package/dist/model/index.d.ts +502 -181
- package/dist/model/index.js +18 -11
- package/dist/{positional-Cptlj-xs.d.ts → positional-DJgs6ltD.d.ts} +85 -8
- package/dist/{positional-DvH_sd8u.d.cts → positional-DMZer-FM.d.cts} +85 -8
- package/dist/theory/index.cjs +35 -6
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +257 -62
- package/dist/theory/index.d.ts +257 -62
- package/dist/theory/index.js +41 -12
- package/package.json +6 -5
- package/dist/chunk-3JXCW6DX.cjs +0 -3220
- package/dist/chunk-3JXCW6DX.cjs.map +0 -1
- package/dist/chunk-4A2RMUCC.js.map +0 -1
- package/dist/chunk-6XPTBE7Y.cjs +0 -49
- package/dist/chunk-6XPTBE7Y.cjs.map +0 -1
- package/dist/chunk-AFM2ULJH.cjs.map +0 -1
- package/dist/chunk-E3F4AHAH.cjs.map +0 -1
- package/dist/chunk-ELCTZUJJ.js +0 -379
- package/dist/chunk-ELCTZUJJ.js.map +0 -1
- package/dist/chunk-FVSI36UV.js.map +0 -1
- package/dist/chunk-GOZG57ER.js +0 -3220
- package/dist/chunk-GOZG57ER.js.map +0 -1
- package/dist/chunk-H3VORETI.js.map +0 -1
- package/dist/chunk-H42UHPYW.js +0 -1577
- package/dist/chunk-H42UHPYW.js.map +0 -1
- package/dist/chunk-HFPS7JFD.js +0 -1
- package/dist/chunk-INHVXP6Z.js.map +0 -1
- package/dist/chunk-K4ZJUGF4.cjs +0 -379
- package/dist/chunk-K4ZJUGF4.cjs.map +0 -1
- package/dist/chunk-KNJEKLKV.js +0 -49
- package/dist/chunk-KNJEKLKV.js.map +0 -1
- package/dist/chunk-M4CWTJWJ.cjs.map +0 -1
- package/dist/chunk-MXO72PLY.cjs.map +0 -1
- package/dist/chunk-NLEU4QSE.cjs +0 -360
- package/dist/chunk-NLEU4QSE.cjs.map +0 -1
- package/dist/chunk-OE6WK2Y2.cjs +0 -1577
- package/dist/chunk-OE6WK2Y2.cjs.map +0 -1
- package/dist/chunk-Q2WGKJNN.cjs.map +0 -1
- package/dist/chunk-RHIJ3S4I.cjs +0 -1
- package/dist/chunk-RHIJ3S4I.cjs.map +0 -1
- package/dist/chunk-TTCLJX6D.js.map +0 -1
- package/dist/chunk-UADYAYAT.cjs.map +0 -1
- package/dist/chunk-VOHZB45S.js.map +0 -1
- package/dist/chunk-VTI6FOLB.js.map +0 -1
- package/dist/chunk-WWURE4XT.cjs.map +0 -1
- package/dist/chunk-YH3BIKHH.js.map +0 -1
- /package/dist/{chunk-HFPS7JFD.js.map → chunk-K6OZXIR6.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @libraz/libcantus
|
|
2
2
|
|
|
3
|
-
Pure-TypeScript music theory for MIDI note events.
|
|
3
|
+
Pure-TypeScript music theory for MIDI note events. Recover the harmony from notes, and write new parts against that same reading. No runtime dependencies.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/libraz/libcantus/actions)
|
|
6
6
|
[](https://www.npmjs.com/package/@libraz/libcantus)
|
|
@@ -10,9 +10,11 @@ Pure-TypeScript music theory for MIDI note events. Build and spell chords, inspe
|
|
|
10
10
|
[](https://nodejs.org/)
|
|
11
11
|
[](https://libraz.github.io/libcantus/)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
The library 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. Note events go in, the harmony comes out, and the generators write against the harmony that was just read.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
## What it does
|
|
16
18
|
|
|
17
19
|
```ts
|
|
18
20
|
import { Composer, Score } from '@libraz/libcantus';
|
|
@@ -31,84 +33,44 @@ Composer.of({ key: chords.key, bpm: 120, seed: 1 }).bass(chords, { style: 'walki
|
|
|
31
33
|
// 16 notes: [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 100 }, ...]
|
|
32
34
|
```
|
|
33
35
|
|
|
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.
|
|
35
|
-
|
|
36
|
-
What each layer covers:
|
|
37
|
-
|
|
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.
|
|
44
|
-
|
|
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.
|
|
46
|
-
|
|
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.
|
|
36
|
+
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. Answers carry their evidence: a chord analysis, a cadence and a Roman numeral each come with a `rationale` and the readings they turned down, and where the input cannot settle a question the field comes back `null` rather than a plausible guess.
|
|
48
37
|
|
|
49
|
-
|
|
38
|
+
## Use cases
|
|
50
39
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## Requirements
|
|
61
|
-
|
|
62
|
-
Node.js >= 22.
|
|
40
|
+
| Use case | What it does | Worked guide |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| A DAW assistant | Infers the harmony from tracks, then writes a bass line against it. | [DAW workflow](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/daw-workflow.md) |
|
|
43
|
+
| A piece analyzer | Key regions, cadences, harmonic reduction, phrases, sections and motifs from one score. | [Piece analysis](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/piece-analysis.md) |
|
|
44
|
+
| A modulation report | Key changes with their pivot chords, confidences and relations. | [Modulation report](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/modulation-report.md) |
|
|
45
|
+
| A harmony exercise checker | Part-writing and species-counterpoint violations, each with the voice it happened in and the rule it broke. | [Harmony exercise checker](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/harmony-exercise-checker.md) |
|
|
46
|
+
| A generative arrangement | One seeded composer writing a progression, its parts and its drums, then a playability check. | [Generative arrangement](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/generative-arrangement.md) |
|
|
47
|
+
| A chord chart importer | Typed chord symbols turned into a timeline, voicings and a bass line. | [Chord chart import](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/chord-chart-import.md) |
|
|
48
|
+
| Part preparation | A part fitted to an instrument and written at the pitch its player reads. | [Part preparation](https://github.com/libraz/libcantus/blob/main/docs/en/use-cases/part-preparation.md) |
|
|
63
49
|
|
|
64
50
|
## Install
|
|
65
51
|
|
|
52
|
+
Node.js 22 or later.
|
|
53
|
+
|
|
66
54
|
```sh
|
|
67
55
|
yarn add @libraz/libcantus
|
|
68
56
|
```
|
|
69
57
|
|
|
70
|
-
|
|
71
|
-
|
|
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:
|
|
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
|
-
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.
|
|
86
|
-
|
|
87
|
-
## Import paths
|
|
88
|
-
|
|
89
|
-
The package root exports everything. To pull in a single layer, import its subpath instead:
|
|
90
|
-
|
|
91
|
-
```ts
|
|
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
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Both ESM and CommonJS builds ship for every path.
|
|
58
|
+
The package root exports the whole API. `@libraz/libcantus/core`, `/theory`, `/analyze`, `/generate` and `/model` are narrower import boundaries onto the same symbols, and every path ships an ESM and a CommonJS build.
|
|
100
59
|
|
|
101
60
|
## Documentation
|
|
102
61
|
|
|
103
|
-
|
|
62
|
+
New to music theory? [The primer](https://github.com/libraz/libcantus/blob/main/docs/en/primer/index.md) teaches the concepts this API is built on — pitch and intervals, scales and keys, chords, harmony, voices, rhythm and meter — for a reader who writes TypeScript rather than scores.
|
|
104
63
|
|
|
105
|
-
|
|
64
|
+
Otherwise start at [Introduction](https://github.com/libraz/libcantus/blob/main/docs/en/introduction.md) and [Getting started](https://github.com/libraz/libcantus/blob/main/docs/en/getting-started.md), which index the domain guides and the reference pages. Every `ts` example in the guides is executed by the test suite, and a trailing comment that names a literal — with or without the reason for it after an em dash — is checked against what the call returns.
|
|
106
65
|
|
|
107
|
-
|
|
66
|
+
## What it doesn't do
|
|
108
67
|
|
|
109
|
-
|
|
68
|
+
- **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. For the layer below, [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.
|
|
69
|
+
- **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.
|
|
70
|
+
- **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 grammar built on it.
|
|
71
|
+
- **No corpus.** Nothing is bundled to run statistics over.
|
|
110
72
|
|
|
111
|
-
|
|
73
|
+
[Questions and limitations](https://github.com/libraz/libcantus/blob/main/docs/en/faq.md) covers the rest, including where a functional reading does not apply and what the engine will not guess.
|
|
112
74
|
|
|
113
75
|
## License
|
|
114
76
|
|
package/README_ja.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @libraz/libcantus
|
|
2
2
|
|
|
3
|
-
MIDI
|
|
3
|
+
MIDI ノートイベントのための、TypeScript 製の音楽理論ライブラリです。ノートから和声を読み取り、その読み取り結果に沿って新しいパートを書けます。実行時依存はありません。
|
|
4
4
|
|
|
5
5
|
[](https://github.com/libraz/libcantus/actions)
|
|
6
6
|
[](https://www.npmjs.com/package/@libraz/libcantus)
|
|
@@ -10,9 +10,11 @@ MIDI ノートイベントを扱う、TypeScript 製の音楽理論ライブラ
|
|
|
10
10
|
[](https://nodejs.org/)
|
|
11
11
|
[](https://libraz.github.io/libcantus/)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
このライブラリは、すでにノートやコード記号を持っているソフトウェア(DAW のプロジェクト、MIDI パーサー、練習支援ツールなど)と、その音が和声的に何を意味するかとの間を埋めます。ノートイベントを渡すと和声が求まり、ジェネレーターはいま読み取ったその和声に沿ってパートを書きます。
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
## できること
|
|
16
18
|
|
|
17
19
|
```ts
|
|
18
20
|
import { Composer, Score } from '@libraz/libcantus';
|
|
@@ -31,85 +33,45 @@ Composer.of({ key: chords.key, bpm: 120, seed: 1 }).bass(chords, { style: 'walki
|
|
|
31
33
|
// 16 音: [{ pitch: 36, startBeat: 0, durationBeat: 1, velocity: 100 }, ...]
|
|
32
34
|
```
|
|
33
35
|
|
|
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` を返します。カデンツが完全か不完全かはヴォイシングがなければ決まりません。ソプラノに何があるかはヴォイシングだけが答えられるからです。
|
|
36
|
+
コードの境界は決め打ちせずに探索し、キーも同様に探します。転調する曲を、冒頭のキーのまま読み続けることはありません。答えには根拠が伴います。コード分析・終止・ローマ数字はいずれも `rationale` と、退けた候補を併せて返し、入力だけでは決まらない項目は、もっともらしい推測ではなく `null` を返します。
|
|
46
37
|
|
|
47
|
-
|
|
38
|
+
## ユースケース
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
- **機能和声には既知の穴があります。** `functionOf` は和音と調だけから答えるため、終止四六の和音はその層では主和音の転回として読まれます。属和音としての読みは時間軸を見る層のものであり、属和音の前の和音を `approach` として渡したときに `detectCadence` がそれを示します。
|
|
59
|
-
|
|
60
|
-
## 要件
|
|
61
|
-
|
|
62
|
-
Node.js >= 22。
|
|
40
|
+
| ユースケース | 内容 | 実例のガイド |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| DAW のアシスタント | トラックから和声を読み取り、それに沿ってベースラインを書く。 | [DAW ワークフロー](docs/ja/use-cases/daw-workflow.md) |
|
|
43
|
+
| 楽曲アナライザー | 1 つのスコアから調区間、終止形、和声的な還元、フレーズ、セクション、モチーフを得る。 | [楽曲の解析](docs/ja/use-cases/piece-analysis.md) |
|
|
44
|
+
| 転調レポート | 転調を、軸和音・確信度・調同士の関係とともに提示する。 | [転調レポート](docs/ja/use-cases/modulation-report.md) |
|
|
45
|
+
| 和声課題のチェッカー | 声部書法と種目対位法の違反を、違反した声部と破った規則つきで報告する。 | [和声課題のチェック](docs/ja/use-cases/harmony-exercise-checker.md) |
|
|
46
|
+
| 自動生成アレンジ | シードを固定した 1 つのコンポーザーがコード進行・各パート・ドラムを書き、演奏可能性を確認する。 | [生成によるアレンジ](docs/ja/use-cases/generative-arrangement.md) |
|
|
47
|
+
| コード譜の取り込み | 打ち込んだコード記号をタイムライン、ヴォイシング、ベースラインに変換する。 | [コード譜の取り込み](docs/ja/use-cases/chord-chart-import.md) |
|
|
48
|
+
| パート譜の準備 | パートを楽器に合わせ、その奏者が読む音高で書き出す。 | [パート譜の準備](docs/ja/use-cases/part-preparation.md) |
|
|
63
49
|
|
|
64
50
|
## インストール
|
|
65
51
|
|
|
52
|
+
Node.js 22 以降が必要です。
|
|
53
|
+
|
|
66
54
|
```sh
|
|
67
55
|
yarn add @libraz/libcantus
|
|
68
56
|
```
|
|
69
57
|
|
|
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 の両方のビルドがあります。
|
|
58
|
+
パッケージのルートから API 全体を公開しています。`@libraz/libcantus/core`、`/theory`、`/analyze`、`/generate`、`/model` は同じシンボル群に対する、より狭い読み込み境界です。いずれのパスも ESM と CommonJS の両方のビルドを同梱しています。
|
|
100
59
|
|
|
101
60
|
## ドキュメント
|
|
102
61
|
|
|
103
|
-
|
|
62
|
+
音楽理論にはじめて触れる場合は、[入門ガイド](docs/ja/primer/index.md)から始めてください。この API が土台にしている考え方 — 音高と音程、音階と調、和音、和声、声部、リズムと拍子 — を、楽譜ではなく TypeScript を書く読者に向けて説明しています。
|
|
104
63
|
|
|
105
|
-
|
|
64
|
+
そうでなければ、[はじめに](docs/ja/introduction.md)と[使いはじめる](docs/ja/getting-started.md)から読んでください。各分野のガイドとリファレンスはそこから辿れます。ガイド中の `ts` の例はすべてテストスイートで実行され、行末コメントがリテラルを名指していれば(em ダッシュに続けて理由が書かれていてもかまいません)実際の戻り値と照合されます。
|
|
106
65
|
|
|
107
|
-
|
|
66
|
+
## できないこと
|
|
108
67
|
|
|
109
|
-
|
|
68
|
+
- **入出力・記譜・音声は扱いません。** MIDI ファイルの読み書き、楽譜の描画、音声解析、再生はいずれも対象外です。パーサーは呼び出し側で用意し、ノートイベントを渡してください。その下の層が必要な場合、[libsonare](https://github.com/libraz/libsonare) が音声解析・マスタリング・合成・SMF の入出力を扱います。両者はコードを共有せず、どちらも他方を必要としません。
|
|
69
|
+
- **微分音の解析は行いません。** 周波数、セント、オクターブの等分割、純正律の比は `core` にありますが、音高より上の層はすべて 12 のピッチクラスで動きます。
|
|
70
|
+
- **旋法体系そのものは扱いません。** `WORLD_SCALES` が記録するのは、その伝統が名前を与えている音の素材 — ターット、マカームの音組織、日本の五音音階 — であって、その上に築かれた語法ではありません。
|
|
71
|
+
- **コーパスは同梱しません。** 統計を取るためのデータは含みません。
|
|
110
72
|
|
|
111
|
-
|
|
73
|
+
残りは[疑問と制限](docs/ja/faq.md)にまとめています。機能和声の読みが適用できない場合や、エンジンが推測しないことについてもそこで扱います。
|
|
112
74
|
|
|
113
75
|
## ライセンス
|
|
114
76
|
|
|
115
|
-
[@libraz/libcantus](https://github.com/libraz/libcantus) は [Apache License 2.0](LICENSE)
|
|
77
|
+
[@libraz/libcantus](https://github.com/libraz/libcantus) は [Apache License 2.0](LICENSE) で公開しています。
|
package/dist/analyze/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkQCXYKSZScjs = require('../chunk-QCXYKSZS.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -18,6 +18,7 @@ var _chunkMXO72PLYcjs = require('../chunk-MXO72PLY.cjs');
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
var _chunkXVMJO3QFcjs = require('../chunk-XVMJO3QF.cjs');
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
|
|
@@ -25,7 +26,6 @@ var _chunkMXO72PLYcjs = require('../chunk-MXO72PLY.cjs');
|
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
|
|
28
|
-
var _chunk3JXCW6DXcjs = require('../chunk-3JXCW6DX.cjs');
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
@@ -50,14 +50,14 @@ var _chunk3JXCW6DXcjs = require('../chunk-3JXCW6DX.cjs');
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
var _chunkOE6WK2Y2cjs = require('../chunk-OE6WK2Y2.cjs');
|
|
54
|
-
require('../chunk-K4ZJUGF4.cjs');
|
|
55
53
|
|
|
56
54
|
|
|
57
|
-
var
|
|
58
|
-
require('../chunk-
|
|
55
|
+
var _chunkQ6R3QAZDcjs = require('../chunk-Q6R3QAZD.cjs');
|
|
56
|
+
require('../chunk-TT6PKMPR.cjs');
|
|
59
57
|
|
|
60
58
|
|
|
59
|
+
var _chunkYPB3A3EYcjs = require('../chunk-YPB3A3EY.cjs');
|
|
60
|
+
require('../chunk-XKSO2V5I.cjs');
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
|
|
@@ -105,5 +105,9 @@ require('../chunk-Q2WGKJNN.cjs');
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
exports.MODAL_SCALE_NAMES = _chunkQ6R3QAZDcjs.MODAL_SCALE_NAMES; exports.NoteSafety = _chunkYPB3A3EYcjs.NoteSafety; exports.analyzeArrangement = _chunkXVMJO3QFcjs.analyzeArrangement; exports.analyzeChord = _chunkQ6R3QAZDcjs.analyzeChord; exports.analyzePolyphony = _chunkXVMJO3QFcjs.analyzePolyphony; exports.analyzeVoice = _chunkQ6R3QAZDcjs.analyzeVoice; exports.assertChordTimeline = _chunkQ6R3QAZDcjs.assertChordTimeline; exports.augmentedSixthChord = _chunkQ6R3QAZDcjs.augmentedSixthChord; exports.augmentedSixthFromPitchClasses = _chunkQ6R3QAZDcjs.augmentedSixthFromPitchClasses; exports.augmentedSixthKind = _chunkQ6R3QAZDcjs.augmentedSixthKind; exports.borrowedSource = _chunkQ6R3QAZDcjs.borrowedSource; exports.chordTimelineFromChords = _chunkQ6R3QAZDcjs.chordTimelineFromChords; exports.chordTimelineFromNotes = _chunkQ6R3QAZDcjs.chordTimelineFromNotes; exports.chordToRoman = _chunkQ6R3QAZDcjs.chordToRoman; exports.compareMelodies = _chunkXVMJO3QFcjs.compareMelodies; exports.createArrangementSession = _chunkXVMJO3QFcjs.createArrangementSession; exports.detectCadence = _chunkQ6R3QAZDcjs.detectCadence; exports.detectCadences = _chunkQ6R3QAZDcjs.detectCadences; exports.detectChord = _chunkQ6R3QAZDcjs.detectChord; exports.detectChordBest = _chunkQ6R3QAZDcjs.detectChordBest; exports.detectKey = _chunkQ6R3QAZDcjs.detectKey; exports.detectKeyBest = _chunkQ6R3QAZDcjs.detectKeyBest; exports.detectKeyFromNotes = _chunkQ6R3QAZDcjs.detectKeyFromNotes; exports.detectModulations = _chunkQ6R3QAZDcjs.detectModulations; exports.explainRoman = _chunkQ6R3QAZDcjs.explainRoman; exports.extractMotifs = _chunkXVMJO3QFcjs.extractMotifs; exports.functionOf = _chunkQ6R3QAZDcjs.functionOf; exports.hypermeter = _chunkXVMJO3QFcjs.hypermeter; exports.isBorrowedChord = _chunkQ6R3QAZDcjs.isBorrowedChord; exports.isDiatonic = _chunkQ6R3QAZDcjs.isDiatonic; exports.isMinorKey = _chunkQ6R3QAZDcjs.isMinorKey; exports.keyTimelineFromNotes = _chunkQ6R3QAZDcjs.keyTimelineFromNotes; exports.melodicContour = _chunkXVMJO3QFcjs.melodicContour; exports.melodicSimilarity = _chunkXVMJO3QFcjs.melodicSimilarity; exports.motifFromNotes = _chunkXVMJO3QFcjs.motifFromNotes; exports.phrasesFromTimeline = _chunkXVMJO3QFcjs.phrasesFromTimeline; exports.pivotChords = _chunkQ6R3QAZDcjs.pivotChords; exports.prevailingKeyOf = _chunkQ6R3QAZDcjs.prevailingKeyOf; exports.reduceProgression = _chunkXVMJO3QFcjs.reduceProgression; exports.relateMotifs = _chunkXVMJO3QFcjs.relateMotifs; exports.romanToChord = _chunkQ6R3QAZDcjs.romanToChord; exports.secondaryDominant = _chunkQ6R3QAZDcjs.secondaryDominant; exports.secondaryDominantOf = _chunkQ6R3QAZDcjs.secondaryDominantOf; exports.sectionsFromNotes = _chunkXVMJO3QFcjs.sectionsFromNotes; exports.spellAugmentedSixth = _chunkQ6R3QAZDcjs.spellAugmentedSixth; exports.spellLine = _chunkQCXYKSZScjs.spellLine; exports.structuralCadences = _chunkXVMJO3QFcjs.structuralCadences; exports.tensionCurve = _chunkXVMJO3QFcjs.tensionCurve; exports.tensionCurveFrom = _chunkXVMJO3QFcjs.tensionCurveFrom; exports.toVoiceNotes = _chunkQ6R3QAZDcjs.toVoiceNotes;
|
|
109
113
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;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;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;AACA;AACA;AACF,+/FAAC","file":"/home/runner/work/libcantus/libcantus/dist/analyze/index.cjs"}
|