The tracks to analyse.
Analysis options; see ArrangementOptions.
A session holding the analysis and the evidence behind it.
import { createArrangementSession } from '@libraz/libcantus';
const melody = [{ pitch: 60, startBeat: 0, durationBeat: 4 }];
const session = createArrangementSession([{ role: 'melody', notes: melody }]);
const moved = [{ pitch: 62, startBeat: 0, durationBeat: 4 }];
const next = session.update([{ trackIndex: 0, notes: moved }]);
next.analysis.timeline.segments; // as if analyzed from scratch
Open an arrangement analysis that can be updated a few beats at a time.
The first pass is an ordinary analyzeArrangement; what the session adds is the slot-level evidence behind it, so a later ArrangementSession.update can work out which beats an edit could possibly have changed and leave the rest of the harmony alone. An update returns a new session, so the analysis before an edit stays valid and a host can keep it for undo.
What an update recomputes is derived rather than guessed at:
Key regions and the per-note annotations are recomputed in full. Both are whole-piece passes — the key search is a shortest-path search with no reset points, sub-voice lane assignment is greedy from the first note, and every note is judged against the other voices sounding beneath it — so neither has a sound local answer, and reporting one would mean an update that quietly disagreed with a fresh analysis.
An update falls back to a full analysis whenever the edit moves the ground the evidence stands on: a changed piece length, a changed first onset (both of which move the slot grid), or an edit to a session whose harmony was supplied through ArrangementOptions.timeline. The answer is the same either way; only the work differs.