@libraz/libcantus 0.9.3 → 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 +29 -20
- package/README_ja.md +268 -0
- package/dist/analyze/index.cjs +39 -1947
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +161 -91
- package/dist/analyze/index.d.ts +161 -91
- package/dist/analyze/index.js +19 -8
- package/dist/chunk-2A2QMA74.cjs +261 -0
- package/dist/chunk-2A2QMA74.cjs.map +1 -0
- package/dist/chunk-2PTFGVD7.js +261 -0
- package/dist/chunk-2PTFGVD7.js.map +1 -0
- package/dist/chunk-357ZDPVU.cjs +162 -0
- package/dist/chunk-357ZDPVU.cjs.map +1 -0
- package/dist/chunk-3KX76RLG.js +1548 -0
- package/dist/chunk-3KX76RLG.js.map +1 -0
- package/dist/chunk-4VZ5MZAM.cjs +889 -0
- package/dist/chunk-4VZ5MZAM.cjs.map +1 -0
- package/dist/{chunk-C5XYKUVG.js → chunk-7EONYVI5.js} +471 -171
- package/dist/chunk-7EONYVI5.js.map +1 -0
- package/dist/{chunk-IT2O4XFE.js → chunk-7JEP3MFY.js} +42 -34
- package/dist/chunk-7JEP3MFY.js.map +1 -0
- package/dist/{chunk-4MHA432G.js → chunk-AID75RN3.js} +572 -250
- package/dist/chunk-AID75RN3.js.map +1 -0
- package/dist/chunk-BSLTLGM3.cjs +497 -0
- package/dist/chunk-BSLTLGM3.cjs.map +1 -0
- package/dist/chunk-CU6VG2YM.cjs +109 -0
- package/dist/chunk-CU6VG2YM.cjs.map +1 -0
- package/dist/{chunk-EH6EM37U.js → chunk-DZMHIGI4.js} +81 -59
- package/dist/chunk-DZMHIGI4.js.map +1 -0
- package/dist/{chunk-AKLYPWIN.js → chunk-EDOTEABK.js} +45 -19
- package/dist/chunk-EDOTEABK.js.map +1 -0
- package/dist/{chunk-2ZWMSJH6.js → chunk-HN2OEUN2.js} +7 -4
- package/dist/chunk-HN2OEUN2.js.map +1 -0
- package/dist/{chunk-MIWO425M.js → chunk-KBTTEX7Q.js} +128 -43
- package/dist/chunk-KBTTEX7Q.js.map +1 -0
- package/dist/chunk-KQN2ZYND.cjs +724 -0
- package/dist/chunk-KQN2ZYND.cjs.map +1 -0
- package/dist/chunk-MPTVJIVG.cjs +3176 -0
- package/dist/chunk-MPTVJIVG.cjs.map +1 -0
- package/dist/chunk-MTMZTMWM.cjs +53 -0
- package/dist/chunk-MTMZTMWM.cjs.map +1 -0
- package/dist/{chunk-CHMXELDS.js → chunk-NNB67XA2.js} +372 -197
- package/dist/chunk-NNB67XA2.js.map +1 -0
- package/dist/chunk-OL3IHHSJ.cjs +1204 -0
- package/dist/chunk-OL3IHHSJ.cjs.map +1 -0
- package/dist/chunk-PI3UXRWK.cjs +528 -0
- package/dist/chunk-PI3UXRWK.cjs.map +1 -0
- package/dist/chunk-R2VVFAIN.js +528 -0
- package/dist/chunk-R2VVFAIN.js.map +1 -0
- package/dist/chunk-T64C7ZD7.cjs +1 -0
- package/dist/chunk-T64C7ZD7.cjs.map +1 -0
- package/dist/chunk-WFDXOLUB.cjs +337 -0
- package/dist/chunk-WFDXOLUB.cjs.map +1 -0
- package/dist/chunk-WTAN4ACG.cjs +1548 -0
- package/dist/chunk-WTAN4ACG.cjs.map +1 -0
- package/dist/chunk-YFJXS3AU.cjs +33 -0
- package/dist/chunk-YFJXS3AU.cjs.map +1 -0
- package/dist/{chunk-GOAW4VYL.js → chunk-YUE6TJ4M.js} +315 -145
- package/dist/chunk-YUE6TJ4M.js.map +1 -0
- package/dist/{chunk-62QZKCJQ.js → chunk-ZGLJM4A4.js} +10 -6
- package/dist/chunk-ZGLJM4A4.js.map +1 -0
- package/dist/core/index.cjs +140 -647
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +313 -41
- package/dist/core/index.d.ts +313 -41
- package/dist/core/index.js +64 -16
- package/dist/{function-DVH4Eusr.d.ts → function-CxixTB02.d.cts} +122 -10
- package/dist/{function-DYt4iKsn.d.cts → function-DTCt675z.d.ts} +122 -10
- package/dist/generate/index.cjs +28 -4085
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +374 -66
- package/dist/generate/index.d.ts +374 -66
- package/dist/generate/index.js +23 -9
- package/dist/{index-Jc0Ryi79.d.ts → index-B2Ulxxpo.d.cts} +21 -5
- package/dist/{index-CpOsP1y9.d.cts → index-BkYJ0xMq.d.cts} +18 -17
- package/dist/{index-CxqBQtH1.d.cts → index-BuaB-ypt.d.ts} +21 -5
- package/dist/index-CAN7v-kw.d.ts +199 -0
- package/dist/{index-Bt4tOUD9.d.ts → index-COw1Ky9g.d.ts} +93 -8
- package/dist/{index-Dikst44v.d.cts → index-Cfx8xgH0.d.ts} +14 -11
- package/dist/{index-DxvARIP2.d.ts → index-DRtIhlJj.d.ts} +18 -17
- package/dist/{index-Cl7mhOFM.d.cts → index-DXd9JikN.d.cts} +92 -10
- package/dist/{index-Cl7mhOFM.d.ts → index-DXd9JikN.d.ts} +92 -10
- package/dist/index-alrRninU.d.cts +199 -0
- package/dist/{index-BNlGP86A.d.cts → index-oTQbYYIs.d.cts} +93 -8
- package/dist/index-tR9jTn26.d.cts +275 -0
- package/dist/index-tR9jTn26.d.ts +275 -0
- package/dist/{index-Bg5dYMmZ.d.ts → index-x2vcsduE.d.cts} +14 -11
- package/dist/index.cjs +429 -7383
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +121 -27
- package/dist/model/index.cjs +8 -2562
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +471 -81
- package/dist/model/index.d.ts +471 -81
- package/dist/model/index.js +6 -7
- package/dist/styled-Bl0ZK28h.d.ts +543 -0
- package/dist/styled-Crv6SA4S.d.cts +543 -0
- package/dist/theory/index.cjs +172 -1822
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +151 -233
- package/dist/theory/index.d.ts +151 -233
- package/dist/theory/index.js +30 -7
- package/dist/{types-MGP29r3t.d.cts → types-BN6_Q9Kl.d.cts} +11 -2
- package/dist/{types-MGP29r3t.d.ts → types-BN6_Q9Kl.d.ts} +11 -2
- package/package.json +34 -13
- package/dist/chunk-2ZWMSJH6.js.map +0 -1
- package/dist/chunk-4MHA432G.js.map +0 -1
- package/dist/chunk-62QZKCJQ.js.map +0 -1
- package/dist/chunk-AKLYPWIN.js.map +0 -1
- package/dist/chunk-C5XYKUVG.js.map +0 -1
- package/dist/chunk-CHMXELDS.js.map +0 -1
- package/dist/chunk-DYWFNC4A.js +0 -152
- package/dist/chunk-DYWFNC4A.js.map +0 -1
- package/dist/chunk-EH6EM37U.js.map +0 -1
- package/dist/chunk-FBQK3ZQN.js +0 -131
- package/dist/chunk-FBQK3ZQN.js.map +0 -1
- package/dist/chunk-GOAW4VYL.js.map +0 -1
- package/dist/chunk-I5R7ZBJS.js +0 -202
- package/dist/chunk-I5R7ZBJS.js.map +0 -1
- package/dist/chunk-IT2O4XFE.js.map +0 -1
- package/dist/chunk-MIWO425M.js.map +0 -1
- package/dist/chunk-SGU7SPLK.js +0 -924
- package/dist/chunk-SGU7SPLK.js.map +0 -1
- package/dist/index-CGMZNCx6.d.cts +0 -140
- package/dist/index-CGMZNCx6.d.ts +0 -140
- package/dist/index-CnZCo29u.d.cts +0 -108
- package/dist/index-JnF4v9bx.d.ts +0 -108
- package/dist/styled-DZ7GjShb.d.ts +0 -282
- package/dist/styled-ZTbdaVFM.d.cts +0 -282
- package/src/analyze/arrange/index.ts +0 -21
- package/src/analyze/arrange/internal.ts +0 -127
- package/src/analyze/arrange/tension.ts +0 -199
- package/src/analyze/arrange/tracks.ts +0 -312
- package/src/analyze/detect/index.ts +0 -272
- package/src/analyze/functional/borrowed.ts +0 -84
- package/src/analyze/functional/cadence.ts +0 -66
- package/src/analyze/functional/function.ts +0 -184
- package/src/analyze/functional/index.ts +0 -23
- package/src/analyze/functional/internal.ts +0 -29
- package/src/analyze/functional/roman.ts +0 -402
- package/src/analyze/index.ts +0 -49
- package/src/analyze/timeline/index.ts +0 -451
- package/src/analyze/voice/index.ts +0 -339
- package/src/core/event-index/index.ts +0 -104
- package/src/core/index.ts +0 -61
- package/src/core/interval/index.ts +0 -81
- package/src/core/meter/index.ts +0 -302
- package/src/core/pitch/index.ts +0 -311
- package/src/core/random/index.ts +0 -76
- package/src/core/tuning/index.ts +0 -186
- package/src/core/types.ts +0 -29
- package/src/core/validation/index.ts +0 -119
- package/src/generate/bass/index.ts +0 -373
- package/src/generate/countermelody/index.ts +0 -470
- package/src/generate/drums/beat.ts +0 -266
- package/src/generate/drums/euclid.ts +0 -65
- package/src/generate/drums/fills.ts +0 -356
- package/src/generate/drums/ghost.ts +0 -119
- package/src/generate/drums/hihat.ts +0 -285
- package/src/generate/drums/hit.ts +0 -31
- package/src/generate/drums/index.ts +0 -361
- package/src/generate/drums/internal.ts +0 -257
- package/src/generate/drums/kick.ts +0 -160
- package/src/generate/drums/percussion.ts +0 -121
- package/src/generate/drums/rng.ts +0 -7
- package/src/generate/drums/swing.ts +0 -71
- package/src/generate/groove/index.ts +0 -351
- package/src/generate/harmonize/index.ts +0 -451
- package/src/generate/index.ts +0 -58
- package/src/generate/motif/index.ts +0 -422
- package/src/generate/progression/index.ts +0 -362
- package/src/generate/reharmony/index.ts +0 -323
- package/src/generate/rhythm/index.ts +0 -175
- package/src/index.ts +0 -13
- package/src/model/chord.ts +0 -442
- package/src/model/index.ts +0 -15
- package/src/model/interval.ts +0 -82
- package/src/model/key.ts +0 -266
- package/src/model/note.ts +0 -176
- package/src/model/progression.ts +0 -161
- package/src/model/shared.ts +0 -12
- package/src/theory/chord/index.ts +0 -375
- package/src/theory/chordscale/index.ts +0 -374
- package/src/theory/counterpoint/index.ts +0 -230
- package/src/theory/harmony/index.ts +0 -77
- package/src/theory/index.ts +0 -112
- package/src/theory/safety/index.ts +0 -488
- package/src/theory/scale/degrees.ts +0 -123
- package/src/theory/scale/index.ts +0 -28
- package/src/theory/scale/key.ts +0 -56
- package/src/theory/scale/masks.ts +0 -153
- package/src/theory/spelling/index.ts +0 -249
- package/src/theory/symbol/index.ts +0 -268
- package/src/theory/voicing/index.ts +0 -5
- package/src/theory/voicing/internal.ts +0 -168
- package/src/theory/voicing/leading.ts +0 -112
- package/src/theory/voicing/satb.ts +0 -216
- package/src/theory/voicing/styled.ts +0 -199
- package/tsconfig.json +0 -23
package/dist/analyze/index.d.ts
CHANGED
|
@@ -1,75 +1,20 @@
|
|
|
1
|
-
import { T as TimeSignature } from '../index-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { C as
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
1
|
+
import { T as TimeSignature } from '../index-DXd9JikN.js';
|
|
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';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* A suspension figure, named by the interval above the bass and the interval it
|
|
13
|
+
* resolves to.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
* directions, so {@link chordToRoman} and {@link romanToChord} stay mutual
|
|
15
|
-
* inverses by construction.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Build the chord denoted by a Roman numeral in a key.
|
|
20
|
-
*
|
|
21
|
-
* Supports accidentals (`bVII`, `#iv`), case-based triad quality, the `o`/`ø`/`+`
|
|
22
|
-
* suffixes, sevenths (`V7`, `viio7`, `Imaj7`), figured-bass inversions
|
|
23
|
-
* (`V6`, `V64`, `V65`, `V43`, `V42`), and applied/secondary chords via a slash
|
|
24
|
-
* (`V7/V`, `viio/ii`). The target after the slash is read as a scale degree
|
|
25
|
-
* whose root becomes a local major tonic for the applied chord. Inverted chords
|
|
26
|
-
* carry a `bassPc`.
|
|
27
|
-
*
|
|
28
|
-
* The `ø` glyph always denotes the half-diminished seventh (`iiø` == `iiø7` ==
|
|
29
|
-
* `m7b5`), since no half-diminished triad exists. Extension and added-tone
|
|
30
|
-
* suffixes are the canonical case-sensitive forms emitted by
|
|
31
|
-
* {@link chordToRoman} and honor the numeral case: `V9` -> `dom9`, `ii9` ->
|
|
32
|
-
* `min9`, `Imaj9` -> `maj9`, `V11` -> `11`, `V13` -> `13`, `Iadd6`/`iadd6` ->
|
|
33
|
-
* `6`/`min6`, `I69` -> `6/9`, `Isus2`/`Isus4`, `Iadd9`/`Iadd11`, `Ib5` ->
|
|
34
|
-
* `majb5`, `I5` -> `5`, and the altered dominants `V7b9`/`V7#9`/`V7#11`/`V7b13`.
|
|
35
|
-
* A figure string that is neither a recognized inversion nor a supported
|
|
36
|
-
* quality suffix throws rather than silently degrading to a triad.
|
|
37
|
-
*
|
|
38
|
-
* @param text The Roman numeral.
|
|
39
|
-
* @param key The prevailing key.
|
|
40
|
-
* @returns The chord.
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* import { romanToChord, majorKey } from '@libraz/libcantus';
|
|
44
|
-
* romanToChord('V7', majorKey(0)); // G7 in C major: { rootPc: 7, quality: 'dom7', ... }
|
|
45
|
-
* ```
|
|
46
|
-
* @category Functional Harmony
|
|
47
|
-
*/
|
|
48
|
-
declare function romanToChord(text: string, key: KeyScale): Chord;
|
|
49
|
-
/**
|
|
50
|
-
* Render a chord as a Roman numeral relative to a key.
|
|
51
|
-
*
|
|
52
|
-
* Diatonic roots take their scale-degree numeral directly, so numerals are
|
|
53
|
-
* correct in both major and minor keys (and any custom scale). The quality
|
|
54
|
-
* selects the case and suffix; chromatic roots receive a flat/sharp spelling by
|
|
55
|
-
* convention. When the chord carries a `bassPc` on a chord tone, a figured-bass
|
|
56
|
-
* inversion (`6`, `64`, `65`, `43`, `42`) is emitted for plain triads and true
|
|
57
|
-
* seventh chords; added-tone and extended qualities have no lossless figure and
|
|
58
|
-
* render in root position instead (the bass is dropped, pitch classes are
|
|
59
|
-
* preserved).
|
|
60
|
-
*
|
|
61
|
-
* @param chord The chord to name.
|
|
62
|
-
* @param key The prevailing key.
|
|
63
|
-
* @returns The Roman numeral string.
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* import { chordToRoman, makeChord, majorKey } from '@libraz/libcantus';
|
|
67
|
-
* chordToRoman(makeChord(7, 'dom7'), majorKey(0)); // => 'V7' (G7 in C major)
|
|
68
|
-
* ```
|
|
69
|
-
* @category Functional Harmony
|
|
15
|
+
* @category Arrangement & Analysis
|
|
70
16
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
17
|
+
type SuspensionFigure = 'sus4-3' | 'sus6-5' | 'sus7-6' | 'sus9-8' | 'sus2-3';
|
|
73
18
|
/**
|
|
74
19
|
* A theory annotation attached to a note.
|
|
75
20
|
*
|
|
@@ -77,7 +22,7 @@ declare function chordToRoman(chord: Chord, key: KeyScale): string;
|
|
|
77
22
|
*/
|
|
78
23
|
type TheoryLabel = {
|
|
79
24
|
kind: 'chordTone';
|
|
80
|
-
role:
|
|
25
|
+
role: ChordToneRole;
|
|
81
26
|
} | {
|
|
82
27
|
kind: 'tension';
|
|
83
28
|
degree: 9 | 11 | 13;
|
|
@@ -89,7 +34,7 @@ type TheoryLabel = {
|
|
|
89
34
|
kind: 'neighbor';
|
|
90
35
|
} | {
|
|
91
36
|
kind: 'suspension';
|
|
92
|
-
type:
|
|
37
|
+
type: SuspensionFigure;
|
|
93
38
|
resolveTo: number;
|
|
94
39
|
} | {
|
|
95
40
|
kind: 'anticipation';
|
|
@@ -105,21 +50,60 @@ type TheoryLabel = {
|
|
|
105
50
|
/**
|
|
106
51
|
* A note with its theory labels and a short rationale.
|
|
107
52
|
*
|
|
53
|
+
* The labels describe the note against the chord sounding at its **onset**;
|
|
54
|
+
* they are not re-derived for the later chords a long note sustains across.
|
|
55
|
+
* `analyzeArrangement` does re-check every crossed chord change, and reports
|
|
56
|
+
* what it finds as conflicts, so a note labelled a chord tone here can still
|
|
57
|
+
* appear in `conflicts` at a later beat.
|
|
58
|
+
*
|
|
59
|
+
* The identity fields make an annotation mappable back to the caller's input:
|
|
60
|
+
* `originalIndex` is the note's position in the array that was passed in, and
|
|
61
|
+
* `trackIndex` is set by {@link analyzeArrangement}.
|
|
62
|
+
*
|
|
108
63
|
* @category Arrangement & Analysis
|
|
109
64
|
*/
|
|
110
65
|
type AnalyzedNote = {
|
|
111
66
|
noteId: number;
|
|
67
|
+
/** The note's index in the caller's own array, when the caller supplied one. */
|
|
68
|
+
originalIndex?: number;
|
|
69
|
+
/** The note's track, set by `analyzeArrangement`. */
|
|
70
|
+
trackIndex?: number;
|
|
71
|
+
pitch: number;
|
|
72
|
+
startBeat: number;
|
|
73
|
+
durationBeat: number;
|
|
112
74
|
labels: TheoryLabel[];
|
|
113
75
|
rationale?: string;
|
|
114
76
|
};
|
|
115
77
|
/**
|
|
116
|
-
* A single note in a monophonic voice: a {@link NoteEvent} with a stable id
|
|
78
|
+
* A single note in a monophonic voice: a {@link NoteEvent} with a stable id and,
|
|
79
|
+
* optionally, its index in the caller's original array.
|
|
117
80
|
*
|
|
118
81
|
* @category Arrangement & Analysis
|
|
119
82
|
*/
|
|
120
83
|
type VoiceNote = NoteEvent & {
|
|
84
|
+
id?: number;
|
|
85
|
+
originalIndex?: number;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* A voice note whose id has been assigned, as {@link toVoiceNotes} returns and
|
|
89
|
+
* {@link analyzeArrangement} works in.
|
|
90
|
+
*
|
|
91
|
+
* @category Arrangement & Analysis
|
|
92
|
+
*/
|
|
93
|
+
type IdentifiedVoiceNote = VoiceNote & {
|
|
121
94
|
id: number;
|
|
122
95
|
};
|
|
96
|
+
/**
|
|
97
|
+
* Give plain note events the ids {@link analyzeVoice} reports back.
|
|
98
|
+
*
|
|
99
|
+
* The id is only an identity handle, so the array position serves; this exists
|
|
100
|
+
* so the mapping is a named call rather than a `map` every caller writes.
|
|
101
|
+
*
|
|
102
|
+
* @param events The note events, in time order.
|
|
103
|
+
* @returns The same notes as voice notes, each carrying its index as its id.
|
|
104
|
+
* @category Arrangement & Analysis
|
|
105
|
+
*/
|
|
106
|
+
declare function toVoiceNotes(events: readonly NoteEvent[]): IdentifiedVoiceNote[];
|
|
123
107
|
/**
|
|
124
108
|
* Label every note of a voice with its theory roles.
|
|
125
109
|
*
|
|
@@ -136,26 +120,28 @@ type VoiceNote = NoteEvent & {
|
|
|
136
120
|
* escape) — only harmonic ones. Callers with truly polyphonic material should
|
|
137
121
|
* split it into monophonic sub-voices first, as `analyzeArrangement` does.
|
|
138
122
|
*
|
|
139
|
-
* @param voice The monophonic voice, in time order.
|
|
123
|
+
* @param voice The monophonic voice, in time order. A note without an `id` is
|
|
124
|
+
* identified by its position, so plain note events can be passed straight in.
|
|
140
125
|
* @param chordAtBeat Chord sounding at a given beat, or null.
|
|
141
126
|
* @param key Key context for leading-tone detection.
|
|
142
|
-
* @param otherVoicesAtBeat Other sounding voices at a given beat
|
|
127
|
+
* @param otherVoicesAtBeat Other sounding voices at a given beat; defaults to
|
|
128
|
+
* none, which is the whole story for a solo line.
|
|
143
129
|
* @returns One annotation per input note.
|
|
144
130
|
* @example
|
|
145
131
|
* ```ts
|
|
146
132
|
* import { analyzeVoice, makeChord, majorKey } from '@libraz/libcantus';
|
|
147
133
|
* const voice = [
|
|
148
|
-
* {
|
|
149
|
-
* {
|
|
150
|
-
* {
|
|
134
|
+
* { pitch: 60, startBeat: 0, durationBeat: 1 },
|
|
135
|
+
* { pitch: 62, startBeat: 1, durationBeat: 1 },
|
|
136
|
+
* { pitch: 64, startBeat: 2, durationBeat: 1 },
|
|
151
137
|
* ];
|
|
152
138
|
* const cMajor = makeChord(0, 'maj');
|
|
153
|
-
* const labels = analyzeVoice(voice, () => cMajor, majorKey(0)
|
|
139
|
+
* const labels = analyzeVoice(voice, () => cMajor, majorKey(0));
|
|
154
140
|
* labels; // one AnalyzedNote per input note, in the same order
|
|
155
141
|
* ```
|
|
156
142
|
* @category Arrangement & Analysis
|
|
157
143
|
*/
|
|
158
|
-
declare function analyzeVoice(voice: VoiceNote[], chordAtBeat: (beat: number) => Chord | null, key: KeyScale, otherVoicesAtBeat
|
|
144
|
+
declare function analyzeVoice(voice: readonly VoiceNote[], chordAtBeat: (beat: number) => Chord | null, key: KeyScale, otherVoicesAtBeat?: (beat: number) => VoiceSnapshot[]): AnalyzedNote[];
|
|
159
145
|
|
|
160
146
|
/**
|
|
161
147
|
* Arrangement track-role analysis: a single harmony is inferred from every
|
|
@@ -167,9 +153,18 @@ declare function analyzeVoice(voice: VoiceNote[], chordAtBeat: (beat: number) =>
|
|
|
167
153
|
/**
|
|
168
154
|
* The musical role a track plays in the arrangement.
|
|
169
155
|
*
|
|
156
|
+
* Only `drums` changes the analysis: its pitches select instruments rather than
|
|
157
|
+
* naming harmony, so such a track is excluded from chord and key inference and
|
|
158
|
+
* from every voice-leading comparison, and is reported back with no
|
|
159
|
+
* annotations. `harmony` is meaningful through
|
|
160
|
+
* {@link ArrangementOptions.harmonyTracks}, which names the tracks the chords
|
|
161
|
+
* are inferred from. The rest are labels carried through to
|
|
162
|
+
* {@link TrackAnalysis.role} for the caller's own use; nothing is inferred, so
|
|
163
|
+
* a track left unlabelled reports `'other'` rather than a guess.
|
|
164
|
+
*
|
|
170
165
|
* @category Arrangement & Analysis
|
|
171
166
|
*/
|
|
172
|
-
type TrackRole = 'melody' | 'harmony' | 'bass' | 'other';
|
|
167
|
+
type TrackRole = 'melody' | 'harmony' | 'bass' | 'drums' | 'other';
|
|
173
168
|
/**
|
|
174
169
|
* One input track: its notes plus optional name and role.
|
|
175
170
|
*
|
|
@@ -178,7 +173,7 @@ type TrackRole = 'melody' | 'harmony' | 'bass' | 'other';
|
|
|
178
173
|
type ArrangementTrack = {
|
|
179
174
|
name?: string;
|
|
180
175
|
role?: TrackRole;
|
|
181
|
-
notes: NoteEvent[];
|
|
176
|
+
notes: readonly NoteEvent[];
|
|
182
177
|
};
|
|
183
178
|
/**
|
|
184
179
|
* A track after analysis: its resolved name, role, and per-note annotations.
|
|
@@ -199,10 +194,22 @@ type TrackAnalysis = {
|
|
|
199
194
|
type Conflict = {
|
|
200
195
|
beat: number;
|
|
201
196
|
trackName: string;
|
|
197
|
+
/** The clashing track's index in the caller's input array. */
|
|
198
|
+
trackIndex: number;
|
|
199
|
+
/** The note's index in that track's own note array. */
|
|
200
|
+
originalIndex?: number;
|
|
201
|
+
/** The id the note carries in {@link TrackAnalysis.notes}. */
|
|
202
|
+
noteId: number;
|
|
202
203
|
pitch: number;
|
|
204
|
+
/**
|
|
205
|
+
* The note's theory labels at its onset, so a caller can tell a genuine clash
|
|
206
|
+
* from a passing tone, a neighbour, or a prepared suspension — all of which
|
|
207
|
+
* are ordinary non-chord tones that still evaluate as unsafe.
|
|
208
|
+
*/
|
|
209
|
+
labels: TheoryLabel[];
|
|
203
210
|
/** The clash severity: {@link NoteSafety.Warning} or {@link NoteSafety.Dissonant}. */
|
|
204
211
|
safety: NoteSafety;
|
|
205
|
-
/** {@link
|
|
212
|
+
/** {@link SafetyResult.reasons} bitmask. */
|
|
206
213
|
reasons: number;
|
|
207
214
|
/** Preferred stepwise resolution, when the safety evaluator provides one. */
|
|
208
215
|
resolveTo?: number;
|
|
@@ -232,6 +239,23 @@ type ArrangementAnalysis = {
|
|
|
232
239
|
type ArrangementOptions = {
|
|
233
240
|
/** Key context; inferred from the pooled notes when omitted. */
|
|
234
241
|
key?: KeyScale;
|
|
242
|
+
/**
|
|
243
|
+
* A chord timeline to analyse against, instead of inferring one from the
|
|
244
|
+
* notes. Supply it to analyse a hand-written progression, or to reuse the
|
|
245
|
+
* timeline of an earlier call rather than re-running chord inference.
|
|
246
|
+
*/
|
|
247
|
+
timeline?: ChordTimeline;
|
|
248
|
+
/**
|
|
249
|
+
* Indices of the tracks the harmony is inferred from. Defaults to every
|
|
250
|
+
* pitched track. Percussion tracks are excluded either way.
|
|
251
|
+
*/
|
|
252
|
+
harmonyTracks?: number[];
|
|
253
|
+
/**
|
|
254
|
+
* Lowest severity reported in `conflicts`.
|
|
255
|
+
*
|
|
256
|
+
* @defaultValue {@link NoteSafety.Warning}
|
|
257
|
+
*/
|
|
258
|
+
minSeverity?: NoteSafety;
|
|
235
259
|
/**
|
|
236
260
|
* Time signature; defaults to 4/4.
|
|
237
261
|
*
|
|
@@ -250,16 +274,31 @@ type ArrangementOptions = {
|
|
|
250
274
|
* @defaultValue `'pop'`
|
|
251
275
|
*/
|
|
252
276
|
profile?: SafetyProfile;
|
|
277
|
+
/**
|
|
278
|
+
* Upper bound on the work this call may do — note counts, windows, and
|
|
279
|
+
* candidate counts are each checked against it before anything is allocated.
|
|
280
|
+
*
|
|
281
|
+
* Raise it to analyse a piece larger than the default allows; the default is
|
|
282
|
+
* {@link DEFAULT_GENERATION_BUDGET}, chosen so a runaway input fails fast
|
|
283
|
+
* rather than blocking the thread.
|
|
284
|
+
*
|
|
285
|
+
* @defaultValue {@link DEFAULT_GENERATION_BUDGET}
|
|
286
|
+
*/
|
|
287
|
+
budget?: number;
|
|
253
288
|
};
|
|
254
289
|
/**
|
|
255
290
|
* Analyse a whole arrangement against a single inferred harmony.
|
|
256
291
|
*
|
|
257
|
-
* The chord timeline and key are inferred from the pooled notes of every
|
|
258
|
-
* (see {@link chordTimelineFromNotes}); pooling all voices is
|
|
259
|
-
* roles are absent or a track doubles the harmony, so it is
|
|
260
|
-
* deriving the harmony from a subset.
|
|
261
|
-
*
|
|
262
|
-
*
|
|
292
|
+
* The chord timeline and key are inferred from the pooled notes of every
|
|
293
|
+
* pitched track (see {@link chordTimelineFromNotes}); pooling all voices is
|
|
294
|
+
* robust even when roles are absent or a track doubles the harmony, so it is
|
|
295
|
+
* preferred over deriving the harmony from a subset. A track marked
|
|
296
|
+
* `role: 'drums'` is excluded — its pitches name instruments, not harmony, and
|
|
297
|
+
* pooling them would corrupt the key, the timeline and every reading built on
|
|
298
|
+
* them. Pass `harmonyTracks` to restrict inference further, or `timeline` to
|
|
299
|
+
* analyse against a progression you already have. Zero- and negative-length
|
|
300
|
+
* notes never sound, so they are dropped at ingest and appear in neither the
|
|
301
|
+
* annotations nor the conflicts.
|
|
263
302
|
*
|
|
264
303
|
* Voice analysis assumes one monophonic voice at a time, so each track is
|
|
265
304
|
* first partitioned into monophonic sub-voices (a polyphonic block-chord track
|
|
@@ -272,6 +311,13 @@ type ArrangementOptions = {
|
|
|
272
311
|
* evaluations that are not {@link NoteSafety.Safe} become conflicts, one per
|
|
273
312
|
* clashing beat, sorted worst severity first and then by beat.
|
|
274
313
|
*
|
|
314
|
+
* Every ordinary non-chord tone — a passing note, a neighbour, a prepared
|
|
315
|
+
* suspension — is by definition unsafe against the chord under it, so the
|
|
316
|
+
* conflict list is a report, not a fault list. Each conflict carries the note's
|
|
317
|
+
* `labels` and its `trackIndex`/`originalIndex`, so a caller can tell those
|
|
318
|
+
* apart and map a conflict back to the note it passed in; `minSeverity` narrows
|
|
319
|
+
* the list to outright dissonance.
|
|
320
|
+
*
|
|
275
321
|
* @param tracks The tracks to analyse.
|
|
276
322
|
* @param opts Analysis options; see {@link ArrangementOptions}.
|
|
277
323
|
* @returns The inferred harmony, per-track annotations, cadences, and conflicts.
|
|
@@ -311,12 +357,12 @@ type TensionPoint = {
|
|
|
311
357
|
*
|
|
312
358
|
* At each sample beat the tension combines three normalized terms:
|
|
313
359
|
* - the sounding chord's harmonic function (dominant `1`, subdominant `0.5`,
|
|
314
|
-
* tonic or no chord `0`), weighted
|
|
360
|
+
* tonic or no chord `0`), weighted `FUNCTION_WEIGHT`;
|
|
315
361
|
* - the dissonance of the sounding notes — the larger of the share of sounding
|
|
316
362
|
* pitches that are not chord tones and the share that {@link evaluateSafety}
|
|
317
|
-
* rates {@link NoteSafety.Dissonant} — weighted
|
|
363
|
+
* rates {@link NoteSafety.Dissonant} — weighted `DISSONANCE_WEIGHT`;
|
|
318
364
|
* - the registral span of the sounding notes, saturating at
|
|
319
|
-
*
|
|
365
|
+
* `SPAN_SATURATION` semitones, weighted `SPAN_WEIGHT`.
|
|
320
366
|
*
|
|
321
367
|
* The weighted sum is clamped to [0, 1]. The harmony is inferred from all tracks
|
|
322
368
|
* pooled together, so the result is deterministic and self-contained.
|
|
@@ -337,5 +383,29 @@ type TensionPoint = {
|
|
|
337
383
|
declare function tensionCurve(tracks: ArrangementTrack[], opts?: ArrangementOptions & {
|
|
338
384
|
step?: number;
|
|
339
385
|
}): TensionPoint[];
|
|
386
|
+
/**
|
|
387
|
+
* Sample the tension of an arrangement already analysed by
|
|
388
|
+
* {@link analyzeArrangement}, reusing its harmony instead of inferring it again.
|
|
389
|
+
*
|
|
390
|
+
* `analyzeArrangement` followed by `tensionCurve` runs chord and key inference
|
|
391
|
+
* twice over the same notes. This takes the analysis it already produced, so
|
|
392
|
+
* the curve and the annotations describe the same harmony by construction.
|
|
393
|
+
*
|
|
394
|
+
* @param tracks The same tracks that were analysed.
|
|
395
|
+
* @param analysis The result of {@link analyzeArrangement} for those tracks.
|
|
396
|
+
* @param opts Analysis options plus an optional `step` (default one beat).
|
|
397
|
+
* @returns One {@link TensionPoint} per sampled beat, in beat order.
|
|
398
|
+
* @example
|
|
399
|
+
* ```ts
|
|
400
|
+
* import { analyzeArrangement, tensionCurveFrom } from '@libraz/libcantus';
|
|
401
|
+
* const tracks = [{ notes: [{ pitch: 60, startBeat: 0, durationBeat: 4 }] }];
|
|
402
|
+
* const analysis = analyzeArrangement(tracks);
|
|
403
|
+
* tensionCurveFrom(tracks, analysis, { step: 1 });
|
|
404
|
+
* ```
|
|
405
|
+
* @category Arrangement & Analysis
|
|
406
|
+
*/
|
|
407
|
+
declare function tensionCurveFrom(tracks: ArrangementTrack[], analysis: ArrangementAnalysis, opts?: ArrangementOptions & {
|
|
408
|
+
step?: number;
|
|
409
|
+
}): TensionPoint[];
|
|
340
410
|
|
|
341
|
-
export { type AnalyzedNote, type ArrangementAnalysis, type ArrangementOptions, type ArrangementTrack, CadenceHit, ChordTimeline, type Conflict, type TensionPoint, type TheoryLabel, type TrackAnalysis, type TrackRole, type VoiceNote, analyzeArrangement, analyzeVoice,
|
|
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.js
CHANGED
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
chordTimelineFromChords,
|
|
5
5
|
chordTimelineFromNotes,
|
|
6
6
|
detectCadences,
|
|
7
|
-
tensionCurve
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
tensionCurve,
|
|
8
|
+
tensionCurveFrom,
|
|
9
|
+
toVoiceNotes
|
|
10
|
+
} from "../chunk-YUE6TJ4M.js";
|
|
11
|
+
import "../chunk-2PTFGVD7.js";
|
|
10
12
|
import {
|
|
11
13
|
analyzeChord,
|
|
12
14
|
borrowedSource,
|
|
@@ -15,6 +17,8 @@ import {
|
|
|
15
17
|
detectChord,
|
|
16
18
|
detectChordBest,
|
|
17
19
|
detectKey,
|
|
20
|
+
detectKeyBest,
|
|
21
|
+
detectKeyFromNotes,
|
|
18
22
|
functionOf,
|
|
19
23
|
isBorrowedChord,
|
|
20
24
|
isDiatonic,
|
|
@@ -22,11 +26,14 @@ import {
|
|
|
22
26
|
parallelKey,
|
|
23
27
|
romanToChord,
|
|
24
28
|
secondaryDominant
|
|
25
|
-
} from "../chunk-
|
|
26
|
-
import
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
} from "../chunk-NNB67XA2.js";
|
|
30
|
+
import {
|
|
31
|
+
NoteSafety
|
|
32
|
+
} from "../chunk-DZMHIGI4.js";
|
|
33
|
+
import "../chunk-KBTTEX7Q.js";
|
|
34
|
+
import "../chunk-R2VVFAIN.js";
|
|
29
35
|
export {
|
|
36
|
+
NoteSafety,
|
|
30
37
|
analyzeArrangement,
|
|
31
38
|
analyzeChord,
|
|
32
39
|
analyzeVoice,
|
|
@@ -39,6 +46,8 @@ export {
|
|
|
39
46
|
detectChord,
|
|
40
47
|
detectChordBest,
|
|
41
48
|
detectKey,
|
|
49
|
+
detectKeyBest,
|
|
50
|
+
detectKeyFromNotes,
|
|
42
51
|
functionOf,
|
|
43
52
|
isBorrowedChord,
|
|
44
53
|
isDiatonic,
|
|
@@ -46,6 +55,8 @@ export {
|
|
|
46
55
|
parallelKey,
|
|
47
56
|
romanToChord,
|
|
48
57
|
secondaryDominant,
|
|
49
|
-
tensionCurve
|
|
58
|
+
tensionCurve,
|
|
59
|
+
tensionCurveFrom,
|
|
60
|
+
toVoiceNotes
|
|
50
61
|
};
|
|
51
62
|
//# sourceMappingURL=index.js.map
|