tonus 0.1.8 → 0.5.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/BIBLIOGRAPHY.md +132 -108
- package/CHANGELOG.md +598 -1
- package/LICENSE +133 -29
- package/README.md +106 -83
- package/dist/data/am.js +2666 -11196
- package/dist/data/ams.d.ts +5 -0
- package/dist/data/ams.js +122 -0
- package/dist/data/attestation.d.ts +19 -0
- package/dist/data/attestation.js +15716 -0
- package/dist/data/attestation.json +15711 -0
- package/dist/data/cadentiae.d.ts +43 -0
- package/dist/data/cadentiae.js +174 -0
- package/dist/data/cal.js +48 -0
- package/dist/data/census.d.ts +12 -0
- package/dist/data/census.js +36 -0
- package/dist/data/commune-office.d.ts +4 -0
- package/dist/data/commune-office.js +2371 -0
- package/dist/data/commune-office.json +2365 -0
- package/dist/data/commune.js +181 -11
- package/dist/data/corpus-overlap.d.ts +17 -0
- package/dist/data/corpus-overlap.js +299 -5
- package/dist/data/cot.d.ts +5 -0
- package/dist/data/cot.js +172 -0
- package/dist/data/cse.d.ts +5 -0
- package/dist/data/cse.js +122 -0
- package/dist/data/gabc-glyphs.d.ts +45 -0
- package/dist/data/gabc-glyphs.js +122 -0
- package/dist/data/gr.js +754 -6394
- package/dist/data/kyriale.js +116 -116
- package/dist/data/la.js +799 -13419
- package/dist/data/lh.js +113 -3473
- package/dist/data/lu.js +931 -17631
- package/dist/data/nocturnale-romanum.js +1659 -10411
- package/dist/data/office-ferial.d.ts +4 -0
- package/dist/data/office-ferial.js +396 -0
- package/dist/data/office-ferial.json +391 -0
- package/dist/data/office-monastic.d.ts +17 -1
- package/dist/data/office-monastic.js +1403 -466
- package/dist/data/office-psalms-monastic.d.ts +13 -1
- package/dist/data/office-psalms-monastic.js +9 -0
- package/dist/data/propers.js +1 -1
- package/dist/data/psalms.js +22919 -5
- package/dist/data/psm.d.ts +5 -0
- package/dist/data/psm.js +122 -0
- package/dist/data/seasonal-respbreve.d.ts +5 -0
- package/dist/data/seasonal-respbreve.js +41 -0
- package/dist/data/seasonal-respbreve.json +35 -0
- package/dist/data/smufl-glyphs.d.ts +17 -0
- package/dist/data/smufl-glyphs.js +1546 -0
- package/dist/data/smufl-glyphs.json +1530 -0
- package/dist/engines/cal/calendar.d.ts +3 -2
- package/dist/engines/cal/calendar.js +105 -29
- package/dist/engines/cal/data/eras.d.ts +35 -0
- package/dist/engines/cal/data/eras.js +128 -0
- package/dist/engines/cal/date.js +44 -0
- package/dist/engines/cal/types.d.ts +15 -3
- package/dist/engines/cal/types.js +5 -5
- package/dist/engines/census/census.d.ts +7 -0
- package/dist/engines/census/census.js +179 -0
- package/dist/engines/census/types.d.ts +55 -0
- package/dist/engines/census/types.js +8 -0
- package/dist/engines/chant/attest.d.ts +39 -0
- package/dist/engines/chant/attest.js +90 -0
- package/dist/engines/chant/chant.d.ts +16 -4
- package/dist/engines/chant/chant.js +220 -30
- package/dist/engines/chant/data/compline.js +2 -1
- package/dist/engines/chant/data/masses.d.ts +56 -4
- package/dist/engines/chant/data/masses.js +305 -80
- package/dist/engines/chant/data/prime.js +1 -1
- package/dist/engines/chant/hour.js +279 -58
- package/dist/engines/chant/ordinary.d.ts +2 -0
- package/dist/engines/chant/ordinary.js +336 -56
- package/dist/engines/chant/propers.js +55 -5
- package/dist/engines/chant/psalm.d.ts +4 -4
- package/dist/engines/chant/psalm.js +25 -11
- package/dist/engines/chant/syllabify.d.ts +1 -0
- package/dist/engines/chant/syllabify.js +90 -17
- package/dist/engines/chant/types.d.ts +115 -12
- package/dist/engines/chant/types.js +38 -3
- package/dist/engines/harmonia/api.js +4 -0
- package/dist/engines/harmonia/data/doctrines.js +3 -1
- package/dist/engines/harmonia/tabula.d.ts +3 -0
- package/dist/engines/harmonia/tabula.js +1 -0
- package/dist/engines/harmonia/voice.d.ts +4 -0
- package/dist/engines/harmonia/voice.js +8 -4
- package/dist/engines/imprint.js +14 -1
- package/dist/engines/planet/orbital.js +4 -4
- package/dist/engines/planet/planet.d.ts +10 -0
- package/dist/engines/planet/planet.js +30 -3
- package/dist/engines/planet/position.js +13 -10
- package/dist/engines/planet/types.d.ts +1 -0
- package/dist/engines/score/api.d.ts +2 -13
- package/dist/engines/score/api.js +21 -8
- package/dist/engines/score/articulation.js +2 -2
- package/dist/engines/score/cadence.d.ts +76 -0
- package/dist/engines/score/cadence.js +96 -0
- package/dist/engines/score/emitters/accidentals.d.ts +21 -0
- package/dist/engines/score/emitters/accidentals.js +88 -0
- package/dist/engines/score/emitters/atramentum.d.ts +107 -0
- package/dist/engines/score/emitters/atramentum.js +239 -0
- package/dist/engines/score/emitters/breaking.d.ts +62 -0
- package/dist/engines/score/emitters/breaking.js +80 -0
- package/dist/engines/score/emitters/moderna.d.ts +38 -0
- package/dist/engines/score/emitters/moderna.js +612 -0
- package/dist/engines/score/emitters/svg.d.ts +143 -0
- package/dist/engines/score/emitters/svg.js +1328 -0
- package/dist/engines/score/emitters/tracks.d.ts +104 -0
- package/dist/engines/score/emitters/tracks.js +728 -0
- package/dist/engines/score/infer.d.ts +3 -3
- package/dist/engines/score/infer.js +2 -2
- package/dist/engines/score/inscriptio.d.ts +69 -0
- package/dist/engines/score/inscriptio.js +138 -0
- package/dist/engines/score/ir.d.ts +2 -2
- package/dist/engines/score/ir.js +59 -12
- package/dist/engines/score/lyric.d.ts +23 -0
- package/dist/engines/score/lyric.js +234 -0
- package/dist/engines/score/meta.d.ts +2 -2
- package/dist/engines/score/modulation.d.ts +12 -0
- package/dist/engines/score/modulation.js +49 -0
- package/dist/engines/score/neume.js +35 -4
- package/dist/engines/score/parse.js +150 -9
- package/dist/engines/score/phrasing.js +4 -3
- package/dist/engines/score/prosody.d.ts +38 -0
- package/dist/engines/score/prosody.js +70 -6
- package/dist/engines/score/tabula.d.ts +37 -5
- package/dist/engines/score/tabula.js +18 -0
- package/dist/engines/score/types.d.ts +88 -1
- package/dist/engines/temper/api.d.ts +4 -1
- package/dist/engines/temper/api.js +28 -5
- package/dist/engines/temper/data/guido.js +6 -2
- package/dist/engines/temper/data/modes.d.ts +6 -0
- package/dist/engines/temper/data/modes.js +42 -0
- package/dist/engines/temper/data/tones.d.ts +1 -1
- package/dist/engines/temper/data/tones.js +20 -11
- package/dist/engines/temper/interval.js +4 -3
- package/dist/engines/temper/modality.d.ts +11 -2
- package/dist/engines/temper/modality.js +74 -2
- package/dist/engines/temper/modes.d.ts +1 -1
- package/dist/engines/temper/pitch.d.ts +1 -1
- package/dist/engines/temper/pitch.js +12 -2
- package/dist/engines/temper/scale.d.ts +53 -0
- package/dist/engines/temper/scale.js +107 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +37 -4
- package/docs/api/calendar.md +279 -0
- package/docs/api/census.md +288 -0
- package/docs/api/chant.md +657 -0
- package/docs/api/heavens.md +346 -0
- package/docs/api/index.md +263 -0
- package/docs/api/score.md +873 -0
- package/docs/api/tuning.md +619 -0
- package/package.json +11 -5
- package/dist/data/office-matins-roman.d.ts +0 -19
- package/dist/data/office-matins-roman.js +0 -4383
- package/dist/data/office-psalms-roman.d.ts +0 -15
- package/dist/data/office-psalms-roman.js +0 -28
- package/dist/data/office-roman.d.ts +0 -19
- package/dist/data/office-roman.js +0 -13792
- package/dist/engines/chant/matutinum.d.ts +0 -33
- package/dist/engines/chant/matutinum.js +0 -81
- package/dist/engines/score/emitters/midi.d.ts +0 -65
- package/dist/engines/score/emitters/midi.js +0 -162
- package/dist/engines/score/emitters/musicxml.d.ts +0 -18
- package/dist/engines/score/emitters/musicxml.js +0 -166
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
# Tuning
|
|
2
|
+
|
|
3
|
+
`tonus.temperamentum` is the library's model of medieval pitch. It builds
|
|
4
|
+
a tuning context (temperament, mode, A4) and returns helper functions to tune and analyze pitch content. The engine depends on nothing
|
|
5
|
+
else in the library and may be used alone; every pitch elsewhere in tonus
|
|
6
|
+
is resolved through one of these contexts. The default tuning is
|
|
7
|
+
Pythagorean, as in the treatises.
|
|
8
|
+
|
|
9
|
+
- [Tuning](#tuning)
|
|
10
|
+
- [The context — `temperamentum`](#the-context--temperamentum)
|
|
11
|
+
- [Pitch input](#pitch-input)
|
|
12
|
+
- [Pitches — `nota`](#pitches--nota)
|
|
13
|
+
- [Steps — `gradus`](#steps--gradus)
|
|
14
|
+
- [Intervals — `intervallum`](#intervals--intervallum)
|
|
15
|
+
- [Neumes — `neuma`](#neumes--neuma)
|
|
16
|
+
- [Ratios — `ratio`](#ratios--ratio)
|
|
17
|
+
- [The gamut — `gamut`](#the-gamut--gamut)
|
|
18
|
+
- [Modes — `modus`](#modes--modus)
|
|
19
|
+
- [Cadence figures](#cadence-figures)
|
|
20
|
+
- [The corpus catalogue — `CADENTIAE`](#the-corpus-catalogue--cadentiae)
|
|
21
|
+
- [Lift — how mode-bound a close is](#lift--how-mode-bound-a-close-is)
|
|
22
|
+
- [Psalm tones — `tonus`](#psalm-tones--tonus)
|
|
23
|
+
- [Theory \& Context](#theory--context)
|
|
24
|
+
- [The presets](#the-presets)
|
|
25
|
+
|
|
26
|
+
## The context — `temperamentum`
|
|
27
|
+
|
|
28
|
+
`temperamentum(input?)` returns a `Temperamentum`. The input is a tuning
|
|
29
|
+
name, an options object, or nothing; with nothing, the context is
|
|
30
|
+
Pythagorean, mode `"auto"`, A4 = 440 Hz. Invalid input throws.
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
tonus.temperamentum(); // pythagorean, mode auto, A4=440
|
|
34
|
+
tonus.temperamentum("pythagorean"); // string shorthand
|
|
35
|
+
tonus.temperamentum({ tuning: "meantone", comma: "1/4" });
|
|
36
|
+
tonus.temperamentum({ tuning: "ptolemy-intense" }); // just intonation
|
|
37
|
+
tonus.temperamentum({ tuning: "equal", mode: 3, a4: 415 });
|
|
38
|
+
tonus.temperamentum({ scale: ["1/1", "9/8", "5/4" /* … */] }); // custom array
|
|
39
|
+
tonus.temperamentum({ scale: "! meanquar.scl\n…" }); // Scala file
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**`TemperamentumOpts`**
|
|
43
|
+
|
|
44
|
+
| Field | Type | Default | Description |
|
|
45
|
+
| ----------- | -------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| `tuning` | `Tuning` | `"pythagorean"` | Base temperament |
|
|
47
|
+
| `mode` | `number \| "auto"` | `"auto"` | Gregorian mode (1–8); `"auto"` resolves from chant, falls back to mode 1 (final D) |
|
|
48
|
+
| `a4` | `number` | `440` | A4 reference frequency in Hz |
|
|
49
|
+
| `root` | `number` | mode finalis | Root pitch class override (0–11) |
|
|
50
|
+
| `transpose` | `number` | `0` | Output semitone transposition |
|
|
51
|
+
| `comma` | `number \| string` | — | Meantone comma (`0.25`, `"1/4"`, `"1/3"`); ignored for other tunings |
|
|
52
|
+
| `scale` | `string \| string[]` | — | Scala `.scl` file string or array of 7/12 ratio/cent values, beginning at `1/1` (degree list) or ending at `2/1` (Scala convention); implies custom tuning, name from the Scala description |
|
|
53
|
+
|
|
54
|
+
The tuning presets:
|
|
55
|
+
|
|
56
|
+
| Name | Description |
|
|
57
|
+
| ------------------- | -------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `"pythagorean"` | Pure fifths (3/2), no tempering. Default |
|
|
59
|
+
| `"meantone"` | Tempered fifths; `comma` controls the amount (default 1/4) |
|
|
60
|
+
| `"equal"` | 12-tone equal temperament |
|
|
61
|
+
| `"ptolemy-intense"` | Ptolemy's intense diatonic (_syntonon_) — classical just intonation, pure major thirds (5/4) |
|
|
62
|
+
| `"ptolemy-soft"` | Ptolemy's soft diatonic (_malakon_) — septimal tuning, 8/7 whole tone |
|
|
63
|
+
| `"ptolemy-equable"` | Ptolemy's equable diatonic (_homalon_) — undecimal tuning, neutral 12/11 seconds |
|
|
64
|
+
|
|
65
|
+
What each preset is, and when to choose it, is treated in
|
|
66
|
+
[Theory & Context](#theory--context). Any other string is accepted as a
|
|
67
|
+
custom tuning name (for instance, from a Scala file description).
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
interface Temperamentum {
|
|
71
|
+
// resolved
|
|
72
|
+
tuning: Tuning;
|
|
73
|
+
mode: number | "auto";
|
|
74
|
+
a4: number;
|
|
75
|
+
root: number;
|
|
76
|
+
transpose: number;
|
|
77
|
+
comma: number;
|
|
78
|
+
|
|
79
|
+
// computed
|
|
80
|
+
ratios: number[]; // frequency ratios relative to root, one per pitch class
|
|
81
|
+
cents: number[]; // cent values per pitch class, relative to root
|
|
82
|
+
|
|
83
|
+
// methods
|
|
84
|
+
nota(input: PitchInput): Pitch;
|
|
85
|
+
gradus(input: PitchInput): Step;
|
|
86
|
+
intervallum(a: PitchInput, b: PitchInput): Interval;
|
|
87
|
+
ratio(input: string): RatioResult & { step: Step | null };
|
|
88
|
+
neuma(inputs: PitchInput[]): Neume;
|
|
89
|
+
gamut(opts?: GamutOptions): Pitch[];
|
|
90
|
+
modus(mode: number): Modus;
|
|
91
|
+
tonus(opts?: TonusOpts): Tonus;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Pitch input
|
|
96
|
+
|
|
97
|
+
Every method that takes a pitch accepts the same forms. A number is a MIDI
|
|
98
|
+
note (a non-integer or a value past 127 reads as a frequency in Hz); a
|
|
99
|
+
string is scientific pitch notation or a GABC letter; an object addresses
|
|
100
|
+
one system explicitly (`{ hz: 293.33 }` for an exact frequency). All inputs resolve to a pitch
|
|
101
|
+
first; `transpose` is applied last as a uniform output shift.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
t.nota(62); // MIDI
|
|
105
|
+
t.nota("D4"); // scientific pitch notation
|
|
106
|
+
t.nota(293.33); // frequency (any non-integer, or > 127)
|
|
107
|
+
t.nota({ gabc: "d", clef: "c4" }); // GABC letter under a clef
|
|
108
|
+
t.nota({ solmization: "RE", hexachord: "naturale" }); // hexachordal address
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
type PitchInput = number | string | PitchObject;
|
|
113
|
+
|
|
114
|
+
interface PitchObject {
|
|
115
|
+
midi?: number;
|
|
116
|
+
spn?: string;
|
|
117
|
+
hz?: number;
|
|
118
|
+
gabc?: string;
|
|
119
|
+
clef?: string; // default "c4", only with gabc
|
|
120
|
+
solfege?: string; // modern fixed-do: "DO" | "RE" | "MI" | "FA" | "SOL" | "LA" | "SI"
|
|
121
|
+
solmization?: string; // medieval: "UT" | "RE" | "MI" | "FA" | "SOL" | "LA"
|
|
122
|
+
hexachord?: "durum" | "naturale" | "molle"; // default "naturale", only with solmization
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Pitches — `nota`
|
|
127
|
+
|
|
128
|
+
`nota` resolves any pitch input to a tuned `Pitch`. The frequency comes
|
|
129
|
+
through the scale; the same note name lands on a different frequency in a
|
|
130
|
+
different tuning.
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
const t = tonus.temperamentum({ mode: 1 }); // pythagorean
|
|
134
|
+
|
|
135
|
+
t.nota("D4");
|
|
136
|
+
// { midi: 62, pc: 2, oct: 4, acc: 0, spn: "D4",
|
|
137
|
+
// hz: 293.33, offset: -1.96, bend: 8112, ratio: 1 }
|
|
138
|
+
|
|
139
|
+
tonus.temperamentum({ root: 0 }).nota("C4").hz; // 260.74 pythagorean
|
|
140
|
+
tonus.temperamentum({ tuning: "meantone", root: 0 }).nota("C4").hz; // 263.18 quarter-comma
|
|
141
|
+
tonus.temperamentum({ tuning: "equal", root: 0 }).nota("C4").hz; // 261.63 equal
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`offset` is the distance in cents from the equal-tempered pitch of the same
|
|
145
|
+
MIDI number; `bend` is the corresponding 14-bit MIDI pitch bend. `Pitch` is
|
|
146
|
+
the tuned identity type used everywhere in tonus: in `Neume.pitches`, as
|
|
147
|
+
`note.pitch` in the score engine, and on `Attractor.pitch` in the imprint.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
interface Pitch {
|
|
151
|
+
midi: number;
|
|
152
|
+
pc: number; // pitch class 0–11
|
|
153
|
+
oct: number;
|
|
154
|
+
acc: -1 | 0 | 1; // flat, natural, sharp
|
|
155
|
+
spn: string; // scientific pitch name, e.g. "D4"
|
|
156
|
+
hz: number; // frequency in Hz (through the scale)
|
|
157
|
+
offset: number; // cents from 12-TET
|
|
158
|
+
bend: number; // 14-bit MIDI pitch bend, 8192 = center
|
|
159
|
+
ratio: number; // scale ratio for this pc
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Steps — `gradus`
|
|
164
|
+
|
|
165
|
+
`gradus` returns the modal and Guidonian identity of a pitch class: its
|
|
166
|
+
letter, its compound name, its hexachord and solmization syllable, the
|
|
167
|
+
mutations available to it, its position on the Guidonian hand, and its
|
|
168
|
+
degree and role in the current mode. `Step` carries no tuning data; that is
|
|
169
|
+
`Pitch`'s office.
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
const t = tonus.temperamentum({ mode: 1 });
|
|
173
|
+
|
|
174
|
+
t.gradus("D4");
|
|
175
|
+
// { pc: 2, name: "d", nomen: "Delasolre",
|
|
176
|
+
// hexachord: "naturale", solmization: "RE",
|
|
177
|
+
// variants: [ { hexachord: "durum", solmization: "SOL" },
|
|
178
|
+
// { hexachord: "naturale", solmization: "RE" },
|
|
179
|
+
// { hexachord: "molle", solmization: "LA" } ],
|
|
180
|
+
// hand: { finger: "middle", region: "tip" },
|
|
181
|
+
// degree: 1, role: "finalis" }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The `variants` array lists the step's solmization in every hexachord that
|
|
185
|
+
contains it; these are the mutations a medieval singer had available at
|
|
186
|
+
that step. `degree` and `role` read against the resolved mode (`"auto"`
|
|
187
|
+
falls back to mode 1); for a chromatic pitch outside the mode's scale they
|
|
188
|
+
are `null`.
|
|
189
|
+
|
|
190
|
+
The hand position names the joint a singer would point to. The loci follow the
|
|
191
|
+
canonical counter-clockwise spiral (Γ ut at the thumb tip, across the finger
|
|
192
|
+
bases, up the little finger, back across the tips, in), not a linear fill:
|
|
193
|
+
|
|
194
|
+
| `hand` field | values |
|
|
195
|
+
| ------------ | ----------------------------------- |
|
|
196
|
+
| `finger` | thumb, index, middle, ring, pinky |
|
|
197
|
+
| `region` | base, mid, top, tip, super |
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
interface StepVariant {
|
|
201
|
+
hexachord: "durum" | "naturale" | "molle";
|
|
202
|
+
solmization: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
interface Step {
|
|
206
|
+
pc: number; // pitch class 0–11
|
|
207
|
+
name: string; // "d" (Guidonian) or SPN letter fallback
|
|
208
|
+
nomen: string | null; // "Delasolre"; null out of gamut
|
|
209
|
+
hexachord: "durum" | "naturale" | "molle" | null;
|
|
210
|
+
solmization: string | null; // null out of gamut
|
|
211
|
+
variants: StepVariant[]; // available mutations across hexachords
|
|
212
|
+
hand: { finger: string; region: string } | null; // Guidonian hand position
|
|
213
|
+
degree: number | null; // 1–7 diatonic degree in mode
|
|
214
|
+
role: "finalis" | "tenor" | "other" | null;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Intervals — `intervallum`
|
|
219
|
+
|
|
220
|
+
`intervallum` classifies the interval between two pitches: its Latin name,
|
|
221
|
+
its Greek alias where one exists, its quality, class, direction, and
|
|
222
|
+
consonance grade.
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
t.intervallum("D4", "A4");
|
|
226
|
+
// { nomen: "Quinta", alias: "Diapente", quality: "perfect",
|
|
227
|
+
// class: "P5", direction: "up", semitones: 7, cents: 700,
|
|
228
|
+
// consonance: "perfect" }
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`semitones` and `cents` describe the interval class in nominal
|
|
232
|
+
(equal-tempered) terms. The tuned distance between two particular pitches
|
|
233
|
+
is the ratio of their frequencies; take it from `nota`.
|
|
234
|
+
|
|
235
|
+
| field | values |
|
|
236
|
+
| ------------ | ---------------------------------------------------------------- |
|
|
237
|
+
| `class` | `P1` `m2` `M2` `m3` `M3` `P4` `TT` `P5` `m6` `M6` `m7` `M7` `P8` |
|
|
238
|
+
| `quality` | perfect, major, minor, augmented |
|
|
239
|
+
| `direction` | up, down, unison |
|
|
240
|
+
| `consonance` | perfect, imperfect, dissonant |
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
interface Interval {
|
|
244
|
+
nomen: string; // e.g. "Quinta", "Semitonium"
|
|
245
|
+
alias?: string; // e.g. "Diapente", "Diatessaron"
|
|
246
|
+
quality: string;
|
|
247
|
+
class: string;
|
|
248
|
+
direction: string;
|
|
249
|
+
semitones: number;
|
|
250
|
+
cents: number; // nominal class value
|
|
251
|
+
consonance: string;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Neumes — `neuma`
|
|
256
|
+
|
|
257
|
+
The neume is chant's unit of notation: a group of notes written as one
|
|
258
|
+
figure and sung on one syllable. `neuma` classifies a sequence of pitches
|
|
259
|
+
as a neume shape, under the Solesmes nomenclature, and returns the tuned
|
|
260
|
+
pitches with the intervals between them.
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
t.neuma(["D4", "F4", "E4"]);
|
|
264
|
+
// shape: "torculus" — up, then down
|
|
265
|
+
// intervals: Tertia minor, Semitonium
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Shapes that match no simple figure classify as `"compound"`.
|
|
269
|
+
|
|
270
|
+
| `shape` | figure | `shape` | figure |
|
|
271
|
+
| ----------- | ------------------ | -------------------- | --------------------------- |
|
|
272
|
+
| `punctum` | a single note | `torculus resupinus` | torculus, then rising |
|
|
273
|
+
| `pes` | two notes, rising | `porrectus flexus` | porrectus, then falling |
|
|
274
|
+
| `clivis` | two notes, falling | `scandicus flexus` | scandicus, then falling |
|
|
275
|
+
| `torculus` | three: up, down | `climacus resupinus` | climacus, then rising |
|
|
276
|
+
| `porrectus` | three: down, up | `pes subpunctis` | pes, then descending points |
|
|
277
|
+
| `scandicus` | three, rising | `compound` | any figure not above |
|
|
278
|
+
| `climacus` | three, falling | | |
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
interface Neume {
|
|
282
|
+
pitches: Pitch[];
|
|
283
|
+
intervals: Interval[];
|
|
284
|
+
shape: string; // a value from the table above
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Ratios — `ratio`
|
|
289
|
+
|
|
290
|
+
`ratio` converts between cents, decimal ratios, and colon display
|
|
291
|
+
notation, following the Scala conventions: a period means cents
|
|
292
|
+
(`"701.955"`); a slash, colon, or bare integer means a ratio (`"3/2"`,
|
|
293
|
+
`"3:2"`, `"2"`). When the ratio corresponds to a degree of the current
|
|
294
|
+
scale, the matching `Step` is returned with it.
|
|
295
|
+
|
|
296
|
+
```js
|
|
297
|
+
t.ratio("3/2");
|
|
298
|
+
// { ratio: 1.5, cents: 701.96, display: "3:2",
|
|
299
|
+
// step: { nomen: "Alamire", degree: 5, role: "tenor", … } }
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
In mode 1 the pure fifth lands on the tenor; the step field says so.
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
interface RatioResult {
|
|
306
|
+
ratio: number; // decimal frequency ratio
|
|
307
|
+
cents: number; // interval in cents
|
|
308
|
+
display: string; // colon notation, e.g. "3:2"
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## The gamut — `gamut`
|
|
313
|
+
|
|
314
|
+
The gamut is the medieval note-space: the ordered range of singable
|
|
315
|
+
pitches Guido's system named from Gammaut upward. `gamut` returns the
|
|
316
|
+
tuned pitches of the scale across a span. With a mode set, the default
|
|
317
|
+
span is the mode's ambitus; mode 1 yields twelve diatonic pitches from D3
|
|
318
|
+
to A4. The `chromatic` option adds the chromatic degrees; `span` sets
|
|
319
|
+
explicit MIDI bounds.
|
|
320
|
+
|
|
321
|
+
```js
|
|
322
|
+
const g = t.gamut(); // 12 pitches, D3 … A4 (mode 1 ambitus)
|
|
323
|
+
t.gamut({ span: [48, 72], chromatic: true });
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
interface GamutOptions {
|
|
328
|
+
span?: [number, number]; // [lowest, highest] MIDI
|
|
329
|
+
chromatic?: boolean; // include chromatic pitches, default false
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Modes — `modus`
|
|
334
|
+
|
|
335
|
+
`modus` returns the full profile of one of the eight modes, as the
|
|
336
|
+
medieval tonaries describe them:
|
|
337
|
+
|
|
338
|
+
- its identity — Latin name, modern alias, _maneria_ (the family: Protus,
|
|
339
|
+
Deuterus, Tritus, Tetrardus), and authentic or plagal type;
|
|
340
|
+
- its structure — finalis, tenor, scale degrees, ambitus, and the species
|
|
341
|
+
of fifth and fourth that build it;
|
|
342
|
+
- its practice — hexachords in rank order, melodic profile, its cadence
|
|
343
|
+
figures, and permitted modulations.
|
|
344
|
+
|
|
345
|
+
Each mode also carries its traditional **ethos** (the character medieval theory
|
|
346
|
+
ascribed to it) as both a Latin epithet (`gravis`, `tristis`, …) and an English
|
|
347
|
+
gloss. The full set and its source are at the data, in
|
|
348
|
+
[`temper/data/modes.ts`](https://github.com/jeffreypierce/tonus/blob/main/src/engines/temper/data/modes.ts).
|
|
349
|
+
|
|
350
|
+
The `modulations` fields (`regular`, `conceded`, and `initials`) are the
|
|
351
|
+
mode's tonal centres and valid openings, each list **ordered by importance**
|
|
352
|
+
(after Rockstro's Grove table [`rockstro-grove`](https://github.com/jeffreypierce/tonus/blob/main/BIBLIOGRAPHY.md)). The
|
|
353
|
+
modal-affinity scorer reads that order; the reasoning is documented at the
|
|
354
|
+
data, in [`temper/data/modes.ts`](https://github.com/jeffreypierce/tonus/blob/main/src/engines/temper/data/modes.ts).
|
|
355
|
+
|
|
356
|
+
`modus` resolves the mode's structural pitches through its own
|
|
357
|
+
temperamentum: the **finalis** and **reciting** tone as tuned notes (pitch +
|
|
358
|
+
Guidonian step), and **ambitusNotes**, the mode's diatonic range walked out
|
|
359
|
+
note by note. The raw `ModeData` fields (`final`, `tenor`, `cadences`, …)
|
|
360
|
+
remain alongside — `Modus` extends `ModeData`.
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
t.modus(1);
|
|
364
|
+
// { mode: 1, nomen: "Protus Authenticus", alias: "dorian",
|
|
365
|
+
// maneria: "Protus", type: "authentic",
|
|
366
|
+
// final: 2, tenor: 9,
|
|
367
|
+
// finalis: { pitch: <D4 293.33 Hz>, step: { … role: "finalis" } },
|
|
368
|
+
// reciting: { pitch: <A4>, step: { … role: "tenor" } },
|
|
369
|
+
// ambitusNotes: [ <D4>, <E4>, <F4>, … ],
|
|
370
|
+
// profile: { mood: "serious", ethos: "gravis", … }, … }
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
interface ModeProfile {
|
|
375
|
+
mood: string; // English gloss of the ethos, e.g. "serious"
|
|
376
|
+
ethos: string; // traditional Latin epithet, e.g. "gravis"
|
|
377
|
+
phrasing: "recitative" | "lyrical" | "hymnic" | "solemn";
|
|
378
|
+
melodic: "rising" | "falling" | "arch" | "neutral";
|
|
379
|
+
tendency: "melismatic" | "neumatic" | "syllabic" | "neutral";
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
interface CadenceFigure {
|
|
383
|
+
id: string; // solmization, e.g. "sol-fa-re"
|
|
384
|
+
steps: number[]; // diatonic steps relative to the final; resolution (0) last
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
interface ModeData {
|
|
388
|
+
mode: number;
|
|
389
|
+
nomen: string; // "Protus Authenticus"
|
|
390
|
+
alias: string; // "dorian" (modern name)
|
|
391
|
+
maneria: string; // "Protus" — the mode family
|
|
392
|
+
type: "authentic" | "plagal";
|
|
393
|
+
final: number; // finalis pitch class (C=0)
|
|
394
|
+
tenor: number; // reciting tone pitch class
|
|
395
|
+
recitingNotes: { pc: number; rank: string; label: string }[]; // tenor + secondary reciting pitches
|
|
396
|
+
scalePcs: number[]; // 7 diatonic pitch classes
|
|
397
|
+
hexachords: ("durum" | "naturale" | "molle")[]; // rank-ordered
|
|
398
|
+
profile: ModeProfile;
|
|
399
|
+
cadences: CadenceFigure[]; // characteristic cadence figures
|
|
400
|
+
modulations: {
|
|
401
|
+
regular: number[];
|
|
402
|
+
conceded: number[];
|
|
403
|
+
initials: number[];
|
|
404
|
+
};
|
|
405
|
+
ambitus: {
|
|
406
|
+
lowest: number;
|
|
407
|
+
highest: number;
|
|
408
|
+
span: number;
|
|
409
|
+
};
|
|
410
|
+
species: {
|
|
411
|
+
fifth: [number, number];
|
|
412
|
+
fourth: [number, number];
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
interface TunedNote {
|
|
417
|
+
pitch: Pitch; // tuned through the temperamentum
|
|
418
|
+
step: Step; // Guidonian annotation
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
interface Modus extends ModeData {
|
|
422
|
+
finalis: TunedNote; // the final, tuned
|
|
423
|
+
reciting: TunedNote; // the tenor / reciting tone, tuned
|
|
424
|
+
ambitusNotes: TunedNote[]; // every diatonic step across the mode's range
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Cadence figures
|
|
429
|
+
|
|
430
|
+
Each mode carries the melodic figures its phrases characteristically close
|
|
431
|
+
on, in `modus(n).cadences` — the shapes by which a chant comes to rest, stored
|
|
432
|
+
as diatonic steps relative to the final. The score engine reads them to name a
|
|
433
|
+
phrase's cadence ([score.md](score.md#cadences)).
|
|
434
|
+
|
|
435
|
+
| Maneria (final) | Figures (solmization → final) |
|
|
436
|
+
| --------------- | --------------------------------- |
|
|
437
|
+
| Protus (Re) | mi-re, ut-re, sol-fa-re, mi-fa-re |
|
|
438
|
+
| Deuterus (Mi) | fa-mi, re-mi, sol-fa-mi |
|
|
439
|
+
| Tritus (Fa) | mi-fa, fa-mi-fa, la-sol-fa |
|
|
440
|
+
| Tetrardus (Sol) | la-sol, fa-sol, ut-sol, ut-ti-sol |
|
|
441
|
+
|
|
442
|
+
The catalogue is an editorial synthesis covering the final cadences; its step
|
|
443
|
+
encoding, sources, and known gaps (medial cadences are not yet included) are
|
|
444
|
+
documented at the data — see `CadenceFigure` in
|
|
445
|
+
[`temper/data/modes.ts`](https://github.com/jeffreypierce/tonus/blob/main/src/engines/temper/data/modes.ts).
|
|
446
|
+
|
|
447
|
+
This is the **tradita** half — what the treatises say. Its counterpart is the
|
|
448
|
+
corpus tally below, and they are not interchangeable: see [one spine, two
|
|
449
|
+
annotations](score.md#one-spine-two-annotations).
|
|
450
|
+
|
|
451
|
+
### The corpus catalogue — `CADENTIAE`
|
|
452
|
+
|
|
453
|
+
Where the figures above are received, [`CADENTIAE`](index.md#the-appendix) is
|
|
454
|
+
**mined**: every phrase-end in the sung corpus, grouped into families by what
|
|
455
|
+
the melody actually did. A family is a **shape** — the closing tail's
|
|
456
|
+
successive semitone intervals — and an **arrival**, where it landed relative
|
|
457
|
+
to the chant's own closing note. Together they are the key, `"2,0,-2 @0"`, and
|
|
458
|
+
the key is the family's whole name.
|
|
459
|
+
|
|
460
|
+
About 110 families clear the floor of 50 occurrences, covering about 57% of all
|
|
461
|
+
phrase-ends. The rest of the tail is real but too thin to characterise.
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
interface CadentiaFamilia {
|
|
465
|
+
key: string; // "shape @arrival" — the name, and the join
|
|
466
|
+
shape: number[]; // successive semitone intervals of the closing tail
|
|
467
|
+
arrival: number; // SIGNED semitones from the chant's own closing note
|
|
468
|
+
n: number; // corpus occurrences
|
|
469
|
+
share: number; // n over ALL phrase-ends (CADENTIAE_POPULATION.ends)
|
|
470
|
+
finality: number; // share of those occurrences at a final close
|
|
471
|
+
modes: Record<string, number>; // occurrences by mode digit ("?" = mode-less)
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
`share` is taken against **every** phrase-end, not against the ~57% that
|
|
476
|
+
cleared the floor. The denominator ships beside the table:
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
CADENTIAE_POPULATION.ends; // 26787 — all phrase-ends, sung corpus
|
|
480
|
+
CADENTIAE_POPULATION.byMode; // the same total per mode digit
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### Lift — how mode-bound a close is
|
|
484
|
+
|
|
485
|
+
`modes` and `byMode` share a denominator, so a family's **lift** in a given
|
|
486
|
+
mode is one division: how much more (or less) that mode reaches for this close
|
|
487
|
+
than the corpus at large.
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
import { CADENTIAE, CADENTIAE_POPULATION as POP } from "tonus";
|
|
491
|
+
|
|
492
|
+
const fam = CADENTIAE.find((f) => f.key === "2,0,-2 @0");
|
|
493
|
+
const lift = (f, mode) =>
|
|
494
|
+
(f.modes[String(mode)] / POP.byMode[String(mode)]) / f.share;
|
|
495
|
+
|
|
496
|
+
lift(fam, 6); // 2.15
|
|
497
|
+
lift(fam, 4); // 0.07
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
The commonest family in the corpus — about 1,100 occurrences, about 4% of all
|
|
501
|
+
phrase-ends, closing a little under half the time — is not reached for evenly.
|
|
502
|
+
Mode 6 reaches for this close more than twice as often as the corpus does;
|
|
503
|
+
mode 4 almost never. That is the figure the tonarium prints under a cadence
|
|
504
|
+
([score.md](score.md#the-analysis-tracks)).
|
|
505
|
+
|
|
506
|
+
**The ratio is not baked.** The table exports the vocabulary — counts and
|
|
507
|
+
their denominators — and leaves the arithmetic to the caller. Two cautions when
|
|
508
|
+
you take it: below roughly ten in-mode occurrences the ratio is one or two
|
|
509
|
+
chants deciding a number that reads like a measurement, and a mode-less chant
|
|
510
|
+
(`"?"`) has no denominator at all. In both cases fall back to `share`.
|
|
511
|
+
|
|
512
|
+
## Psalm tones — `tonus`
|
|
513
|
+
|
|
514
|
+
`tonus` returns the recitation formula of the context's mode as tuned
|
|
515
|
+
pitches: the **intonatio** (the opening rise), the **mediatio** (the
|
|
516
|
+
cadence at the verse's colon), and the **terminatio** (the closing
|
|
517
|
+
cadence). The termination varies by **differentia**, the cadential variant
|
|
518
|
+
chosen to lead back into the antiphon; the mode's default differentia is
|
|
519
|
+
used when none is given. The mode must be set explicitly — with mode
|
|
520
|
+
`"auto"`, `tonus()` throws.
|
|
521
|
+
|
|
522
|
+
```js
|
|
523
|
+
const t = tonus.temperamentum({ mode: 1 });
|
|
524
|
+
|
|
525
|
+
t.tonus();
|
|
526
|
+
// { mode: 1, differentia: "1g",
|
|
527
|
+
// intonatio: [F3, A3, C4],
|
|
528
|
+
// mediatio: [C4, A3, G3, A3],
|
|
529
|
+
// terminatio: [C4, A3, G3, A3, G3] } // each entry a tuned Pitch
|
|
530
|
+
|
|
531
|
+
t.tonus({ differentia: "1f" });
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
To sing psalm texts to these formulas, use
|
|
535
|
+
[`tonus.psalmus`](chant.md#psalms--psalmus), which returns
|
|
536
|
+
GABC-encoded verses pointed to the tone.
|
|
537
|
+
|
|
538
|
+
```ts
|
|
539
|
+
interface TonusOpts {
|
|
540
|
+
differentia?: string; // e.g. "6F", "4e"; mode comes from Temperamentum, throws if "auto"
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
interface Tonus {
|
|
544
|
+
mode: number;
|
|
545
|
+
differentia: string;
|
|
546
|
+
intonatio: Pitch[]; // opening intonation formula
|
|
547
|
+
mediatio: Pitch[]; // mediant cadence at the verse colon
|
|
548
|
+
terminatio: Pitch[]; // termination cadence (per differentia)
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## Theory & Context
|
|
553
|
+
|
|
554
|
+
`temperamentum` represents a tuning as a table of twelve frequency ratios,
|
|
555
|
+
one per pitch class, relative to the context's root and anchored at the
|
|
556
|
+
reference A4. The presets fill that table from history: the Pythagorean
|
|
557
|
+
division the treatises teach, the meantone compromise of the Renaissance,
|
|
558
|
+
Ptolemy's three diatonic shades, and the modern equal division.
|
|
559
|
+
|
|
560
|
+
### The presets
|
|
561
|
+
|
|
562
|
+
Six ways to fill the table, five historical and one modern. Each has a
|
|
563
|
+
character; the interval arithmetic, the commas that drive it, and the
|
|
564
|
+
editorial choices behind it are documented at the builder, in
|
|
565
|
+
[`temper/scale.ts`](https://github.com/jeffreypierce/tonus/blob/main/src/engines/temper/scale.ts).
|
|
566
|
+
|
|
567
|
+
- **`"pythagorean"`** — the medieval default. All intervals from the pure
|
|
568
|
+
fifth and the octave: perfect melodic fifths and fourths, a narrow keen
|
|
569
|
+
semitone, a wide third that never has to be a consonance. Correct for
|
|
570
|
+
unaccompanied chant, and the tuning the treatises teach.
|
|
571
|
+
|
|
572
|
+
```js
|
|
573
|
+
tonus.temperamentum(); // pythagorean, A4 = 440
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
- **`"meantone"`** — the Renaissance compromise. Narrows each fifth to buy
|
|
577
|
+
purer thirds; `comma` sets how far (`"1/4"`, the default, gives pure major
|
|
578
|
+
thirds and the 16th-century sound; `"1/3"` pure minor thirds; `"1/6"` leans
|
|
579
|
+
baroque). One fifth is left over as the _wolf_.
|
|
580
|
+
|
|
581
|
+
```js
|
|
582
|
+
tonus.temperamentum({ tuning: "meantone", comma: "1/4" });
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
- **The three Ptolemaic diatonics** — antiquity's just intonations, Ptolemy's
|
|
586
|
+
three "shades" of the diatonic. `"ptolemy-intense"` is classical just
|
|
587
|
+
intonation (pure thirds; coherent with the Ptolemy doctrina in
|
|
588
|
+
[`harmonia`](heavens.md)); `"ptolemy-soft"` is septimal and dark;
|
|
589
|
+
`"ptolemy-equable"` has neutral, near-equal steps outside the Latin tradition.
|
|
590
|
+
Each tunes one fixed scale, so pairing one with a non-default mode can surface
|
|
591
|
+
unexpected intervals, including a wolf.
|
|
592
|
+
|
|
593
|
+
```js
|
|
594
|
+
tonus.temperamentum({ tuning: "ptolemy-intense" });
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
- **`"equal"`** — twelve identical semitones; nothing pure, nothing unusable.
|
|
598
|
+
Anachronistic for chant by some seven centuries, included as a reference point.
|
|
599
|
+
|
|
600
|
+
```js
|
|
601
|
+
tonus.temperamentum({ tuning: "equal", a4: 415 }); // equal at baroque pitch
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Any 7- or 12-step scale can also be supplied directly as ratios or cents, or as
|
|
605
|
+
a [Scala `.scl`](https://www.huygens-fokker.org/scala/scl_format.html) file:
|
|
606
|
+
|
|
607
|
+
```js
|
|
608
|
+
tonus.temperamentum({
|
|
609
|
+
scale: ["1/1", "9/8", "5/4", "4/3", "3/2", "5/3", "15/8"],
|
|
610
|
+
});
|
|
611
|
+
tonus.temperamentum({ scale: sclFileString }); // name taken from the file
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
## Sources
|
|
615
|
+
|
|
616
|
+
Sources for this page are in the central [bibliography](https://github.com/jeffreypierce/tonus/blob/main/BIBLIOGRAPHY.md):
|
|
617
|
+
`boethius-institutione`, `ptolemy-harmonics`, `schulter-harmony`,
|
|
618
|
+
`rockstro-grove`, `niedermeyer-ortigue`, `bragers-treatise`,
|
|
619
|
+
`sunol-textbook`, `saulnier-modes`, `liber-usualis`, `scala-format`.
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tonus",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"private": false,
|
|
3
|
+
"version": "0.5.0",
|
|
5
4
|
"type": "module",
|
|
6
5
|
"description": "Medieval music analysis and performance: GABC plainchant exports, liturgical calendar, tuning systems, ephemeris, and the harmony of the spheres",
|
|
7
6
|
"author": "Jeffrey Pierce <jeffrey@jeffreypierce.net>",
|
|
8
|
-
"license": "
|
|
7
|
+
"license": "PolyForm-Noncommercial-1.0.0",
|
|
9
8
|
"repository": {
|
|
10
9
|
"type": "git",
|
|
11
10
|
"url": "git+https://github.com/jeffreypierce/tonus.git"
|
|
@@ -39,6 +38,7 @@
|
|
|
39
38
|
"types": "./dist/index.d.ts",
|
|
40
39
|
"files": [
|
|
41
40
|
"dist",
|
|
41
|
+
"docs/api",
|
|
42
42
|
"!dist/**/*.js.map",
|
|
43
43
|
"!dist/**/*.d.ts.map",
|
|
44
44
|
"LICENSE",
|
|
@@ -46,10 +46,16 @@
|
|
|
46
46
|
"BIBLIOGRAPHY.md"
|
|
47
47
|
],
|
|
48
48
|
"scripts": {
|
|
49
|
-
"build": "tsc && cp src/data/psalms.json dist/data/psalms.json",
|
|
49
|
+
"build": "tsc && cp src/data/psalms.json dist/data/psalms.json && cp src/data/smufl-glyphs.json dist/data/smufl-glyphs.json && cp src/data/office-ferial.json dist/data/office-ferial.json && cp src/data/commune-office.json dist/data/commune-office.json && cp src/data/seasonal-respbreve.json dist/data/seasonal-respbreve.json && cp src/data/attestation.json dist/data/attestation.json && node scripts/bake-data.mjs",
|
|
50
50
|
"clean": "rm -rf dist",
|
|
51
51
|
"test": "npm run build && node --test --test-reporter=spec tests/*.test.mjs",
|
|
52
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
52
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
53
|
+
"check:links": "node scripts/check-doc-links.mjs",
|
|
54
|
+
"site": "npm run build && node scripts/vendor-ink.mjs && rm -rf docs/dist && cp -R dist docs/dist",
|
|
55
|
+
"serve": "npm run site && node scripts/serve.mjs",
|
|
56
|
+
"diagrams": "npm run site && node scripts/diagram-lab.mjs",
|
|
57
|
+
"lab": "npm run build && node scripts/render-lab.mjs",
|
|
58
|
+
"stress": "npm run build && node scripts/render-stress.mjs"
|
|
53
59
|
},
|
|
54
60
|
"devDependencies": {
|
|
55
61
|
"@types/node": "^22.0.0",
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export interface MatinsChant {
|
|
2
|
-
id: string;
|
|
3
|
-
type: string;
|
|
4
|
-
pos: string;
|
|
5
|
-
}
|
|
6
|
-
export interface MatinsNocturn {
|
|
7
|
-
n: number;
|
|
8
|
-
chants: MatinsChant[];
|
|
9
|
-
}
|
|
10
|
-
export interface MatinsDay {
|
|
11
|
-
id: string;
|
|
12
|
-
tonusFeastId: string | null;
|
|
13
|
-
name: string;
|
|
14
|
-
rank: string;
|
|
15
|
-
nocturns: MatinsNocturn[];
|
|
16
|
-
redirectedFrom: string | null;
|
|
17
|
-
}
|
|
18
|
-
export declare const MATINS_ROMAN: MatinsDay[];
|
|
19
|
-
//# sourceMappingURL=office-matins-roman.d.ts.map
|