Files
noteman-slicer/CONTEXT.md
T
Esa Kataja 46ae7e813a Replace the handoff notes with a durable spec and ADRs
The handoff was written as a message to relay information; several
decisions lived only there. Split into permanent homes:

- docs/spec.md — scope, geometry model, pipeline order, detection,
  levels, editor, project file, markers, bundle format, noteman's
  changes, reference values
- ADR 0002 — raster only in release 1; SVG slices measured at 40x WebP
  naive, 2.6x with a bounding-box cull, deferred on risk not size
- ADR 0003 — lossless WebP with levels and 16-level alpha; every lossy
  option and alternative format measured larger for line art
- ADR 0004 — detection proposes, the human disposes; no unattended mode
- ADR 0005 — PyMuPDF for all PDF access, accepting AGPL
- ADR 0006 — systems are found by vertical brackets, not row-darkness
  gaps, which miscount every page of a 6-voice score

Also from testing against the hardest score in the repertoire: scanned
PDFs carry their scan as an embedded image and must be extracted at
native resolution rather than re-rendered at 600 DPI, and per-page
deskew is mandatory (skew varies -2.6 to +1.2 within one PDF).
2026-07-28 22:05:09 +03:00

5.8 KiB
Raw Blame History

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 412 bars with lyrics intact. Same definition as noteman's. Structurally, a horizontal region of a page: 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. 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, so any export can be regenerated without repeating human work. One PDF, one song, one project, one bundle — never a many-to-one in any direction. 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 horizontal line placed on a page that splits one slice into two. Straight at first; a later polyline form handles pages where systems slant or interleave. Placement is forgiving — anywhere inside the whitespace gap yields the same output, because trim crops to ink afterwards. Avoid: split, divider, break

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.