linked-rolls 0.56.0 → 0.58.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.
Files changed (131) hide show
  1. package/README.md +54 -361
  2. package/lib/{constraints.d.ts → analysis/constraints.d.ts} +1 -1
  3. package/lib/{constraints.js → analysis/constraints.js} +9 -8
  4. package/lib/analysis/ownPaper.d.ts +26 -0
  5. package/lib/analysis/ownPaper.js +41 -0
  6. package/lib/{reservations.d.ts → analysis/reservations.d.ts} +3 -3
  7. package/lib/{reservations.js → analysis/reservations.js} +3 -3
  8. package/lib/{sigla.d.ts → analysis/sigla.d.ts} +2 -2
  9. package/lib/{sigla.js → analysis/sigla.js} +4 -4
  10. package/lib/{witnesses.d.ts → analysis/witnesses.d.ts} +2 -2
  11. package/lib/{witnesses.js → analysis/witnesses.js} +4 -4
  12. package/lib/{Collation.d.ts → collation/Collation.d.ts} +4 -4
  13. package/lib/{Collation.js → collation/Collation.js} +4 -4
  14. package/lib/{alignment.d.ts → collation/alignment.d.ts} +4 -4
  15. package/lib/{alignment.js → collation/alignment.js} +10 -16
  16. package/lib/{scatter.d.ts → collation/scatter.d.ts} +4 -4
  17. package/lib/{scatter.js → collation/scatter.js} +6 -6
  18. package/lib/{statistics.d.ts → collation/statistics.d.ts} +1 -1
  19. package/lib/{statistics.js → collation/statistics.js} +2 -2
  20. package/lib/{substitution.d.ts → collation/substitution.d.ts} +9 -24
  21. package/lib/{substitution.js → collation/substitution.js} +13 -37
  22. package/lib/emulation/Emulation.d.ts +64 -0
  23. package/lib/emulation/Emulation.js +282 -0
  24. package/lib/emulation/negotiation.d.ts +14 -0
  25. package/lib/emulation/negotiation.js +20 -0
  26. package/lib/index.d.ts +43 -35
  27. package/lib/index.js +36 -35
  28. package/lib/{asJsonLd.d.ts → io/asJsonLd.d.ts} +1 -1
  29. package/lib/{asJsonLd.js → io/asJsonLd.js} +22 -51
  30. package/lib/{context.d.ts → io/context.d.ts} +4 -4
  31. package/lib/{context.js → io/context.js} +4 -4
  32. package/lib/{importJsonLd.d.ts → io/importJsonLd.d.ts} +1 -1
  33. package/lib/io/importJsonLd.js +128 -0
  34. package/lib/{migrate.d.ts → io/migrate.d.ts} +9 -0
  35. package/lib/{migrate.js → io/migrate.js} +97 -54
  36. package/lib/{Agent.d.ts → model/Agent.d.ts} +1 -1
  37. package/lib/{Assumption.d.ts → model/Assumption.d.ts} +1 -1
  38. package/lib/{ConditionState.d.ts → model/ConditionState.d.ts} +1 -2
  39. package/lib/{Edit.d.ts → model/Edit.d.ts} +1 -1
  40. package/lib/{Edition.d.ts → model/Edition.d.ts} +2 -2
  41. package/lib/{Feature.d.ts → model/Feature.d.ts} +3 -1
  42. package/lib/{Feature.js → model/Feature.js} +2 -0
  43. package/lib/{FeatureSource.d.ts → model/FeatureSource.d.ts} +1 -1
  44. package/lib/{Perforator.d.ts → model/Perforator.d.ts} +1 -1
  45. package/lib/{RollCopy.d.ts → model/RollCopy.d.ts} +5 -12
  46. package/lib/{RollCopy.js → model/RollCopy.js} +3 -5
  47. package/lib/{Symbol.d.ts → model/Symbol.d.ts} +1 -1
  48. package/lib/{Version.d.ts → model/Version.d.ts} +11 -3
  49. package/lib/{Version.js → model/Version.js} +24 -1
  50. package/lib/{vocabulary.js → model/vocabulary.js} +2 -2
  51. package/lib/ops/beliefs.d.ts +9 -0
  52. package/lib/ops/beliefs.js +31 -0
  53. package/lib/ops/collation.d.ts +62 -0
  54. package/lib/ops/collation.js +228 -0
  55. package/lib/ops/commands.d.ts +9 -0
  56. package/lib/ops/commands.js +29 -0
  57. package/lib/ops/copies.d.ts +74 -0
  58. package/lib/ops/copies.js +135 -0
  59. package/lib/ops/draft.d.ts +59 -0
  60. package/lib/ops/draft.js +81 -0
  61. package/lib/ops/edits.d.ts +10 -0
  62. package/lib/ops/edits.js +82 -0
  63. package/lib/ops/features.d.ts +84 -0
  64. package/lib/ops/features.js +296 -0
  65. package/lib/ops/forget.d.ts +31 -0
  66. package/lib/ops/forget.js +110 -0
  67. package/lib/ops/immutable.d.ts +16 -0
  68. package/lib/ops/immutable.js +46 -0
  69. package/lib/ops/index.d.ts +13 -0
  70. package/lib/ops/index.js +7 -0
  71. package/lib/ops/versions.d.ts +33 -0
  72. package/lib/ops/versions.js +95 -0
  73. package/lib/readers/AtonParser.js +5 -7
  74. package/lib/readers/phillipsEroll.d.ts +3 -3
  75. package/lib/readers/phillipsEroll.js +4 -5
  76. package/lib/readers/spencerBar.d.ts +2 -2
  77. package/lib/readers/spencerBar.js +2 -3
  78. package/lib/readers/stanfordAton.d.ts +3 -3
  79. package/lib/readers/stanfordAton.js +2 -4
  80. package/lib/schema.json +11 -151
  81. package/lib/spec/context.json +2 -12
  82. package/lib/{ReproducingSystem.d.ts → systems/ReproducingSystem.d.ts} +3 -3
  83. package/lib/{TrackerBar.d.ts → systems/TrackerBar.d.ts} +48 -8
  84. package/lib/{TrackerBar.js → systems/TrackerBar.js} +11 -2
  85. package/lib/systems/index.d.ts +8 -2
  86. package/lib/systems/index.js +7 -1
  87. package/lib/systems/welte.d.ts +100 -0
  88. package/lib/systems/welte.js +119 -0
  89. package/lib/systems/welteLicensee/bar.d.ts +1 -1
  90. package/lib/systems/welteLicensee/bar.js +5 -2
  91. package/lib/systems/welteLicensee/system.d.ts +1 -1
  92. package/lib/systems/welteLicensee/system.js +1 -1
  93. package/lib/systems/welteT100/bar.d.ts +27 -1
  94. package/lib/systems/welteT100/bar.js +44 -2
  95. package/lib/systems/welteT100/system.d.ts +6 -39
  96. package/lib/systems/welteT100/system.js +19 -128
  97. package/lib/systems/welteT98/bar.d.ts +1 -1
  98. package/lib/systems/welteT98/bar.js +18 -2
  99. package/lib/systems/welteT98/system.d.ts +20 -38
  100. package/lib/systems/welteT98/system.js +20 -121
  101. package/lib/validate.d.ts +1 -1
  102. package/lib/{EditionView.d.ts → view/EditionView.d.ts} +38 -48
  103. package/lib/{EditionView.js → view/EditionView.js} +90 -96
  104. package/package.json +7 -2
  105. package/lib/Emulation.d.ts +0 -36
  106. package/lib/Emulation.js +0 -250
  107. package/lib/editionOps.d.ts +0 -260
  108. package/lib/editionOps.js +0 -1081
  109. package/lib/importJsonLd.js +0 -62
  110. /package/lib/{Agent.js → model/Agent.js} +0 -0
  111. /package/lib/{Assumption.js → model/Assumption.js} +0 -0
  112. /package/lib/{ConditionState.js → model/ConditionState.js} +0 -0
  113. /package/lib/{Edit.js → model/Edit.js} +0 -0
  114. /package/lib/{Edition.js → model/Edition.js} +0 -0
  115. /package/lib/{FeatureSource.js → model/FeatureSource.js} +0 -0
  116. /package/lib/{Perforator.js → model/Perforator.js} +0 -0
  117. /package/lib/{Quantity.d.ts → model/Quantity.d.ts} +0 -0
  118. /package/lib/{Quantity.js → model/Quantity.js} +0 -0
  119. /package/lib/{Symbol.js → model/Symbol.js} +0 -0
  120. /package/lib/{TrackCalibration.d.ts → model/TrackCalibration.d.ts} +0 -0
  121. /package/lib/{TrackCalibration.js → model/TrackCalibration.js} +0 -0
  122. /package/lib/{notes.d.ts → model/notes.d.ts} +0 -0
  123. /package/lib/{notes.js → model/notes.js} +0 -0
  124. /package/lib/{procedures.d.ts → model/procedures.d.ts} +0 -0
  125. /package/lib/{procedures.js → model/procedures.js} +0 -0
  126. /package/lib/{vocabulary.d.ts → model/vocabulary.d.ts} +0 -0
  127. /package/lib/{sorted.d.ts → shared/sorted.d.ts} +0 -0
  128. /package/lib/{sorted.js → shared/sorted.js} +0 -0
  129. /package/lib/{utils.d.ts → shared/utils.d.ts} +0 -0
  130. /package/lib/{utils.js → shared/utils.js} +0 -0
  131. /package/lib/{ReproducingSystem.js → systems/ReproducingSystem.js} +0 -0
