tonus 0.1.3 → 0.1.6
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 +143 -96
- package/CHANGELOG.md +62 -0
- package/README.md +7 -9
- package/dist/data/am.d.ts +5 -0
- package/dist/data/am.js +14299 -0
- package/dist/data/office-monastic.d.ts +3 -0
- package/dist/data/office-monastic.js +6956 -0
- package/dist/data/office-psalms-monastic.d.ts +3 -0
- package/dist/data/office-psalms-monastic.js +21 -0
- package/dist/data/{office-psalms.d.ts → office-psalms-roman.d.ts} +1 -1
- package/dist/data/{office-psalms.js → office-psalms-roman.js} +3 -3
- package/dist/engines/cal/calendar.js +16 -1
- package/dist/engines/cal/date.js +5 -0
- package/dist/engines/chant/chant.js +2 -0
- package/dist/{data → engines/chant/data}/compline.d.ts +1 -1
- package/dist/{data → engines/chant/data}/masses.d.ts +1 -1
- package/dist/{data → engines/chant/data}/masses.js +1 -1
- package/dist/{data → engines/chant/data}/prime.d.ts +1 -1
- package/dist/{data → engines/chant/data}/prime.js +1 -1
- package/dist/engines/chant/hour.js +37 -22
- package/dist/engines/chant/intone.js +6 -1
- package/dist/engines/chant/ordinary.js +1 -1
- package/dist/engines/chant/psalm.d.ts +4 -4
- package/dist/engines/chant/psalm.js +6 -4
- package/dist/engines/chant/types.d.ts +5 -1
- package/dist/engines/harmonia/api.js +11 -0
- package/dist/engines/harmonia/data/doctrines.js +27 -1
- package/dist/engines/imprint.d.ts +8 -7
- package/dist/engines/imprint.js +31 -27
- package/dist/engines/planet/position.js +51 -5
- package/dist/engines/score/api.d.ts +4 -0
- package/dist/engines/score/api.js +11 -1
- package/dist/engines/score/articulation.js +60 -3
- package/dist/engines/score/cadence.js +3 -3
- package/dist/engines/score/emitters/midi.js +6 -2
- package/dist/engines/score/infer.js +13 -1
- package/dist/engines/score/ir.d.ts +2 -1
- package/dist/engines/score/ir.js +54 -12
- package/dist/engines/score/modulation.d.ts +20 -0
- package/dist/engines/score/modulation.js +74 -0
- package/dist/engines/score/parse.js +16 -8
- package/dist/engines/score/phrasing.js +26 -0
- package/dist/engines/score/prosody.js +5 -0
- package/dist/engines/score/tabula.d.ts +2 -0
- package/dist/engines/score/tabula.js +1 -0
- package/dist/engines/score/types.d.ts +11 -2
- package/dist/engines/temper/api.d.ts +17 -1
- package/dist/engines/temper/api.js +20 -2
- package/dist/engines/temper/data/guido.d.ts +3 -2
- package/dist/engines/temper/data/guido.js +30 -25
- package/dist/engines/temper/data/modes.js +3 -0
- package/dist/{data → engines/temper/data}/tones.js +1 -1
- package/dist/engines/temper/gabc.js +25 -2
- package/dist/engines/temper/guido.d.ts +3 -2
- package/dist/engines/temper/interval.js +12 -0
- package/dist/engines/temper/modality.d.ts +11 -0
- package/dist/engines/temper/modality.js +58 -0
- package/dist/engines/temper/scale.js +33 -2
- package/dist/engines/temper/step.d.ts +2 -2
- package/dist/index.d.ts +5 -5
- package/package.json +2 -1
- package/dist/data/office.d.ts +0 -12
- package/dist/data/office.js +0 -13052
- /package/dist/{data → engines/chant/data}/compline.js +0 -0
- /package/dist/{data → engines/temper/data}/tones.d.ts +0 -0
|
@@ -62,6 +62,9 @@ export function buildPhrasing(type = "lyrical", options = {}) {
|
|
|
62
62
|
...(options.overrides ?? {}),
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
// Authentic modes reach a fifth or more above the final and pull harder toward
|
|
66
|
+
// their tenor/reciting note; plagal modes straddle the final and pull less
|
|
67
|
+
// [biblio: sunol-textbook]. These nudge the tenor and cadence gains accordingly.
|
|
65
68
|
const MODE_TYPE_TENOR_MULTIPLIER = {
|
|
66
69
|
authentic: 1.08,
|
|
67
70
|
plagal: 0.92,
|
|
@@ -70,12 +73,20 @@ const MODE_TYPE_CADENCE_MULTIPLIER = {
|
|
|
70
73
|
authentic: 1.05,
|
|
71
74
|
plagal: 0.95,
|
|
72
75
|
};
|
|
76
|
+
// A more melismatic mode leans into its cadences; a syllabic one under-plays them.
|
|
73
77
|
const MODE_TENDENCY_CADENCE_MULTIPLIER = {
|
|
74
78
|
melismatic: 1.06,
|
|
75
79
|
neumatic: 1.0,
|
|
76
80
|
syllabic: 0.96,
|
|
77
81
|
neutral: 1.0,
|
|
78
82
|
};
|
|
83
|
+
// The modal ethos → performance mapping. Each mode carries a mood epithet (the
|
|
84
|
+
// Niedermeyer & d'Ortigue tradition [biblio: niedermeyer-ortigue], stored on
|
|
85
|
+
// ModeProfile in modes.ts); these translate that mood into small shaping deltas.
|
|
86
|
+
// The interpretation is tonus's own — the epithets are sourced, these numbers
|
|
87
|
+
// are a tuned editorial gesture, deliberately small. Note the coherence: sadder
|
|
88
|
+
// moods drop the velocity floor AND deepen the phrase curve (below), so they
|
|
89
|
+
// read quieter and more arched; brighter moods do the reverse.
|
|
79
90
|
const MODE_MOOD_BASE_VELOCITY_DELTA = {
|
|
80
91
|
neutral: 0,
|
|
81
92
|
serious: -0.01,
|
|
@@ -144,9 +155,17 @@ const DURATION_ARCH_FACTOR = 0.2;
|
|
|
144
155
|
const DURATION_MIN = 0.2;
|
|
145
156
|
const DURATION_MAX = 4.0;
|
|
146
157
|
const TENOR_GAIN = 0.05;
|
|
158
|
+
// Tenor pull falls linearly with pitch-class distance from the reciting tone and
|
|
159
|
+
// reaches zero at 6 semitones (a tritone) — the far side of the octave, past
|
|
160
|
+
// which a note no longer reads as gravitating to the tenor.
|
|
147
161
|
const TENOR_DISTANCE_DIVISOR = 6;
|
|
148
162
|
const CADENCE_VELOCITY_FACTOR = 0.5;
|
|
149
163
|
const CADENCE_DURATION_FACTOR = 0.6;
|
|
164
|
+
// The phrasing-side reading of the divisio (bar-line) hierarchy. This is the same
|
|
165
|
+
// bar hierarchy tabulated canonically in docs/score.md and weighted for analysis
|
|
166
|
+
// by prosody.ts's cadenceWeight ladder — but here the weights differ on purpose:
|
|
167
|
+
// this is a *shaping* factor, so the virgula (`) gets 0 (a breath, no cadential
|
|
168
|
+
// stress), where the analytic ladder still counts it. Do not unify the three.
|
|
150
169
|
const DIVISIO_STRENGTH = {
|
|
151
170
|
"::": 1.0,
|
|
152
171
|
":": 0.7,
|
|
@@ -214,8 +233,15 @@ export function applyPhrasing(events, profile, tenorPc) {
|
|
|
214
233
|
const arsis = note.context.weight;
|
|
215
234
|
const arsisRelative = (arsis - minArsis) / arsisSpan;
|
|
216
235
|
const contourRelative = (note.pitch.midi - minStep) / stepSpan;
|
|
236
|
+
// A raised-cosine (Hann) window over the phrase: 0 at the ends, 1 at the
|
|
237
|
+
// middle, so each phrase swells and subsides — the Solesmes grand rythme,
|
|
238
|
+
// the phrase-arch [biblio: mocquereau-nombre]. `t` is the note's fractional
|
|
239
|
+
// position through the phrase.
|
|
217
240
|
const t = (order + 0.5) / (noteEntries.length + 0.0001);
|
|
218
241
|
const arch = 0.5 - 0.5 * Math.cos(2 * Math.PI * t);
|
|
242
|
+
// Blend the note's intrinsic arsic weight against its positional arch;
|
|
243
|
+
// `curve` is the mix knob (0 = follow the note's own weight, 1 = follow the
|
|
244
|
+
// phrase arch). The result is then re-centred on 0.5 and spread by velSpread.
|
|
219
245
|
let velocity = arsisRelative * (1 - profile.curve) + arch * profile.curve;
|
|
220
246
|
velocity += (contourRelative - VELOCITY_CENTER) * profile.contourVel;
|
|
221
247
|
velocity =
|
|
@@ -55,6 +55,11 @@ export function computeProsody(phrases) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
if (phrase.divisio) {
|
|
58
|
+
// Analytic bar-importance weights, one rung per divisio in the bar-line
|
|
59
|
+
// hierarchy (the canonical table is in docs/score.md). These are a
|
|
60
|
+
// MEASUREMENT — every divisio counts, including the virgula (`) — distinct
|
|
61
|
+
// from phrasing.ts's DIVISIO_STRENGTH, which zeroes the virgula because it
|
|
62
|
+
// is a shaping factor, not a count.
|
|
58
63
|
const d = phrase.divisio.divisio;
|
|
59
64
|
if (d === "::") {
|
|
60
65
|
cadDist.doubleBar++;
|
|
@@ -42,6 +42,8 @@ export interface ChantTabulaRow {
|
|
|
42
42
|
liquescent: boolean;
|
|
43
43
|
strophicus: boolean;
|
|
44
44
|
oriscus: boolean;
|
|
45
|
+
/** Mora vocis count: 0 none, 1 dot '.', 2 double dot '..' (a stronger cadential hold). */
|
|
46
|
+
mora: 0 | 1 | 2;
|
|
45
47
|
divisio: string | null;
|
|
46
48
|
/** Index into score.cadences[] when this note forms a cadence; null otherwise. */
|
|
47
49
|
cadenceRef: number | null;
|
|
@@ -104,6 +104,7 @@ export function computeTabula(ir, options = {}) {
|
|
|
104
104
|
liquescent: n.context.liquescent,
|
|
105
105
|
strophicus: n.context.strophicus,
|
|
106
106
|
oriscus: n.context.oriscus,
|
|
107
|
+
mora: n.context.mora,
|
|
107
108
|
divisio: a.divisio,
|
|
108
109
|
cadenceRef: cadenceRefByPos.get(`${a.phraseIndex}:${a.syllableIndex}:${a.noteIndex}`) ?? null,
|
|
109
110
|
role: n.step.role,
|
|
@@ -3,6 +3,11 @@ import type { Step } from "../temper/step.js";
|
|
|
3
3
|
import type { NeumeShape } from "../temper/neume.js";
|
|
4
4
|
import type { OfficeCode, OrdinaryCode } from "../chant/types.js";
|
|
5
5
|
export type ArsisThesis = "arsic" | "thetic";
|
|
6
|
+
export type RhythmicType = "IV" | "V" | "VI" | "VII" | "VIII" | null;
|
|
7
|
+
export interface CompoundBeat {
|
|
8
|
+
shape: ArsisThesis;
|
|
9
|
+
noteCount: number;
|
|
10
|
+
}
|
|
6
11
|
export interface Performance {
|
|
7
12
|
velocity: number;
|
|
8
13
|
duration: number;
|
|
@@ -21,7 +26,7 @@ export interface Context {
|
|
|
21
26
|
liquescent: boolean;
|
|
22
27
|
strophicus: boolean;
|
|
23
28
|
oriscus: boolean;
|
|
24
|
-
|
|
29
|
+
mora: 0 | 1 | 2;
|
|
25
30
|
weight: number;
|
|
26
31
|
}
|
|
27
32
|
export interface Note {
|
|
@@ -123,7 +128,7 @@ export interface ParsedNote {
|
|
|
123
128
|
liquescent: boolean;
|
|
124
129
|
strophicus: boolean;
|
|
125
130
|
oriscus: boolean;
|
|
126
|
-
|
|
131
|
+
mora: 0 | 1 | 2;
|
|
127
132
|
}
|
|
128
133
|
export interface RestEvent {
|
|
129
134
|
type: "rest";
|
|
@@ -151,6 +156,10 @@ export interface Syllable {
|
|
|
151
156
|
export interface Phrase {
|
|
152
157
|
syllables: Syllable[];
|
|
153
158
|
divisio?: RestEvent;
|
|
159
|
+
/** The phrase's compound beats in order — the A/T sequence of the incise. */
|
|
160
|
+
beats: CompoundBeat[];
|
|
161
|
+
/** Le Guennant/Carroll rhythmic type of the incise; null if none fits. */
|
|
162
|
+
rhythmicType: RhythmicType;
|
|
154
163
|
}
|
|
155
164
|
export interface Score {
|
|
156
165
|
chant: {
|
|
@@ -28,6 +28,22 @@ export interface Tonus {
|
|
|
28
28
|
mediatio: Pitch[];
|
|
29
29
|
terminatio: Pitch[];
|
|
30
30
|
}
|
|
31
|
+
/** A pitch resolved through the tuning, with its Guidonian annotation. */
|
|
32
|
+
export interface TunedNote {
|
|
33
|
+
pitch: Pitch;
|
|
34
|
+
step: Step;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A mode's reference data (ModeData), enriched with its structural pitches
|
|
38
|
+
* tuned through the temperamentum that returned it. `modus()`. Cadence figures
|
|
39
|
+
* stay in their diatonic-step form on `cadences` — they are transposition-
|
|
40
|
+
* relative by design.
|
|
41
|
+
*/
|
|
42
|
+
export interface Modus extends ModeData {
|
|
43
|
+
finalis: TunedNote;
|
|
44
|
+
reciting: TunedNote;
|
|
45
|
+
ambitusNotes: TunedNote[];
|
|
46
|
+
}
|
|
31
47
|
export interface Temperamentum {
|
|
32
48
|
tuning: Tuning;
|
|
33
49
|
mode: number | "auto";
|
|
@@ -45,7 +61,7 @@ export interface Temperamentum {
|
|
|
45
61
|
step: Step | null;
|
|
46
62
|
};
|
|
47
63
|
gamut(opts?: GamutOptions): Pitch[];
|
|
48
|
-
modus(mode: number):
|
|
64
|
+
modus(mode: number): Modus;
|
|
49
65
|
tonus(opts?: TonusOpts): Tonus;
|
|
50
66
|
}
|
|
51
67
|
/**
|
|
@@ -8,7 +8,7 @@ import { classifyInterval } from "./interval.js";
|
|
|
8
8
|
import { buildNeume } from "./neume.js";
|
|
9
9
|
import { buildGamut } from "./gamut.js";
|
|
10
10
|
import { getMode } from "./modes.js";
|
|
11
|
-
import { getTone, getDifferentia } from "
|
|
11
|
+
import { getTone, getDifferentia } from "./data/tones.js";
|
|
12
12
|
function resolveOpts(input) {
|
|
13
13
|
if (!input)
|
|
14
14
|
return {};
|
|
@@ -110,7 +110,25 @@ export function buildTemper(input) {
|
|
|
110
110
|
return buildGamut(scala, gamutOpts);
|
|
111
111
|
},
|
|
112
112
|
modus(mode) {
|
|
113
|
-
|
|
113
|
+
const data = getMode(mode);
|
|
114
|
+
// The mode's degrees are stored as semitone offsets from C (pc 0), with
|
|
115
|
+
// values past 12 in the upper octave. Anchor them at C4 (MIDI 60).
|
|
116
|
+
const tuned = (offset) => ({
|
|
117
|
+
pitch: toPitch(60 + offset, scala),
|
|
118
|
+
step: toStep(60 + offset, scala),
|
|
119
|
+
});
|
|
120
|
+
const scaleSet = new Set(data.scalePcs);
|
|
121
|
+
const ambitusNotes = [];
|
|
122
|
+
for (let off = data.ambitus.lowest; off <= data.ambitus.highest; off++) {
|
|
123
|
+
if (scaleSet.has(((off % 12) + 12) % 12))
|
|
124
|
+
ambitusNotes.push(tuned(off));
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
...data,
|
|
128
|
+
finalis: tuned(data.final),
|
|
129
|
+
reciting: tuned(data.tenor),
|
|
130
|
+
ambitusNotes,
|
|
131
|
+
};
|
|
114
132
|
},
|
|
115
133
|
tonus(tonusOpts) {
|
|
116
134
|
if (modeVal === "auto")
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import type { Finger, Region } from "../step.js";
|
|
1
2
|
export interface GuidonianVariant {
|
|
2
3
|
hexachord: "durum" | "naturale" | "molle";
|
|
3
4
|
solmization: "UT" | "RE" | "MI" | "FA" | "SOL" | "LA";
|
|
4
5
|
}
|
|
5
6
|
export interface GuidonianEntry {
|
|
6
7
|
hand: {
|
|
7
|
-
finger:
|
|
8
|
-
region:
|
|
8
|
+
finger: Finger;
|
|
9
|
+
region: Region;
|
|
9
10
|
};
|
|
10
11
|
name: [string, string];
|
|
11
12
|
variants: GuidonianVariant[];
|
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// The hand loci follow the CANONICAL Guidonian spiral, not a linear fill:
|
|
2
|
+
// begin at the thumb tip, come down the thumb, cross the finger BASES
|
|
3
|
+
// index→little, climb the little finger, return across the finger TIPS
|
|
4
|
+
// little→index, descend the index, then spiral inward; ee (76) floats above the
|
|
5
|
+
// middle fingertip (region "super"). The two b/♮ pairs (58/59, 70/71) share a
|
|
6
|
+
// locus by design — one joint, two readings (fa in molle, mi in durum), the
|
|
7
|
+
// tradition, not a duplication to fix. After Suñol [biblio: sunol-textbook] and
|
|
8
|
+
// Apel [biblio: apel-chant]; realized in working/diagram-hand-08.html.
|
|
4
9
|
// prettier-ignore
|
|
5
10
|
export const GUIDONIAN_DATA = new Map([
|
|
6
|
-
[43, { hand: { finger: "
|
|
7
|
-
[45, { hand: { finger: "
|
|
8
|
-
[47, { hand: { finger: "
|
|
9
|
-
[48, { hand: { finger: "
|
|
10
|
-
[50, { hand: { finger: "
|
|
11
|
-
[52, { hand: { finger: "
|
|
12
|
-
[53, { hand: { finger: "
|
|
13
|
-
[55, { hand: { finger: "
|
|
14
|
-
[57, { hand: { finger: "
|
|
15
|
-
[58, { hand: { finger: "
|
|
16
|
-
[59, { hand: { finger: "
|
|
17
|
-
[60, { hand: { finger: "
|
|
18
|
-
[62, { hand: { finger: "middle", region: "
|
|
19
|
-
[64, { hand: { finger: "
|
|
20
|
-
[65, { hand: { finger: "
|
|
21
|
-
[67, { hand: { finger: "
|
|
22
|
-
[69, { hand: { finger: "
|
|
23
|
-
[70, { hand: { finger: "ring", region: "
|
|
24
|
-
[71, { hand: { finger: "
|
|
25
|
-
[72, { hand: { finger: "
|
|
26
|
-
[74, { hand: { finger: "
|
|
27
|
-
[76, { hand: { finger: "
|
|
11
|
+
[43, { hand: { finger: "thumb", region: "tip" }, name: ["Γ", "Gammaut"], variants: [{ hexachord: "durum", solmization: "UT" }] }],
|
|
12
|
+
[45, { hand: { finger: "thumb", region: "mid" }, name: ["A", "Are"], variants: [{ hexachord: "durum", solmization: "RE" }] }],
|
|
13
|
+
[47, { hand: { finger: "thumb", region: "base" }, name: ["B", "Bemi"], variants: [{ hexachord: "durum", solmization: "MI" }] }],
|
|
14
|
+
[48, { hand: { finger: "index", region: "base" }, name: ["C", "Cefaut"], variants: [{ hexachord: "durum", solmization: "FA" }, { hexachord: "naturale", solmization: "UT" }] }],
|
|
15
|
+
[50, { hand: { finger: "middle", region: "base" }, name: ["D", "Desolre"], variants: [{ hexachord: "durum", solmization: "SOL" }, { hexachord: "naturale", solmization: "RE" }] }],
|
|
16
|
+
[52, { hand: { finger: "ring", region: "base" }, name: ["E", "Elami"], variants: [{ hexachord: "durum", solmization: "LA" }, { hexachord: "naturale", solmization: "MI" }] }],
|
|
17
|
+
[53, { hand: { finger: "pinky", region: "base" }, name: ["F", "Fefaut"], variants: [{ hexachord: "naturale", solmization: "FA" }, { hexachord: "molle", solmization: "UT" }] }],
|
|
18
|
+
[55, { hand: { finger: "pinky", region: "mid" }, name: ["G", "Gesolreut"], variants: [{ hexachord: "durum", solmization: "UT" }, { hexachord: "naturale", solmization: "SOL" }, { hexachord: "molle", solmization: "RE" }] }],
|
|
19
|
+
[57, { hand: { finger: "pinky", region: "top" }, name: ["a", "Alamire"], variants: [{ hexachord: "durum", solmization: "RE" }, { hexachord: "naturale", solmization: "LA" }, { hexachord: "molle", solmization: "MI" }] }],
|
|
20
|
+
[58, { hand: { finger: "pinky", region: "tip" }, name: ["b", "Befa"], variants: [{ hexachord: "molle", solmization: "FA" }] }],
|
|
21
|
+
[59, { hand: { finger: "pinky", region: "tip" }, name: ["♮", "Bemi"], variants: [{ hexachord: "durum", solmization: "MI" }] }],
|
|
22
|
+
[60, { hand: { finger: "ring", region: "tip" }, name: ["c", "Cesolfaut"], variants: [{ hexachord: "durum", solmization: "FA" }, { hexachord: "naturale", solmization: "UT" }, { hexachord: "molle", solmization: "SOL" }] }],
|
|
23
|
+
[62, { hand: { finger: "middle", region: "tip" }, name: ["d", "Delasolre"], variants: [{ hexachord: "durum", solmization: "SOL" }, { hexachord: "naturale", solmization: "RE" }, { hexachord: "molle", solmization: "LA" }] }],
|
|
24
|
+
[64, { hand: { finger: "index", region: "tip" }, name: ["e", "Elami"], variants: [{ hexachord: "durum", solmization: "LA" }, { hexachord: "naturale", solmization: "MI" }] }],
|
|
25
|
+
[65, { hand: { finger: "index", region: "top" }, name: ["f", "Fefaut"], variants: [{ hexachord: "naturale", solmization: "FA" }, { hexachord: "molle", solmization: "UT" }] }],
|
|
26
|
+
[67, { hand: { finger: "index", region: "mid" }, name: ["g", "Gesolreut"], variants: [{ hexachord: "durum", solmization: "UT" }, { hexachord: "naturale", solmization: "SOL" }, { hexachord: "molle", solmization: "RE" }] }],
|
|
27
|
+
[69, { hand: { finger: "middle", region: "mid" }, name: ["aa", "Alamire"], variants: [{ hexachord: "durum", solmization: "RE" }, { hexachord: "naturale", solmization: "LA" }, { hexachord: "molle", solmization: "MI" }] }],
|
|
28
|
+
[70, { hand: { finger: "ring", region: "mid" }, name: ["bb", "Befa"], variants: [{ hexachord: "molle", solmization: "FA" }] }],
|
|
29
|
+
[71, { hand: { finger: "ring", region: "mid" }, name: ["♮♮", "Bemi"], variants: [{ hexachord: "durum", solmization: "MI" }] }],
|
|
30
|
+
[72, { hand: { finger: "middle", region: "top" }, name: ["cc", "Cesolfa"], variants: [{ hexachord: "durum", solmization: "FA" }, { hexachord: "naturale", solmization: "UT" }, { hexachord: "molle", solmization: "SOL" }] }],
|
|
31
|
+
[74, { hand: { finger: "ring", region: "top" }, name: ["dd", "Delasol"], variants: [{ hexachord: "durum", solmization: "SOL" }, { hexachord: "naturale", solmization: "RE" }, { hexachord: "molle", solmization: "LA" }] }],
|
|
32
|
+
[76, { hand: { finger: "middle", region: "super" }, name: ["ee", "Ela"], variants: [{ hexachord: "durum", solmization: "LA" }, { hexachord: "naturale", solmization: "MI" }] }],
|
|
28
33
|
]);
|
|
29
34
|
//# sourceMappingURL=guido.js.map
|
|
@@ -39,6 +39,9 @@ export const MODES = new Map([
|
|
|
39
39
|
scalePcs: [2, 4, 5, 7, 9, 11, 0],
|
|
40
40
|
hexachords: ["naturale"],
|
|
41
41
|
profile: { mood: "sad", ethos: "tristis", phrasing: "lyrical", melodic: "arch", tendency: "neumatic" },
|
|
42
|
+
// Shared with mode 1 (both Protus). An earlier seed here was wrong — a copy
|
|
43
|
+
// of mode 5's figures, landing on F with an Ab outside hypodorian's scale;
|
|
44
|
+
// Suñol's tables surfaced it, and it was corrected to the Protus descent.
|
|
42
45
|
cadences: [
|
|
43
46
|
{ id: "mi-re", steps: [1, 0] },
|
|
44
47
|
{ id: "ut-re", steps: [-1, 0] },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// temper/data/tones — psalm tones (Graduale Romanum appendix)
|
|
2
2
|
// Pitches as MIDI numbers; tone codes follow DO convention: "1g", "6F", "4e".
|
|
3
3
|
// c4 clef reference: f=53 g=55 h=57 i=59 j=60 k=62 l=64 (F3–F4)
|
|
4
4
|
const f = 53, g = 55, h = 57, i = 59, j = 60, k = 62, l = 64;
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// engines/temper/gabc — GABC pitch letter utilities
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
+
// GABC pitch letters (a–m) are DIATONIC STAFF POSITIONS, not pitch classes: the
|
|
5
|
+
// thirteen letters are the thirteen slots of the four-line staff and its ledger
|
|
6
|
+
// space, spanning roughly two octaves of white-key steps [biblio: gregorio-gabc].
|
|
7
|
+
// A letter has no fixed pitch on its own — the clef fixes it. So converting to
|
|
8
|
+
// and from MIDI is staff-position arithmetic, done in two moduli: 7 for the
|
|
9
|
+
// diatonic staff (steps per octave) and 12 for MIDI (semitones per octave).
|
|
10
|
+
//
|
|
11
|
+
// DIATONIC maps a diatonic step (0–6, do re mi fa sol la si) to its pitch class.
|
|
12
|
+
// LETTERS is the staff-slot alphabet, low to high.
|
|
4
13
|
const DIATONIC = [0, 2, 4, 5, 7, 9, 11];
|
|
5
14
|
const LETTERS = "abcdefghijklm";
|
|
15
|
+
// A GABC clef names the staff line that carries "do" (c-clefs) or "fa" (f-clefs)
|
|
16
|
+
// and thereby anchors every letter. `doIdx` is the LETTERS slot that line falls
|
|
17
|
+
// on; `doMidi` is the MIDI pitch of "do" there (60 = middle C; 53 = the F below).
|
|
18
|
+
// A higher c-clef (c4 vs c1) moves "do" up the staff, so the same letter reads a
|
|
19
|
+
// lower pitch — hence doIdx climbs 3→5→7→9 across c1→c4. The f-clefs anchor on
|
|
20
|
+
// fa (MIDI 53) and are used for lower-tessitura chant.
|
|
6
21
|
const CLEFS = {
|
|
7
22
|
c1: { doMidi: 60, doIdx: 3 },
|
|
8
23
|
c2: { doMidi: 60, doIdx: 5 },
|
|
9
24
|
c3: { doMidi: 60, doIdx: 7 },
|
|
10
25
|
c4: { doMidi: 60, doIdx: 9 },
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
// f-clefs anchor fa on the named line. Staff lines (bottom→top) sit at
|
|
27
|
+
// letters d/f/h/j (per the Gregorio spec: 2-line staff = a–i, 3-line = a–k,
|
|
28
|
+
// 4-line = a–m, pinning the lines at slots 3/5/7/9), so f3 puts fa at 'h'
|
|
29
|
+
// (7) and f4 at 'j' (9). Previous values (5 and 3) were off by a third and
|
|
30
|
+
// read every f-clef chant at the wrong staff position.
|
|
31
|
+
f3: { doMidi: 53, doIdx: 7 },
|
|
32
|
+
f4: { doMidi: 53, doIdx: 9 },
|
|
13
33
|
};
|
|
14
34
|
export function midiToGabc(midi, clef = "c4") {
|
|
15
35
|
const def = CLEFS[clef];
|
|
@@ -34,6 +54,9 @@ export function gabcToMidi(letter, clef = "c4") {
|
|
|
34
54
|
const staffPos = LETTERS.indexOf(letter.toLowerCase());
|
|
35
55
|
if (staffPos === -1)
|
|
36
56
|
throw new Error(`Unknown GABC letter: ${letter}`);
|
|
57
|
+
// Diatonic steps from "do", split into whole octaves (÷7) and the step within
|
|
58
|
+
// the octave. The `((x % 7) + 7) % 7` form keeps the step in 0–6 for letters
|
|
59
|
+
// below "do", where stepsFromDo is negative and JS `%` would return negative.
|
|
37
60
|
const stepsFromDo = staffPos - def.doIdx;
|
|
38
61
|
const octOffset = Math.floor(stepsFromDo / 7);
|
|
39
62
|
const diatStep = ((stepsFromDo % 7) + 7) % 7;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Finger, Region } from "./step.js";
|
|
1
2
|
export type { GuidonianVariant, GuidonianEntry } from "./data/guido.js";
|
|
2
3
|
export declare function lookupGuido(midi: number, mode?: number): {
|
|
3
4
|
name: string | null;
|
|
@@ -9,8 +10,8 @@ export declare function lookupGuido(midi: number, mode?: number): {
|
|
|
9
10
|
solmization: string;
|
|
10
11
|
}[];
|
|
11
12
|
hand: {
|
|
12
|
-
finger:
|
|
13
|
-
region:
|
|
13
|
+
finger: Finger;
|
|
14
|
+
region: Region;
|
|
14
15
|
} | null;
|
|
15
16
|
};
|
|
16
17
|
//# sourceMappingURL=guido.d.ts.map
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
// engines/temper/interval — interval classification between pitches
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { INTERVAL, UNISONUS } from "./data/constants.js";
|
|
5
|
+
// The three-tier consonance taxonomy [biblio: schulter-harmony] (the same table
|
|
6
|
+
// stated at docs/heavens.md and docs/tuning.md). Note that the perfect fourth is
|
|
7
|
+
// deliberately NOT perfect here: in medieval counterpoint the P4 above the bass
|
|
8
|
+
// is treated as a dissonance, unlike the melodic P4. So P1/P5/P8 are perfect,
|
|
9
|
+
// the thirds and sixths imperfect, and everything else — including P4 and the
|
|
10
|
+
// tritone — dissonant.
|
|
5
11
|
const PERFECT_CLASSES = new Set(["P1", "P5", "P8"]);
|
|
6
12
|
const IMPERFECT_CLASSES = new Set(["m3", "M3", "m6", "M6"]);
|
|
7
13
|
function classifyConsonance(intervalClass) {
|
|
@@ -16,6 +22,9 @@ export function classifyInterval(a, b) {
|
|
|
16
22
|
const abs = Math.abs(semitones);
|
|
17
23
|
const simple = abs % 12;
|
|
18
24
|
const direction = semitones > 0 ? "up" : semitones < 0 ? "down" : "unison";
|
|
25
|
+
// A true zero-distance unison (abs === 0) is UNISONUS; a compound octave
|
|
26
|
+
// (simple === 0 but abs a nonzero multiple of 12) folds to INTERVAL[0], the
|
|
27
|
+
// octave entry. The two share simple === 0 but name different intervals.
|
|
19
28
|
const entry = abs === 0 ? UNISONUS : (simple === 0 ? INTERVAL[0] : INTERVAL[simple]);
|
|
20
29
|
return {
|
|
21
30
|
nomen: entry.latin,
|
|
@@ -24,6 +33,9 @@ export function classifyInterval(a, b) {
|
|
|
24
33
|
class: entry.class,
|
|
25
34
|
direction,
|
|
26
35
|
semitones,
|
|
36
|
+
// Nominal equal-tempered cents (100 per semitone), NOT the tuned distance —
|
|
37
|
+
// the actual sounding interval depends on the temperament (see the ratio a
|
|
38
|
+
// temperamentum reports for a nota, and docs/tuning.md on nominal vs tuned).
|
|
27
39
|
cents: semitones * 100,
|
|
28
40
|
consonance: classifyConsonance(entry.class),
|
|
29
41
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ModalAffinity {
|
|
2
|
+
mode: number;
|
|
3
|
+
alias: string;
|
|
4
|
+
score: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Rank a pitch-class distribution against the eight modes, best fit first.
|
|
8
|
+
* `firstNotePc`, when given, applies the rank-weighted initials bonus.
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeModalAffinity(pcDistribution: Record<number, number>, firstNotePc?: number): ModalAffinity[];
|
|
11
|
+
//# sourceMappingURL=modality.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// engines/temper/modality — how well pitch content fits each church mode
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Modal theory, not tied to any one caller: the imprint uses it to fingerprint a
|
|
5
|
+
// whole chant, modulation detection to read each phrase. A pure function of a
|
|
6
|
+
// pitch-class distribution (and, optionally, the chant's opening note).
|
|
7
|
+
import { MODES } from "./modes.js";
|
|
8
|
+
// A mode's structural degrees are not equal: the finalis defines it, the tenor
|
|
9
|
+
// anchors its recitation, and modulation degrees are only secondary colour. Time
|
|
10
|
+
// spent on each pitch counts toward the mode in that proportion.
|
|
11
|
+
const FINALIS_WEIGHT = 3;
|
|
12
|
+
const TENOR_WEIGHT = 2;
|
|
13
|
+
const REGULAR_MOD_WEIGHT = 1;
|
|
14
|
+
const CONCEDED_MOD_WEIGHT = 0.5;
|
|
15
|
+
// A chant's opening note is a modal signal: each mode lists its valid initials
|
|
16
|
+
// in rank order, most characteristic first (Rockstro's Grove ordering
|
|
17
|
+
// [biblio: rockstro-grove]). Opening on a mode's primary initial boosts it more
|
|
18
|
+
// than opening on a lower-ranked one — which is what separates an authentic mode
|
|
19
|
+
// from its plagal partner, since the two share a finalis but rank the same
|
|
20
|
+
// opening pitch differently.
|
|
21
|
+
const INITIAL_BONUS = 0.3;
|
|
22
|
+
/**
|
|
23
|
+
* Rank a pitch-class distribution against the eight modes, best fit first.
|
|
24
|
+
* `firstNotePc`, when given, applies the rank-weighted initials bonus.
|
|
25
|
+
*/
|
|
26
|
+
export function computeModalAffinity(pcDistribution, firstNotePc) {
|
|
27
|
+
const results = [];
|
|
28
|
+
for (let m = 1; m <= 8; m++) {
|
|
29
|
+
const data = MODES.get(m);
|
|
30
|
+
if (!data)
|
|
31
|
+
continue;
|
|
32
|
+
// Weight each degree by its modal role; a pc that fills more than one role
|
|
33
|
+
// (e.g. a modulation degree that is also the tenor) takes the strongest.
|
|
34
|
+
const degreeWeight = new Map();
|
|
35
|
+
const set = (pc, w) => {
|
|
36
|
+
degreeWeight.set(pc, Math.max(degreeWeight.get(pc) ?? 0, w));
|
|
37
|
+
};
|
|
38
|
+
for (const pc of data.modulations.conceded)
|
|
39
|
+
set(pc % 12, CONCEDED_MOD_WEIGHT);
|
|
40
|
+
for (const pc of data.modulations.regular)
|
|
41
|
+
set(pc % 12, REGULAR_MOD_WEIGHT);
|
|
42
|
+
set(data.tenor, TENOR_WEIGHT);
|
|
43
|
+
set(data.final, FINALIS_WEIGHT);
|
|
44
|
+
let score = 0;
|
|
45
|
+
for (const [pc, w] of degreeWeight)
|
|
46
|
+
score += (pcDistribution[pc] ?? 0) * w;
|
|
47
|
+
// Initials bonus, scaled by how highly the mode ranks the opening pitch.
|
|
48
|
+
if (firstNotePc != null) {
|
|
49
|
+
const initials = data.modulations.initials;
|
|
50
|
+
const rank = initials.findIndex((pc) => pc % 12 === firstNotePc);
|
|
51
|
+
if (rank !== -1)
|
|
52
|
+
score += (INITIAL_BONUS * (initials.length - rank)) / initials.length;
|
|
53
|
+
}
|
|
54
|
+
results.push({ mode: m, alias: data.alias, score });
|
|
55
|
+
}
|
|
56
|
+
return results.sort((a, b) => b.score - a.score);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=modality.js.map
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// engines/temper/scale — tuning ratio builder
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
+
// Builds the 12 pitch-class ratios for a temperament. The default is pure
|
|
5
|
+
// Pythagorean — all intervals from the 3/2 fifth and the octave — because that
|
|
6
|
+
// is the tuning of medieval theory from Boethius through the Guidonian gamut
|
|
7
|
+
// [biblio: boethius-institutione, guidonian-gamut], and it is correct for
|
|
8
|
+
// unaccompanied chant: melodic fifths/fourths are perfect, the narrow limma
|
|
9
|
+
// (256/243) gives half-steps a keen leading quality, and the wide Pythagorean
|
|
10
|
+
// third (81/64) never has to serve as a consonance.
|
|
11
|
+
//
|
|
12
|
+
// `comma` tempers the fifth toward meantone by narrowing it by a fraction of
|
|
13
|
+
// the syntonic comma (81/80, the gap between the Pythagorean and pure 5/4
|
|
14
|
+
// third): comma "1/4" stacks four fifths to a pure major third — quarter-comma
|
|
15
|
+
// meantone, the 16th-century sound.
|
|
16
|
+
//
|
|
17
|
+
// The `steps` presets supply just-intonation genera in place of the tempered
|
|
18
|
+
// fifth: the three Ptolemaic diatonics (intense/soft/equable, his χρόαι
|
|
19
|
+
// "shades") come straight from Ptolemy's tetrachord divisions [biblio:
|
|
20
|
+
// ptolemy-harmonics, Harmonics I.15–16]. See expandDiatonicSteps for how a
|
|
21
|
+
// 7-ratio genus is laid onto the fixed gamut, and why.
|
|
4
22
|
import { MODES } from "./modes.js";
|
|
5
23
|
// Stern-Brocot rational approximation — finds nearest simple fraction
|
|
6
24
|
function approximate(value, maxDen = 1000) {
|
|
@@ -110,7 +128,14 @@ export function parseScala(input) {
|
|
|
110
128
|
}
|
|
111
129
|
const PURE_FIFTH = 3 / 2;
|
|
112
130
|
const SYNTONIC_COMMA = 81 / 80;
|
|
131
|
+
// The circle of fifths, as chromatic pitch classes: C G D A E B F♯ … stacking
|
|
132
|
+
// twelve 3/2s. buildPythagoreanRatios walks this and octave-folds each.
|
|
113
133
|
const FIFTH_TO_CHROM = [0, 7, 2, 9, 4, 11, 6, 1, 8, 3, 10, 5];
|
|
134
|
+
// Ptolemy's three diatonic genera [biblio: ptolemy-harmonics, Harmonics I.15–16],
|
|
135
|
+
// each a tetrachord (1/1 … 4/3) doubled up a 3/2 to fill the octave:
|
|
136
|
+
// intense (syntonon) — classical just intonation: pure 5/4 major, 6/5 minor.
|
|
137
|
+
// soft (malakon) — septimal: the 7th harmonic gives a large 8/7 whole tone.
|
|
138
|
+
// equable (homalon) — undecimal: near-equal ~150–182¢ steps.
|
|
114
139
|
const PTOLEMAIC = {
|
|
115
140
|
"ptolemy-intense": ["1/1", "9/8", "5/4", "4/3", "3/2", "5/3", "15/8"],
|
|
116
141
|
"ptolemy-soft": ["1/1", "8/7", "80/63", "4/3", "3/2", "12/7", "40/21"],
|
|
@@ -143,8 +168,14 @@ const NATURAL_PCS = [0, 2, 4, 5, 7, 9, 11];
|
|
|
143
168
|
// pitch order — NOT onto the mode's scalePcs. A church mode is an octave
|
|
144
169
|
// species of this one gamut, so its interval qualities emerge from *where the
|
|
145
170
|
// final sits within the fixed tuning*, handled downstream by normalizeToRoot.
|
|
146
|
-
//
|
|
147
|
-
//
|
|
171
|
+
// This yields the authentic per-mode qualities (a Dorian minor third, a
|
|
172
|
+
// Mixolydian ♭7) and the honest syntonic wolf (D–A = 40/27 under
|
|
173
|
+
// ptolemy-intense).
|
|
174
|
+
//
|
|
175
|
+
// Mapping the genus degree-per-mode onto scalePcs instead would force
|
|
176
|
+
// major-scale qualities — a 5/4 major third above *every* final — onto every
|
|
177
|
+
// mode. Re-deriving a per-mode just intonation would attribute a modern just
|
|
178
|
+
// tuning to Ptolemy, who described tetrachord divisions, not modal scales.
|
|
148
179
|
function expandDiatonicSteps(diatonic) {
|
|
149
180
|
const base = buildPythagoreanRatios(0);
|
|
150
181
|
const out = base.slice();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Scale } from "./scale.js";
|
|
2
|
-
export type Finger = "
|
|
3
|
-
export type Region = "base" | "mid" | "tip" | "
|
|
2
|
+
export type Finger = "thumb" | "index" | "middle" | "ring" | "pinky";
|
|
3
|
+
export type Region = "base" | "mid" | "top" | "tip" | "super";
|
|
4
4
|
export interface StepVariant {
|
|
5
5
|
hexachord: "durum" | "naturale" | "molle";
|
|
6
6
|
solmization: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,16 +9,16 @@ import { buildScore } from "./engines/score/api.js";
|
|
|
9
9
|
import { getCosmos } from "./engines/planet/planet.js";
|
|
10
10
|
import { buildHarmonia } from "./engines/harmonia/api.js";
|
|
11
11
|
import type { FeastQuery, Feast, Pascha, Season, Grade } from "./engines/cal/types.js";
|
|
12
|
-
import type { CantusQuery, Chant, OrdinaryChant, PropriumQuery, OrdinariumQuery, OfficiumQuery, PsalmusQuery } from "./engines/chant/types.js";
|
|
13
|
-
import type { TemperamentumInput, Temperamentum, Tuning, TemperamentumOpts, Pitch, PitchInput, Step, Neume, NeumeShape, Interval, ModeData, CadenceFigure, GamutOptions, Tonus, TonusOpts } from "./engines/temper/api.js";
|
|
14
|
-
import type { Score, ScoreOpts, PondusInput, PondusOpts, AccentusInput, AccentusOpts, Cadence, CadenceTarget, CadenceApproach, MidiOpts, MidiEmitResult, MidiJsonResult, MidiJsonEvent, MusicXmlOpts, MusicXmlEmitResult } from "./engines/score/api.js";
|
|
12
|
+
import type { CantusQuery, Chant, OrdinaryChant, PropriumQuery, OrdinariumQuery, OfficiumQuery, PsalmusQuery, Rite } from "./engines/chant/types.js";
|
|
13
|
+
import type { TemperamentumInput, Temperamentum, Tuning, TemperamentumOpts, Pitch, PitchInput, Step, Neume, NeumeShape, Interval, ModeData, CadenceFigure, Modus, TunedNote, GamutOptions, Tonus, TonusOpts } from "./engines/temper/api.js";
|
|
14
|
+
import type { Score, ScoreOpts, PondusInput, PondusOpts, AccentusInput, AccentusOpts, Cadence, CadenceTarget, CadenceApproach, Modulation, MidiOpts, MidiEmitResult, MidiJsonResult, MidiJsonEvent, MusicXmlOpts, MusicXmlEmitResult } from "./engines/score/api.js";
|
|
15
15
|
import type { ChantTabulaRow } from "./engines/score/tabula.js";
|
|
16
16
|
import type { Imprint, Attractor, VowelAttractor, ModalAffinity } from "./engines/imprint.js";
|
|
17
17
|
import type { Prosody, RhythmicProfile, NoteRange, CadenceDistribution } from "./engines/score/prosody.js";
|
|
18
18
|
import type { Harmony, HarmoniaOpts, VoicedBody, VoicedAspect, Frame, Author } from "./engines/harmonia/api.js";
|
|
19
19
|
import type { HarmonyTabulaRow } from "./engines/harmonia/tabula.js";
|
|
20
20
|
import type { PlanetVowel } from "./engines/harmonia/data/vowels.js";
|
|
21
|
-
import type { Note, Performance, Phrase, Syllable, RestEvent, ParseError, ArsisThesis } from "./engines/score/types.js";
|
|
21
|
+
import type { Note, Performance, Phrase, Syllable, RestEvent, ParseError, ArsisThesis, RhythmicType, CompoundBeat } from "./engines/score/types.js";
|
|
22
22
|
import type { VoicedPitch } from "./engines/harmonia/voice.js";
|
|
23
23
|
import type { Cosmos, CosmosQuery, Body, BodyName, Aspect } from "./engines/planet/types.js";
|
|
24
24
|
declare const tonus: {
|
|
@@ -36,5 +36,5 @@ declare const tonus: {
|
|
|
36
36
|
};
|
|
37
37
|
export default tonus;
|
|
38
38
|
export { SEASON_LABELS, TEMPUS_NAMES, GRADE_ORDER, GRADE_NAMES, gradeOrder, compareGrade, ritusToGrade, } from "./engines/cal/types.js";
|
|
39
|
-
export type { Feast, FeastQuery, Pascha, Season, Grade, Chant, CantusQuery, OrdinaryChant, PropriumQuery, OrdinariumQuery, OfficiumQuery, PsalmusQuery, Temperamentum, TemperamentumInput, TemperamentumOpts, Tuning, Pitch, PitchInput, Step, Neume, NeumeShape, Interval, ModeData, CadenceFigure, GamutOptions, Tonus, TonusOpts, Score, ScoreOpts, PondusInput, PondusOpts, AccentusInput, AccentusOpts, Cadence, CadenceTarget, CadenceApproach, MidiOpts, MidiEmitResult, MidiJsonResult, MidiJsonEvent, MusicXmlOpts, MusicXmlEmitResult, ChantTabulaRow, Note, Performance, Phrase, Syllable, RestEvent, ParseError, ArsisThesis, VoicedPitch, Cosmos, CosmosQuery, Body, BodyName, Aspect, Imprint, Attractor, VowelAttractor, ModalAffinity, Prosody, RhythmicProfile, NoteRange, CadenceDistribution, Harmony, HarmoniaOpts, VoicedBody, VoicedAspect, Frame, Author, HarmonyTabulaRow, PlanetVowel, };
|
|
39
|
+
export type { Feast, FeastQuery, Pascha, Season, Grade, Chant, CantusQuery, OrdinaryChant, PropriumQuery, OrdinariumQuery, OfficiumQuery, PsalmusQuery, Rite, Temperamentum, TemperamentumInput, TemperamentumOpts, Tuning, Pitch, PitchInput, Step, Neume, NeumeShape, Interval, ModeData, CadenceFigure, Modus, TunedNote, GamutOptions, Tonus, TonusOpts, Score, ScoreOpts, PondusInput, PondusOpts, AccentusInput, AccentusOpts, Cadence, CadenceTarget, CadenceApproach, Modulation, MidiOpts, MidiEmitResult, MidiJsonResult, MidiJsonEvent, MusicXmlOpts, MusicXmlEmitResult, ChantTabulaRow, Note, Performance, Phrase, Syllable, RestEvent, ParseError, ArsisThesis, RhythmicType, CompoundBeat, VoicedPitch, Cosmos, CosmosQuery, Body, BodyName, Aspect, Imprint, Attractor, VowelAttractor, ModalAffinity, Prosody, RhythmicProfile, NoteRange, CadenceDistribution, Harmony, HarmoniaOpts, VoicedBody, VoicedAspect, Frame, Author, HarmonyTabulaRow, PlanetVowel, };
|
|
40
40
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tonus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Medieval music analysis and performance: GABC plainchant exports, liturgical calendar, tuning systems, ephemeris, and the harmony of the spheres",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"!dist/**/*.js.map",
|
|
43
43
|
"!dist/**/*.d.ts.map",
|
|
44
44
|
"LICENSE",
|
|
45
|
+
"CHANGELOG.md",
|
|
45
46
|
"BIBLIOGRAPHY.md"
|
|
46
47
|
],
|
|
47
48
|
"scripts": {
|
package/dist/data/office.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export interface OfficeDay {
|
|
2
|
-
feastId: string;
|
|
3
|
-
doFile: string;
|
|
4
|
-
antLaudes: string[];
|
|
5
|
-
antBenedictus: string | null;
|
|
6
|
-
antVespera: string[];
|
|
7
|
-
antMagnificat: string | null;
|
|
8
|
-
hymnLaudes: string | null;
|
|
9
|
-
hymnVespera: string | null;
|
|
10
|
-
}
|
|
11
|
-
export declare const OFFICE: OfficeDay[];
|
|
12
|
-
//# sourceMappingURL=office.d.ts.map
|