import { Grid, Half, Model, ModelInput, Parameters, PedalInput, PedalMode, PedalTravel, PortGeometry, Spool } from "welte-mignon-emulator"; import { Expression } from "../model/Symbol.js"; import { NegotiatedEvent, Performance, RollProperties } from "./ReproducingSystem.js"; import { MetersPerMinute, Millimeters, Seconds, Track } from "../model/Quantity.js"; import { type VelocityMap } from "./velocity.js"; /** * What the Welte systems share downstream of the relay. Hagmann has the * nuancing unit built the same for both tracker scales (p. 96) and the valves * and bellows that move the pedals the same in both (p. 106), so the way a * performance is read off the emulator is one; what differs is in front of it, * and each system says that in the `Mechanism` it hands to `performWelte`. */ /** * The options every Welte system takes. * @category Systems and emulation */ export type WelteOptions = { /** * The take-up spool, which sets the time axis: it is held at a constant * rate of revolution, so the paper runs faster as the spool fills. * Where a speed is stated for the version's copies, or a re-cut is timed * by the roll it was made from, the spool is started at that speed and * only its geometry is taken from here; see `spoolFor`. */ spool: Spool; /** Constants of the nuancing mechanism, one set for each half of the keyboard. */ nuance: Record; /** Constants of the two pedal actions, one of `pedalPresets` or a set of one's own. */ pedals: Parameters; velocity: VelocityMap; /** * How the pedals go out: as a continuous controller carrying the travel * of the bellows, or thresholded to the two values a switching renderer * understands. */ pedalMode: PedalMode; /** Diameter of the tracker-bar bore. */ trackerBore: Millimeters; /** Punch diameter for an edition whose copies record none. */ punchDiameter: Millimeters; /** * The track at which the keyboard is divided, so that notes from here * upwards follow the treble expression and the ones below it the bass. * Which side an expression perforation itself belongs to is not decided * here but read off the tracker bar. */ division: Track; }; /** Whether two sets of constants are the same, value for value. */ export declare const sameParameters: (a: Parameters, b: Parameters) => boolean; /** * The two readings of the pedal mechanism the emulator offers, by name, * which the systems share: Hagmann has the valves and bellows that carry * out the movements "in beiden Systemen dieselbe" (p. 106), and only the * Vorpneumatik differs. Under `damping` the dampers reach the strings * within the shortest lift the rolls punch, so every lift damps. Under * `brushing` their fall is slowed until the quick runs of latch changes * in the SUPRA corpus dip without damping, at the price that lifts * shorter than about 265 ms brush as well. * @category Systems and emulation */ export declare const pedalPresets: { damping: Readonly>; brushing: Readonly>; }; /** * The name of one of the readings of the pedal mechanism, `damping` or * `brushing`. * @category Systems and emulation */ export type PedalPreset = keyof typeof pedalPresets; /** * The preset a set of pedal constants is, if it is one. * @category Systems and emulation */ export declare const pedalPresetOf: (pedals: Parameters) => PedalPreset | undefined; /** * Between the edition's shared place axis and this version's own paper. * `toOwnPaper` is 1 for a version on the axis it was measured on, and about * 0.775 for a green version whose places are in the red axis; see * `RollProperties`. * * Rows are rows of the version's own paper, so the spool is asked in * `paperOfRow` and never in `placeOfRow`: one is the paper that passes the * tracker bar, the other is the coordinate the edition states. A place is * put to the spool through `paperOfPlace` for the same reason, so that a * note sounds on the clock its pedal and bellows run on. */ export type Paper = { readonly rowOf: (place: Millimeters) => number; readonly placeOfRow: (row: number) => Millimeters; readonly paperOfRow: (row: number) => Millimeters; readonly paperOfPlace: (place: Millimeters) => Millimeters; }; /** * When the spool brings a place on the roll to the tracker bar. * @category Systems and emulation */ export declare const secondsAt: (spool: Spool, place: Millimeters) => Seconds; /** The speed the spool starts the paper at. */ export declare const startingSpeedOf: (spool: Spool) => MetersPerMinute; /** * The spool a version runs on. * * A speed stated for the version's copies is where it starts, as a tempo * marking is the speed at the beginning of the roll. Failing that, a system * whose spool is a reading of its own instruments runs on it as it stands: * the red and the green spool are both calibrated at Welte's Tempo 70. A * system with no spool of its own, as the Licensee has none, times a re-cut * by the roll it was re-cut from, at that roll's stated speed or else the * spool's own, shortened by the length ratio, so that it sounds at the tempo * of the original. Where none of this applies the spool stands as given. */ export declare const spoolFor: (spool: Spool, roll: RollProperties, ownSpool: boolean) => Spool; /** A perforation as the emulator reads it: the control it operates and the rows it spans. */ export type WeltePunch = { readonly half: Half; readonly control: string; readonly rowOn: number; readonly rowOff: number; }; export type Ports = ModelInput['ports']; /** * What a Welte system puts in front of the shared nuancing unit and pedals: * how it reads a perforation, how it opens the ports, which pneumatic model * drives the bellows, and which the pedals. */ export type Mechanism

= { /** The punch the expression is read as, or nothing for one the mechanism does not read. */ readonly punchOf: (event: NegotiatedEvent & Expression, rows: { rowOn: number; rowOff: number; }) => P | undefined; readonly portsOf: (grid: Grid, punches: readonly P[], geometry: PortGeometry) => Ports; readonly model: Model; readonly runPedals: (input: PedalInput, params: Parameters) => PedalTravel; /** * Whether the spool in the options is a reading of this system's own * instruments. Where it is not, a re-cut is timed by the roll it was * re-cut from (`spoolFor`). */ readonly ownSpool: boolean; /** The name of the instrument the curves say they came from. */ readonly instrument: string; }; /** A performance, with the grid and ports it was read off, for a system that has more to ask of them. */ export type WeltePerformance = Performance & { readonly grid: Grid; readonly ports: Ports; }; /** * Plays the events on a Welte mechanism: notes at the velocity of their half's * bellows, and the two pedals as the travel of theirs, on the spool * `spoolFor` gives the version. */ export declare const performWelte:

(events: readonly NegotiatedEvent[], options: WelteOptions, roll: RollProperties, mechanism: Mechanism

) => WeltePerformance;