@@ -1,7 +1,7 @@
1
- import { Edit } from "./Edit.js";
2
- import { HorizontalSpan } from "./Feature.js";
3
- import { AnySymbol } from "./Symbol.js";
4
- import { Millimeters } from "./Quantity.js";
1
+ import { Edit } from "../model/Edit.js";
2
+ import { HorizontalSpan } from "../model/Feature.js";
3
+ import { AnySymbol } from "../model/Symbol.js";
4
+ import { Millimeters } from "../model/Quantity.js";
5
5
  /** A value taken at each end of a feature: where it begins and where it stops. */
6
6
  export interface BothEnds<T> {
7
7
  from: T;
@@ -1,7 +1,7 @@
1
- import { keyOf } from "./TrackerBar.js";
2
- import { distance, mm } from "./Quantity.js";
3
- import { partitionPoint } from "./sorted.js";
4
- import { groupBy } from "./utils.js";
1
+ import { keyOf } from "../systems/TrackerBar.js";
2
+ import { distance, mm } from "../model/Quantity.js";
3
+ import { partitionPoint } from "../shared/sorted.js";
4
+ import { groupBy } from "../shared/utils.js";
5
5
  export const defaultCollationTolerance = { toleranceStart: mm(5), toleranceEnd: mm(5) };
6
6
  /** Where the window is centred at the start of a feature, on nothing where it names no offset. */
7
7
  export const offsetStartOf = (tolerance) => tolerance.offsetStart ?? mm(0);
@@ -1,7 +1,7 @@
1
- import { FeatureOrPatch } from "./Feature.js";
2
- import { RollCopy, Shift } from "./RollCopy.js";
3
- import { TrackerBar } from "./TrackerBar.js";
4
- import { Millimeters } from "./Quantity.js";
1
+ import { FeatureOrPatch } from "../model/Feature.js";
2
+ import { RollCopy, Shift } from "../model/RollCopy.js";
3
+ import { TrackerBar } from "../systems/TrackerBar.js";
4
+ import { Millimeters } from "../model/Quantity.js";
5
5
  export declare const applyShift: (shift: Shift, copy: RollCopy) => void;
6
6
  /** Scales the copy's features away from the beginning of the roll, and records the factor. */
7
7
  export declare const applyScale: (factor: number, copy: RollCopy) => void;
@@ -1,6 +1,6 @@
1
- import { featuresOf } from "./RollCopy.js";
2
- import { welteT100 } from "./systems/welteT100/bar.js";
3
- import { add, mm, scale, subtract } from "./Quantity.js";
1
+ import { featuresOf } from "../model/RollCopy.js";
2
+ import { defaultTrackerBar } from "../systems/index.js";
3
+ import { add, mm, scale, subtract } from "../model/Quantity.js";
4
4
  /** Moves both ends of a span, the far end only where the span has one. */
5
5
  const move = (span, by) => {
6
6
  span.from = add(span.from, by);
@@ -15,43 +15,39 @@ const stretch = (span, factor) => {
15
15
  };
16
16
  const back = (shift) => ({ horizontal: scale(shift.horizontal, -1), vertical: scale(shift.vertical, -1) });
17
17
  export const applyShift = (shift, copy) => {
18
- if (copy.ops.includes('shifted'))
18
+ if (copy.measurements.shift)
19
19
  return;
20
20
  featuresOf(copy).forEach(feature => {
21
21
  move(feature.horizontal, shift.horizontal);
22
22
  move(feature.vertical, shift.vertical);
23
23
  });
24
- copy.ops = [...copy.ops, 'shifted'];
25
24
  copy.measurements.shift = shift;
26
25
  };
27
26
  /** Scales the copy's features away from the beginning of the roll, and records the factor. */
28
27
  export const applyScale = (factor, copy) => {
29
- if (copy.ops.includes('stretched'))
28
+ if (copy.measurements.scale !== undefined)
30
29
  return;
31
30
  featuresOf(copy).forEach(feature => stretch(feature.horizontal, factor));
32
- copy.ops = [...copy.ops, 'stretched'];
33
31
  copy.measurements.scale = factor;
34
32
  };
35
33
  /** Takes the shift off the copy's features again, as far as one was applied. */
36
34
  export const revertShift = (copy) => {
37
35
  const shift = copy.measurements.shift;
38
- if (!copy.ops.includes('shifted') || !shift)
36
+ if (!shift)
39
37
  return;
40
38
  const reversed = back(shift);
41
39
  featuresOf(copy).forEach(feature => {
42
40
  move(feature.horizontal, reversed.horizontal);
43
41
  move(feature.vertical, reversed.vertical);
44
42
  });
45
- copy.ops = copy.ops.filter(op => op !== 'shifted');
46
43
  delete copy.measurements.shift;
47
44
  };
48
45
  /** Takes the scale off the copy's features again, as far as one was applied. */
49
46
  export const revertScale = (copy) => {
50
47
  const factor = copy.measurements.scale;
51
- if (!copy.ops.includes('stretched') || factor === undefined)
48
+ if (factor === undefined)
52
49
  return;
53
50
  featuresOf(copy).forEach(feature => stretch(feature.horizontal, 1 / factor));
54
- copy.ops = copy.ops.filter(op => op !== 'stretched');
55
51
  delete copy.measurements.scale;
56
52
  };
57
53
  const chainsOf = (copy) => featuresOf(copy).filter(feature => feature.type === 'HoleChain');
@@ -103,7 +99,7 @@ export const tooShortToShorten = (extension, copy, leaving = new Set()) => chain
103
99
  * extension, `tooShortToShorten` saying beforehand which those are.
104
100
  */
105
101
  export const shortenChains = (extension, copy, leaving = new Set()) => {
106
- if (copy.ops.includes('shortened'))
102
+ if (copy.measurements.readerExtension)
107
103
  return;
108
104
  const tooShort = tooShortToShorten(extension, copy, leaving);
109
105
  if (tooShort.length > 0) {
@@ -115,19 +111,17 @@ export const shortenChains = (extension, copy, leaving = new Set()) => {
115
111
  chainsOf(copy)
116
112
  .filter(chain => !leaving.has(chain.id))
117
113
  .forEach(chain => { chain.horizontal.to = subtract(chain.horizontal.to, extension); });
118
- copy.ops = [...copy.ops, 'shortened'];
119
114
  copy.measurements.readerExtension = { length: extension, ...(left.length > 0 && { leaving: left }) };
120
115
  };
121
116
  /** Puts the reader's extension back on the chains it was taken off, as far as one was taken off. */
122
117
  export const revertShortening = (copy) => {
123
118
  const taken = copy.measurements.readerExtension;
124
- if (!copy.ops.includes('shortened') || taken === undefined)
119
+ if (taken === undefined)
125
120
  return;
126
121
  const left = new Set(taken.leaving ?? []);
127
122
  chainsOf(copy)
128
123
  .filter(chain => !left.has(chain.id))
129
124
  .forEach(chain => { chain.horizontal.to = add(chain.horizontal.to, taken.length); });
130
- copy.ops = copy.ops.filter(op => op !== 'shortened');
131
125
  delete copy.measurements.readerExtension;
132
126
  };
133
127
  const byPlace = (x, y) => x.at - y.at || x.pitch - y.pitch;
@@ -251,7 +245,7 @@ const resultOf = ({ line, matches }) => {
251
245
  * sounds, and it is the pitches that are matched. Where a copy's holes
252
246
  * have already been put onto the edition's bar, that bar reads it.
253
247
  */
254
- export function alignFeatures(rollA, rollB, barA = welteT100, barB = barA) {
248
+ export function alignFeatures(rollA, rollB, barA = defaultTrackerBar, barB = barA) {
255
249
  const a = noteOnsets(rollA, barA);
256
250
  const b = noteOnsets(rollB, barB);
257
251
  const coarse = robustLine(anchors(a, b));
@@ -1,9 +1,9 @@
1
- import { Belief } from "./Assumption.js";
1
+ import { Belief } from "../model/Assumption.js";
2
2
  import { BothEnds, CollationTolerance, Displacement } from "./Collation.js";
3
- import { EditionView } from "./EditionView.js";
4
- import { Millimeters } from "./Quantity.js";
3
+ import { EditionView } from "../view/EditionView.js";
4
+ import { Millimeters } from "../model/Quantity.js";
5
5
  import { Histogram, Spread, Tail } from "./statistics.js";
6
- import { AnySymbol } from "./Symbol.js";
6
+ import { AnySymbol } from "../model/Symbol.js";
7
7
  /**
8
8
  * How far the copies of a roll disagree about where a symbol lies, and
9
9
  * the collation tolerance that follows from it.
@@ -1,9 +1,9 @@
1
1
  import { v4 } from "uuid";
2
2
  import { admits, offsetEndOf, offsetStartOf } from "./Collation.js";
3
- import { mean, mm } from "./Quantity.js";
3
+ import { mean, mm } from "../model/Quantity.js";
4
4
  import { excessKurtosisOf, histogramOf, normalQuantile, spreadOf, standardise, tailOf } from "./statistics.js";
5
- import { groupBy } from "./utils.js";
6
- import { deletedBy, insertedBy } from "./Version.js";
5
+ import { groupBy } from "../shared/utils.js";
6
+ import { deletedBy, insertedBy } from "../model/Version.js";
7
7
  const placeOf = (carriers) => ({
8
8
  from: mean(carriers.map(carrier => carrier.horizontal.from)),
9
9
  to: mean(carriers.map(carrier => carrier.horizontal.to))
@@ -37,7 +37,7 @@ const sitsOn = (view, copies) => (feature) => {
37
37
  export const readingsOf = (view, symbols, copies) => {
38
38
  const tested = sitsOn(view, copies);
39
39
  return symbols.flatMap((symbol) => {
40
- const carriers = view.carriersOf(symbol);
40
+ const carriers = view.placedCarriersOf(symbol);
41
41
  const here = carriers.filter(tested);
42
42
  const there = carriers.filter(carrier => !tested(carrier));
43
43
  if (here.length === 0 || there.length === 0)
@@ -220,12 +220,12 @@ const copiesBearing = (view, symbols) => {
220
220
  * stopped saying and an editor has to.
221
221
  */
222
222
  export const sidesOf = (view, versionId) => {
223
- const version = view.get(versionId);
223
+ const version = view.version(versionId);
224
224
  if (!version)
225
225
  return undefined;
226
226
  return {
227
227
  child: copiesBearing(view, insertedBy(version)),
228
- parent: copiesBearing(view, view.getAll(deletedBy(version)))
228
+ parent: copiesBearing(view, view.symbols(deletedBy(version)))
229
229
  };
230
230
  };
231
231
  const inMillimetres = (value) => `${value.toFixed(2)} mm`;
@@ -1,4 +1,4 @@
1
- import { Quantity } from "./Quantity.js";
1
+ import { Quantity } from "../model/Quantity.js";
2
2
  /**
3
3
  * The statistics a sample of measurements is described with.
4
4
  *
@@ -1,4 +1,4 @@
1
- import { quantity } from "./Quantity.js";
1
+ import { quantity } from "../model/Quantity.js";
2
2
  /**
3
3
  * The statistics a sample of measurements is described with.
4
4
  *
@@ -116,6 +116,6 @@ export const histogramOf = (values, binWidth) => {
116
116
  counts: values.reduce((tally, value) => {
117
117
  tally[Math.min(bins - 1, Math.floor((value - first) / binWidth))] += 1;
118
118
  return tally;
119
- }, new Array(bins).fill(0))
119
+ }, Array.from({ length: bins }, () => 0))
120
120
  };
121
121
  };
@@ -1,29 +1,14 @@
1
1
  import { CollationTolerance, Locate } from "./Collation.js";
2
- import { AnySymbol, Expression } from "./Symbol.js";
3
- import { Millimeters, Track } from "./Quantity.js";
4
- import { TrackerBar } from "./TrackerBar.js";
2
+ import { AnySymbol, Expression } from "../model/Symbol.js";
3
+ import { Millimeters, Track } from "../model/Quantity.js";
4
+ import { Operation, TrackerBar } from "../systems/TrackerBar.js";
5
+ export type { Operation, Spelling } from "../systems/TrackerBar.js";
5
6
  /**
6
- * How a scale words a function: as a command that turns it on, one that
7
- * cancels it, or one that holds it for as long as it lasts.
7
+ * What an expression type operates, as the bar that reads it says, or
8
+ * nothing for a word no bar here knows or one without a counterpart in
9
+ * another scale. The bars share their words where they share a scale,
10
+ * as the Licensee does the T-100's, so the first that reads it answers.
8
11
  */
9
- export type Spelling = 'on' | 'off' | 'held';
10
- /**
11
- * What a word of a scale operates, rather than the word itself, so that
12
- * two scales can be compared at all.
13
- */
14
- export interface Operation {
15
- /** The function operated, named the same wherever a scale has it. */
16
- operates: string;
17
- spelling: Spelling;
18
- /**
19
- * Whether the half of the keyboard the valve serves is part of the
20
- * function operated. The dynamics are per half; the pedals are not,
21
- * and the two Welte scales put them on opposite edges of the paper,
22
- * so a rule that compared sides would leave every pedal unpaired.
23
- */
24
- sided: boolean;
25
- }
26
- /** What an expression type operates, or nothing for a word no scale here knows. */
27
12
  export declare const operationOf: (expressionType: string) => Operation | undefined;
28
13
  /**
29
14
  * A latched function of the older version and the held command of the
@@ -46,7 +31,7 @@ export interface Substitution {
46
31
  * 2.66 mm grid with bridges of about a millimetre, so a scan read hole
47
32
  * by hole shows a run where the paper shows one command.
48
33
  */
49
- export declare const defaultChainGap: import("./Quantity.js").Quantity<"mm">;
34
+ export declare const defaultChainGap: import("../index.js").Quantity<"mm">;
50
35
  /**
51
36
  * The position a bar reads its own command for the same function on,
52
37
  * where it has no word for this one.
@@ -1,44 +1,20 @@
1
1
  import { defaultCollationTolerance } from "./Collation.js";
2
- import { distance, mm, track } from "./Quantity.js";
2
+ import { distance, mm, track } from "../model/Quantity.js";
3
+ import { trackerBars } from "../systems/index.js";
3
4
  /**
4
- * What each Welte expression type operates.
5
- *
6
- * This cannot be read off the names. The T-100 latches a function on
7
- * with one perforation and cancels it with a second, while the T-98
8
- * holds it for as long as one perforation lasts (Hagmann pp. 89 f. and
9
- * 100–103; Phillips p. 121), and Welte renamed two of the functions
10
- * between the scales: the red `SlowCrescendo` is the green `Crescendo`,
11
- * and the red's single `Forzando` valve answers to two green ones that
12
- * name the end they pull towards. So the correspondence is stated here
13
- * rather than derived, and only two types that operate one function can
14
- * stand for each other.
15
- *
16
- * The T-100's `MotorOn`/`MotorOff`, `Rewind` and `ElectricCutOff` are
17
- * left out on purpose: the green scale has no word for any of them, its
18
- * motor switch being an automatic mercury contact (Skala-Rolle 98 §12)
19
- * and its rewind riding on the bass sforzando-piano line. A red command
20
- * of those kinds has no counterpart and stays a plain deletion.
5
+ * What an expression type operates, as the bar that reads it says, or
6
+ * nothing for a word no bar here knows or one without a counterpart in
7
+ * another scale. The bars share their words where they share a scale,
8
+ * as the Licensee does the T-100's, so the first that reads it answers.
21
9
  */
22
- const operations = {
23
- MezzoforteOn: { operates: 'mezzoforte', spelling: 'on', sided: true },
24
- MezzoforteOff: { operates: 'mezzoforte', spelling: 'off', sided: true },
25
- SlowCrescendoOn: { operates: 'crescendo', spelling: 'on', sided: true },
26
- SlowCrescendoOff: { operates: 'crescendo', spelling: 'off', sided: true },
27
- ForzandoOn: { operates: 'sforzando', spelling: 'on', sided: true },
28
- ForzandoOff: { operates: 'sforzando', spelling: 'off', sided: true },
29
- SustainPedalOn: { operates: 'sustainPedal', spelling: 'on', sided: false },
30
- SustainPedalOff: { operates: 'sustainPedal', spelling: 'off', sided: false },
31
- SoftPedalOn: { operates: 'softPedal', spelling: 'on', sided: false },
32
- SoftPedalOff: { operates: 'softPedal', spelling: 'off', sided: false },
33
- Mezzoforte: { operates: 'mezzoforte', spelling: 'held', sided: true },
34
- Crescendo: { operates: 'crescendo', spelling: 'held', sided: true },
35
- SforzandoForte: { operates: 'sforzando', spelling: 'held', sided: true },
36
- SforzandoPiano: { operates: 'sforzando', spelling: 'held', sided: true },
37
- SustainPedal: { operates: 'sustainPedal', spelling: 'held', sided: false },
38
- SoftPedal: { operates: 'softPedal', spelling: 'held', sided: false }
10
+ export const operationOf = (expressionType) => {
11
+ for (const bar of trackerBars) {
12
+ const operation = bar.operationOf(expressionType);
13
+ if (operation)
14
+ return operation;
15
+ }
16
+ return undefined;
39
17
  };
40
- /** What an expression type operates, or nothing for a word no scale here knows. */
41
- export const operationOf = (expressionType) => operations[expressionType];
42
18
  /**
43
19
  * How wide a paper bridge may be for two held perforations to be one
44
20
  * command. The T-98 punches a hold as a chain of round holes on a
@@ -0,0 +1,64 @@
1
+ import { MidiFile } from "midifile-ts";
2
+ import { EditionView } from "../view/EditionView.js";
3
+ import type { TrackerBar } from "../systems/TrackerBar.js";
4
+ import { Version } from "../model/Version.js";
5
+ import { AnyPerformedRollFeature, EmulatedCurve, NegotiatedEvent, ReproducingSystem } from "../systems/ReproducingSystem.js";
6
+ import { Millimeters } from "../model/Quantity.js";
7
+ export type EmulationScope = {
8
+ /** Only notes whose onset lies within this span of the roll are played. */
9
+ range?: [Millimeters, Millimeters];
10
+ /** Start the clock at the first note rather than at the beginning of the roll. */
11
+ skipToFirstNote?: boolean;
12
+ };
13
+ /**
14
+ * The events moved to where their statements put them, the events given
15
+ * left as they were. The view supplies the copies, whose measurements
16
+ * decide how far before or after its reference a command goes, and a
17
+ * punch diameter, or a millimetre, where no copy agrees with a statement.
18
+ */
19
+ export declare const withPlacementsApplied: (view: EditionView, events: readonly NegotiatedEvent[]) => NegotiatedEvent[];
20
+ /**
21
+ * The commands of a version as the bar performs them, in order of place,
22
+ * within the scope and with the placements applied. A note plays only
23
+ * where its onset falls in the range; expressions play throughout.
24
+ */
25
+ export declare const negotiatedEventsOf: (view: EditionView, version: Readonly<Version>, bar: TrackerBar, { range }?: Pick<EmulationScope, 'range'>) => NegotiatedEvent[];
26
+ /** A version performed: what was negotiated, and what the system made of it. */
27
+ export interface Emulated {
28
+ /** The id of the version performed. */
29
+ readonly source: string;
30
+ readonly negotiated: readonly NegotiatedEvent[];
31
+ /** The performed events in order of time, from the origin the scope sets. */
32
+ readonly events: readonly AnyPerformedRollFeature[];
33
+ readonly curves: readonly EmulatedCurve[];
34
+ }
35
+ /**
36
+ * Performs a version on a reproducing system: the symbols are negotiated
37
+ * into placed events and the system plays them. Nothing given is changed.
38
+ */
39
+ export declare const emulate: <Options extends object>(system: ReproducingSystem<Options>, version: Readonly<Version>, view: EditionView, options?: Options, { range, skipToFirstNote }?: EmulationScope) => Emulated;
40
+ /**
41
+ * The performed events as a MIDI file, in which every note and pedal step
42
+ * is labelled with the symbol it performs. The file names the system, the
43
+ * version and the options it was played with.
44
+ */
45
+ export declare const midiOf: (events: readonly AnyPerformedRollFeature[], systemName: string, options: object, source?: string) => MidiFile;
46
+ /**
47
+ * A version of the edition, performed and kept: `emulate` and `midiOf`
48
+ * with the result held on the object between the two calls. Prefer the
49
+ * functions where nothing needs holding.
50
+ */
51
+ export declare class Emulation<Options extends object> {
52
+ readonly system: ReproducingSystem<Options>;
53
+ options: Options;
54
+ midiEvents: AnyPerformedRollFeature[];
55
+ negotiatedEvents: NegotiatedEvent[];
56
+ curves: readonly EmulatedCurve[];
57
+ source?: string;
58
+ constructor(system: ReproducingSystem<Options>, options?: Options);
59
+ /** Moves the negotiated events to where their statements put them; see `withPlacementsApplied`. */
60
+ applyConstraints(view: EditionView): void;
61
+ emulateVersion(version: Version, view: EditionView, scope?: EmulationScope): AnyPerformedRollFeature[];
62
+ findEventsPerforming(id: string): AnyPerformedRollFeature[];
63
+ asMIDI(): MidiFile;
64
+ }