@libraz/libcantus 0.9.4 → 0.9.5
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 -18
- package/README_ja.md +268 -0
- package/dist/analyze/index.cjs +7 -7
- package/dist/analyze/index.d.cts +9 -99
- package/dist/analyze/index.d.ts +9 -99
- package/dist/analyze/index.js +6 -6
- package/dist/{chunk-36N73KZ3.cjs → chunk-2A2QMA74.cjs} +80 -65
- package/dist/chunk-2A2QMA74.cjs.map +1 -0
- package/dist/{chunk-YLEMGEFH.js → chunk-2PTFGVD7.js} +50 -35
- package/dist/chunk-2PTFGVD7.js.map +1 -0
- package/dist/{chunk-ZEJR4TKL.cjs → chunk-357ZDPVU.cjs} +36 -47
- package/dist/chunk-357ZDPVU.cjs.map +1 -0
- package/dist/{chunk-EHVEBWM5.js → chunk-3KX76RLG.js} +136 -37
- package/dist/chunk-3KX76RLG.js.map +1 -0
- package/dist/{chunk-RC6GBMCD.cjs → chunk-4VZ5MZAM.cjs} +155 -111
- package/dist/chunk-4VZ5MZAM.cjs.map +1 -0
- package/dist/{chunk-RK35RIN7.js → chunk-7EONYVI5.js} +115 -28
- package/dist/chunk-7EONYVI5.js.map +1 -0
- package/dist/{chunk-GQSGS2N4.js → chunk-7JEP3MFY.js} +5 -16
- package/dist/chunk-7JEP3MFY.js.map +1 -0
- package/dist/{chunk-7NKDPF74.js → chunk-AID75RN3.js} +203 -104
- package/dist/chunk-AID75RN3.js.map +1 -0
- package/dist/{chunk-FNDWXRRI.cjs → chunk-BSLTLGM3.cjs} +55 -37
- package/dist/chunk-BSLTLGM3.cjs.map +1 -0
- package/dist/{chunk-NP4NA2FB.cjs → chunk-CU6VG2YM.cjs} +39 -36
- package/dist/chunk-CU6VG2YM.cjs.map +1 -0
- package/dist/{chunk-NYYWMV2C.js → chunk-DZMHIGI4.js} +27 -17
- package/dist/chunk-DZMHIGI4.js.map +1 -0
- package/dist/{chunk-I24MV65U.js → chunk-EDOTEABK.js} +18 -15
- package/dist/{chunk-I24MV65U.js.map → chunk-EDOTEABK.js.map} +1 -1
- package/dist/{chunk-NKIBQ6PT.js → chunk-HN2OEUN2.js} +7 -4
- package/dist/chunk-HN2OEUN2.js.map +1 -0
- package/dist/{chunk-D2FAJBYL.js → chunk-KBTTEX7Q.js} +30 -12
- package/dist/chunk-KBTTEX7Q.js.map +1 -0
- package/dist/{chunk-CAN76NCU.cjs → chunk-KQN2ZYND.cjs} +147 -102
- package/dist/chunk-KQN2ZYND.cjs.map +1 -0
- package/dist/{chunk-4HLLZPXT.cjs → chunk-MPTVJIVG.cjs} +350 -251
- package/dist/chunk-MPTVJIVG.cjs.map +1 -0
- package/dist/{chunk-RUMU3UA6.cjs → chunk-MTMZTMWM.cjs} +12 -12
- package/dist/{chunk-RUMU3UA6.cjs.map → chunk-MTMZTMWM.cjs.map} +1 -1
- package/dist/{chunk-KMHOICIY.js → chunk-NNB67XA2.js} +90 -45
- package/dist/chunk-NNB67XA2.js.map +1 -0
- package/dist/{chunk-LW53AHQU.cjs → chunk-OL3IHHSJ.cjs} +228 -141
- package/dist/chunk-OL3IHHSJ.cjs.map +1 -0
- package/dist/{chunk-7MGZ7D62.cjs → chunk-PI3UXRWK.cjs} +43 -13
- package/dist/chunk-PI3UXRWK.cjs.map +1 -0
- package/dist/{chunk-XEBG3G53.js → chunk-R2VVFAIN.js} +42 -12
- package/dist/chunk-R2VVFAIN.js.map +1 -0
- package/dist/{chunk-Q6OP4U43.cjs → chunk-WFDXOLUB.cjs} +50 -40
- package/dist/chunk-WFDXOLUB.cjs.map +1 -0
- package/dist/{chunk-NVE34YGZ.cjs → chunk-WTAN4ACG.cjs} +212 -113
- package/dist/chunk-WTAN4ACG.cjs.map +1 -0
- package/dist/{chunk-FCANXBAT.cjs → chunk-YFJXS3AU.cjs} +8 -5
- package/dist/chunk-YFJXS3AU.cjs.map +1 -0
- package/dist/{chunk-Q2XUP227.js → chunk-YUE6TJ4M.js} +89 -45
- package/dist/chunk-YUE6TJ4M.js.map +1 -0
- package/dist/{chunk-HKGYCQ34.js → chunk-ZGLJM4A4.js} +2 -2
- package/dist/core/index.cjs +15 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +14 -4
- package/dist/core/index.d.ts +14 -4
- package/dist/core/index.js +14 -4
- package/dist/{function-DNugAOrt.d.cts → function-CxixTB02.d.cts} +98 -7
- package/dist/{function-BtiZb9i9.d.ts → function-DTCt675z.d.ts} +98 -7
- package/dist/generate/index.cjs +10 -10
- package/dist/generate/index.d.cts +21 -21
- package/dist/generate/index.d.ts +21 -21
- package/dist/generate/index.js +9 -9
- package/dist/{index-tJhkmQgE.d.cts → index-B2Ulxxpo.d.cts} +3 -2
- package/dist/{index-Be74mcon.d.cts → index-BkYJ0xMq.d.cts} +2 -2
- package/dist/{index-6VR8-kit.d.ts → index-BuaB-ypt.d.ts} +3 -2
- package/dist/{index-70p168VM.d.ts → index-CAN7v-kw.d.ts} +9 -2
- package/dist/{index-C83mZI1P.d.ts → index-COw1Ky9g.d.ts} +1 -1
- package/dist/{index-tSQh-xwY.d.ts → index-Cfx8xgH0.d.ts} +1 -1
- package/dist/{index-C5UBbQ4G.d.ts → index-DRtIhlJj.d.ts} +2 -2
- package/dist/{index-BtXT6UQ0.d.cts → index-alrRninU.d.cts} +9 -2
- package/dist/{index-y_ak9_Hi.d.cts → index-oTQbYYIs.d.cts} +1 -1
- package/dist/{index-OG65ocOr.d.ts → index-tR9jTn26.d.cts} +4 -1
- package/dist/{index-OG65ocOr.d.cts → index-tR9jTn26.d.ts} +4 -1
- package/dist/{index-D6b6na69.d.cts → index-x2vcsduE.d.cts} +1 -1
- package/dist/index.cjs +24 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +23 -13
- package/dist/model/index.cjs +7 -7
- package/dist/model/index.d.cts +48 -16
- package/dist/model/index.d.ts +48 -16
- package/dist/model/index.js +6 -6
- package/dist/{styled-DIRkk9Uz.d.ts → styled-Bl0ZK28h.d.ts} +40 -3
- package/dist/{styled-DJbkJQfj.d.cts → styled-Crv6SA4S.d.cts} +40 -3
- package/dist/theory/index.cjs +6 -6
- package/dist/theory/index.d.cts +9 -9
- package/dist/theory/index.d.ts +9 -9
- package/dist/theory/index.js +5 -5
- package/package.json +12 -9
- package/dist/chunk-36N73KZ3.cjs.map +0 -1
- package/dist/chunk-4HLLZPXT.cjs.map +0 -1
- package/dist/chunk-7MGZ7D62.cjs.map +0 -1
- package/dist/chunk-7NKDPF74.js.map +0 -1
- package/dist/chunk-CAN76NCU.cjs.map +0 -1
- package/dist/chunk-D2FAJBYL.js.map +0 -1
- package/dist/chunk-EHVEBWM5.js.map +0 -1
- package/dist/chunk-FCANXBAT.cjs.map +0 -1
- package/dist/chunk-FNDWXRRI.cjs.map +0 -1
- package/dist/chunk-GQSGS2N4.js.map +0 -1
- package/dist/chunk-KMHOICIY.js.map +0 -1
- package/dist/chunk-LW53AHQU.cjs.map +0 -1
- package/dist/chunk-NKIBQ6PT.js.map +0 -1
- package/dist/chunk-NP4NA2FB.cjs.map +0 -1
- package/dist/chunk-NVE34YGZ.cjs.map +0 -1
- package/dist/chunk-NYYWMV2C.js.map +0 -1
- package/dist/chunk-Q2XUP227.js.map +0 -1
- package/dist/chunk-Q6OP4U43.cjs.map +0 -1
- package/dist/chunk-RC6GBMCD.cjs.map +0 -1
- package/dist/chunk-RK35RIN7.js.map +0 -1
- package/dist/chunk-XEBG3G53.js.map +0 -1
- package/dist/chunk-YLEMGEFH.js.map +0 -1
- package/dist/chunk-ZEJR4TKL.cjs.map +0 -1
- /package/dist/{chunk-HKGYCQ34.js.map → chunk-ZGLJM4A4.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# @libraz/libcantus
|
|
2
2
|
|
|
3
|
-
Pure-TypeScript
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Pure-TypeScript music theory engine. It takes MIDI note numbers and chord
|
|
4
|
+
symbols and gives back harmonic meaning (Roman numerals, function, cadence,
|
|
5
|
+
key), then generates new parts against that meaning. Built for the tools that
|
|
6
|
+
sit next to a DAW: analyzers, generators, and composition assistants.
|
|
7
|
+
|
|
8
|
+
It is a theory layer, not an I/O or audio layer. There is no MIDI file reader or
|
|
9
|
+
writer, no audio analysis, and no playback — bring your own parser and hand it
|
|
10
|
+
note events. No runtime dependencies. If you need that other layer as well,
|
|
11
|
+
[libsonare](https://github.com/libraz/libsonare) covers audio analysis,
|
|
12
|
+
mastering, synthesis, and SMF I/O, and its npm binding sits alongside this one;
|
|
13
|
+
the two share no code and neither requires the other.
|
|
7
14
|
|
|
8
15
|
[](https://github.com/libraz/libcantus/actions)
|
|
9
16
|
[](https://www.npmjs.com/package/@libraz/libcantus)
|
|
@@ -21,7 +28,7 @@ dependencies.
|
|
|
21
28
|
(`V7/V`), or lead-sheet symbols (`Cmaj7`, `F#m7b5`, `C/G`).
|
|
22
29
|
- **Analyze harmony** — Roman-numeral analysis, harmonic function, cadence
|
|
23
30
|
detection, and borrowed / modal-interchange chords.
|
|
24
|
-
- **Recognize
|
|
31
|
+
- **Recognize chords and keys** — notes in, chord or key out (the inverse of the
|
|
25
32
|
builders).
|
|
26
33
|
- **Reharmonize** — tritone subs, chromatic mediants, negative harmony, modal
|
|
27
34
|
interchange palettes.
|
|
@@ -29,17 +36,18 @@ dependencies.
|
|
|
29
36
|
rootless comping styles.
|
|
30
37
|
- **Generate parts** — bass lines, countermelodies, drums, rhythms, motifs, and
|
|
31
38
|
whole progressions; deterministic for a given seed.
|
|
32
|
-
- **
|
|
39
|
+
- **Analyze a whole arrangement** — feed raw multi-track note events, recover the
|
|
33
40
|
harmony, get a whole-piece analysis (with per-note conflicts), and generate the
|
|
34
41
|
missing parts against it.
|
|
35
42
|
- **Work with pitch as sound** — frequencies, cents, EDO, and just intonation.
|
|
36
43
|
|
|
37
|
-
The
|
|
38
|
-
|
|
39
|
-
`
|
|
40
|
-
**
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
The theory itself lives in **tree-shakeable pure functions**. On top of them sits
|
|
45
|
+
a **fluent, immutable class API** (`Note`, `Interval`, `Chord`, `Key`,
|
|
46
|
+
`Progression`) that reads like music theory. Which one you get follows a single
|
|
47
|
+
rule: the musical **values** — notes, chords, keys, progressions — have both
|
|
48
|
+
forms and interoperate freely, while operations over **collections and
|
|
49
|
+
timelines** (part generation, whole-arrangement analysis, key ranking) take
|
|
50
|
+
arrays of note events and are exposed as functions only.
|
|
43
51
|
|
|
44
52
|
## Install
|
|
45
53
|
|
|
@@ -88,11 +96,11 @@ pure functions, so the two styles interoperate freely. The same task with the
|
|
|
88
96
|
functional API:
|
|
89
97
|
|
|
90
98
|
```ts
|
|
91
|
-
import { chordFromDegree, chordPitchClasses, classifyInterval, majorKey } from '@libraz/libcantus';
|
|
99
|
+
import { chordFromDegree, chordPitchClasses, classifyInterval, ConsonanceClass, majorKey } from '@libraz/libcantus';
|
|
92
100
|
|
|
93
101
|
const cMajor = majorKey(0);
|
|
94
102
|
|
|
95
|
-
classifyInterval(7); //
|
|
103
|
+
classifyInterval(7); // ConsonanceClass.PerfectConsonance
|
|
96
104
|
chordPitchClasses(chordFromDegree(4, 'dom7', cMajor)); // [2, 5, 7, 11] (G7)
|
|
97
105
|
```
|
|
98
106
|
|
|
@@ -160,7 +168,7 @@ Chord.of('F', 'min').analyze(Key.major('C'));
|
|
|
160
168
|
// { function: 'subdominant', borrowed: true, source: 'parallelMinor', roman: 'iv' }
|
|
161
169
|
```
|
|
162
170
|
|
|
163
|
-
## Recognize
|
|
171
|
+
## Recognize chords and keys
|
|
164
172
|
|
|
165
173
|
Notes in, chord or key out — the inverse of the builders:
|
|
166
174
|
|
|
@@ -256,10 +264,11 @@ motif.notes.length > 0; // true — a deterministic short melodic cell
|
|
|
256
264
|
`humanize`, `extractGrooveTemplate`, and `applyGrooveTemplate` add a meter-aware
|
|
257
265
|
feel — or capture the feel of one performance and transplant it onto another.
|
|
258
266
|
|
|
259
|
-
##
|
|
267
|
+
## Analyze and extend an arrangement
|
|
260
268
|
|
|
261
|
-
The arrangement layer takes raw multi-track `NoteEvent`s
|
|
262
|
-
then analyses and generates
|
|
269
|
+
The arrangement layer takes raw multi-track `NoteEvent`s — whatever your DAW or
|
|
270
|
+
MIDI-file parser produced — recovers the harmony, then analyses and generates
|
|
271
|
+
against it:
|
|
263
272
|
|
|
264
273
|
```ts
|
|
265
274
|
import {
|
package/README_ja.md
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# @libraz/libcantus
|
|
2
|
+
|
|
3
|
+
TypeScript だけで書かれた音楽理論エンジンです。MIDI ノート番号とコードネームを受け取り、和声的な意味(ローマ数字、和声機能、終止、キー)を返します。さらにその解析結果を土台にして新しいパートを生成します。DAW の隣に置くツール(解析器、ジェネレーター、作曲アシスタント)で使うことを想定しています。
|
|
4
|
+
|
|
5
|
+
扱うのは理論の層だけで、I/O やオーディオには踏み込みません。MIDI ファイルの読み書き、オーディオ解析、再生のいずれも持たないので、パースは呼び出し側で行い、ノートイベントとして渡してください。実行時依存はありません。その層も必要であれば、[libsonare](https://github.com/libraz/libsonare) が音声解析・マスタリング・音源合成・SMF の読み書きを担当していて、npm パッケージなので本ライブラリと並べて置けます。両者はコードを共有しておらず、どちらも単独で使えます。
|
|
6
|
+
|
|
7
|
+
[](https://github.com/libraz/libcantus/actions)
|
|
8
|
+
[](https://www.npmjs.com/package/@libraz/libcantus)
|
|
9
|
+
[](https://codecov.io/gh/libraz/libcantus)
|
|
10
|
+
[](https://github.com/libraz/libcantus/blob/main/LICENSE)
|
|
11
|
+
[](https://www.typescriptlang.org/)
|
|
12
|
+
[](https://nodejs.org/)
|
|
13
|
+
[](https://libraz.github.io/libcantus/)
|
|
14
|
+
|
|
15
|
+
## 何ができるか
|
|
16
|
+
|
|
17
|
+
- **音名を扱う** — `C4` のパース、移調、MIDI との相互変換、異名同音を区別した音程の綴り(`F#` と `Gb`)。
|
|
18
|
+
- **コードと進行を組み立てる** — スケール度数、ローマ数字(`V7/V`)、リードシート記号(`Cmaj7`, `F#m7b5`, `C/G`)のいずれからでも。
|
|
19
|
+
- **和声を解析する** — ローマ数字解析、和声機能、終止形の検出、借用和音とモーダルインターチェンジ。
|
|
20
|
+
- **コードとキーを判定する** — ノートを入れるとコードやキーが返る、組み立ての逆方向の処理。
|
|
21
|
+
- **リハーモナイズする** — 裏コード、クロマチックメディアント、ネガティブハーモニー、モーダルインターチェンジのパレット。
|
|
22
|
+
- **コードをボイシングする** — 声部の動きを最小化した 4 声(SATB)に加えて、drop-2/3、シェル、ルートレスのコンピングスタイル。
|
|
23
|
+
- **パートを生成する** — ベースライン、対旋律、ドラム、リズム、モチーフ、進行全体。シードを与えれば結果は決定的になります。
|
|
24
|
+
- **アレンジ全体を解析する** — マルチトラックのノートイベントを渡すと和声を復元し、曲全体の解析(ノート単位の衝突検出つき)を返します。そこから足りないパートを生成できます。
|
|
25
|
+
- **音高を音響として扱う** — 周波数、セント、EDO、純正律。
|
|
26
|
+
|
|
27
|
+
理論の本体は tree-shaking の効く純粋関数として実装してあります。その上に、音楽理論の記述に近い形で書ける不変(immutable)なクラス API(`Note`, `Interval`, `Chord`, `Key`, `Progression`)が乗ります。どちらの形で提供されるかは一つの規則で決まります。音符・コード・キー・進行といった値は両方の形を持ち、相互に行き来できます。一方でコレクションやタイムラインを対象とする操作(パート生成、アレンジ全体の解析、キーのランキング)はノートイベントの配列を受け取るため、関数としてのみ公開されます。
|
|
28
|
+
|
|
29
|
+
## インストール
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
yarn add @libraz/libcantus
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## サブパスインポート
|
|
36
|
+
|
|
37
|
+
パッケージのルートからはすべてがエクスポートされます。特定の層だけを取り込みたい場合は、その層のサブパスからインポートしてください。
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { Chord, Key, Note } from '@libraz/libcantus/model'; // クラス API
|
|
41
|
+
import { majorKey, makeChord } from '@libraz/libcantus/theory'; // スケール、コード
|
|
42
|
+
import { generateDrums, generateProgression } from '@libraz/libcantus/generate';
|
|
43
|
+
import { analyzeArrangement, detectKey } from '@libraz/libcantus/analyze';
|
|
44
|
+
import { parseNote, edo } from '@libraz/libcantus/core'; // 音高、拍子、音律
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
層は `core`, `theory`, `analyze`, `generate`, `model` の 5 つです。
|
|
48
|
+
|
|
49
|
+
## クイックスタート
|
|
50
|
+
|
|
51
|
+
クラス API は不変のままメソッドチェーンでき、キーの文脈を持ち回るので、解析のたびにキーを渡し直す必要はありません。
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { Chord, Key, Note } from '@libraz/libcantus';
|
|
55
|
+
|
|
56
|
+
const c = Key.major('C');
|
|
57
|
+
|
|
58
|
+
c.chord(4, 'dom7').pitchClasses(); // [2, 5, 7, 11] (G7)
|
|
59
|
+
c.roman('V7/V').voice(); // [ ...SATB の MIDI ノート ] (セカンダリードミナントをボイシング)
|
|
60
|
+
Note.of('C4').transpose(7).name; // 'G4'
|
|
61
|
+
|
|
62
|
+
// ii–V–I を組み立てて、そのまま 1 行で解析する:
|
|
63
|
+
c.chord(1, 'min').progressionTo(c.chord(4, 'dom7'), c.chord(0, 'maj')).analyze();
|
|
64
|
+
// { chords: [...機能和声の解析...], cadence: 'authentic' }
|
|
65
|
+
|
|
66
|
+
Chord.detect([60, 64, 67])[0].quality; // 'maj'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
どのクラスもプレーンなオブジェクト(`Chord.data`, `Note.data`)を包んでいるだけで、処理は純粋関数に委譲されます。そのため二つのスタイルは自由に混ぜられます。同じ処理を関数 API で書くとこうなります。
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { chordFromDegree, chordPitchClasses, classifyInterval, ConsonanceClass, majorKey } from '@libraz/libcantus';
|
|
73
|
+
|
|
74
|
+
const cMajor = majorKey(0);
|
|
75
|
+
|
|
76
|
+
classifyInterval(7); // ConsonanceClass.PerfectConsonance
|
|
77
|
+
chordPitchClasses(chordFromDegree(4, 'dom7', cMajor)); // [2, 5, 7, 11] (G7)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 音名を扱う
|
|
81
|
+
|
|
82
|
+
音名のパースと整形、MIDI への変換、そしてピッチクラスの層では区別できない異名同音を正しく綴り分ける音程計算ができます。
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { Interval, Note } from '@libraz/libcantus';
|
|
86
|
+
|
|
87
|
+
Note.of('C4').transpose(7).name; // 'G4'
|
|
88
|
+
Note.of('C4').midi; // 60
|
|
89
|
+
Interval.between(Note.of('C4'), Note.of('F#4')).name; // 'A4' (増四度)
|
|
90
|
+
Interval.between(Note.of('C4'), Note.of('Gb4')).name; // 'd5' (減五度)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## キーとスケール
|
|
94
|
+
|
|
95
|
+
`KeyScale` はルートのピッチクラスと 12 ビットの `modeMask12` の組です(ビット `n` が立っていれば、ピッチクラス `(rootPc + n) % 12` がスケールに含まれます)。`majorKey`, `minorKey`, `scaleByName` が教会旋法・ペンタトニック・ブルース・ホールトーン・オクタトニックをカバーし、`MAJOR_MASK` と `NATURAL_MINOR_MASK` を使えば独自のキーも定義できます。
|
|
96
|
+
|
|
97
|
+
`nearestScaleTone` は与えた音高を最も近いスケール構成音の MIDI ノートにスナップします(同距離なら低い方を優先)。生成した音をキーに収める場面で使えます。
|
|
98
|
+
|
|
99
|
+
## コードと進行を組み立てる
|
|
100
|
+
|
|
101
|
+
スケール度数、ローマ数字、リードシート記号のいずれからでも組み立てられ、逆方向にも戻せます。
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { Chord, Key } from '@libraz/libcantus';
|
|
105
|
+
|
|
106
|
+
const c = Key.major('C');
|
|
107
|
+
|
|
108
|
+
c.roman('V7/V').symbol(); // 'D7' (セカンダリードミナント)
|
|
109
|
+
c.chord(4, 'dom7').roman(); // 'V7'
|
|
110
|
+
Chord.parse('F#m7b5').pitchClasses(); // [0, 4, 6, 9]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
コードの語彙は三和音から 13th までを網羅していて、`dim7`, `m7b5`, `minMaj7`, `aug7`、6th 系、オルタードドミナントも含みます。
|
|
114
|
+
|
|
115
|
+
スタイルのプリセットから進行そのものを生成することもできます(コレクション単位の操作なので関数として提供されます)。
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { generateProgression, majorKey } from '@libraz/libcantus';
|
|
119
|
+
|
|
120
|
+
// 1 小節につき 1 コード。収まる箇所にはセカンダリードミナントを挿入する:
|
|
121
|
+
generateProgression({ key: majorKey(0), style: 'idol', bars: 8, reharmonize: true, seed: 1 });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 和声を解析する
|
|
125
|
+
|
|
126
|
+
コードを、和声機能・終止・モーダルインターチェンジつきのローマ数字解析に変換します。長調と短調の双方に対応し、転回形も反映されます。
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { Chord, Key } from '@libraz/libcantus';
|
|
130
|
+
|
|
131
|
+
// 長調に現れる短調の iv は、借用されたサブドミナントとして解釈される:
|
|
132
|
+
Chord.of('F', 'min').analyze(Key.major('C'));
|
|
133
|
+
// { function: 'subdominant', borrowed: true, source: 'parallelMinor', roman: 'iv' }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## コードとキーを判定する
|
|
137
|
+
|
|
138
|
+
ノートを入れるとコードやキーが返ります。組み立てとちょうど逆方向の処理です。
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { Chord, detectKey } from '@libraz/libcantus';
|
|
142
|
+
|
|
143
|
+
Chord.detect([60, 64, 67])[0].symbol(); // 'C'
|
|
144
|
+
Chord.detectBest([60, 63, 67, 70])?.symbol(); // 'Cm7'
|
|
145
|
+
detectKey([0, 0, 0, 4, 7])[0]; // 最も適合する C メジャー (キーのランキングは関数として提供)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## コードとスケールを綴る
|
|
149
|
+
|
|
150
|
+
`Key` は綴りを持ったトニックを保持しているので、ピッチクラスで動くコア部分からでも音名の文字列が得られます。長調でも短調でも綴りは正しくなります。
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { Chord, Key } from '@libraz/libcantus';
|
|
154
|
+
|
|
155
|
+
Key.named('harmonicMinor', 'A').noteNames(); // ['A', 'B', 'C', 'D', 'E', 'F', 'G#']
|
|
156
|
+
Key.minor('E').noteNames(); // ['E', 'F#', 'G', 'A', 'B', 'C', 'D']
|
|
157
|
+
|
|
158
|
+
// コードもキーの文脈に沿って綴られる:
|
|
159
|
+
Key.major('C').chord(4, 'dom7').spell().map((n) => n.name); // ['G', 'B', 'D', 'F']
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## リハーモナイズする
|
|
163
|
+
|
|
164
|
+
クラス側ではネガティブハーモニーによる反転を、関数側では代理コードの候補(裏コード、平行調、借用、クロマチックメディアント、およびモーダルインターチェンジのパレット)の列挙を扱います。
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { Chord, Key, majorKey, parseChordSymbol, substituteChord } from '@libraz/libcantus';
|
|
168
|
+
|
|
169
|
+
Key.major('C').chord(4, 'dom7').negativeHarmony().symbol(); // 'Dm7b5'
|
|
170
|
+
|
|
171
|
+
// 代理コードやパレットの検索はリストを返すので関数として提供される:
|
|
172
|
+
substituteChord(parseChordSymbol('G7'), majorKey(0));
|
|
173
|
+
// [{ chord: Db7, type: 'tritone', ... }, ...]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## スケールとテンションを選ぶ
|
|
177
|
+
|
|
178
|
+
クラス側で、あるコードに使えるスケールと、そこで利用できるテンションおよびアボイドノートを求められます。`scalesForChanges` を使えば、コード進行全体を通して繋がりが最適になるスケール選択が得られます。
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { Chord } from '@libraz/libcantus';
|
|
182
|
+
|
|
183
|
+
Chord.of('C', 'dom7').scales()[0]; // { name: 'mixolydian', rootPc: 0 }
|
|
184
|
+
Chord.of('C', 'maj7').tensions('ionian'); // [2, 9] (9th と 13th。11th はアボイドノート)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## コードをボイシングする
|
|
188
|
+
|
|
189
|
+
進行全体を、声部の動きが最小になる 4 声(SATB)の MIDI ボイシングに展開できます。単体のコードをコンピングスタイル(drop-2/3、シェル、ルートレス)でボイシングすることもできます。
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { Chord, Key } from '@libraz/libcantus';
|
|
193
|
+
|
|
194
|
+
const c = Key.major('C');
|
|
195
|
+
|
|
196
|
+
// 進行全体を、動きが最小になるようボイシングする:
|
|
197
|
+
c.chord(0, 'maj').progressionTo(c.chord(5, 'maj'), c.chord(4, 'dom7'), c.chord(0, 'maj')).voice();
|
|
198
|
+
// [[...], [...], [...], [...]] (各声部の音高が昇順に並ぶ)
|
|
199
|
+
|
|
200
|
+
// 単体のコードをシェルボイシングで:
|
|
201
|
+
Chord.of('C', 'maj7').styledVoicing({ style: 'shell' }); // ルート、3rd、7th
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
声部の進行を細かく制御したい場合は `voiceLeadingCost` と `nextVoicing` を、結果を検証したい場合は `counterpoint` の述語群(並行・隠伏の完全音程、音域の間隔、声部の交差、導音の解決など)を使います。
|
|
205
|
+
|
|
206
|
+
## パートを生成する
|
|
207
|
+
|
|
208
|
+
旋律と伴奏のジェネレーターは、いずれもシードを取り決定的に動きます。
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import {
|
|
212
|
+
generateBassLine, generateCounterMelody, generateDrums, generateRhythm,
|
|
213
|
+
generateMotif, majorKey, parseTimeSignature,
|
|
214
|
+
} from '@libraz/libcantus';
|
|
215
|
+
|
|
216
|
+
generateRhythm(parseTimeSignature('4/4'), { seed: 1, density: 0.5 }); // 強拍に重みを置いた発音位置
|
|
217
|
+
const motif = generateMotif({ key: majorKey(0), bars: 2, contour: 'arch', seed: 1 });
|
|
218
|
+
motif.notes.length > 0; // true — 決定的に生成された短い旋律の断片
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`humanize`, `extractGrooveTemplate`, `applyGrooveTemplate` は拍子を踏まえたノリを付け足します。ある演奏のノリを取り出して別の演奏に移植する使い方もできます。
|
|
222
|
+
|
|
223
|
+
## アレンジを解析して足す
|
|
224
|
+
|
|
225
|
+
アレンジ層は、DAW や MIDI ファイルのパーサーが吐いたマルチトラックの `NoteEvent` をそのまま受け取り、和声を復元してから解析と生成を行います。
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
import {
|
|
229
|
+
analyzeArrangement, chordTimelineFromNotes, generateBassLine, generateCounterMelody,
|
|
230
|
+
} from '@libraz/libcantus';
|
|
231
|
+
|
|
232
|
+
// 演奏されたノートからコード進行(とキー)を推定する:
|
|
233
|
+
const { timeline, key } = chordTimelineFromNotes(melodyAndChordNotes);
|
|
234
|
+
|
|
235
|
+
// 曲全体の解析。推定されたコード、終止、ノート単位の理論ラベル、そして
|
|
236
|
+
// 鳴っている和声とぶつかるノート(理由と修正候補つき)が得られる:
|
|
237
|
+
const report = analyzeArrangement([
|
|
238
|
+
{ role: 'melody', notes: melodyNotes },
|
|
239
|
+
{ role: 'harmony', notes: chordNotes },
|
|
240
|
+
]);
|
|
241
|
+
report.conflicts; // [{ beat, trackName, pitch, safety, reasons, rationale }, ...]
|
|
242
|
+
|
|
243
|
+
// 復元されたタイムラインから、足りないパートを生成する:
|
|
244
|
+
generateBassLine({ segments: timeline.segments, key, style: 'walking', seed: 1 });
|
|
245
|
+
generateCounterMelody({ melody: melodyNotes, timeline, key, register: 'below' });
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`harmonizeMelody` は逆方向を担当します。旋律だけを渡すと、それを和声づけするのに最適なキー・移調量・コードの経路を(必要ならリハーモナイズも含めて)探索します。
|
|
249
|
+
|
|
250
|
+
アレンジ層と生成層のあいだでやり取りするノートイベントは `NoteEvent`(`{ pitch, startBeat, durationBeat, velocity? }`。音高は MIDI ノート番号、時間は 4 分音符を 1 とする拍数)の一種類に統一されています。シードを取るジェネレーター(`bass`, `groove`, `countermelody`, `rhythm`, `drums`, `motif`, `progression`)は、同じシードに対して常に同じ結果を返します。
|
|
251
|
+
|
|
252
|
+
## 音高を音響として扱う
|
|
253
|
+
|
|
254
|
+
周波数、セント、EDO、純正律を扱えます。音律の設計、微分音、そして解析に使えます。
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
import { frequencyOf, edo, justDeviationCents } from '@libraz/libcantus';
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
拍子まわりのヘルパー(`TimeSignature`, `parseTimeSignature`, `beatsPerBar`, `metricWeight`, `isStrongBeat`, `tuplet`)は単純拍子と複合拍子の両方を扱い、アクセントを考慮するジェネレーター群の土台にもなっています。
|
|
261
|
+
|
|
262
|
+
## ドキュメント
|
|
263
|
+
|
|
264
|
+
すべてのエクスポートをシグネチャつきで、領域ごとに分類し、動かせる例を添えた API リファレンスをソースから生成して **[libraz.github.io/libcantus](https://libraz.github.io/libcantus/)** に公開しています。
|
|
265
|
+
|
|
266
|
+
## ライセンス
|
|
267
|
+
|
|
268
|
+
Apache-2.0
|
package/dist/analyze/index.cjs
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
11
|
-
require('../chunk-
|
|
10
|
+
var _chunk4VZ5MZAMcjs = require('../chunk-4VZ5MZAM.cjs');
|
|
11
|
+
require('../chunk-2A2QMA74.cjs');
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
@@ -26,12 +26,12 @@ require('../chunk-36N73KZ3.cjs');
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
var
|
|
29
|
+
var _chunkKQN2ZYNDcjs = require('../chunk-KQN2ZYND.cjs');
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
var
|
|
33
|
-
require('../chunk-
|
|
34
|
-
require('../chunk-
|
|
32
|
+
var _chunkWFDXOLUBcjs = require('../chunk-WFDXOLUB.cjs');
|
|
33
|
+
require('../chunk-BSLTLGM3.cjs');
|
|
34
|
+
require('../chunk-PI3UXRWK.cjs');
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
|
|
@@ -58,5 +58,5 @@ require('../chunk-7MGZ7D62.cjs');
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
exports.NoteSafety =
|
|
61
|
+
exports.NoteSafety = _chunkWFDXOLUBcjs.NoteSafety; exports.analyzeArrangement = _chunk4VZ5MZAMcjs.analyzeArrangement; exports.analyzeChord = _chunkKQN2ZYNDcjs.analyzeChord; exports.analyzeVoice = _chunk4VZ5MZAMcjs.analyzeVoice; exports.borrowedSource = _chunkKQN2ZYNDcjs.borrowedSource; exports.chordTimelineFromChords = _chunk4VZ5MZAMcjs.chordTimelineFromChords; exports.chordTimelineFromNotes = _chunk4VZ5MZAMcjs.chordTimelineFromNotes; exports.chordToRoman = _chunkKQN2ZYNDcjs.chordToRoman; exports.detectCadence = _chunkKQN2ZYNDcjs.detectCadence; exports.detectCadences = _chunk4VZ5MZAMcjs.detectCadences; exports.detectChord = _chunkKQN2ZYNDcjs.detectChord; exports.detectChordBest = _chunkKQN2ZYNDcjs.detectChordBest; exports.detectKey = _chunkKQN2ZYNDcjs.detectKey; exports.detectKeyBest = _chunkKQN2ZYNDcjs.detectKeyBest; exports.detectKeyFromNotes = _chunkKQN2ZYNDcjs.detectKeyFromNotes; exports.functionOf = _chunkKQN2ZYNDcjs.functionOf; exports.isBorrowedChord = _chunkKQN2ZYNDcjs.isBorrowedChord; exports.isDiatonic = _chunkKQN2ZYNDcjs.isDiatonic; exports.isMinorKey = _chunkKQN2ZYNDcjs.isMinorKey; exports.parallelKey = _chunkKQN2ZYNDcjs.parallelKey; exports.romanToChord = _chunkKQN2ZYNDcjs.romanToChord; exports.secondaryDominant = _chunkKQN2ZYNDcjs.secondaryDominant; exports.tensionCurve = _chunk4VZ5MZAMcjs.tensionCurve; exports.tensionCurveFrom = _chunk4VZ5MZAMcjs.tensionCurveFrom; exports.toVoiceNotes = _chunk4VZ5MZAMcjs.toVoiceNotes;
|
|
62
62
|
//# sourceMappingURL=index.cjs.map
|
package/dist/analyze/index.d.cts
CHANGED
|
@@ -1,102 +1,12 @@
|
|
|
1
1
|
import { T as TimeSignature } from '../index-DXd9JikN.cjs';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export { a as ChordQuality, b as ChordSegment, c as ChordSpan, P as PitchSpelling } from '../index-
|
|
5
|
-
import { V as VoiceSnapshot, N as NoteSafety, S as SafetyProfile } from '../index-
|
|
6
|
-
import { a as ChordTimeline, C as CadenceHit } from '../index-
|
|
7
|
-
export { b as ChordTimelineOptions, c as ChordTimelineResult, d as chordTimelineFromChords, e as chordTimelineFromNotes, f as detectCadences } from '../index-
|
|
8
|
-
export { C as ChordMatch, D as DetectChordOptions, a as DetectKeyOptions, K as KeyMatch, b as KeyVariant, d as detectChord, c as detectChordBest, e as detectKey, f as detectKeyBest, g as detectKeyFromNotes } from '../index-
|
|
9
|
-
export { B as BorrowedSource, C as Cadence, a as ChordAnalysis, H as HarmonicFunction,
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Roman-numeral parsing and formatting.
|
|
13
|
-
*
|
|
14
|
-
* The {@link ROMAN_STYLE} table is the single source of truth for both
|
|
15
|
-
* directions, so {@link chordToRoman} and {@link romanToChord} stay mutual
|
|
16
|
-
* inverses by construction.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Build the chord denoted by a Roman numeral in a key.
|
|
21
|
-
*
|
|
22
|
-
* Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`
|
|
23
|
-
* suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions
|
|
24
|
-
* (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash
|
|
25
|
-
* (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree
|
|
26
|
-
* whose root becomes a local major tonic for the applied chord. Inverted chords
|
|
27
|
-
* carry a `bassPc`.
|
|
28
|
-
*
|
|
29
|
-
* The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==
|
|
30
|
-
* `m7b5`), since no half-diminished triad exists. Extension and added-tone
|
|
31
|
-
* suffixes are the canonical case-sensitive forms emitted by
|
|
32
|
-
* {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->
|
|
33
|
-
* `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->
|
|
34
|
-
* `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->
|
|
35
|
-
* `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.
|
|
36
|
-
* A figure string that is neither a recognized inversion nor a supported
|
|
37
|
-
* quality suffix throws rather than silently degrading to a triad.
|
|
38
|
-
*
|
|
39
|
-
* @param text The Roman numeral.
|
|
40
|
-
* @param key The prevailing key.
|
|
41
|
-
* @returns The chord.
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* import { romanToChord, majorKey } from '@libraz/libcantus';
|
|
45
|
-
* romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }
|
|
46
|
-
* ```
|
|
47
|
-
* @category Functional Harmony
|
|
48
|
-
*/
|
|
49
|
-
declare function romanToChord(text: string, key: KeyScale): Chord;
|
|
50
|
-
/**
|
|
51
|
-
* Options for {@link chordToRoman}.
|
|
52
|
-
*
|
|
53
|
-
* @category Functional Harmony
|
|
54
|
-
*/
|
|
55
|
-
type ChordToRomanOptions = {
|
|
56
|
-
/**
|
|
57
|
-
* Render a tonicizing chord as an applied numeral (`V7/V`, `viio7/ii`)
|
|
58
|
-
* instead of naming its root against the home key (`II7`, `#ivo7`).
|
|
59
|
-
*
|
|
60
|
-
* Off by default: naming the root is always a correct spelling, whereas
|
|
61
|
-
* whether a chromatic dominant is genuinely applied is a reading only the
|
|
62
|
-
* caller can make. Turning it on makes {@link chordToRoman} the exact inverse
|
|
63
|
-
* of {@link romanToChord} for the chords {@link secondaryDominant} builds.
|
|
64
|
-
*/
|
|
65
|
-
applied?: boolean;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Render a chord as a Roman numeral relative to a key.
|
|
69
|
-
*
|
|
70
|
-
* Diatonic roots take their scale-degree numeral directly, so numerals are
|
|
71
|
-
* correct in both major and minor keys (and any custom scale). The quality
|
|
72
|
-
* selects the case and suffix; chromatic roots receive a flat/sharp spelling by
|
|
73
|
-
* convention. A key that is not heptatonic has no numeral of its own for every
|
|
74
|
-
* degree, so its roots are named against its parallel major.
|
|
75
|
-
*
|
|
76
|
-
* When the chord carries a `bassPc` on a chord tone, a figured-bass inversion
|
|
77
|
-
* (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true seventh
|
|
78
|
-
* chords; added-tone and extended qualities have no lossless figure and render
|
|
79
|
-
* in root position instead (the bass is dropped, pitch classes are preserved).
|
|
80
|
-
*
|
|
81
|
-
* A `bassPc` that is *not* a chord tone — a pedal or passing bass such as
|
|
82
|
-
* `C/D` — is likewise dropped, and the numeral names the upper chord alone.
|
|
83
|
-
* Roman-numeral notation spends its slash on applied chords (`V7/V`), so there
|
|
84
|
-
* is no unambiguous way to write such a bass; a caller that must keep it should
|
|
85
|
-
* read `chord.bassPc` alongside the numeral.
|
|
86
|
-
*
|
|
87
|
-
* @param chord The chord to name.
|
|
88
|
-
* @param key The prevailing key.
|
|
89
|
-
* @param opts `applied` renders tonicizing chords as `V7/V`-style numerals.
|
|
90
|
-
* @returns The Roman numeral string.
|
|
91
|
-
* @example
|
|
92
|
-
* ```ts
|
|
93
|
-
* import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';
|
|
94
|
-
* chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)
|
|
95
|
-
* chordToRoman(makeChord(2, 'dom7'), majorKey(0), { applied: true }); // => 'V7/V'
|
|
96
|
-
* ```
|
|
97
|
-
* @category Functional Harmony
|
|
98
|
-
*/
|
|
99
|
-
declare function chordToRoman(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): string;
|
|
2
|
+
import { N as NoteEvent, K as KeyScale } from '../types-BN6_Q9Kl.cjs';
|
|
3
|
+
import { d as ChordToneRole, C as Chord } from '../index-oTQbYYIs.cjs';
|
|
4
|
+
export { a as ChordQuality, b as ChordSegment, c as ChordSpan, P as PitchSpelling } from '../index-oTQbYYIs.cjs';
|
|
5
|
+
import { V as VoiceSnapshot, N as NoteSafety, S as SafetyProfile } from '../index-B2Ulxxpo.cjs';
|
|
6
|
+
import { a as ChordTimeline, C as CadenceHit } from '../index-BkYJ0xMq.cjs';
|
|
7
|
+
export { b as ChordTimelineOptions, c as ChordTimelineResult, d as chordTimelineFromChords, e as chordTimelineFromNotes, f as detectCadences } from '../index-BkYJ0xMq.cjs';
|
|
8
|
+
export { C as ChordMatch, D as DetectChordOptions, a as DetectKeyOptions, K as KeyMatch, b as KeyVariant, d as detectChord, c as detectChordBest, e as detectKey, f as detectKeyBest, g as detectKeyFromNotes } from '../index-alrRninU.cjs';
|
|
9
|
+
export { B as BorrowedSource, C as Cadence, a as ChordAnalysis, b as ChordToRomanOptions, H as HarmonicFunction, c as analyzeChord, d as borrowedSource, e as chordToRoman, f as detectCadence, g as functionOf, i as isBorrowedChord, h as isDiatonic, j as isMinorKey, p as parallelKey, r as romanToChord, s as secondaryDominant } from '../function-CxixTB02.cjs';
|
|
100
10
|
|
|
101
11
|
/**
|
|
102
12
|
* A suspension figure, named by the interval above the bass and the interval it
|
|
@@ -498,4 +408,4 @@ declare function tensionCurveFrom(tracks: ArrangementTrack[], analysis: Arrangem
|
|
|
498
408
|
step?: number;
|
|
499
409
|
}): TensionPoint[];
|
|
500
410
|
|
|
501
|
-
export { type AnalyzedNote, type ArrangementAnalysis, type ArrangementOptions, type ArrangementTrack, CadenceHit, Chord as ChordData, ChordTimeline,
|
|
411
|
+
export { type AnalyzedNote, type ArrangementAnalysis, type ArrangementOptions, type ArrangementTrack, CadenceHit, Chord as ChordData, ChordTimeline, ChordToneRole, type Conflict, type IdentifiedVoiceNote, KeyScale, NoteEvent, NoteSafety, SafetyProfile, type SuspensionFigure, type TensionPoint, type TheoryLabel, TimeSignature, type TrackAnalysis, type TrackRole, type VoiceNote, VoiceSnapshot, analyzeArrangement, analyzeVoice, tensionCurve, tensionCurveFrom, toVoiceNotes };
|
package/dist/analyze/index.d.ts
CHANGED
|
@@ -1,102 +1,12 @@
|
|
|
1
1
|
import { T as TimeSignature } from '../index-DXd9JikN.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export { a as ChordQuality, b as ChordSegment, c as ChordSpan, P as PitchSpelling } from '../index-
|
|
5
|
-
import { V as VoiceSnapshot, N as NoteSafety, S as SafetyProfile } from '../index-
|
|
6
|
-
import { a as ChordTimeline, C as CadenceHit } from '../index-
|
|
7
|
-
export { b as ChordTimelineOptions, c as ChordTimelineResult, d as chordTimelineFromChords, e as chordTimelineFromNotes, f as detectCadences } from '../index-
|
|
8
|
-
export { C as ChordMatch, D as DetectChordOptions, a as DetectKeyOptions, K as KeyMatch, b as KeyVariant, d as detectChord, c as detectChordBest, e as detectKey, f as detectKeyBest, g as detectKeyFromNotes } from '../index-
|
|
9
|
-
export { B as BorrowedSource, C as Cadence, a as ChordAnalysis, H as HarmonicFunction,
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Roman-numeral parsing and formatting.
|
|
13
|
-
*
|
|
14
|
-
* The {@link ROMAN_STYLE} table is the single source of truth for both
|
|
15
|
-
* directions, so {@link chordToRoman} and {@link romanToChord} stay mutual
|
|
16
|
-
* inverses by construction.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Build the chord denoted by a Roman numeral in a key.
|
|
21
|
-
*
|
|
22
|
-
* Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`
|
|
23
|
-
* suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions
|
|
24
|
-
* (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash
|
|
25
|
-
* (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree
|
|
26
|
-
* whose root becomes a local major tonic for the applied chord. Inverted chords
|
|
27
|
-
* carry a `bassPc`.
|
|
28
|
-
*
|
|
29
|
-
* The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==
|
|
30
|
-
* `m7b5`), since no half-diminished triad exists. Extension and added-tone
|
|
31
|
-
* suffixes are the canonical case-sensitive forms emitted by
|
|
32
|
-
* {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->
|
|
33
|
-
* `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->
|
|
34
|
-
* `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->
|
|
35
|
-
* `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.
|
|
36
|
-
* A figure string that is neither a recognized inversion nor a supported
|
|
37
|
-
* quality suffix throws rather than silently degrading to a triad.
|
|
38
|
-
*
|
|
39
|
-
* @param text The Roman numeral.
|
|
40
|
-
* @param key The prevailing key.
|
|
41
|
-
* @returns The chord.
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* import { romanToChord, majorKey } from '@libraz/libcantus';
|
|
45
|
-
* romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }
|
|
46
|
-
* ```
|
|
47
|
-
* @category Functional Harmony
|
|
48
|
-
*/
|
|
49
|
-
declare function romanToChord(text: string, key: KeyScale): Chord;
|
|
50
|
-
/**
|
|
51
|
-
* Options for {@link chordToRoman}.
|
|
52
|
-
*
|
|
53
|
-
* @category Functional Harmony
|
|
54
|
-
*/
|
|
55
|
-
type ChordToRomanOptions = {
|
|
56
|
-
/**
|
|
57
|
-
* Render a tonicizing chord as an applied numeral (`V7/V`, `viio7/ii`)
|
|
58
|
-
* instead of naming its root against the home key (`II7`, `#ivo7`).
|
|
59
|
-
*
|
|
60
|
-
* Off by default: naming the root is always a correct spelling, whereas
|
|
61
|
-
* whether a chromatic dominant is genuinely applied is a reading only the
|
|
62
|
-
* caller can make. Turning it on makes {@link chordToRoman} the exact inverse
|
|
63
|
-
* of {@link romanToChord} for the chords {@link secondaryDominant} builds.
|
|
64
|
-
*/
|
|
65
|
-
applied?: boolean;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Render a chord as a Roman numeral relative to a key.
|
|
69
|
-
*
|
|
70
|
-
* Diatonic roots take their scale-degree numeral directly, so numerals are
|
|
71
|
-
* correct in both major and minor keys (and any custom scale). The quality
|
|
72
|
-
* selects the case and suffix; chromatic roots receive a flat/sharp spelling by
|
|
73
|
-
* convention. A key that is not heptatonic has no numeral of its own for every
|
|
74
|
-
* degree, so its roots are named against its parallel major.
|
|
75
|
-
*
|
|
76
|
-
* When the chord carries a `bassPc` on a chord tone, a figured-bass inversion
|
|
77
|
-
* (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true seventh
|
|
78
|
-
* chords; added-tone and extended qualities have no lossless figure and render
|
|
79
|
-
* in root position instead (the bass is dropped, pitch classes are preserved).
|
|
80
|
-
*
|
|
81
|
-
* A `bassPc` that is *not* a chord tone — a pedal or passing bass such as
|
|
82
|
-
* `C/D` — is likewise dropped, and the numeral names the upper chord alone.
|
|
83
|
-
* Roman-numeral notation spends its slash on applied chords (`V7/V`), so there
|
|
84
|
-
* is no unambiguous way to write such a bass; a caller that must keep it should
|
|
85
|
-
* read `chord.bassPc` alongside the numeral.
|
|
86
|
-
*
|
|
87
|
-
* @param chord The chord to name.
|
|
88
|
-
* @param key The prevailing key.
|
|
89
|
-
* @param opts `applied` renders tonicizing chords as `V7/V`-style numerals.
|
|
90
|
-
* @returns The Roman numeral string.
|
|
91
|
-
* @example
|
|
92
|
-
* ```ts
|
|
93
|
-
* import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';
|
|
94
|
-
* chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)
|
|
95
|
-
* chordToRoman(makeChord(2, 'dom7'), majorKey(0), { applied: true }); // => 'V7/V'
|
|
96
|
-
* ```
|
|
97
|
-
* @category Functional Harmony
|
|
98
|
-
*/
|
|
99
|
-
declare function chordToRoman(chord: Chord, key: KeyScale, opts?: ChordToRomanOptions): string;
|
|
2
|
+
import { N as NoteEvent, K as KeyScale } from '../types-BN6_Q9Kl.js';
|
|
3
|
+
import { d as ChordToneRole, C as Chord } from '../index-COw1Ky9g.js';
|
|
4
|
+
export { a as ChordQuality, b as ChordSegment, c as ChordSpan, P as PitchSpelling } from '../index-COw1Ky9g.js';
|
|
5
|
+
import { V as VoiceSnapshot, N as NoteSafety, S as SafetyProfile } from '../index-BuaB-ypt.js';
|
|
6
|
+
import { a as ChordTimeline, C as CadenceHit } from '../index-DRtIhlJj.js';
|
|
7
|
+
export { b as ChordTimelineOptions, c as ChordTimelineResult, d as chordTimelineFromChords, e as chordTimelineFromNotes, f as detectCadences } from '../index-DRtIhlJj.js';
|
|
8
|
+
export { C as ChordMatch, D as DetectChordOptions, a as DetectKeyOptions, K as KeyMatch, b as KeyVariant, d as detectChord, c as detectChordBest, e as detectKey, f as detectKeyBest, g as detectKeyFromNotes } from '../index-CAN7v-kw.js';
|
|
9
|
+
export { B as BorrowedSource, C as Cadence, a as ChordAnalysis, b as ChordToRomanOptions, H as HarmonicFunction, c as analyzeChord, d as borrowedSource, e as chordToRoman, f as detectCadence, g as functionOf, i as isBorrowedChord, h as isDiatonic, j as isMinorKey, p as parallelKey, r as romanToChord, s as secondaryDominant } from '../function-DTCt675z.js';
|
|
100
10
|
|
|
101
11
|
/**
|
|
102
12
|
* A suspension figure, named by the interval above the bass and the interval it
|
|
@@ -498,4 +408,4 @@ declare function tensionCurveFrom(tracks: ArrangementTrack[], analysis: Arrangem
|
|
|
498
408
|
step?: number;
|
|
499
409
|
}): TensionPoint[];
|
|
500
410
|
|
|
501
|
-
export { type AnalyzedNote, type ArrangementAnalysis, type ArrangementOptions, type ArrangementTrack, CadenceHit, Chord as ChordData, ChordTimeline,
|
|
411
|
+
export { type AnalyzedNote, type ArrangementAnalysis, type ArrangementOptions, type ArrangementTrack, CadenceHit, Chord as ChordData, ChordTimeline, ChordToneRole, type Conflict, type IdentifiedVoiceNote, KeyScale, NoteEvent, NoteSafety, SafetyProfile, type SuspensionFigure, type TensionPoint, type TheoryLabel, TimeSignature, type TrackAnalysis, type TrackRole, type VoiceNote, VoiceSnapshot, analyzeArrangement, analyzeVoice, tensionCurve, tensionCurveFrom, toVoiceNotes };
|