Page 1 of Engel (Bosse/Partitura) has a boxed VERSE 1 label in the left margin at the same rows as the preceding system's bass lyric line — ink on both sides of the page throughout the band, so no horizontal line separates them. The label belongs to system 2, the lyrics to system 1. A cut is therefore a polyline spanning the page, two points being the ordinary straight case. A slice bounded by a non-straight cut is not rectangular: its image is the region's bounding box with everything outside made transparent, which composites invisibly on the viewer's sheet. Masking paints transparency, never white.
131 lines
6.3 KiB
Markdown
131 lines
6.3 KiB
Markdown
# 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, 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 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.
|