linked-rolls 0.8.0 → 0.9.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/lib/schema.json CHANGED
@@ -194,15 +194,15 @@
194
194
  "type": "string"
195
195
  },
196
196
  "CollationTolerance": {
197
- "description": "Tolerance used in collation of roll copies. The start and end tolerances define the acceptable deviation (in mm) when aligning features across copies.",
197
+ "description": "Tolerance used in collation of roll copies: the acceptable deviation at either end when aligning features across copies.",
198
198
  "properties": {
199
199
  "toleranceEnd": {
200
- "description": "Tolerance at the end position of a feature (in mm).",
201
- "type": "number"
200
+ "$ref": "#/definitions/Millimeters",
201
+ "description": "Tolerance at the end position of a feature."
202
202
  },
203
203
  "toleranceStart": {
204
- "description": "Tolerance at the start position of a feature (in mm).",
205
- "type": "number"
204
+ "$ref": "#/definitions/Millimeters",
205
+ "description": "Tolerance at the start position of a feature."
206
206
  }
207
207
  },
208
208
  "required": [
@@ -648,12 +648,12 @@
648
648
  "description": "Describes the horizontal extent of a feature on the roll, measured in millimeters from the beginning of the roll. The `from` value is the start position and `to` is the end position. [ontology: crm:E54 Dimension]",
649
649
  "properties": {
650
650
  "from": {
651
- "description": "The start position of the feature in millimeters from the beginning of the roll. [ontology: reo:from]",
652
- "type": "number"
651
+ "$ref": "#/definitions/Millimeters",
652
+ "description": "The start position of the feature in millimeters from the beginning of the roll. [ontology: reo:from]"
653
653
  },
654
654
  "to": {
655
- "description": "The end position of the feature in millimeters from the beginning of the roll. [ontology: reo:to]",
656
- "type": "number"
655
+ "$ref": "#/definitions/Millimeters",
656
+ "description": "The end position of the feature in millimeters from the beginning of the roll. [ontology: reo:to]"
657
657
  },
658
658
  "unit": {
659
659
  "const": "mm",
@@ -699,6 +699,48 @@
699
699
  ],
700
700
  "type": "object"
701
701
  },
702
+ "Margins<\"mm\">": {
703
+ "description": "The margins on the treble and bass sides of the roll, in the unit the scan was measured in.",
704
+ "properties": {
705
+ "bass": {
706
+ "$ref": "#/definitions/Quantity%3C%22mm%22%3E"
707
+ },
708
+ "treble": {
709
+ "$ref": "#/definitions/Quantity%3C%22mm%22%3E"
710
+ },
711
+ "unit": {
712
+ "const": "mm",
713
+ "type": "string"
714
+ }
715
+ },
716
+ "required": [
717
+ "treble",
718
+ "bass",
719
+ "unit"
720
+ ],
721
+ "type": "object"
722
+ },
723
+ "Margins<\"px\">": {
724
+ "description": "The margins on the treble and bass sides of the roll, in the unit the scan was measured in.",
725
+ "properties": {
726
+ "bass": {
727
+ "$ref": "#/definitions/Quantity%3C%22px%22%3E"
728
+ },
729
+ "treble": {
730
+ "$ref": "#/definitions/Quantity%3C%22px%22%3E"
731
+ },
732
+ "unit": {
733
+ "const": "px",
734
+ "type": "string"
735
+ }
736
+ },
737
+ "required": [
738
+ "treble",
739
+ "bass",
740
+ "unit"
741
+ ],
742
+ "type": "object"
743
+ },
702
744
  "Mark": {
703
745
  "description": "A visible mark on the roll, such as a pencil mark, ink mark, or other non-textual annotation. [ontology: crm:E25 Human-Made Feature]",
704
746
  "properties": {
@@ -768,6 +810,48 @@
768
810
  ],
769
811
  "type": "object"
770
812
  },
813
+ "Measure<\"mm\">": {
814
+ "description": "A value together with the unit it was measured in, as a record states it. [ontology: crm:E54 Dimension]",
815
+ "properties": {
816
+ "unit": {
817
+ "const": "mm",
818
+ "description": "The unit of measurement. [ontology: crm:P91 has unit]",
819
+ "type": "string"
820
+ },
821
+ "value": {
822
+ "$ref": "#/definitions/Quantity%3C%22mm%22%3E",
823
+ "description": "The measured value. [ontology: crm:P90 has value]"
824
+ }
825
+ },
826
+ "required": [
827
+ "value",
828
+ "unit"
829
+ ],
830
+ "type": "object"
831
+ },
832
+ "Measure<\"px\">": {
833
+ "description": "A value together with the unit it was measured in, as a record states it. [ontology: crm:E54 Dimension]",
834
+ "properties": {
835
+ "unit": {
836
+ "const": "px",
837
+ "description": "The unit of measurement. [ontology: crm:P91 has unit]",
838
+ "type": "string"
839
+ },
840
+ "value": {
841
+ "$ref": "#/definitions/Quantity%3C%22px%22%3E",
842
+ "description": "The measured value. [ontology: crm:P90 has value]"
843
+ }
844
+ },
845
+ "required": [
846
+ "value",
847
+ "unit"
848
+ ],
849
+ "type": "object"
850
+ },
851
+ "Millimeters": {
852
+ "$ref": "#/definitions/Quantity%3C%22mm%22%3E",
853
+ "description": "A place along the roll, or any length on the paper."
854
+ },
771
855
  "Modification": {
772
856
  "anyOf": [
773
857
  {
@@ -1208,45 +1292,91 @@
1208
1292
  "type": "object"
1209
1293
  },
1210
1294
  "ObjectAssumption<RollTempo>": {
1211
- "description": "An object assumption wraps a complex object with an optional annotation. Used for structured values (e.g. persons, conditions) whose properties may be uncertain.",
1212
- "properties": {
1213
- "@annotation": {
1214
- "description": "An optional annotation expressing a belief about this assumption. Uses the JSON-LD-star `@annotation` mechanism to attach epistemic metadata (certainty and reasons) to any triple.",
1295
+ "anyOf": [
1296
+ {
1215
1297
  "properties": {
1216
- "belief": {
1217
- "$ref": "#/definitions/Belief",
1218
- "description": "The belief held about the annotated statement. [ontology: crminf:J4i is subject of]"
1298
+ "@annotation": {
1299
+ "description": "An optional annotation expressing a belief about this assumption. Uses the JSON-LD-star `@annotation` mechanism to attach epistemic metadata (certainty and reasons) to any triple.",
1300
+ "properties": {
1301
+ "belief": {
1302
+ "$ref": "#/definitions/Belief",
1303
+ "description": "The belief held about the annotated statement. [ontology: crminf:J4i is subject of]"
1304
+ },
1305
+ "@id": {
1306
+ "description": "A unique identifier for this object.",
1307
+ "type": "string"
1308
+ }
1309
+ },
1310
+ "required": [
1311
+ "belief",
1312
+ "@id"
1313
+ ],
1314
+ "type": "object"
1219
1315
  },
1220
- "@id": {
1221
- "description": "A unique identifier for this object.",
1316
+ "endsWith": {
1317
+ "$ref": "#/definitions/Quantity%3C%22ft%2Fmin%22%3E",
1318
+ "description": "The tempo at the end of the roll. [ontology: reo:to]"
1319
+ },
1320
+ "startsWith": {
1321
+ "$ref": "#/definitions/Quantity%3C%22ft%2Fmin%22%3E",
1322
+ "description": "The tempo at the beginning of the roll. [ontology: reo:from]"
1323
+ },
1324
+ "unit": {
1325
+ "const": "ft/min",
1326
+ "description": "The unit of the tempo measurement. [ontology: crm:P91 has unit]",
1222
1327
  "type": "string"
1223
1328
  }
1224
1329
  },
1225
1330
  "required": [
1226
- "belief",
1227
- "@id"
1331
+ "endsWith",
1332
+ "startsWith",
1333
+ "unit"
1228
1334
  ],
1229
1335
  "type": "object"
1230
1336
  },
1231
- "endsWith": {
1232
- "description": "The tempo at the end of the roll. [ontology: reo:to]",
1233
- "type": "number"
1234
- },
1235
- "startsWith": {
1236
- "description": "The tempo at the beginning of the roll. [ontology: reo:from]",
1237
- "type": "number"
1238
- },
1239
- "unit": {
1240
- "description": "The unit of the tempo measurement (e.g. 'ft/min', 'm/min'). [ontology: crm:P91 has unit]",
1241
- "type": "string"
1337
+ {
1338
+ "properties": {
1339
+ "@annotation": {
1340
+ "description": "An optional annotation expressing a belief about this assumption. Uses the JSON-LD-star `@annotation` mechanism to attach epistemic metadata (certainty and reasons) to any triple.",
1341
+ "properties": {
1342
+ "belief": {
1343
+ "$ref": "#/definitions/Belief",
1344
+ "description": "The belief held about the annotated statement. [ontology: crminf:J4i is subject of]"
1345
+ },
1346
+ "@id": {
1347
+ "description": "A unique identifier for this object.",
1348
+ "type": "string"
1349
+ }
1350
+ },
1351
+ "required": [
1352
+ "belief",
1353
+ "@id"
1354
+ ],
1355
+ "type": "object"
1356
+ },
1357
+ "endsWith": {
1358
+ "$ref": "#/definitions/Quantity%3C%22m%2Fmin%22%3E",
1359
+ "description": "The tempo at the end of the roll. [ontology: reo:to]"
1360
+ },
1361
+ "startsWith": {
1362
+ "$ref": "#/definitions/Quantity%3C%22m%2Fmin%22%3E",
1363
+ "description": "The tempo at the beginning of the roll. [ontology: reo:from]"
1364
+ },
1365
+ "unit": {
1366
+ "const": "m/min",
1367
+ "description": "The unit of the tempo measurement. [ontology: crm:P91 has unit]",
1368
+ "type": "string"
1369
+ }
1370
+ },
1371
+ "required": [
1372
+ "endsWith",
1373
+ "startsWith",
1374
+ "unit"
1375
+ ],
1376
+ "type": "object"
1242
1377
  }
1243
- },
1244
- "required": [
1245
- "endsWith",
1246
- "startsWith",
1247
- "unit"
1248
1378
  ],
1249
- "type": "object"
1379
+ "description": "An object assumption wraps a complex object with an optional annotation. Used for structured values (e.g. persons, conditions) whose properties may be uncertain."
1250
1380
  },
1251
1381
  "ObjectAssumption<Transcription>": {
1252
1382
  "description": "An object assumption wraps a complex object with an optional annotation. Used for structured values (e.g. persons, conditions) whose properties may be uncertain.",
@@ -1305,6 +1435,10 @@
1305
1435
  "$ref": "#/definitions/Agent",
1306
1436
  "description": "An agent that is a person."
1307
1437
  },
1438
+ "Pixels": {
1439
+ "$ref": "#/definitions/Quantity%3C%22px%22%3E",
1440
+ "description": "A place in a scan. Comparable within one scan only, since the resolution is the scan's."
1441
+ },
1308
1442
  "Place": {
1309
1443
  "description": "A place, e.g. a recording location, publishing location, etc. [ontology: crm:E53 Place]",
1310
1444
  "properties": {
@@ -1347,6 +1481,21 @@
1347
1481
  },
1348
1482
  "type": "object"
1349
1483
  },
1484
+ "Quantity<\"ft/min\">": {
1485
+ "type": "number"
1486
+ },
1487
+ "Quantity<\"m/min\">": {
1488
+ "type": "number"
1489
+ },
1490
+ "Quantity<\"mm\">": {
1491
+ "type": "number"
1492
+ },
1493
+ "Quantity<\"px\">": {
1494
+ "type": "number"
1495
+ },
1496
+ "Quantity<\"track\">": {
1497
+ "type": "number"
1498
+ },
1350
1499
  "RecordingEvent": {
1351
1500
  "description": "Describes the event of recording and documents the persons involved in the process (e.g. pianist), the place, and the date of the recording. [ontology: lrmoo:F28 Expression Creation]",
1352
1501
  "properties": {
@@ -1477,16 +1626,17 @@
1477
1626
  "description": "The physical dimensions of the roll. [ontology: reo:dimensions]",
1478
1627
  "properties": {
1479
1628
  "height": {
1480
- "description": "The total height (length) of the roll in the given unit. [ontology: reo:height]",
1481
- "type": "number"
1629
+ "$ref": "#/definitions/Millimeters",
1630
+ "description": "The total height (length) of the roll. [ontology: reo:height]"
1482
1631
  },
1483
1632
  "unit": {
1484
- "description": "The unit of measurement (e.g. 'mm'). [ontology: crm:P91 has unit]",
1633
+ "const": "mm",
1634
+ "description": "The unit of measurement. [ontology: crm:P91 has unit]",
1485
1635
  "type": "string"
1486
1636
  },
1487
1637
  "width": {
1488
- "description": "The width of the roll in the given unit. [ontology: reo:width]",
1489
- "type": "number"
1638
+ "$ref": "#/definitions/Millimeters",
1639
+ "description": "The width of the roll. [ontology: reo:width]"
1490
1640
  }
1491
1641
  },
1492
1642
  "required": [
@@ -1497,45 +1647,26 @@
1497
1647
  "type": "object"
1498
1648
  },
1499
1649
  "holeSeparation": {
1500
- "description": "The distance between adjacent tracker bar holes. [ontology: reo:holeSeparation]",
1501
- "properties": {
1502
- "unit": {
1503
- "description": "The unit of measurement (e.g. 'px', 'mm'). [ontology: crm:P91 has unit]",
1504
- "type": "string"
1650
+ "anyOf": [
1651
+ {
1652
+ "$ref": "#/definitions/Measure%3C%22px%22%3E"
1505
1653
  },
1506
- "value": {
1507
- "description": "The measured hole separation value. [ontology: crm:P90 has value]",
1508
- "type": "number"
1654
+ {
1655
+ "$ref": "#/definitions/Measure%3C%22mm%22%3E"
1509
1656
  }
1510
- },
1511
- "required": [
1512
- "value",
1513
- "unit"
1514
1657
  ],
1515
- "type": "object"
1658
+ "description": "The distance between adjacent tracker bar holes, in the unit the scan was measured in. [ontology: reo:holeSeparation]"
1516
1659
  },
1517
1660
  "margins": {
1518
- "description": "The margins on the treble and bass sides of the roll. Not exported to RDF.",
1519
- "properties": {
1520
- "bass": {
1521
- "description": "The margin on the bass side.",
1522
- "type": "number"
1661
+ "anyOf": [
1662
+ {
1663
+ "$ref": "#/definitions/Margins%3C%22px%22%3E"
1523
1664
  },
1524
- "treble": {
1525
- "description": "The margin on the treble side.",
1526
- "type": "number"
1527
- },
1528
- "unit": {
1529
- "description": "The unit of measurement (e.g. 'px', 'mm').",
1530
- "type": "string"
1665
+ {
1666
+ "$ref": "#/definitions/Margins%3C%22mm%22%3E"
1531
1667
  }
1532
- },
1533
- "required": [
1534
- "treble",
1535
- "bass",
1536
- "unit"
1537
1668
  ],
1538
- "type": "object"
1669
+ "description": "The margins on the treble and bass sides of the roll. Not exported to RDF."
1539
1670
  },
1540
1671
  "measuredBy": {
1541
1672
  "description": "Information about the software used to take the measurements. [ontology: crmdig:L23 used software or firmware]",
@@ -1562,22 +1693,8 @@
1562
1693
  "type": "object"
1563
1694
  },
1564
1695
  "punchDiameter": {
1565
- "description": "The average diameter of punched holes. [ontology: reo:punchDiameter]",
1566
- "properties": {
1567
- "unit": {
1568
- "description": "The unit of measurement (e.g. 'mm'). [ontology: crm:P91 has unit]",
1569
- "type": "string"
1570
- },
1571
- "value": {
1572
- "description": "The measured punch diameter value. [ontology: crm:P90 has value]",
1573
- "type": "number"
1574
- }
1575
- },
1576
- "required": [
1577
- "value",
1578
- "unit"
1579
- ],
1580
- "type": "object"
1696
+ "$ref": "#/definitions/Measure%3C%22mm%22%3E",
1697
+ "description": "The average diameter of punched holes. [ontology: reo:punchDiameter]"
1581
1698
  },
1582
1699
  "shift": {
1583
1700
  "$ref": "#/definitions/Shift",
@@ -1643,12 +1760,12 @@
1643
1760
  "description": "A shift correction applied to a roll copy to align it with other copies. The shift is defined as horizontal (along the roll length, in mm) and vertical (across tracks).",
1644
1761
  "properties": {
1645
1762
  "horizontal": {
1646
- "description": "Horizontal shift in millimeters (along the roll length).",
1647
- "type": "number"
1763
+ "$ref": "#/definitions/Millimeters",
1764
+ "description": "Along the roll."
1648
1765
  },
1649
1766
  "vertical": {
1650
- "description": "Vertical shift in track numbers (across the tracker bar).",
1651
- "type": "number"
1767
+ "$ref": "#/definitions/Track",
1768
+ "description": "Across the tracker bar."
1652
1769
  }
1653
1770
  },
1654
1771
  "required": [
@@ -1690,20 +1807,24 @@
1690
1807
  ],
1691
1808
  "type": "object"
1692
1809
  },
1810
+ "Track": {
1811
+ "$ref": "#/definitions/Quantity%3C%22track%22%3E",
1812
+ "description": "A position across the roll, numbered as the tracker bar does."
1813
+ },
1693
1814
  "TrackCalibration": {
1694
1815
  "description": "Relates a scan to the tracker bar it was read with.\n\nScanning software numbers the hole columns it finds by their position in the image, so its numbering is offset by however far the roll lay from the edge of the scanner bed. Calibrating means finding that offset, usually from a landmark such as the rewind perforation.\n\n column = offset + scannerTrack * separation trackerBar = scannerTrack + shift",
1695
1816
  "properties": {
1696
1817
  "offset": {
1697
- "description": "Image column of the scanning software's track 0.",
1698
- "type": "number"
1818
+ "$ref": "#/definitions/Pixels",
1819
+ "description": "Image column of the scanning software's track 0."
1699
1820
  },
1700
1821
  "separation": {
1701
- "description": "Distance between the centres of adjacent tracks.",
1702
- "type": "number"
1822
+ "$ref": "#/definitions/Pixels",
1823
+ "description": "Distance between the centres of adjacent tracks."
1703
1824
  },
1704
1825
  "shift": {
1705
- "description": "Added to the scanning software's numbering to reach the tracker bar.",
1706
- "type": "number"
1826
+ "$ref": "#/definitions/Track",
1827
+ "description": "Added to the scanning software's numbering to reach the tracker bar."
1707
1828
  },
1708
1829
  "unit": {
1709
1830
  "const": "px",
@@ -1780,12 +1901,12 @@
1780
1901
  "description": "Describes the vertical extent of a feature on the roll, measured in track numbers. Track numbers correspond to positions on the tracker bar. [ontology: crm:E54 Dimension]",
1781
1902
  "properties": {
1782
1903
  "from": {
1783
- "description": "The start track number of the feature. [ontology: reo:from]",
1784
- "type": "number"
1904
+ "$ref": "#/definitions/Track",
1905
+ "description": "The start track number of the feature. [ontology: reo:from]"
1785
1906
  },
1786
1907
  "to": {
1787
- "description": "The end track number, if the feature spans multiple tracks. If omitted, the feature occupies a single track. [ontology: reo:to]",
1788
- "type": "number"
1908
+ "$ref": "#/definitions/Track",
1909
+ "description": "The end track number, if the feature spans multiple tracks. If omitted, the feature occupies a single track. [ontology: reo:to]"
1789
1910
  },
1790
1911
  "unit": {
1791
1912
  "const": "track",
@@ -1,4 +1,5 @@
1
1
  import { describeTrackerBar } from "../../TrackerBar";
2
+ import { mm } from "../../Quantity";
2
3
  /**
3
4
  * The commands of the Welte-Mignon T-100, as its tracker bar reads them.
4
5
  */
@@ -28,7 +29,7 @@ export const welteT100ExpressionTypes = [
28
29
  export const welteT100 = describeTrackerBar({
29
30
  id: 'welte-t100',
30
31
  name: 'Welte-Mignon T100',
31
- width: 328,
32
+ width: mm(328),
32
33
  trackCount: 100,
33
34
  notes: { from: 11, to: 90, lowestPitch: 24 },
34
35
  expressions: new Map([
@@ -1,5 +1,6 @@
1
1
  import { Half, Instrument, Parameters, PedalMode, RollNumber, Spool } from "welte-t100-emulator";
2
2
  import { ReproducingSystem } from "../../ReproducingSystem";
3
+ import { Millimeters, Seconds, Track } from "../../Quantity";
3
4
  /**
4
5
  * MIDI velocity at the open rail of the Nuancierbalg, at the Mezzoforte pin,
5
6
  * and at the closed rail, joined linearly in between. Nothing in the
@@ -59,21 +60,21 @@ export type WelteT100Options = {
59
60
  * understands.
60
61
  */
61
62
  pedalMode: PedalMode;
62
- /** Diameter of the tracker-bar bore, in mm. */
63
- trackerBore: number;
64
- /** Punch diameter in mm, for an edition whose copies record none. */
65
- punchDiameter: number;
63
+ /** Diameter of the tracker-bar bore. */
64
+ trackerBore: Millimeters;
65
+ /** Punch diameter for an edition whose copies record none. */
66
+ punchDiameter: Millimeters;
66
67
  /**
67
68
  * The track at which the keyboard is divided, so that notes from
68
69
  * here upwards follow the treble expression and the ones below it
69
70
  * the bass. Which side an expression perforation itself belongs to
70
71
  * is not decided here but read off the tracker bar.
71
72
  */
72
- division: number;
73
+ division: Track;
73
74
  };
74
75
  export declare const defaultWelteT100Options: WelteT100Options;
75
- /** When the spool brings a place on the roll, in mm, to the tracker bar. */
76
- export declare const secondsAt: (spool: Spool, mm: number) => number;
76
+ /** When the spool brings a place on the roll to the tracker bar. */
77
+ export declare const secondsAt: (spool: Spool, place: Millimeters) => Seconds;
77
78
  /**
78
79
  * The red Welte, as welte-t100-emulator models it: the take-up spool sets
79
80
  * the time axis, the Nuancierbälge fill through their conduits and are
@@ -1,5 +1,6 @@
1
1
  import { aperturePorts, CONSENSUS, DEFAULT_PUNCH_MM, geometryInMm, Grid, levelChanges, mezzoforteTravel, paperSeconds, pedalBrushing, pedalDefaults, pneumaticModel, PRESETS, ROWS_PER_MM, runPedals, TRACKER_BORE_MM, travelBetweenRails, WELTE_SPOOL, } from "welte-t100-emulator";
2
2
  import { welteT100 } from "./bar";
3
+ import { add, inCentimeters, mm, seconds, track } from "../../Quantity";
3
4
  /**
4
5
  * The instruments the emulator was fitted as: the consensus over the six
5
6
  * rolls with drawn nuance lines, and the setting that drew each of them,
@@ -35,9 +36,9 @@ export const defaultWelteT100Options = {
35
36
  pedals: pedalPresets.damping,
36
37
  velocity: { piano: 35, mezzoforte: 60, forte: 90 },
37
38
  pedalMode: 'continuous',
38
- trackerBore: TRACKER_BORE_MM,
39
- punchDiameter: DEFAULT_PUNCH_MM,
40
- division: 54
39
+ trackerBore: mm(TRACKER_BORE_MM),
40
+ punchDiameter: mm(DEFAULT_PUNCH_MM),
41
+ division: track(54)
41
42
  };
42
43
  /** What each expression code operates, in the emulator's terms. */
43
44
  const CODES = {
@@ -59,7 +60,7 @@ const CODES = {
59
60
  const isWelteT100ExpressionType = (type) => Object.hasOwn(CODES, type);
60
61
  const codeOf = (expressionType) => isWelteT100ExpressionType(expressionType) ? CODES[expressionType] : undefined;
61
62
  /** Paper the grid runs on past the last hole, so that a final pedal release completes. */
62
- const RUN_OUT_MM = 100;
63
+ const RUN_OUT = mm(100);
63
64
  /**
64
65
  * Which stack of valves an expression perforation belongs to. The symbol
65
66
  * usually says so, having been read off the tracker bar already; where it
@@ -74,9 +75,11 @@ const scopeOf = (event) => {
74
75
  };
75
76
  const isNote = (event) => event.type === 'note';
76
77
  const isExpression = (event) => event.type === 'expression';
77
- const rowOf = (mm) => mm * ROWS_PER_MM;
78
- /** When the spool brings a place on the roll, in mm, to the tracker bar. */
79
- export const secondsAt = (spool, mm) => paperSeconds(spool, mm / 10);
78
+ /** The row of the scan the constants were fitted on that a place on the roll falls in. */
79
+ const rowOf = (place) => place * ROWS_PER_MM;
80
+ const placeOfRow = (row) => mm(row / ROWS_PER_MM);
81
+ /** When the spool brings a place on the roll to the tracker bar. */
82
+ export const secondsAt = (spool, place) => seconds(paperSeconds(spool, inCentimeters(place)));
80
83
  const halfOf = (note, division) => note.vertical.from >= division ? 'treble' : 'bass';
81
84
  const readingOf = (event) => {
82
85
  const code = codeOf(event.expressionType);
@@ -108,10 +111,10 @@ const velocityOf = (travel, hook, map) => {
108
111
  * emulator expects.
109
112
  */
110
113
  const gridOver = (events, spool) => {
111
- const lastMm = events.reduce((furthest, event) => Math.max(furthest, event.horizontal.to), 0);
112
- const length = Math.ceil(rowOf(lastMm + RUN_OUT_MM)) + 1;
113
- const seconds = Float64Array.from({ length }, (_, row) => secondsAt(spool, row / ROWS_PER_MM));
114
- return new Grid(0, seconds);
114
+ const last = mm(events.reduce((furthest, event) => Math.max(furthest, event.horizontal.to), 0));
115
+ const length = Math.ceil(rowOf(add(last, RUN_OUT))) + 1;
116
+ const times = Float64Array.from({ length }, (_, row) => secondsAt(spool, placeOfRow(row)));
117
+ return new Grid(0, times);
115
118
  };
116
119
  const nuanceCurves = (grid, ports, samples, options) => {
117
120
  const curveOf = (half) => {
@@ -162,7 +165,7 @@ const performPedal = (type, curve, grid, readings, mode) => {
162
165
  type,
163
166
  performs: causeOf(grid.rowAt(change.index)),
164
167
  value: change.value,
165
- at: curve.seconds[change.index]
168
+ at: seconds(curve.seconds[change.index])
166
169
  }));
167
170
  };
168
171
  /**
@@ -179,7 +182,7 @@ const perform = (events, options, roll) => {
179
182
  const geometry = geometryInMm(roll.punchDiameter ?? options.punchDiameter, options.trackerBore);
180
183
  const ports = aperturePorts(grid, readings.map(reading => reading.punch), geometry);
181
184
  const samples = {
182
- place: Float64Array.from(grid.seconds, (_, row) => row / ROWS_PER_MM),
185
+ place: Float64Array.from(grid.seconds, (_, row) => placeOfRow(row)),
183
186
  seconds: grid.seconds
184
187
  };
185
188
  const nuance = nuanceCurves(grid, ports, samples, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linked-rolls",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Digital editions of piano rolls: import, collation, editorial assumptions, JSON-LD export, and emulation through a reproducing system",
5
5
  "license": "MIT",
6
6
  "repository": {