-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsetBpm.js
More file actions
26 lines (23 loc) · 1.32 KB
/
setBpm.js
File metadata and controls
26 lines (23 loc) · 1.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// setBpm.js - Emit BPM MIDI event and recompute spMeasure.
// Single responsibility: BPM changes. Always emits set_bpm to active buffer.
// Split from midiTiming.js for SRP (R43).
// Freezes timing snapshot after computation (R44 -- fail fast on mutation).
/** @type {{ effectiveBpm: number, spMeasure: number, bpmScale: number } | null} */
let lastBpmSnapshot = null;
setBpm = () => {
if (!Number.isFinite(BPM) || BPM <= 0) {
throw new Error('setBpm: BPM must be a positive finite number, got ' + BPM);
}
const effectiveBpm = BPM * (Number.isFinite(sectionBpmScale) ? sectionBpmScale : 1.0);
spMeasure = (60 / effectiveBpm) * 4 * meterRatio;
if (!Number.isFinite(spMeasure) || spMeasure <= 0) {
throw new Error('setBpm: invalid spMeasure ' + spMeasure + ' from BPM=' + BPM + ' meterRatio=' + meterRatio);
}
p(c, { timeInSeconds: measureStartTime, type: 'bpm', vals: [effectiveBpm] });
L0.post(L0_CHANNELS.tickDuration, LM.activeLayer || 'shared', measureStartTime, {
oneTickInSeconds: 60 / (effectiveBpm * PPQ), effectiveBpm, bpmScale: sectionBpmScale
});
lastBpmSnapshot = deepFreeze({ effectiveBpm, spMeasure, bpmScale: Number.isFinite(sectionBpmScale) ? sectionBpmScale : 1.0 });
};
/** @returns {{ effectiveBpm: number, spMeasure: number, bpmScale: number } | null} */
setBpm.getSnapshot = () => lastBpmSnapshot;