@libraz/libcantus 0.9.2 → 0.9.4
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 +6 -5
- package/dist/analyze/index.cjs +41 -1676
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +194 -122
- package/dist/analyze/index.d.ts +194 -122
- package/dist/analyze/index.js +19 -8
- package/dist/chunk-36N73KZ3.cjs +246 -0
- package/dist/chunk-36N73KZ3.cjs.map +1 -0
- package/dist/chunk-4HLLZPXT.cjs +3077 -0
- package/dist/chunk-4HLLZPXT.cjs.map +1 -0
- package/dist/chunk-7MGZ7D62.cjs +498 -0
- package/dist/chunk-7MGZ7D62.cjs.map +1 -0
- package/dist/{chunk-R3S2LUBH.js → chunk-7NKDPF74.js} +660 -305
- package/dist/chunk-7NKDPF74.js.map +1 -0
- package/dist/chunk-CAN76NCU.cjs +679 -0
- package/dist/chunk-CAN76NCU.cjs.map +1 -0
- package/dist/{chunk-7Y7WF64D.js → chunk-D2FAJBYL.js} +104 -35
- package/dist/chunk-D2FAJBYL.js.map +1 -0
- package/dist/{chunk-COKTX2G5.js → chunk-EHVEBWM5.js} +1052 -510
- package/dist/chunk-EHVEBWM5.js.map +1 -0
- package/dist/chunk-FCANXBAT.cjs +30 -0
- package/dist/chunk-FCANXBAT.cjs.map +1 -0
- package/dist/chunk-FNDWXRRI.cjs +479 -0
- package/dist/chunk-FNDWXRRI.cjs.map +1 -0
- package/dist/{chunk-GQKN5KDT.js → chunk-GQSGS2N4.js} +43 -29
- package/dist/chunk-GQSGS2N4.js.map +1 -0
- package/dist/chunk-HKGYCQ34.js +53 -0
- package/dist/chunk-HKGYCQ34.js.map +1 -0
- package/dist/chunk-I24MV65U.js +106 -0
- package/dist/chunk-I24MV65U.js.map +1 -0
- package/dist/{chunk-LN7ZZMD2.js → chunk-KMHOICIY.js} +322 -173
- package/dist/chunk-KMHOICIY.js.map +1 -0
- package/dist/chunk-LW53AHQU.cjs +1117 -0
- package/dist/chunk-LW53AHQU.cjs.map +1 -0
- package/dist/chunk-N6IHQUOX.js +1 -0
- package/dist/chunk-N6IHQUOX.js.map +1 -0
- package/dist/chunk-NKIBQ6PT.js +30 -0
- package/dist/chunk-NKIBQ6PT.js.map +1 -0
- package/dist/chunk-NP4NA2FB.cjs +106 -0
- package/dist/chunk-NP4NA2FB.cjs.map +1 -0
- package/dist/chunk-NVE34YGZ.cjs +1449 -0
- package/dist/chunk-NVE34YGZ.cjs.map +1 -0
- package/dist/{chunk-A4532ZFR.js → chunk-NYYWMV2C.js} +115 -47
- package/dist/chunk-NYYWMV2C.js.map +1 -0
- package/dist/{chunk-5HTNMQW4.js → chunk-Q2XUP227.js} +310 -118
- package/dist/chunk-Q2XUP227.js.map +1 -0
- package/dist/chunk-Q6OP4U43.cjs +327 -0
- package/dist/chunk-Q6OP4U43.cjs.map +1 -0
- package/dist/chunk-RC6GBMCD.cjs +845 -0
- package/dist/chunk-RC6GBMCD.cjs.map +1 -0
- package/dist/{chunk-XTC3X6MS.js → chunk-RK35RIN7.js} +453 -152
- package/dist/chunk-RK35RIN7.js.map +1 -0
- package/dist/chunk-RUMU3UA6.cjs +53 -0
- package/dist/chunk-RUMU3UA6.cjs.map +1 -0
- package/dist/chunk-T64C7ZD7.cjs +1 -0
- package/dist/chunk-T64C7ZD7.cjs.map +1 -0
- package/dist/chunk-XEBG3G53.js +498 -0
- package/dist/chunk-XEBG3G53.js.map +1 -0
- package/dist/chunk-YLEMGEFH.js +246 -0
- package/dist/chunk-YLEMGEFH.js.map +1 -0
- package/dist/chunk-ZEJR4TKL.cjs +173 -0
- package/dist/chunk-ZEJR4TKL.cjs.map +1 -0
- package/dist/core/index.cjs +130 -431
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +331 -17
- package/dist/core/index.d.ts +331 -17
- package/dist/core/index.js +71 -13
- package/dist/{function-2bJW1Zp_.d.ts → function-BtiZb9i9.d.ts} +28 -7
- package/dist/{function-r2sh-jOO.d.cts → function-DNugAOrt.d.cts} +28 -7
- package/dist/generate/index.cjs +30 -3751
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +373 -59
- package/dist/generate/index.d.ts +373 -59
- package/dist/generate/index.js +23 -9
- package/dist/{index-DZ1M21do.d.cts → index-6VR8-kit.d.ts} +20 -4
- package/dist/index-70p168VM.d.ts +192 -0
- package/dist/{index-D_ZTUNKp.d.cts → index-Be74mcon.d.cts} +18 -17
- package/dist/index-BtXT6UQ0.d.cts +192 -0
- package/dist/{index-BMPxwjwV.d.ts → index-C5UBbQ4G.d.ts} +18 -17
- package/dist/{index-BOBXBNwP.d.cts → index-C83mZI1P.d.ts} +93 -8
- package/dist/{index-BdeQ1r_p.d.cts → index-D6b6na69.d.cts} +14 -11
- 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-OG65ocOr.d.cts +272 -0
- package/dist/index-OG65ocOr.d.ts +272 -0
- package/dist/{index-BreoJRw0.d.ts → index-tJhkmQgE.d.cts} +20 -4
- package/dist/{index-CP3wAfEH.d.ts → index-tSQh-xwY.d.ts} +14 -11
- package/dist/{index-CM5W4rcm.d.ts → index-y_ak9_Hi.d.cts} +93 -8
- package/dist/index.cjs +419 -6848
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -13
- package/dist/index.d.ts +14 -13
- package/dist/index.js +132 -27
- package/dist/model/index.cjs +8 -2423
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +433 -74
- package/dist/model/index.d.ts +433 -74
- package/dist/model/index.js +6 -7
- package/dist/styled-DIRkk9Uz.d.ts +506 -0
- package/dist/styled-DJbkJQfj.d.cts +506 -0
- package/dist/theory/index.cjs +172 -1676
- 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 +31 -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 +73 -24
- package/dist/chunk-5HTNMQW4.js.map +0 -1
- package/dist/chunk-7Y7WF64D.js.map +0 -1
- package/dist/chunk-A4532ZFR.js.map +0 -1
- package/dist/chunk-BHUT2S5G.js +0 -22
- package/dist/chunk-BHUT2S5G.js.map +0 -1
- package/dist/chunk-CCBLVAPK.js +0 -42
- package/dist/chunk-CCBLVAPK.js.map +0 -1
- package/dist/chunk-COKTX2G5.js.map +0 -1
- package/dist/chunk-DYWFNC4A.js +0 -152
- package/dist/chunk-DYWFNC4A.js.map +0 -1
- package/dist/chunk-GQKN5KDT.js.map +0 -1
- package/dist/chunk-LN7ZZMD2.js.map +0 -1
- package/dist/chunk-MSWFZF7J.js +0 -118
- package/dist/chunk-MSWFZF7J.js.map +0 -1
- package/dist/chunk-R3S2LUBH.js.map +0 -1
- package/dist/chunk-SDM3VJJ5.js +0 -41
- package/dist/chunk-SDM3VJJ5.js.map +0 -1
- package/dist/chunk-XTC3X6MS.js.map +0 -1
- package/dist/chunk-ZXW5YIWK.js +0 -55
- package/dist/chunk-ZXW5YIWK.js.map +0 -1
- package/dist/index-CGMZNCx6.d.cts +0 -140
- package/dist/index-CGMZNCx6.d.ts +0 -140
- package/dist/styled-BjXtOFNk.d.cts +0 -282
- package/dist/styled-D7BAx3S3.d.ts +0 -282
- package/src/analyze/arrange/index.ts +0 -21
- package/src/analyze/arrange/internal.ts +0 -125
- package/src/analyze/arrange/tension.ts +0 -187
- package/src/analyze/arrange/tracks.ts +0 -279
- package/src/analyze/detect/index.ts +0 -235
- 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 -393
- package/src/analyze/index.ts +0 -49
- package/src/analyze/timeline/index.ts +0 -415
- package/src/analyze/voice/index.ts +0 -330
- package/src/core/index.ts +0 -47
- package/src/core/interval/index.ts +0 -81
- package/src/core/meter/index.ts +0 -282
- package/src/core/pitch/index.ts +0 -311
- package/src/core/random/index.ts +0 -53
- package/src/core/tuning/index.ts +0 -156
- package/src/core/types.ts +0 -29
- package/src/generate/bass/index.ts +0 -350
- package/src/generate/countermelody/index.ts +0 -379
- package/src/generate/drums/beat.ts +0 -266
- package/src/generate/drums/euclid.ts +0 -58
- 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 -329
- 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 -326
- package/src/generate/harmonize/index.ts +0 -440
- package/src/generate/index.ts +0 -59
- package/src/generate/motif/index.ts +0 -398
- package/src/generate/progression/index.ts +0 -370
- package/src/generate/reharmony/index.ts +0 -330
- package/src/generate/rhythm/index.ts +0 -165
- package/src/index.ts +0 -247
- package/src/model/chord.ts +0 -423
- 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 -373
- package/src/theory/chordscale/index.ts +0 -374
- package/src/theory/counterpoint/index.ts +0 -230
- package/src/theory/harmony/index.ts +0 -92
- package/src/theory/index.ts +0 -107
- package/src/theory/safety/index.ts +0 -419
- 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 -182
- 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 -195
- package/src/theory/voicing/styled.ts +0 -176
- package/tsconfig.json +0 -23
package/dist/core/index.d.ts
CHANGED
|
@@ -1,13 +1,154 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
import { N as NoteEvent } from '../types-BN6_Q9Kl.js';
|
|
2
|
+
export { K as KeyScale } from '../types-BN6_Q9Kl.js';
|
|
3
|
+
import { T as TimeSignature } from '../index-DXd9JikN.js';
|
|
4
|
+
export { B as BarPosition, b as barPositionToBeat, a as barPositionToPulse, c as beatToBarPosition, d as beatsPerBar, f as formatBarPosition, e as formatTimeSignature, i as isCompound, g as isStrongBeat, m as metricWeight, p as parseTimeSignature, h as pulseBeats, j as pulsesPerBar, t as tuplet } from '../index-DXd9JikN.js';
|
|
5
|
+
export { I as IntervalQualityLabel, N as NoteData, S as SpelledInterval, d as diatonicLetterOf, f as formatNote, i as intervalSemitones, m as midiToNote, n as naturalPitchClassOf, a as noteToMidi, b as noteToPitchClass, p as parseInterval, c as parseNote, e as pitchClassOf, s as spelledInterval, t as transposeByInterval, g as transposeNote } from '../index-OG65ocOr.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* The library's error taxonomy.
|
|
7
9
|
*
|
|
10
|
+
* Every failure this library raises falls into one of three kinds, and the kind
|
|
11
|
+
* decides what a caller can do about it. Batch-voicing a lead sheet, for
|
|
12
|
+
* instance, has to tell "fix the input" apart from "loosen the constraints",
|
|
13
|
+
* and a message string is not a contract.
|
|
14
|
+
*
|
|
15
|
+
* The classes extend the built-in error types a caller would otherwise catch —
|
|
16
|
+
* a rejected argument is still a `RangeError` — so the `code` narrows an
|
|
17
|
+
* existing category rather than replacing it.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* What kind of failure an error reports.
|
|
21
|
+
*
|
|
22
|
+
* - `INVALID_INPUT`: an argument is malformed or out of range. The caller's
|
|
23
|
+
* input must change.
|
|
24
|
+
* - `NO_SOLUTION`: the input is valid but nothing satisfies the constraints.
|
|
25
|
+
* The constraints must change, or the failure must be accepted.
|
|
26
|
+
* - `BUDGET_EXCEEDED`: the requested work is larger than the synchronous
|
|
27
|
+
* generation budget. The request must be smaller, or the budget larger.
|
|
28
|
+
*
|
|
29
|
+
* @category Core
|
|
30
|
+
*/
|
|
31
|
+
type LibcantusErrorCode = 'INVALID_INPUT' | 'NO_SOLUTION' | 'BUDGET_EXCEEDED';
|
|
32
|
+
/**
|
|
33
|
+
* A rejected argument: malformed, out of range, or naming something unknown.
|
|
34
|
+
*
|
|
35
|
+
* @category Core
|
|
36
|
+
*/
|
|
37
|
+
declare class InvalidInputError extends RangeError {
|
|
38
|
+
readonly code: "INVALID_INPUT";
|
|
39
|
+
readonly name = "InvalidInputError";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A valid request with no answer: no voicing fits the given ranges, no chord
|
|
43
|
+
* matches the pitches, no preset claims the style.
|
|
44
|
+
*
|
|
45
|
+
* @category Core
|
|
46
|
+
*/
|
|
47
|
+
declare class NoSolutionError extends Error {
|
|
48
|
+
readonly code: "NO_SOLUTION";
|
|
49
|
+
readonly name = "NoSolutionError";
|
|
50
|
+
/**
|
|
51
|
+
* Where in a sequence the failure occurred, when the operation was working
|
|
52
|
+
* through one — the chord index of a progression, say.
|
|
53
|
+
*/
|
|
54
|
+
readonly at: number | undefined;
|
|
55
|
+
constructor(message: string, options?: {
|
|
56
|
+
at?: number;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Work that would exceed the synchronous generation budget.
|
|
61
|
+
*
|
|
62
|
+
* @category Core
|
|
63
|
+
*/
|
|
64
|
+
declare class BudgetExceededError extends RangeError {
|
|
65
|
+
readonly code: "BUDGET_EXCEEDED";
|
|
66
|
+
readonly name = "BudgetExceededError";
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Whether a caught value is one of this library's coded errors.
|
|
70
|
+
*
|
|
71
|
+
* @param value The caught value.
|
|
72
|
+
* @returns True when it carries a {@link LibcantusErrorCode}.
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { isLibcantusError, voiceChord, parseChordSymbol } from '@libraz/libcantus';
|
|
76
|
+
* try {
|
|
77
|
+
* voiceChord(parseChordSymbol('C'), { ranges: [] });
|
|
78
|
+
* } catch (error) {
|
|
79
|
+
* if (isLibcantusError(error) && error.code === 'NO_SOLUTION') {
|
|
80
|
+
* // loosen the constraints rather than blaming the input
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
* @category Core
|
|
85
|
+
*/
|
|
86
|
+
declare function isLibcantusError(value: unknown): value is InvalidInputError | NoSolutionError | BudgetExceededError;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* A validated note retaining its position in the caller's original array.
|
|
90
|
+
*
|
|
91
|
+
* @category Core
|
|
92
|
+
*/
|
|
93
|
+
type IndexedNoteEvent = {
|
|
94
|
+
note: NoteEvent;
|
|
95
|
+
originalIndex: number;
|
|
96
|
+
endBeat: number;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Which note wins when several sound from the same onset.
|
|
100
|
+
*
|
|
101
|
+
* `'highest'` and `'lowest'` name a voice, so the answer does not depend on the
|
|
102
|
+
* order the caller happened to store the chord in; `'last'` takes the one
|
|
103
|
+
* latest in the input array.
|
|
104
|
+
*
|
|
105
|
+
* @category Core
|
|
106
|
+
*/
|
|
107
|
+
type OnsetTieBreak = 'highest' | 'lowest' | 'last';
|
|
108
|
+
/**
|
|
109
|
+
* Binary-searchable, stable-sorted index over note onsets and active spans.
|
|
110
|
+
*
|
|
111
|
+
* @category Core
|
|
112
|
+
*/
|
|
113
|
+
type NoteEventIndex = {
|
|
114
|
+
notes: IndexedNoteEvent[];
|
|
115
|
+
/**
|
|
116
|
+
* Latest-onset note sounding at `beat`. Simultaneous onsets are resolved by
|
|
117
|
+
* the index's {@link OnsetTieBreak}.
|
|
118
|
+
*/
|
|
119
|
+
at: (beat: number) => IndexedNoteEvent | undefined;
|
|
120
|
+
/** Whether one or more sounding notes attack at `beat`. */
|
|
121
|
+
attacksAt: (beat: number) => boolean;
|
|
122
|
+
/** Unique sounding-note attack beats strictly inside `(startBeat, endBeat)`. */
|
|
123
|
+
onsetsBetween: (startBeat: number, endBeat: number) => number[];
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Validate and stable-sort note events once, then expose logarithmic onset and
|
|
127
|
+
* active-note lookups. Non-positive-duration notes may be retained for callers
|
|
128
|
+
* that intentionally filter them later, but never count as sounding.
|
|
129
|
+
*
|
|
130
|
+
* @category Core
|
|
131
|
+
*/
|
|
132
|
+
declare function createNoteEventIndex(events: readonly NoteEvent[], options?: {
|
|
133
|
+
allowNonPositiveDuration?: boolean;
|
|
134
|
+
tieBreak?: OnsetTieBreak;
|
|
135
|
+
budget?: number;
|
|
136
|
+
/** What the events are, for the validation error message. */
|
|
137
|
+
name?: string;
|
|
138
|
+
}): NoteEventIndex;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Counterpoint classification of a harmonic interval by consonance.
|
|
142
|
+
*
|
|
143
|
+
* Distinct from a spelled interval's quality label — see
|
|
144
|
+
* {@link IntervalQualityLabel}, which names the `'P'` / `'M'` / `'m'` / `'A'` /
|
|
145
|
+
* `'d'` spelling of an interval rather than how it sounds against another
|
|
146
|
+
* voice.
|
|
147
|
+
*
|
|
148
|
+
* @see {@link IntervalQualityLabel}
|
|
8
149
|
* @category Pitch & Intervals
|
|
9
150
|
*/
|
|
10
|
-
declare enum
|
|
151
|
+
declare enum ConsonanceClass {
|
|
11
152
|
PerfectConsonance = 0,
|
|
12
153
|
ImperfectConsonance = 1,
|
|
13
154
|
Dissonance = 2
|
|
@@ -25,16 +166,22 @@ declare enum IntervalQuality {
|
|
|
25
166
|
* @returns The counterpoint quality of the interval.
|
|
26
167
|
* @example
|
|
27
168
|
* ```ts
|
|
28
|
-
* import { classifyInterval,
|
|
29
|
-
* classifyInterval(7); //
|
|
30
|
-
* classifyInterval(5); //
|
|
31
|
-
* classifyInterval(5, false); //
|
|
169
|
+
* import { classifyInterval, ConsonanceClass } from '@libraz/libcantus';
|
|
170
|
+
* classifyInterval(7); // ConsonanceClass.PerfectConsonance
|
|
171
|
+
* classifyInterval(5); // ConsonanceClass.Dissonance (two-voice)
|
|
172
|
+
* classifyInterval(5, false); // ConsonanceClass.ImperfectConsonance
|
|
32
173
|
* ```
|
|
33
174
|
* @category Pitch & Intervals
|
|
34
175
|
*/
|
|
35
|
-
declare function classifyInterval(semitones: number, twoVoice?: boolean):
|
|
176
|
+
declare function classifyInterval(semitones: number, twoVoice?: boolean): ConsonanceClass;
|
|
36
177
|
/**
|
|
37
|
-
* Test whether an interval is a perfect
|
|
178
|
+
* Test whether an interval is a perfect consonance: the unison/octave or the
|
|
179
|
+
* fifth.
|
|
180
|
+
*
|
|
181
|
+
* The perfect fourth is deliberately excluded. This is the predicate the
|
|
182
|
+
* parallel-motion rules are written against, where the fourth behaves as a
|
|
183
|
+
* dissonance between two voices; {@link classifyInterval} is the general
|
|
184
|
+
* classifier, and it treats the fourth as context-dependent.
|
|
38
185
|
*
|
|
39
186
|
* @param semitones Interval size in semitones (may be negative or compound).
|
|
40
187
|
* @returns True for the unison/octave (0) and the perfect fifth (7) mod 12.
|
|
@@ -109,11 +256,11 @@ declare function createRng(seed: number): Rng;
|
|
|
109
256
|
*/
|
|
110
257
|
type Tuning = {
|
|
111
258
|
/** Step index (MIDI number when `divisions` is 12) whose frequency is `refFreq`. */
|
|
112
|
-
refStep: number;
|
|
259
|
+
readonly refStep: number;
|
|
113
260
|
/** Frequency in Hz of `refStep`. */
|
|
114
|
-
refFreq: number;
|
|
261
|
+
readonly refFreq: number;
|
|
115
262
|
/** Equal divisions of the octave (12 standard; e.g. 19 or 31 for microtonal). */
|
|
116
|
-
divisions: number;
|
|
263
|
+
readonly divisions: number;
|
|
117
264
|
};
|
|
118
265
|
/**
|
|
119
266
|
* Standard twelve-tone equal temperament, A4 (MIDI 69) = 440 Hz.
|
|
@@ -162,6 +309,67 @@ declare function frequencyOf(step: number, tuning?: Tuning): number;
|
|
|
162
309
|
* @category Pitch & Intervals
|
|
163
310
|
*/
|
|
164
311
|
declare function nearestStep(freq: number, tuning?: Tuning): number;
|
|
312
|
+
/**
|
|
313
|
+
* Step index of a frequency under a tuning, unrounded.
|
|
314
|
+
*
|
|
315
|
+
* The exact inverse of {@link frequencyOf}. {@link nearestStep} rounds it,
|
|
316
|
+
* which discards how far off the pitch actually is — the figure a tuner
|
|
317
|
+
* display, a pitch-bend amount, or an intonation check is built on.
|
|
318
|
+
*
|
|
319
|
+
* @param freq Frequency in Hz.
|
|
320
|
+
* @param tuning The tuning (default 12-TET).
|
|
321
|
+
* @returns The fractional step index.
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* import { stepOf } from '@libraz/libcantus';
|
|
325
|
+
* stepOf(442); // slightly above 69, the step for A440
|
|
326
|
+
* ```
|
|
327
|
+
* @category Pitch & Intervals
|
|
328
|
+
*/
|
|
329
|
+
declare function stepOf(freq: number, tuning?: Tuning): number;
|
|
330
|
+
/**
|
|
331
|
+
* How far a frequency sits from its nearest step, in cents.
|
|
332
|
+
*
|
|
333
|
+
* Positive means sharp of the step, negative flat.
|
|
334
|
+
*
|
|
335
|
+
* @param freq Frequency in Hz.
|
|
336
|
+
* @param tuning The tuning (default 12-TET).
|
|
337
|
+
* @returns The signed deviation in cents.
|
|
338
|
+
* @example
|
|
339
|
+
* ```ts
|
|
340
|
+
* import { centsFromNearestStep } from '@libraz/libcantus';
|
|
341
|
+
* Math.round(centsFromNearestStep(442)); // 8
|
|
342
|
+
* ```
|
|
343
|
+
* @category Pitch & Intervals
|
|
344
|
+
*/
|
|
345
|
+
declare function centsFromNearestStep(freq: number, tuning?: Tuning): number;
|
|
346
|
+
/**
|
|
347
|
+
* Steps spanned by an interval in cents, unrounded — the inverse of
|
|
348
|
+
* {@link centsOfSteps}.
|
|
349
|
+
*
|
|
350
|
+
* @param cents The interval in cents.
|
|
351
|
+
* @param tuning The tuning (default 12-TET).
|
|
352
|
+
* @returns The fractional step count.
|
|
353
|
+
* @category Pitch & Intervals
|
|
354
|
+
*/
|
|
355
|
+
declare function stepsOfCents(cents: number, tuning?: Tuning): number;
|
|
356
|
+
/**
|
|
357
|
+
* The frequency ratio an interval in cents spans — the inverse of
|
|
358
|
+
* {@link ratioToCents}.
|
|
359
|
+
*
|
|
360
|
+
* Multiply a frequency by this to move it by that many cents, which is how a
|
|
361
|
+
* cents offset (a pitch-bend spec, a tuning table entry) is applied.
|
|
362
|
+
*
|
|
363
|
+
* @param cents The interval in cents.
|
|
364
|
+
* @returns The frequency ratio.
|
|
365
|
+
* @example
|
|
366
|
+
* ```ts
|
|
367
|
+
* import { centsToRatio } from '@libraz/libcantus';
|
|
368
|
+
* 440 * centsToRatio(14); // A440 raised by 14 cents
|
|
369
|
+
* ```
|
|
370
|
+
* @category Pitch & Intervals
|
|
371
|
+
*/
|
|
372
|
+
declare function centsToRatio(cents: number): number;
|
|
165
373
|
/**
|
|
166
374
|
* Interval in cents between two frequencies.
|
|
167
375
|
*
|
|
@@ -196,15 +404,121 @@ declare function ratioToCents(numerator: number, denominator: number): number;
|
|
|
196
404
|
*
|
|
197
405
|
* @category Pitch & Intervals
|
|
198
406
|
*/
|
|
199
|
-
declare const JUST_RATIOS: Record<number, [number, number]
|
|
407
|
+
declare const JUST_RATIOS: Readonly<Record<number, readonly [number, number]>>;
|
|
200
408
|
/**
|
|
201
409
|
* Cents by which a five-limit just interval departs from its 12-TET tempering
|
|
202
410
|
* (positive means the just interval is wider).
|
|
203
411
|
*
|
|
204
412
|
* @param semitoneClass Semitone class in [0, 12].
|
|
205
|
-
* @returns The deviation in cents
|
|
413
|
+
* @returns The deviation in cents.
|
|
414
|
+
* @throws If `semitoneClass` is not an integer in [0, 12].
|
|
206
415
|
* @category Pitch & Intervals
|
|
207
416
|
*/
|
|
208
417
|
declare function justDeviationCents(semitoneClass: number): number;
|
|
209
418
|
|
|
210
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Default upper bound for synchronous event/window/candidate generation.
|
|
421
|
+
*
|
|
422
|
+
* @category Core
|
|
423
|
+
*/
|
|
424
|
+
declare const DEFAULT_GENERATION_BUDGET = 1000000;
|
|
425
|
+
/**
|
|
426
|
+
* Require a finite JavaScript number and return it unchanged.
|
|
427
|
+
*
|
|
428
|
+
* @category Core
|
|
429
|
+
*/
|
|
430
|
+
declare function assertFiniteNumber(value: number, name: string): number;
|
|
431
|
+
/**
|
|
432
|
+
* Require an integer in the inclusive range `[min, max]`.
|
|
433
|
+
*
|
|
434
|
+
* @category Core
|
|
435
|
+
*/
|
|
436
|
+
declare function assertInteger(value: number, name: string, min?: number, max?: number): number;
|
|
437
|
+
/**
|
|
438
|
+
* Drop the notes that never sound.
|
|
439
|
+
*
|
|
440
|
+
* A MIDI or DAW import routinely carries zero-length artefacts. Every entry
|
|
441
|
+
* point in this library ignores them, but a caller holding such an array still
|
|
442
|
+
* has to decide what to do with it before comparing note counts or indices;
|
|
443
|
+
* this is the one filter to apply.
|
|
444
|
+
*
|
|
445
|
+
* @param events The note events to filter.
|
|
446
|
+
* @returns A new array containing only the notes with a positive duration.
|
|
447
|
+
* @example
|
|
448
|
+
* ```ts
|
|
449
|
+
* import { dropSilentNotes } from '@libraz/libcantus';
|
|
450
|
+
* dropSilentNotes([{ pitch: 60, startBeat: 0, durationBeat: 0 }]); // []
|
|
451
|
+
* ```
|
|
452
|
+
* @category Core
|
|
453
|
+
*/
|
|
454
|
+
declare function dropSilentNotes(events: readonly NoteEvent[]): NoteEvent[];
|
|
455
|
+
/**
|
|
456
|
+
* Require a value to be one of a fixed set of names.
|
|
457
|
+
*
|
|
458
|
+
* TypeScript checks string-union options at compile time only, so a value that
|
|
459
|
+
* arrives from JSON, a config file, or a JavaScript caller reaches the engine
|
|
460
|
+
* unchecked and is then read against a table that has no entry for it —
|
|
461
|
+
* producing a silent `undefined`, a NaN velocity, or a crash far from the call.
|
|
462
|
+
*
|
|
463
|
+
* @param value The value to check.
|
|
464
|
+
* @param allowed Every accepted name.
|
|
465
|
+
* @param name What the value is, for the error message.
|
|
466
|
+
* @returns The value, narrowed to the allowed union.
|
|
467
|
+
* @throws If the value is not one of `allowed`.
|
|
468
|
+
*
|
|
469
|
+
* @category Core
|
|
470
|
+
*/
|
|
471
|
+
declare function assertOneOf<const T extends string>(value: unknown, allowed: readonly T[], name: string): T;
|
|
472
|
+
/**
|
|
473
|
+
* Require a positive safe integer, optionally capped by `max`.
|
|
474
|
+
*
|
|
475
|
+
* @category Core
|
|
476
|
+
*/
|
|
477
|
+
declare function assertPositiveInt(value: number, name: string, max?: number): number;
|
|
478
|
+
/**
|
|
479
|
+
* Require a finite number in the inclusive range `[min, max]`.
|
|
480
|
+
*
|
|
481
|
+
* @category Core
|
|
482
|
+
*/
|
|
483
|
+
declare function assertRange(value: number, min: number, max: number, name: string): number;
|
|
484
|
+
/**
|
|
485
|
+
* Reject work estimates that would exceed a synchronous generation budget.
|
|
486
|
+
*
|
|
487
|
+
* @category Core
|
|
488
|
+
*/
|
|
489
|
+
declare function assertGenerationBudget(estimated: number, name: string, limit?: number | undefined): number;
|
|
490
|
+
/**
|
|
491
|
+
* Validate a time signature, including additive grouping, before any early return.
|
|
492
|
+
*
|
|
493
|
+
* @category Core
|
|
494
|
+
*/
|
|
495
|
+
declare function assertTimeSignature(ts: TimeSignature, name?: string): TimeSignature;
|
|
496
|
+
/**
|
|
497
|
+
* How strictly {@link assertNoteEvent} and {@link assertNoteEvents} read an
|
|
498
|
+
* event array.
|
|
499
|
+
*
|
|
500
|
+
* @category Core
|
|
501
|
+
*/
|
|
502
|
+
type NoteEventAssertOptions = {
|
|
503
|
+
/**
|
|
504
|
+
* Accept notes that never sound. The analysis side does, so an array from a
|
|
505
|
+
* MIDI import can be validated before the zero-length artefacts are dropped.
|
|
506
|
+
*/
|
|
507
|
+
allowNonPositiveDuration?: boolean;
|
|
508
|
+
/** Upper bound on the event count; defaults to the generation budget. */
|
|
509
|
+
budget?: number;
|
|
510
|
+
};
|
|
511
|
+
/**
|
|
512
|
+
* Validate the finite fields of one timeline note event.
|
|
513
|
+
*
|
|
514
|
+
* @category Core
|
|
515
|
+
*/
|
|
516
|
+
declare function assertNoteEvent(event: NoteEvent, name?: string, options?: NoteEventAssertOptions): NoteEvent;
|
|
517
|
+
/**
|
|
518
|
+
* Validate an event array and its allocation budget without copying it.
|
|
519
|
+
*
|
|
520
|
+
* @category Core
|
|
521
|
+
*/
|
|
522
|
+
declare function assertNoteEvents(events: readonly NoteEvent[], name?: string, options?: NoteEventAssertOptions): NoteEvent[];
|
|
523
|
+
|
|
524
|
+
export { BudgetExceededError, ConsonanceClass, DEFAULT_GENERATION_BUDGET, type IndexedNoteEvent, InvalidInputError, JUST_RATIOS, type LibcantusErrorCode, NoSolutionError, NoteEvent, type NoteEventAssertOptions, type NoteEventIndex, type OnsetTieBreak, type Rng, TWELVE_TET, TimeSignature, type Tuning, assertFiniteNumber, assertGenerationBudget, assertInteger, assertNoteEvent, assertNoteEvents, assertOneOf, assertPositiveInt, assertRange, assertTimeSignature, centsBetweenFreq, centsFromNearestStep, centsOfSteps, centsToRatio, classifyInterval, createNoteEventIndex, createRng, dropSilentNotes, edo, frequencyOf, isConsonantInterval, isLibcantusError, isPerfectInterval, justDeviationCents, nearestStep, ratioToCents, stepOf, stepsOfCents };
|
package/dist/core/index.js
CHANGED
|
@@ -2,72 +2,130 @@ import {
|
|
|
2
2
|
JUST_RATIOS,
|
|
3
3
|
TWELVE_TET,
|
|
4
4
|
centsBetweenFreq,
|
|
5
|
+
centsFromNearestStep,
|
|
5
6
|
centsOfSteps,
|
|
7
|
+
centsToRatio,
|
|
6
8
|
edo,
|
|
7
9
|
frequencyOf,
|
|
8
10
|
justDeviationCents,
|
|
9
11
|
nearestStep,
|
|
10
|
-
ratioToCents
|
|
11
|
-
|
|
12
|
+
ratioToCents,
|
|
13
|
+
stepOf,
|
|
14
|
+
stepsOfCents
|
|
15
|
+
} from "../chunk-I24MV65U.js";
|
|
12
16
|
import {
|
|
13
17
|
createRng
|
|
14
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-HKGYCQ34.js";
|
|
15
19
|
import {
|
|
16
20
|
barPositionToBeat,
|
|
21
|
+
barPositionToPulse,
|
|
17
22
|
beatToBarPosition,
|
|
18
23
|
beatsPerBar,
|
|
24
|
+
createNoteEventIndex,
|
|
25
|
+
formatBarPosition,
|
|
19
26
|
formatTimeSignature,
|
|
20
27
|
isCompound,
|
|
21
28
|
isStrongBeat,
|
|
22
29
|
metricWeight,
|
|
23
30
|
parseTimeSignature,
|
|
31
|
+
pulseBeats,
|
|
24
32
|
pulsesPerBar,
|
|
25
33
|
tuplet
|
|
26
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-YLEMGEFH.js";
|
|
27
35
|
import {
|
|
36
|
+
BudgetExceededError,
|
|
37
|
+
ConsonanceClass,
|
|
38
|
+
DEFAULT_GENERATION_BUDGET,
|
|
39
|
+
InvalidInputError,
|
|
40
|
+
NoSolutionError,
|
|
41
|
+
assertFiniteNumber,
|
|
42
|
+
assertGenerationBudget,
|
|
43
|
+
assertInteger,
|
|
44
|
+
assertNoteEvent,
|
|
45
|
+
assertNoteEvents,
|
|
46
|
+
assertOneOf,
|
|
47
|
+
assertPositiveInt,
|
|
48
|
+
assertRange,
|
|
49
|
+
assertTimeSignature,
|
|
50
|
+
classifyInterval,
|
|
51
|
+
diatonicLetterOf,
|
|
52
|
+
dropSilentNotes,
|
|
28
53
|
formatNote,
|
|
54
|
+
intervalSemitones,
|
|
55
|
+
isConsonantInterval,
|
|
56
|
+
isLibcantusError,
|
|
57
|
+
isPerfectInterval,
|
|
29
58
|
midiToNote,
|
|
59
|
+
naturalPitchClassOf,
|
|
30
60
|
noteToMidi,
|
|
31
61
|
noteToPitchClass,
|
|
62
|
+
parseInterval,
|
|
32
63
|
parseNote,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
isConsonantInterval,
|
|
39
|
-
isPerfectInterval
|
|
40
|
-
} from "../chunk-CCBLVAPK.js";
|
|
64
|
+
pitchClassOf,
|
|
65
|
+
spelledInterval,
|
|
66
|
+
transposeByInterval,
|
|
67
|
+
transposeNote
|
|
68
|
+
} from "../chunk-XEBG3G53.js";
|
|
41
69
|
export {
|
|
42
|
-
|
|
70
|
+
BudgetExceededError,
|
|
71
|
+
ConsonanceClass,
|
|
72
|
+
DEFAULT_GENERATION_BUDGET,
|
|
73
|
+
InvalidInputError,
|
|
43
74
|
JUST_RATIOS,
|
|
75
|
+
NoSolutionError,
|
|
44
76
|
TWELVE_TET,
|
|
77
|
+
assertFiniteNumber,
|
|
78
|
+
assertGenerationBudget,
|
|
79
|
+
assertInteger,
|
|
80
|
+
assertNoteEvent,
|
|
81
|
+
assertNoteEvents,
|
|
82
|
+
assertOneOf,
|
|
83
|
+
assertPositiveInt,
|
|
84
|
+
assertRange,
|
|
85
|
+
assertTimeSignature,
|
|
45
86
|
barPositionToBeat,
|
|
87
|
+
barPositionToPulse,
|
|
46
88
|
beatToBarPosition,
|
|
47
89
|
beatsPerBar,
|
|
48
90
|
centsBetweenFreq,
|
|
91
|
+
centsFromNearestStep,
|
|
49
92
|
centsOfSteps,
|
|
93
|
+
centsToRatio,
|
|
50
94
|
classifyInterval,
|
|
95
|
+
createNoteEventIndex,
|
|
51
96
|
createRng,
|
|
97
|
+
diatonicLetterOf,
|
|
98
|
+
dropSilentNotes,
|
|
52
99
|
edo,
|
|
100
|
+
formatBarPosition,
|
|
53
101
|
formatNote,
|
|
54
102
|
formatTimeSignature,
|
|
55
103
|
frequencyOf,
|
|
104
|
+
intervalSemitones,
|
|
56
105
|
isCompound,
|
|
57
106
|
isConsonantInterval,
|
|
107
|
+
isLibcantusError,
|
|
58
108
|
isPerfectInterval,
|
|
59
109
|
isStrongBeat,
|
|
60
110
|
justDeviationCents,
|
|
61
111
|
metricWeight,
|
|
62
112
|
midiToNote,
|
|
113
|
+
naturalPitchClassOf,
|
|
63
114
|
nearestStep,
|
|
64
115
|
noteToMidi,
|
|
65
116
|
noteToPitchClass,
|
|
117
|
+
parseInterval,
|
|
66
118
|
parseNote,
|
|
67
119
|
parseTimeSignature,
|
|
120
|
+
pitchClassOf,
|
|
121
|
+
pulseBeats,
|
|
68
122
|
pulsesPerBar,
|
|
69
123
|
ratioToCents,
|
|
70
124
|
spelledInterval,
|
|
125
|
+
stepOf,
|
|
126
|
+
stepsOfCents,
|
|
127
|
+
transposeByInterval,
|
|
128
|
+
transposeNote,
|
|
71
129
|
tuplet
|
|
72
130
|
};
|
|
73
131
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as KeyScale } from './types-
|
|
2
|
-
import { C as Chord } from './index-
|
|
1
|
+
import { K as KeyScale } from './types-BN6_Q9Kl.js';
|
|
2
|
+
import { C as Chord } from './index-C83mZI1P.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Borrowed chords (modal interchange) and the Neapolitan.
|
|
@@ -14,7 +14,7 @@ import { C as Chord } from './index-CM5W4rcm.js';
|
|
|
14
14
|
*
|
|
15
15
|
* @category Functional Harmony
|
|
16
16
|
*/
|
|
17
|
-
type BorrowedSource = '
|
|
17
|
+
type BorrowedSource = 'parallelMinor' | 'parallelMajor' | 'neapolitan' | null;
|
|
18
18
|
/**
|
|
19
19
|
* Whether a chord is borrowed from the parallel mode (modal interchange).
|
|
20
20
|
*
|
|
@@ -107,13 +107,33 @@ type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';
|
|
|
107
107
|
*/
|
|
108
108
|
declare function isMinorKey(key: KeyScale): boolean;
|
|
109
109
|
/**
|
|
110
|
-
* The harmonic function of a chord in a key
|
|
111
|
-
*
|
|
112
|
-
*
|
|
110
|
+
* The harmonic function of a chord in a key.
|
|
111
|
+
*
|
|
112
|
+
* The root's offset above the tonic gives the baseline mapping, which follows
|
|
113
|
+
* common-practice major-key function and is a useful approximation in minor and
|
|
114
|
+
* for borrowed chords. Chord quality then refines it where the sonority settles
|
|
115
|
+
* an ambiguity the root offset cannot:
|
|
116
|
+
*
|
|
117
|
+
* - A chord that *sounds* like a dominant — a major third with a minor seventh,
|
|
118
|
+
* or a diminished-family chord — and is not diatonic to the key has dominant
|
|
119
|
+
* function when its root resolves down a fifth or by a semitone onto a
|
|
120
|
+
* diatonic degree. This is what makes an applied dominant (`A7` in C, which
|
|
121
|
+
* tonicizes ii) and its tritone substitute (`Db7`) read as dominant rather
|
|
122
|
+
* than inheriting the function of the degree they happen to sit on.
|
|
123
|
+
* - The Neapolitan is subdominant.
|
|
124
|
+
* - A major triad on bVI or bVII of a major key is subdominant — the borrowed
|
|
125
|
+
* pop cadence chord, distinct from the bVII7 above, which has a seventh and
|
|
126
|
+
* is a dominant sonority.
|
|
113
127
|
*
|
|
114
128
|
* @param chord The chord.
|
|
115
129
|
* @param key The prevailing key.
|
|
116
130
|
* @returns The harmonic function.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { functionOf, makeChord, majorKey } from '@libraz/libcantus';
|
|
134
|
+
* functionOf(makeChord(9, 'dom7'), majorKey(0)); // 'dominant' — A7 tonicizes ii
|
|
135
|
+
* functionOf(makeChord(10, 'maj'), majorKey(0)); // 'subdominant' — borrowed bVII
|
|
136
|
+
* ```
|
|
117
137
|
* @category Functional Harmony
|
|
118
138
|
*/
|
|
119
139
|
declare function functionOf(chord: Chord, key: KeyScale): HarmonicFunction;
|
|
@@ -177,9 +197,10 @@ declare function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis;
|
|
|
177
197
|
/**
|
|
178
198
|
* The secondary dominant (V7) that tonicizes a scale degree.
|
|
179
199
|
*
|
|
180
|
-
* @param targetDegree 0-based scale degree to tonicize.
|
|
200
|
+
* @param targetDegree 0-based scale degree to tonicize, in 0..6.
|
|
181
201
|
* @param key The prevailing key.
|
|
182
202
|
* @returns A dominant-seventh chord a fifth above the target's root.
|
|
203
|
+
* @throws If `targetDegree` is not an integer in 0..6.
|
|
183
204
|
* @category Functional Harmony
|
|
184
205
|
*/
|
|
185
206
|
declare function secondaryDominant(targetDegree: number, key: KeyScale): Chord;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as KeyScale } from './types-
|
|
2
|
-
import { C as Chord } from './index-
|
|
1
|
+
import { K as KeyScale } from './types-BN6_Q9Kl.cjs';
|
|
2
|
+
import { C as Chord } from './index-y_ak9_Hi.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Borrowed chords (modal interchange) and the Neapolitan.
|
|
@@ -14,7 +14,7 @@ import { C as Chord } from './index-BOBXBNwP.cjs';
|
|
|
14
14
|
*
|
|
15
15
|
* @category Functional Harmony
|
|
16
16
|
*/
|
|
17
|
-
type BorrowedSource = '
|
|
17
|
+
type BorrowedSource = 'parallelMinor' | 'parallelMajor' | 'neapolitan' | null;
|
|
18
18
|
/**
|
|
19
19
|
* Whether a chord is borrowed from the parallel mode (modal interchange).
|
|
20
20
|
*
|
|
@@ -107,13 +107,33 @@ type HarmonicFunction = 'tonic' | 'subdominant' | 'dominant';
|
|
|
107
107
|
*/
|
|
108
108
|
declare function isMinorKey(key: KeyScale): boolean;
|
|
109
109
|
/**
|
|
110
|
-
* The harmonic function of a chord in a key
|
|
111
|
-
*
|
|
112
|
-
*
|
|
110
|
+
* The harmonic function of a chord in a key.
|
|
111
|
+
*
|
|
112
|
+
* The root's offset above the tonic gives the baseline mapping, which follows
|
|
113
|
+
* common-practice major-key function and is a useful approximation in minor and
|
|
114
|
+
* for borrowed chords. Chord quality then refines it where the sonority settles
|
|
115
|
+
* an ambiguity the root offset cannot:
|
|
116
|
+
*
|
|
117
|
+
* - A chord that *sounds* like a dominant — a major third with a minor seventh,
|
|
118
|
+
* or a diminished-family chord — and is not diatonic to the key has dominant
|
|
119
|
+
* function when its root resolves down a fifth or by a semitone onto a
|
|
120
|
+
* diatonic degree. This is what makes an applied dominant (`A7` in C, which
|
|
121
|
+
* tonicizes ii) and its tritone substitute (`Db7`) read as dominant rather
|
|
122
|
+
* than inheriting the function of the degree they happen to sit on.
|
|
123
|
+
* - The Neapolitan is subdominant.
|
|
124
|
+
* - A major triad on bVI or bVII of a major key is subdominant — the borrowed
|
|
125
|
+
* pop cadence chord, distinct from the bVII7 above, which has a seventh and
|
|
126
|
+
* is a dominant sonority.
|
|
113
127
|
*
|
|
114
128
|
* @param chord The chord.
|
|
115
129
|
* @param key The prevailing key.
|
|
116
130
|
* @returns The harmonic function.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { functionOf, makeChord, majorKey } from '@libraz/libcantus';
|
|
134
|
+
* functionOf(makeChord(9, 'dom7'), majorKey(0)); // 'dominant' — A7 tonicizes ii
|
|
135
|
+
* functionOf(makeChord(10, 'maj'), majorKey(0)); // 'subdominant' — borrowed bVII
|
|
136
|
+
* ```
|
|
117
137
|
* @category Functional Harmony
|
|
118
138
|
*/
|
|
119
139
|
declare function functionOf(chord: Chord, key: KeyScale): HarmonicFunction;
|
|
@@ -177,9 +197,10 @@ declare function analyzeChord(chord: Chord, key: KeyScale): ChordAnalysis;
|
|
|
177
197
|
/**
|
|
178
198
|
* The secondary dominant (V7) that tonicizes a scale degree.
|
|
179
199
|
*
|
|
180
|
-
* @param targetDegree 0-based scale degree to tonicize.
|
|
200
|
+
* @param targetDegree 0-based scale degree to tonicize, in 0..6.
|
|
181
201
|
* @param key The prevailing key.
|
|
182
202
|
* @returns A dominant-seventh chord a fifth above the target's root.
|
|
203
|
+
* @throws If `targetDegree` is not an integer in 0..6.
|
|
183
204
|
* @category Functional Harmony
|
|
184
205
|
*/
|
|
185
206
|
declare function secondaryDominant(targetDegree: number, key: KeyScale): Chord;
|