Opening an exported song starts a fresh session from detection instead of resuming: cuts, discards and metadata do not carry over, so a re-cut never inherits decisions that have already shipped. --resume overrides it on edit, export and project. This reverses what was agreed in planning and written into docs/spec.md and CONTEXT.md, which promised resume-across-sessions and re-export. Both are corrected. The cost is deliberate and worth stating: changing the width cap or adding the SVG renderer later now means re-cutting each song by hand rather than regenerating every bundle from its project file. Export records the flag in bundle.write, so no caller can forget it. Also removed --refit and the Auto-fit buttons, which were added without being asked for and whose only purpose - migrating projects made before the content rectangle was proposed - disappears once exported projects start fresh. Reset now restores detection's proposal rather than the whole page: clearing to full width would undo the thing the rectangle exists for, so one button covers it. open_project() replaces four copies of load-or-detect across the CLI and the editor.
6.4 KiB
noteman-slicer — Context
A local, single-user tool that turns a score PDF into the ordered slice images noteman consumes, plus the navigation markers that sit on them. It automates the mechanical part of noteman's ingestion boundary; it does not replace GIMP for erasing previous-owner annotations.
Language
Score source: The original PDF as distributed to the choir. Either vector (engraved by a notation program) or raster (a flatbed scan of a printed page). Avoid: original, input file
Source type: Whether a score source is vector or raster. Determined once per PDF, not per page; the slicer detects it and asks the user to confirm before routing. Avoid: mode, format
Slice: The atomic visual unit of a song — one system, one full line of music across all voices, typically 4–12 bars with lyrics intact. Same definition as noteman's. Structurally, a region of a page bounded above and below by cuts: a page begins as a single slice and each cut splits one slice into two, so slices always tile the page with no gaps and no overlap. Rectangular when its cuts are straight, and stepped when they are not — the slice image is then its bounding box with everything outside the region transparent. Avoid: segment, strip, row, band
Discard: A flag on a slice meaning it produces no output. How headers, footers and blank regions leave the song — they are slices that are simply not exported. Detection pre-sets it on a page's top and bottom slice when they contain no system. Avoid: delete, skip, exclude
Slice image:
The rendered artifact of a slice: lossless WebP, RGB pure black,
alpha = 255 − luminance, width capped at 1920px — paper is transparency, ink is
alpha. Display-ready as produced; nothing downstream reprocesses it. An SVG form
for vector sources is designed but deferred, which is why the geometry model is
renderer-agnostic.
Avoid: PNG, page image, tile
Marker:
A semantic tag placed on a slice for navigation. Vocabulary is noteman's enum
verbatim (rehearsal_letter, section_label, segno, coda, fine,
repeat_start, repeat_end, volta, to_coda, ds_al_coda, ds_al_fine,
dc_al_coda, dc_al_fine, generic_jump) and is shared coupling between the
two repos.
Project: The persistent state of slicing one song: the source PDF it points at, its cuts, discards, content rectangle, levels, staff-height overrides, markers and metadata. Autosaved beside the PDF; the bundle is generated from it. One PDF, one song, one project, one bundle — never a many-to-one in any direction.
Spent once its song has been exported: opening the PDF again begins a fresh session from detection rather than resuming, so a re-cut never inherits decisions that have already shipped. Avoid: session, document, edit list
Bundle: The single compressed file that is the only channel between the slicer and noteman. There is no API call, no direct upload. Carries the slice images in order, their markers, the original PDF and the song-level text metadata. Rehearsal MIDI and MP3s are deliberately out of the first bundle and stay noteman's upload chore until a later phase. Avoid: export, package, upload
Marker label:
The free text some markers carry — rehearsal_letter ("C"), section_label
("CHORUS"), volta ("1."). All other types are bare tags.
Jump source:
A marker that sends the reader elsewhere — to_coda, ds_al_coda,
ds_al_fine, dc_al_coda, dc_al_fine, generic_jump. Every jump source
stores its target slice explicitly; none is resolved by type at read time.
Authoring the target costs one click on a slice already on screen, and in
exchange the bundle is self-describing — no "exactly one Coda per song" rule
living unenforced in two repos, and a score with two codas simply works.
Avoid: link, reference, pointer
Cut:
A boundary placed on a page that splits one slice into two. Modelled as a
polyline spanning the page from left edge to right edge, with two points —
a straight horizontal line — as the ordinary case. Extra vertices handle the
common publisher habit of printing a section label (VERSE 1, INTRO) in the
left margin at the same height as the previous system's lyrics: the cut steps
above the label on the left and below the lyrics on the right.
Placement along the boundary is forgiving — anywhere inside the whitespace yields the same output, because trim crops to ink afterwards. Avoid: split, divider, break, cut line
Content rectangle: The region of a page that holds music. Set per PDF, adjustable per page, applied before cutting. Everything outside it — scan-edge bands, spine shadows, margin page numbers — is dropped. Handles margin junk structurally rather than case-by-case, because margin junk is by definition outside the music. Avoid: crop box, mask, margin
Detection: Any automatic proposal the slicer makes — skew angle, cut positions, source type, ink bounds. Detection is always a suggestion: the human confirms or modifies every result before it is committed. Source quality varies too widely for unattended processing to be trustworthy. Avoid: auto-slicing, automatic mode
Trim: Cropping a slice tight to its ink on all four sides, per slice. Normalises away the left-margin drift between scanned pages, and flattens the engraved indent of the first system — correct here, since the printed header it made room for is stripped anyway. The viewer supplies margins with CSS padding.
Staff height: The distance between a system's top and bottom staff line. The invariant a reader perceives as "the notes are the same size", and therefore what slices are normalised against — not their width. Falls out of the same row-darkness profile used for cut detection. Manually overridable, since it is detected on the same speckled scans where detection already struggles.
Song scale: Two steps, both per song, never per slice. First every slice is normalised to a common staff height, so a rescanned page or a re-engraved slice sits at the same note size as its neighbours. Then the whole song is scaled uniformly so its widest slice lands at 1920px — a ceiling, never a target: a song that comes out narrower stays narrower, because upscaling a scan past its real resolution buys softness and bytes and no detail.
Right pad: The transparent space added to the right of every slice narrower than the widest, bringing all slices in a song to the same width. Keeps the music the same size and flush left; a short system simply ends earlier.