@libraz/libcantus 0.9.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -261
- package/README_ja.md +115 -0
- package/dist/analyze/index.cjs +54 -7
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +213 -456
- package/dist/analyze/index.d.ts +213 -456
- package/dist/analyze/index.js +56 -9
- package/dist/chunk-3JXCW6DX.cjs +3220 -0
- package/dist/chunk-3JXCW6DX.cjs.map +1 -0
- package/dist/chunk-4A2RMUCC.js +7647 -0
- package/dist/chunk-4A2RMUCC.js.map +1 -0
- package/dist/chunk-6XPTBE7Y.cjs +49 -0
- package/dist/chunk-6XPTBE7Y.cjs.map +1 -0
- package/dist/chunk-AFM2ULJH.cjs +5121 -0
- package/dist/chunk-AFM2ULJH.cjs.map +1 -0
- package/dist/chunk-E3F4AHAH.cjs +690 -0
- package/dist/chunk-E3F4AHAH.cjs.map +1 -0
- package/dist/chunk-ELCTZUJJ.js +379 -0
- package/dist/chunk-ELCTZUJJ.js.map +1 -0
- package/dist/chunk-FVSI36UV.js +690 -0
- package/dist/chunk-FVSI36UV.js.map +1 -0
- package/dist/chunk-GEDTJHAC.cjs +1 -0
- package/dist/chunk-GEDTJHAC.cjs.map +1 -0
- package/dist/chunk-GOZG57ER.js +3220 -0
- package/dist/chunk-GOZG57ER.js.map +1 -0
- package/dist/chunk-H3VORETI.js +2243 -0
- package/dist/chunk-H3VORETI.js.map +1 -0
- package/dist/chunk-H42UHPYW.js +1577 -0
- package/dist/chunk-H42UHPYW.js.map +1 -0
- package/dist/chunk-HFPS7JFD.js +1 -0
- package/dist/chunk-INHVXP6Z.js +3053 -0
- package/dist/chunk-INHVXP6Z.js.map +1 -0
- package/dist/chunk-K4ZJUGF4.cjs +379 -0
- package/dist/chunk-K4ZJUGF4.cjs.map +1 -0
- package/dist/chunk-KNJEKLKV.js +49 -0
- package/dist/chunk-KNJEKLKV.js.map +1 -0
- package/dist/chunk-M4CWTJWJ.cjs +7647 -0
- package/dist/chunk-M4CWTJWJ.cjs.map +1 -0
- package/dist/chunk-MXO72PLY.cjs +211 -0
- package/dist/chunk-MXO72PLY.cjs.map +1 -0
- package/dist/chunk-NLEU4QSE.cjs +360 -0
- package/dist/chunk-NLEU4QSE.cjs.map +1 -0
- package/dist/chunk-OE6WK2Y2.cjs +1577 -0
- package/dist/chunk-OE6WK2Y2.cjs.map +1 -0
- package/dist/chunk-Q2WGKJNN.cjs +1064 -0
- package/dist/chunk-Q2WGKJNN.cjs.map +1 -0
- package/dist/chunk-QYQQ5J6E.js +1 -0
- package/dist/chunk-QYQQ5J6E.js.map +1 -0
- package/dist/chunk-RHIJ3S4I.cjs +1 -0
- package/dist/chunk-RHIJ3S4I.cjs.map +1 -0
- package/dist/chunk-TTCLJX6D.js +211 -0
- package/dist/chunk-TTCLJX6D.js.map +1 -0
- package/dist/chunk-UADYAYAT.cjs +3053 -0
- package/dist/chunk-UADYAYAT.cjs.map +1 -0
- package/dist/chunk-VOHZB45S.js +5121 -0
- package/dist/chunk-VOHZB45S.js.map +1 -0
- package/dist/chunk-VTI6FOLB.js +1064 -0
- package/dist/chunk-VTI6FOLB.js.map +1 -0
- package/dist/chunk-WWURE4XT.cjs +2243 -0
- package/dist/chunk-WWURE4XT.cjs.map +1 -0
- package/dist/chunk-YH3BIKHH.js +360 -0
- package/dist/chunk-YH3BIKHH.js.map +1 -0
- package/dist/core/index.cjs +103 -6
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +96 -345
- package/dist/core/index.d.ts +96 -345
- package/dist/core/index.js +104 -7
- package/dist/generate/index.cjs +89 -10
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +437 -1095
- package/dist/generate/index.d.ts +437 -1095
- package/dist/generate/index.js +94 -15
- package/dist/index-9wcMhG73.d.ts +1095 -0
- package/dist/{index-D6b6na69.d.cts → index-B4o55NDr.d.cts} +13 -9
- package/dist/index-B9MNZboQ.d.cts +770 -0
- package/dist/index-B9MNZboQ.d.ts +770 -0
- package/dist/index-BGFW-8P2.d.cts +2307 -0
- package/dist/index-BO6xE9YU.d.cts +1804 -0
- package/dist/index-BkGmlyI3.d.cts +470 -0
- package/dist/index-CCNJRG-P.d.cts +1095 -0
- package/dist/index-CGpRv5sl.d.cts +643 -0
- package/dist/index-C_8o--VE.d.cts +1242 -0
- package/dist/index-CgHqxdps.d.ts +2307 -0
- package/dist/index-Chbst3Jx.d.ts +1343 -0
- package/dist/index-Cj49F892.d.ts +470 -0
- package/dist/{index-tSQh-xwY.d.ts → index-CunYKLiu.d.ts} +13 -9
- package/dist/index-D57QRbVn.d.ts +1804 -0
- package/dist/index-DInQqT8Q.d.cts +66 -0
- package/dist/index-DInQqT8Q.d.ts +66 -0
- package/dist/index-Dzr13q3d.d.cts +1343 -0
- package/dist/index-G1uwGGWQ.d.ts +643 -0
- package/dist/index-szBv3496.d.ts +1242 -0
- package/dist/index.cjs +358 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -15
- package/dist/index.d.ts +17 -15
- package/dist/index.js +407 -64
- package/dist/masks-DYbE485J.d.cts +445 -0
- package/dist/masks-DYbE485J.d.ts +445 -0
- package/dist/model/index.cjs +39 -7
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +4685 -243
- package/dist/model/index.d.ts +4685 -243
- package/dist/model/index.js +40 -8
- package/dist/positional-Cptlj-xs.d.ts +287 -0
- package/dist/positional-DvH_sd8u.d.cts +287 -0
- package/dist/theory/index.cjs +101 -7
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +513 -173
- package/dist/theory/index.d.ts +513 -173
- package/dist/theory/index.js +118 -24
- package/package.json +16 -11
- package/dist/chunk-36N73KZ3.cjs +0 -246
- package/dist/chunk-36N73KZ3.cjs.map +0 -1
- package/dist/chunk-4HLLZPXT.cjs +0 -3077
- package/dist/chunk-4HLLZPXT.cjs.map +0 -1
- package/dist/chunk-7MGZ7D62.cjs +0 -498
- package/dist/chunk-7MGZ7D62.cjs.map +0 -1
- package/dist/chunk-7NKDPF74.js +0 -3077
- package/dist/chunk-7NKDPF74.js.map +0 -1
- package/dist/chunk-CAN76NCU.cjs +0 -679
- package/dist/chunk-CAN76NCU.cjs.map +0 -1
- package/dist/chunk-D2FAJBYL.js +0 -479
- package/dist/chunk-D2FAJBYL.js.map +0 -1
- package/dist/chunk-EHVEBWM5.js +0 -1449
- package/dist/chunk-EHVEBWM5.js.map +0 -1
- package/dist/chunk-FCANXBAT.cjs +0 -30
- package/dist/chunk-FCANXBAT.cjs.map +0 -1
- package/dist/chunk-FNDWXRRI.cjs +0 -479
- package/dist/chunk-FNDWXRRI.cjs.map +0 -1
- package/dist/chunk-GQSGS2N4.js +0 -173
- package/dist/chunk-GQSGS2N4.js.map +0 -1
- package/dist/chunk-HKGYCQ34.js +0 -53
- package/dist/chunk-HKGYCQ34.js.map +0 -1
- package/dist/chunk-I24MV65U.js +0 -106
- package/dist/chunk-I24MV65U.js.map +0 -1
- package/dist/chunk-KMHOICIY.js +0 -679
- package/dist/chunk-KMHOICIY.js.map +0 -1
- package/dist/chunk-LW53AHQU.cjs +0 -1117
- package/dist/chunk-LW53AHQU.cjs.map +0 -1
- package/dist/chunk-N6IHQUOX.js +0 -1
- package/dist/chunk-NKIBQ6PT.js +0 -30
- package/dist/chunk-NKIBQ6PT.js.map +0 -1
- package/dist/chunk-NP4NA2FB.cjs +0 -106
- package/dist/chunk-NP4NA2FB.cjs.map +0 -1
- package/dist/chunk-NVE34YGZ.cjs +0 -1449
- package/dist/chunk-NVE34YGZ.cjs.map +0 -1
- package/dist/chunk-NYYWMV2C.js +0 -327
- package/dist/chunk-NYYWMV2C.js.map +0 -1
- package/dist/chunk-Q2XUP227.js +0 -845
- package/dist/chunk-Q2XUP227.js.map +0 -1
- package/dist/chunk-Q6OP4U43.cjs +0 -327
- package/dist/chunk-Q6OP4U43.cjs.map +0 -1
- package/dist/chunk-RC6GBMCD.cjs +0 -845
- package/dist/chunk-RC6GBMCD.cjs.map +0 -1
- package/dist/chunk-RK35RIN7.js +0 -1117
- package/dist/chunk-RK35RIN7.js.map +0 -1
- package/dist/chunk-RUMU3UA6.cjs +0 -53
- package/dist/chunk-RUMU3UA6.cjs.map +0 -1
- package/dist/chunk-T64C7ZD7.cjs +0 -1
- package/dist/chunk-T64C7ZD7.cjs.map +0 -1
- package/dist/chunk-XEBG3G53.js +0 -498
- package/dist/chunk-XEBG3G53.js.map +0 -1
- package/dist/chunk-YLEMGEFH.js +0 -246
- package/dist/chunk-YLEMGEFH.js.map +0 -1
- package/dist/chunk-ZEJR4TKL.cjs +0 -173
- package/dist/chunk-ZEJR4TKL.cjs.map +0 -1
- package/dist/function-BtiZb9i9.d.ts +0 -208
- package/dist/function-DNugAOrt.d.cts +0 -208
- package/dist/index-6VR8-kit.d.ts +0 -143
- package/dist/index-70p168VM.d.ts +0 -192
- package/dist/index-Be74mcon.d.cts +0 -152
- package/dist/index-BtXT6UQ0.d.cts +0 -192
- package/dist/index-C5UBbQ4G.d.ts +0 -152
- package/dist/index-C83mZI1P.d.ts +0 -242
- package/dist/index-DXd9JikN.d.cts +0 -246
- package/dist/index-DXd9JikN.d.ts +0 -246
- package/dist/index-OG65ocOr.d.cts +0 -272
- package/dist/index-OG65ocOr.d.ts +0 -272
- package/dist/index-tJhkmQgE.d.cts +0 -143
- package/dist/index-y_ak9_Hi.d.cts +0 -242
- package/dist/styled-DIRkk9Uz.d.ts +0 -506
- package/dist/styled-DJbkJQfj.d.cts +0 -506
- package/dist/types-BN6_Q9Kl.d.cts +0 -39
- package/dist/types-BN6_Q9Kl.d.ts +0 -39
- /package/dist/{chunk-N6IHQUOX.js.map → chunk-HFPS7JFD.js.map} +0 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import { g as NoteEvent } from './index-B9MNZboQ.js';
|
|
2
|
+
import { e as StringFingering, c as Limb, I as InstrumentProfile } from './positional-Cptlj-xs.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What makes a passage hard or impossible on an instrument.
|
|
6
|
+
*
|
|
7
|
+
* `noteOutOfRange` and `articulationUnavailable` belong to the first layer: the
|
|
8
|
+
* instrument has no position for what was written. `stringConflict`,
|
|
9
|
+
* `stretchTooWide`, `limbConflict` and `polyphonyExceeded` belong to the second:
|
|
10
|
+
* the notes exist but the arrangement cannot be held or struck. `tooFast`
|
|
11
|
+
* belongs to the third, the only one that depends on tempo.
|
|
12
|
+
*
|
|
13
|
+
* @category Core
|
|
14
|
+
*/
|
|
15
|
+
type PlayabilityIssueType = 'noteOutOfRange' | 'articulationUnavailable' | 'stringConflict' | 'stretchTooWide' | 'limbConflict' | 'polyphonyExceeded' | 'tooFast';
|
|
16
|
+
/**
|
|
17
|
+
* Which playability layer an issue belongs to: 1 the note does not exist, 2 the
|
|
18
|
+
* arrangement does not hold together, 3 there is not enough time.
|
|
19
|
+
*
|
|
20
|
+
* @category Core
|
|
21
|
+
*/
|
|
22
|
+
type PlayabilityLayer = 1 | 2 | 3;
|
|
23
|
+
/**
|
|
24
|
+
* One thing standing between a passage and a performance of it.
|
|
25
|
+
*
|
|
26
|
+
* @category Core
|
|
27
|
+
*/
|
|
28
|
+
type PlayabilityIssue = {
|
|
29
|
+
type: PlayabilityIssueType;
|
|
30
|
+
layer: PlayabilityLayer;
|
|
31
|
+
/** Indices into the analysed note array, ascending. */
|
|
32
|
+
notes: readonly number[];
|
|
33
|
+
/** Where the problem occurs, in quarter-note beats. */
|
|
34
|
+
startBeat: number;
|
|
35
|
+
/**
|
|
36
|
+
* True when practice cannot fix it. Layers 1 and 2 depend on the instrument
|
|
37
|
+
* alone, so they are impossible however skilled the player; only a layer-3
|
|
38
|
+
* issue is a matter of degree.
|
|
39
|
+
*/
|
|
40
|
+
impossible: boolean;
|
|
41
|
+
message: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* How one note is actually produced: the string and fret it is stopped at, or
|
|
45
|
+
* the limb that strikes it.
|
|
46
|
+
*
|
|
47
|
+
* This is reported for every note that has a position at all, whether or not
|
|
48
|
+
* the passage raises issues, so a caller can apply its own standard rather than
|
|
49
|
+
* take this module's.
|
|
50
|
+
*
|
|
51
|
+
* @category Core
|
|
52
|
+
*/
|
|
53
|
+
type NotePlacement = {
|
|
54
|
+
/** Index into the analysed note array. */
|
|
55
|
+
note: number;
|
|
56
|
+
/** String instruments: where the note is stopped. */
|
|
57
|
+
fingering?: StringFingering;
|
|
58
|
+
/** Percussion: which limb plays the stroke. */
|
|
59
|
+
limb?: Limb;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The verdict on a passage: how hard it is, what stands in the way, and how
|
|
63
|
+
* each note would be produced.
|
|
64
|
+
*
|
|
65
|
+
* @category Core
|
|
66
|
+
*/
|
|
67
|
+
type PlayabilityReport = {
|
|
68
|
+
/**
|
|
69
|
+
* Movement per unit time, mapped onto 1 (trivial) to 5 (at the limit).
|
|
70
|
+
* Without a tempo the passage is measured at 120 BPM, so the number stays
|
|
71
|
+
* comparable between passages; with one it rises as the tempo does.
|
|
72
|
+
*/
|
|
73
|
+
difficulty: number;
|
|
74
|
+
issues: PlayabilityIssue[];
|
|
75
|
+
placements: NotePlacement[];
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Judge whether a passage can be played on an instrument, and how hard it is.
|
|
79
|
+
*
|
|
80
|
+
* Inspection is deliberately separate from generation: this answers "can this
|
|
81
|
+
* be played" for a chart handed to a player or a practice tool, and never
|
|
82
|
+
* rewrites or rejects anything. The three layers are reported together but stay
|
|
83
|
+
* distinct — an out-of-range note or an impossible stretch is not the bottom of
|
|
84
|
+
* the difficulty scale but a different axis, since no amount of skill puts a
|
|
85
|
+
* note on an instrument that does not have it. Only the third layer consults
|
|
86
|
+
* `bpm`, so omitting the tempo reports what the instrument alone decides.
|
|
87
|
+
*
|
|
88
|
+
* @param notes The passage, in any order. Drum hits qualify as note events.
|
|
89
|
+
* @param profile The instrument to play it on.
|
|
90
|
+
* @param bpm Tempo in quarter-note beats per minute; enables the third layer.
|
|
91
|
+
* @returns Difficulty, the issues found, and each note's string/fret or limb.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { BASS_4_STRING, playability } from '@libraz/libcantus';
|
|
96
|
+
* const report = playability([{ pitch: 27, startBeat: 0, durationBeat: 1 }], BASS_4_STRING);
|
|
97
|
+
* report.issues[0]?.type; // 'noteOutOfRange'
|
|
98
|
+
* ```
|
|
99
|
+
* @category Core
|
|
100
|
+
*/
|
|
101
|
+
declare function playability(notes: readonly NoteEvent[], profile: InstrumentProfile, bpm?: number): PlayabilityReport;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Note values: the written durations a score shows — a base value, its
|
|
105
|
+
* augmentation dots, and an optional tuplet ratio — and the conversion between
|
|
106
|
+
* them and the quarter-note beats the rest of the library measures in.
|
|
107
|
+
*
|
|
108
|
+
* The base values are named the American way (whole, half, quarter, eighth),
|
|
109
|
+
* matching the library's "quarter-note beat" convention and the vocabulary of
|
|
110
|
+
* the MIDI and DAW world this engine reads events from.
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* A written base note value, from the whole note down to the sixty-fourth.
|
|
114
|
+
*
|
|
115
|
+
* Longer values (the breve and beyond) are written as tied notes; see
|
|
116
|
+
* {@link beatsToTiedDurations}.
|
|
117
|
+
*
|
|
118
|
+
* @category Rhythm & Meter
|
|
119
|
+
*/
|
|
120
|
+
type NoteValue = 'whole' | 'half' | 'quarter' | 'eighth' | 'sixteenth' | 'thirtySecond' | 'sixtyFourth';
|
|
121
|
+
/**
|
|
122
|
+
* Every base note value, longest first.
|
|
123
|
+
*
|
|
124
|
+
* @category Rhythm & Meter
|
|
125
|
+
*/
|
|
126
|
+
declare const NOTE_VALUES: readonly NoteValue[];
|
|
127
|
+
/**
|
|
128
|
+
* A tuplet ratio: `actual` written notes played in the time of `normal` ones —
|
|
129
|
+
* `{ actual: 3, normal: 2 }` for a triplet, `{ actual: 5, normal: 4 }` for a
|
|
130
|
+
* quintuplet.
|
|
131
|
+
*
|
|
132
|
+
* @category Rhythm & Meter
|
|
133
|
+
*/
|
|
134
|
+
type Tuplet = {
|
|
135
|
+
/** How many notes are written. */
|
|
136
|
+
actual: number;
|
|
137
|
+
/** How many of the same base value they occupy. */
|
|
138
|
+
normal: number;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* A written duration: a base value, optional augmentation dots, and an optional
|
|
142
|
+
* tuplet ratio. Its length is `base * (2 - 2^-dots) * normal / actual`.
|
|
143
|
+
*
|
|
144
|
+
* @category Rhythm & Meter
|
|
145
|
+
*/
|
|
146
|
+
type DurationData = {
|
|
147
|
+
base: NoteValue;
|
|
148
|
+
/** Augmentation dots, 0 when absent; up to four are accepted. */
|
|
149
|
+
dots?: number;
|
|
150
|
+
tuplet?: Tuplet;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* A duration as {@link beatsToDuration} spells it, with the dot count always
|
|
154
|
+
* stated.
|
|
155
|
+
*
|
|
156
|
+
* @category Rhythm & Meter
|
|
157
|
+
*/
|
|
158
|
+
type SpelledDuration = {
|
|
159
|
+
base: NoteValue;
|
|
160
|
+
dots: number;
|
|
161
|
+
tuplet?: Tuplet;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Length of a written duration in beats.
|
|
165
|
+
*
|
|
166
|
+
* @param duration The duration, or a bare base value as shorthand for an
|
|
167
|
+
* undotted one.
|
|
168
|
+
* @param options `beatUnit` sets what one beat is; a quarter note by default,
|
|
169
|
+
* so a dotted quarter reads as 1.5. Pass `{ base: 'quarter', dots: 1 }` to
|
|
170
|
+
* count in the felt beats of a compound meter.
|
|
171
|
+
* @returns The length in beats.
|
|
172
|
+
* @throws If the base value is unknown, the dot count is not an integer in
|
|
173
|
+
* 0..4, or a tuplet side is not a positive integer.
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* import { durationToBeats } from '@libraz/libcantus';
|
|
177
|
+
* durationToBeats('quarter'); // 1
|
|
178
|
+
* durationToBeats({ base: 'quarter', dots: 1 }); // 1.5
|
|
179
|
+
* durationToBeats({ base: 'eighth', tuplet: { actual: 3, normal: 2 } }); // 1/3
|
|
180
|
+
* ```
|
|
181
|
+
* @category Rhythm & Meter
|
|
182
|
+
*/
|
|
183
|
+
declare function durationToBeats(duration: NoteValue | DurationData, options?: {
|
|
184
|
+
beatUnit?: NoteValue | DurationData;
|
|
185
|
+
}): number;
|
|
186
|
+
/**
|
|
187
|
+
* Spell a length in beats as the note value a score would show.
|
|
188
|
+
*
|
|
189
|
+
* The spelling is the conventional one, not merely an arithmetically valid one:
|
|
190
|
+
* 1.5 beats is a dotted quarter rather than a quarter tied to an eighth, and a
|
|
191
|
+
* third of a beat is an eighth triplet rather than a twenty-fourth note. Plain
|
|
192
|
+
* values are preferred to dotted ones and both to tuplets, and within the
|
|
193
|
+
* tuplets triplets come before quintuplets and septuplets.
|
|
194
|
+
*
|
|
195
|
+
* Lengths are matched within 1e-6 beats, so a rounded decimal such as 0.3333333
|
|
196
|
+
* still reads as a triplet.
|
|
197
|
+
*
|
|
198
|
+
* @param beats The length in beats.
|
|
199
|
+
* @param options `beatUnit` sets what one beat is; a quarter note by default.
|
|
200
|
+
* @returns The base value, its dot count, and its tuplet when it has one.
|
|
201
|
+
* @throws If `beats` is not positive, or — as a `NoSolutionError` — if no single
|
|
202
|
+
* note value spells it, as for 5 beats in 4/4. Use
|
|
203
|
+
* {@link beatsToTiedDurations} for those.
|
|
204
|
+
* @example
|
|
205
|
+
* ```ts
|
|
206
|
+
* import { beatsToDuration } from '@libraz/libcantus';
|
|
207
|
+
* beatsToDuration(1.5); // { base: 'quarter', dots: 1 }
|
|
208
|
+
* beatsToDuration(1 / 3); // { base: 'eighth', dots: 0, tuplet: { actual: 3, normal: 2 } }
|
|
209
|
+
* ```
|
|
210
|
+
* @category Rhythm & Meter
|
|
211
|
+
*/
|
|
212
|
+
declare function beatsToDuration(beats: number, options?: {
|
|
213
|
+
beatUnit?: NoteValue | DurationData;
|
|
214
|
+
}): SpelledDuration;
|
|
215
|
+
/**
|
|
216
|
+
* Spell a length in beats as a chain of tied note values.
|
|
217
|
+
*
|
|
218
|
+
* A length with a single spelling comes back as a one-element chain. Anything
|
|
219
|
+
* else is broken into undotted values, longest first, and a value immediately
|
|
220
|
+
* followed by its own half is then written as a dot instead: 5 beats reads as a
|
|
221
|
+
* whole note tied to a quarter, and 1.9375 beats as a double-dotted quarter tied
|
|
222
|
+
* to a dotted thirty-second. The chain knows nothing of barlines or beat
|
|
223
|
+
* grouping — an engraver splits further at those — and it uses no tuplets, so a
|
|
224
|
+
* length off the plain grid and with no single spelling has no chain either.
|
|
225
|
+
*
|
|
226
|
+
* @param beats The length in beats.
|
|
227
|
+
* @param options `beatUnit` sets what one beat is; a quarter note by default.
|
|
228
|
+
* @returns The tied durations, longest first, summing to `beats`.
|
|
229
|
+
* @throws If `beats` is not positive, if the chain would exceed the generation
|
|
230
|
+
* budget, or — as a `NoSolutionError` — if no chain of plain and dotted values
|
|
231
|
+
* sums to it.
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* import { beatsToTiedDurations } from '@libraz/libcantus';
|
|
235
|
+
* beatsToTiedDurations(5); // [{ base: 'whole', dots: 0 }, { base: 'quarter', dots: 0 }]
|
|
236
|
+
* ```
|
|
237
|
+
* @category Rhythm & Meter
|
|
238
|
+
*/
|
|
239
|
+
declare function beatsToTiedDurations(beats: number, options?: {
|
|
240
|
+
beatUnit?: NoteValue | DurationData;
|
|
241
|
+
}): SpelledDuration[];
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* A validated note retaining its position in the caller's original array.
|
|
245
|
+
*
|
|
246
|
+
* @category Core
|
|
247
|
+
*/
|
|
248
|
+
type IndexedNoteEvent = {
|
|
249
|
+
note: Readonly<NoteEvent>;
|
|
250
|
+
originalIndex: number;
|
|
251
|
+
endBeat: number;
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* Which note wins when several sound from the same onset.
|
|
255
|
+
*
|
|
256
|
+
* `'highest'` and `'lowest'` name a voice, so the answer does not depend on the
|
|
257
|
+
* order the caller happened to store the chord in; `'last'` takes the one
|
|
258
|
+
* latest in the input array.
|
|
259
|
+
*
|
|
260
|
+
* @category Core
|
|
261
|
+
*/
|
|
262
|
+
type OnsetTieBreak = 'highest' | 'lowest' | 'last';
|
|
263
|
+
/**
|
|
264
|
+
* Binary-searchable, stable-sorted index over note onsets and active spans.
|
|
265
|
+
*
|
|
266
|
+
* @category Core
|
|
267
|
+
*/
|
|
268
|
+
type NoteEventIndex = {
|
|
269
|
+
notes: readonly IndexedNoteEvent[];
|
|
270
|
+
/**
|
|
271
|
+
* Latest-onset note sounding at `beat`. Simultaneous onsets are resolved by
|
|
272
|
+
* the index's {@link OnsetTieBreak}.
|
|
273
|
+
*
|
|
274
|
+
* @throws If `beat` is not finite.
|
|
275
|
+
*/
|
|
276
|
+
at: (beat: number) => IndexedNoteEvent | undefined;
|
|
277
|
+
/**
|
|
278
|
+
* Whether one or more sounding notes attack at `beat`.
|
|
279
|
+
*
|
|
280
|
+
* @throws If `beat` is not finite.
|
|
281
|
+
*/
|
|
282
|
+
attacksAt: (beat: number) => boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Unique sounding-note attack beats strictly inside `(startBeat, endBeat)`.
|
|
285
|
+
*
|
|
286
|
+
* @throws If either bound is not finite.
|
|
287
|
+
*/
|
|
288
|
+
onsetsBetween: (startBeat: number, endBeat: number) => number[];
|
|
289
|
+
};
|
|
290
|
+
/**
|
|
291
|
+
* How an index reads the events it is built from.
|
|
292
|
+
*
|
|
293
|
+
* @category Core
|
|
294
|
+
*/
|
|
295
|
+
type NoteEventIndexOptions = {
|
|
296
|
+
allowNonPositiveDuration?: boolean;
|
|
297
|
+
tieBreak?: OnsetTieBreak;
|
|
298
|
+
budget?: number;
|
|
299
|
+
/** What the events are, for the validation error message. */
|
|
300
|
+
name?: string;
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Validate and stable-sort note events once, then expose logarithmic onset and
|
|
304
|
+
* active-note lookups. Non-positive-duration notes may be retained for callers
|
|
305
|
+
* that intentionally filter them later, but never count as sounding.
|
|
306
|
+
*
|
|
307
|
+
* @category Core
|
|
308
|
+
*/
|
|
309
|
+
declare function createNoteEventIndex(events: readonly NoteEvent[], options?: NoteEventIndexOptions): NoteEventIndex;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Tempo and time conversion: beats to wall-clock seconds across tempo changes,
|
|
313
|
+
* and beats to MIDI ticks.
|
|
314
|
+
*
|
|
315
|
+
* Positions are measured in quarter-note beats, matching the rest of the
|
|
316
|
+
* library's beat convention. A {@link TempoMap} is piecewise constant: each
|
|
317
|
+
* entry sets the tempo from its beat onwards, so the elapsed time over a span is
|
|
318
|
+
* the sum of the segments it crosses rather than the tempo at either end.
|
|
319
|
+
*/
|
|
320
|
+
/**
|
|
321
|
+
* A tempo change: the beat it takes effect on, and the tempo it sets.
|
|
322
|
+
*
|
|
323
|
+
* The tempo holds until the next entry, so a map of one entry is a constant
|
|
324
|
+
* tempo for the whole timeline.
|
|
325
|
+
*
|
|
326
|
+
* @category Rhythm & Meter
|
|
327
|
+
*/
|
|
328
|
+
type TempoEvent = {
|
|
329
|
+
/** Onset in quarter-note beats, absolute from the start of the timeline. */
|
|
330
|
+
readonly startBeat: number;
|
|
331
|
+
/** Quarter-note beats per minute from `startBeat` onwards. */
|
|
332
|
+
readonly bpm: number;
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* A tempo track: {@link TempoEvent}s sorted by `startBeat`, strictly ascending.
|
|
336
|
+
*
|
|
337
|
+
* The first entry is the time origin — {@link beatsToSeconds} returns 0 for its
|
|
338
|
+
* `startBeat` — and its tempo also governs the beats before it, which is where
|
|
339
|
+
* a pickup sounds. A map cannot say anything else about that stretch, and a
|
|
340
|
+
* piece is played into its first downbeat at the tempo it starts in, so elapsed
|
|
341
|
+
* time there is negative rather than an error.
|
|
342
|
+
*
|
|
343
|
+
* @category Rhythm & Meter
|
|
344
|
+
*/
|
|
345
|
+
type TempoMap = readonly TempoEvent[];
|
|
346
|
+
/**
|
|
347
|
+
* Wall-clock seconds from the start of a tempo map to a beat.
|
|
348
|
+
*
|
|
349
|
+
* The result integrates every tempo segment the span crosses; it is not the
|
|
350
|
+
* tempo in effect at `beat` applied to the whole span.
|
|
351
|
+
*
|
|
352
|
+
* A beat before the map's first event reports negative elapsed time, at the
|
|
353
|
+
* opening tempo: a pickup sounds before the downbeat, and asking when it sounds
|
|
354
|
+
* is a fair question.
|
|
355
|
+
*
|
|
356
|
+
* @param beat Position in quarter-note beats.
|
|
357
|
+
* @param map The tempo map; its first event is the time origin.
|
|
358
|
+
* @returns Elapsed seconds, 0 at the map's first event and negative before it.
|
|
359
|
+
* @throws If the map is empty, unsorted, or carries a non-positive tempo.
|
|
360
|
+
* @example
|
|
361
|
+
* ```ts
|
|
362
|
+
* import { beatsToSeconds } from '@libraz/libcantus';
|
|
363
|
+
* const map = [{ startBeat: 0, bpm: 120 }, { startBeat: 4, bpm: 60 }];
|
|
364
|
+
* beatsToSeconds(8, map); // 6 = 4 beats at 120 + 4 beats at 60
|
|
365
|
+
* ```
|
|
366
|
+
* @category Rhythm & Meter
|
|
367
|
+
*/
|
|
368
|
+
declare function beatsToSeconds(beat: number, map: TempoMap): number;
|
|
369
|
+
/**
|
|
370
|
+
* The beat reached after a number of seconds — the inverse of
|
|
371
|
+
* {@link beatsToSeconds}.
|
|
372
|
+
*
|
|
373
|
+
* @param seconds Elapsed seconds from the map's first event; negative for a
|
|
374
|
+
* position before it, such as a pickup.
|
|
375
|
+
* @param map The tempo map.
|
|
376
|
+
* @returns The position in quarter-note beats.
|
|
377
|
+
* @throws If the map is malformed or `seconds` is not finite.
|
|
378
|
+
* @example
|
|
379
|
+
* ```ts
|
|
380
|
+
* import { secondsToBeats } from '@libraz/libcantus';
|
|
381
|
+
* const map = [{ startBeat: 0, bpm: 120 }, { startBeat: 4, bpm: 60 }];
|
|
382
|
+
* secondsToBeats(6, map); // 8
|
|
383
|
+
* ```
|
|
384
|
+
* @category Rhythm & Meter
|
|
385
|
+
*/
|
|
386
|
+
declare function secondsToBeats(seconds: number, map: TempoMap): number;
|
|
387
|
+
/**
|
|
388
|
+
* Duration in seconds of a span of beats.
|
|
389
|
+
*
|
|
390
|
+
* Equal to the difference of two {@link beatsToSeconds} calls — the integral is
|
|
391
|
+
* additive, so that reading is exact — but integrated over the span directly, so
|
|
392
|
+
* a short note late in a long piece does not lose precision to the subtraction
|
|
393
|
+
* of two large elapsed times.
|
|
394
|
+
*
|
|
395
|
+
* @param startBeat Where the span begins, in quarter-note beats; a pickup
|
|
396
|
+
* starts before the map's first event and is measured like any other span.
|
|
397
|
+
* @param lengthBeats How long the span lasts, in quarter-note beats.
|
|
398
|
+
* @param map The tempo map.
|
|
399
|
+
* @returns The span's duration in seconds, never negative.
|
|
400
|
+
* @throws If the map is malformed or the length is negative.
|
|
401
|
+
* @example
|
|
402
|
+
* ```ts
|
|
403
|
+
* import { durationToSeconds } from '@libraz/libcantus';
|
|
404
|
+
* const map = [{ startBeat: 0, bpm: 120 }, { startBeat: 4, bpm: 60 }];
|
|
405
|
+
* durationToSeconds(2, 4, map); // 3 = 2 beats at 120 + 2 beats at 60
|
|
406
|
+
* ```
|
|
407
|
+
* @category Rhythm & Meter
|
|
408
|
+
*/
|
|
409
|
+
declare function durationToSeconds(startBeat: number, lengthBeats: number, map: TempoMap): number;
|
|
410
|
+
/**
|
|
411
|
+
* The tempo in effect at a beat.
|
|
412
|
+
*
|
|
413
|
+
* A beat before the first event reads the opening tempo, which is the tempo a
|
|
414
|
+
* pickup is played at.
|
|
415
|
+
*
|
|
416
|
+
* @param beat Position in quarter-note beats.
|
|
417
|
+
* @param map The tempo map.
|
|
418
|
+
* @returns Quarter-note beats per minute.
|
|
419
|
+
* @throws If the map is malformed.
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* import { tempoAt } from '@libraz/libcantus';
|
|
423
|
+
* tempoAt(5, [{ startBeat: 0, bpm: 120 }, { startBeat: 4, bpm: 60 }]); // 60
|
|
424
|
+
* ```
|
|
425
|
+
* @category Rhythm & Meter
|
|
426
|
+
*/
|
|
427
|
+
declare function tempoAt(beat: number, map: TempoMap): number;
|
|
428
|
+
/**
|
|
429
|
+
* Convert quarter-note beats to MIDI ticks.
|
|
430
|
+
*
|
|
431
|
+
* Ticks are whole units of a sequencer's grid, so the result is rounded to the
|
|
432
|
+
* nearest tick; a beat that is not on the grid is not representable and comes
|
|
433
|
+
* back quantized.
|
|
434
|
+
*
|
|
435
|
+
* A position before the first downbeat is a negative tick count, which is how a
|
|
436
|
+
* pickup crosses the MIDI boundary and comes back.
|
|
437
|
+
*
|
|
438
|
+
* @param beat Position or length in quarter-note beats.
|
|
439
|
+
* @param ppq Pulses (ticks) per quarter note, e.g. 96, 480, or 960.
|
|
440
|
+
* @returns The whole tick count.
|
|
441
|
+
* @throws If `beat` is not finite or `ppq` is not a positive integer.
|
|
442
|
+
* @example
|
|
443
|
+
* ```ts
|
|
444
|
+
* import { beatsToTicks } from '@libraz/libcantus';
|
|
445
|
+
* beatsToTicks(1.5, 480); // 720
|
|
446
|
+
* ```
|
|
447
|
+
* @category Rhythm & Meter
|
|
448
|
+
*/
|
|
449
|
+
declare function beatsToTicks(beat: number, ppq: number): number;
|
|
450
|
+
/**
|
|
451
|
+
* Convert MIDI ticks to quarter-note beats.
|
|
452
|
+
*
|
|
453
|
+
* @param ticks Whole tick count, negative before the first downbeat.
|
|
454
|
+
* @param ppq Pulses (ticks) per quarter note, e.g. 96, 480, or 960.
|
|
455
|
+
* @returns The position or length in quarter-note beats.
|
|
456
|
+
* @throws If `ticks` is not an integer or `ppq` is not a positive integer.
|
|
457
|
+
* @example
|
|
458
|
+
* ```ts
|
|
459
|
+
* import { ticksToBeats } from '@libraz/libcantus';
|
|
460
|
+
* ticksToBeats(720, 480); // 1.5
|
|
461
|
+
* ```
|
|
462
|
+
* @category Rhythm & Meter
|
|
463
|
+
*/
|
|
464
|
+
declare function ticksToBeats(ticks: number, ppq: number): number;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Tuning and microtonality: frequency conversion, cents, arbitrary equal
|
|
468
|
+
* temperaments (EDO), and just-intonation ratios.
|
|
469
|
+
*
|
|
470
|
+
* The rest of the library reasons in twelve-tone pitch classes, which is a
|
|
471
|
+
* deliberate scope choice for tonal theory. This module is the escape hatch for
|
|
472
|
+
* anyone who needs actual frequencies, cents, non-12 equal temperaments, or the
|
|
473
|
+
* acoustic (just) tuning behind the tempered intervals.
|
|
474
|
+
*/
|
|
475
|
+
/**
|
|
476
|
+
* An equal-tempered tuning: a reference pitch and a number of equal divisions of
|
|
477
|
+
* the octave. With `divisions === 12` a step index is an ordinary MIDI number.
|
|
478
|
+
*
|
|
479
|
+
* @category Pitch & Intervals
|
|
480
|
+
*/
|
|
481
|
+
type TuningTable = {
|
|
482
|
+
/** Step index (MIDI number when `divisions` is 12) whose frequency is `refFreq`. */
|
|
483
|
+
readonly refStep: number;
|
|
484
|
+
/** Frequency in Hz of `refStep`. */
|
|
485
|
+
readonly refFreq: number;
|
|
486
|
+
/** Equal divisions of the octave (12 standard; e.g. 19 or 31 for microtonal). */
|
|
487
|
+
readonly divisions: number;
|
|
488
|
+
};
|
|
489
|
+
/**
|
|
490
|
+
* Standard twelve-tone equal temperament, A4 (MIDI 69) = 440 Hz.
|
|
491
|
+
*
|
|
492
|
+
* @category Pitch & Intervals
|
|
493
|
+
*/
|
|
494
|
+
declare const TWELVE_TET: TuningTable;
|
|
495
|
+
/**
|
|
496
|
+
* Build an equal temperament with `n` divisions of the octave.
|
|
497
|
+
*
|
|
498
|
+
* @param n Divisions of the octave (e.g. 19, 24, 31).
|
|
499
|
+
* @param refFreq Reference frequency in Hz (default 440).
|
|
500
|
+
* @param refStep Step index of the reference (default 69).
|
|
501
|
+
* @returns The tuning.
|
|
502
|
+
* @example
|
|
503
|
+
* ```ts
|
|
504
|
+
* import { edo, frequencyOf } from '@libraz/libcantus';
|
|
505
|
+
* const et19 = edo(19); // { refStep: 69, refFreq: 440, divisions: 19 }
|
|
506
|
+
* frequencyOf(70, et19); // one 19-EDO step above A4
|
|
507
|
+
* ```
|
|
508
|
+
* @category Pitch & Intervals
|
|
509
|
+
*/
|
|
510
|
+
declare function edo(n: number, refFreq?: number, refStep?: number): TuningTable;
|
|
511
|
+
/**
|
|
512
|
+
* Frequency in Hz of a step index under a tuning.
|
|
513
|
+
*
|
|
514
|
+
* @param step Step index (a MIDI number under 12-EDO).
|
|
515
|
+
* @param tuning The tuning (default 12-TET).
|
|
516
|
+
* @returns The frequency in Hz.
|
|
517
|
+
* @example
|
|
518
|
+
* ```ts
|
|
519
|
+
* import { frequencyOf } from '@libraz/libcantus';
|
|
520
|
+
* frequencyOf(69); // 440 (A4 in 12-TET)
|
|
521
|
+
* frequencyOf(60); // middle C in Hz
|
|
522
|
+
* ```
|
|
523
|
+
* @category Pitch & Intervals
|
|
524
|
+
*/
|
|
525
|
+
declare function frequencyOf(step: number, tuning?: TuningTable): number;
|
|
526
|
+
/**
|
|
527
|
+
* Nearest step index to a frequency under a tuning (the inverse of
|
|
528
|
+
* {@link frequencyOf}, rounded).
|
|
529
|
+
*
|
|
530
|
+
* @param freq Frequency in Hz.
|
|
531
|
+
* @param tuning The tuning (default 12-TET).
|
|
532
|
+
* @returns The nearest step index.
|
|
533
|
+
* @category Pitch & Intervals
|
|
534
|
+
*/
|
|
535
|
+
declare function nearestStep(freq: number, tuning?: TuningTable): number;
|
|
536
|
+
/**
|
|
537
|
+
* Step index of a frequency under a tuning, unrounded.
|
|
538
|
+
*
|
|
539
|
+
* The exact inverse of {@link frequencyOf}. {@link nearestStep} rounds it,
|
|
540
|
+
* which discards how far off the pitch actually is — the figure a tuner
|
|
541
|
+
* display, a pitch-bend amount, or an intonation check is built on.
|
|
542
|
+
*
|
|
543
|
+
* @param freq Frequency in Hz.
|
|
544
|
+
* @param tuning The tuning (default 12-TET).
|
|
545
|
+
* @returns The fractional step index.
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* import { stepOf } from '@libraz/libcantus';
|
|
549
|
+
* stepOf(442); // slightly above 69, the step for A440
|
|
550
|
+
* ```
|
|
551
|
+
* @category Pitch & Intervals
|
|
552
|
+
*/
|
|
553
|
+
declare function stepOf(freq: number, tuning?: TuningTable): number;
|
|
554
|
+
/**
|
|
555
|
+
* How far a frequency sits from its nearest step, in cents.
|
|
556
|
+
*
|
|
557
|
+
* Positive means sharp of the step, negative flat.
|
|
558
|
+
*
|
|
559
|
+
* @param freq Frequency in Hz.
|
|
560
|
+
* @param tuning The tuning (default 12-TET).
|
|
561
|
+
* @returns The signed deviation in cents.
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* import { centsFromNearestStep } from '@libraz/libcantus';
|
|
565
|
+
* Math.round(centsFromNearestStep(442)); // 8
|
|
566
|
+
* ```
|
|
567
|
+
* @category Pitch & Intervals
|
|
568
|
+
*/
|
|
569
|
+
declare function centsFromNearestStep(freq: number, tuning?: TuningTable): number;
|
|
570
|
+
/**
|
|
571
|
+
* Steps spanned by an interval in cents, unrounded — the inverse of
|
|
572
|
+
* {@link centsOfSteps}.
|
|
573
|
+
*
|
|
574
|
+
* @param cents The interval in cents.
|
|
575
|
+
* @param tuning The tuning (default 12-TET).
|
|
576
|
+
* @returns The fractional step count.
|
|
577
|
+
* @category Pitch & Intervals
|
|
578
|
+
*/
|
|
579
|
+
declare function stepsOfCents(cents: number, tuning?: TuningTable): number;
|
|
580
|
+
/**
|
|
581
|
+
* The frequency ratio an interval in cents spans — the inverse of
|
|
582
|
+
* {@link ratioToCents}.
|
|
583
|
+
*
|
|
584
|
+
* Multiply a frequency by this to move it by that many cents, which is how a
|
|
585
|
+
* cents offset (a pitch-bend spec, a tuning table entry) is applied.
|
|
586
|
+
*
|
|
587
|
+
* @param cents The interval in cents.
|
|
588
|
+
* @returns The frequency ratio.
|
|
589
|
+
* @example
|
|
590
|
+
* ```ts
|
|
591
|
+
* import { centsToRatio } from '@libraz/libcantus';
|
|
592
|
+
* 440 * centsToRatio(14); // A440 raised by 14 cents
|
|
593
|
+
* ```
|
|
594
|
+
* @category Pitch & Intervals
|
|
595
|
+
*/
|
|
596
|
+
declare function centsToRatio(cents: number): number;
|
|
597
|
+
/**
|
|
598
|
+
* Interval in cents between two frequencies.
|
|
599
|
+
*
|
|
600
|
+
* @param a Lower/first frequency in Hz.
|
|
601
|
+
* @param b Upper/second frequency in Hz.
|
|
602
|
+
* @returns Cents from `a` to `b` (negative if `b` is lower).
|
|
603
|
+
* @category Pitch & Intervals
|
|
604
|
+
*/
|
|
605
|
+
declare function centsBetweenFreq(a: number, b: number): number;
|
|
606
|
+
/**
|
|
607
|
+
* Cents spanned by a number of equal-temperament steps.
|
|
608
|
+
*
|
|
609
|
+
* @param steps Number of steps.
|
|
610
|
+
* @param tuning The tuning (default 12-TET).
|
|
611
|
+
* @returns The cents.
|
|
612
|
+
* @category Pitch & Intervals
|
|
613
|
+
*/
|
|
614
|
+
declare function centsOfSteps(steps: number, tuning?: TuningTable): number;
|
|
615
|
+
/**
|
|
616
|
+
* Cents of a frequency ratio, e.g. `ratioToCents(3, 2)` ≈ 701.955 for the just
|
|
617
|
+
* perfect fifth.
|
|
618
|
+
*
|
|
619
|
+
* @param numerator Ratio numerator.
|
|
620
|
+
* @param denominator Ratio denominator.
|
|
621
|
+
* @returns The interval in cents.
|
|
622
|
+
* @category Pitch & Intervals
|
|
623
|
+
*/
|
|
624
|
+
declare function ratioToCents(numerator: number, denominator: number): number;
|
|
625
|
+
/**
|
|
626
|
+
* Five-limit just-intonation ratios for the twelve interval classes above a
|
|
627
|
+
* unison, indexed by semitone class (0..12).
|
|
628
|
+
*
|
|
629
|
+
* @category Pitch & Intervals
|
|
630
|
+
*/
|
|
631
|
+
declare const JUST_RATIOS: Readonly<Record<number, readonly [number, number]>>;
|
|
632
|
+
/**
|
|
633
|
+
* Cents by which a five-limit just interval departs from its 12-TET tempering
|
|
634
|
+
* (positive means the just interval is wider).
|
|
635
|
+
*
|
|
636
|
+
* @param semitoneClass Semitone class in [0, 12].
|
|
637
|
+
* @returns The deviation in cents.
|
|
638
|
+
* @throws If `semitoneClass` is not an integer in [0, 12].
|
|
639
|
+
* @category Pitch & Intervals
|
|
640
|
+
*/
|
|
641
|
+
declare function justDeviationCents(semitoneClass: number): number;
|
|
642
|
+
|
|
643
|
+
export { playability as A, ratioToCents as B, secondsToBeats as C, type DurationData as D, stepOf as E, stepsOfCents as F, tempoAt as G, ticksToBeats as H, type IndexedNoteEvent as I, JUST_RATIOS as J, NOTE_VALUES as N, type OnsetTieBreak as O, type PlayabilityIssue as P, type SpelledDuration as S, TWELVE_TET as T, type NoteEventIndex as a, type NoteEventIndexOptions as b, type NotePlacement as c, type NoteValue as d, type PlayabilityIssueType as e, type PlayabilityLayer as f, type PlayabilityReport as g, type TempoEvent as h, type TempoMap as i, type TuningTable as j, type Tuplet as k, beatsToDuration as l, beatsToSeconds as m, beatsToTicks as n, beatsToTiedDurations as o, centsBetweenFreq as p, centsFromNearestStep as q, centsOfSteps as r, centsToRatio as s, createNoteEventIndex as t, durationToBeats as u, durationToSeconds as v, edo as w, frequencyOf as x, justDeviationCents as y, nearestStep as z };
|