End each fingering chart at the thumb hole.
AppImage release / appimage (push) Successful in 53s

The beak, window, and mouthpiece lines are gone. The staff stays underneath. Version 0.2.4.

Co-authored-by: catpersonisme <catpersonisme@gmail.com>
This commit is contained in:
Cursor Agentandchen committed 2026-10-11 11:02:53 +00:00
1 parent 7c988e9347
commit 837fcb2751
5 files changed
+14 -18

No files matched your search

+6 -6
View File
@@ -1,20 +1,20 @@
# Recorder fingering editor # Recorder fingering editor
A soprano recorder tool for arranging fingering charts. Drag a chart, a rest, or a space onto a line, reorder it, set how long it lasts, or take it off. Resize the line box, then save the finished row as a PNG. Baroque fingering is the chart. The foot, with the double holes, is at the top of each chart, and the mouthpiece is at the bottom. A soprano recorder tool for arranging fingering charts. Drag a chart, a rest, or a space onto a line, reorder it, set how long it lasts, or take it off. Resize the line box, then save the finished row as a PNG. Baroque fingering is the chart. The foot, with the double holes, is at the top of each chart. The tube ends at the thumb hole.
The usual way to run it is one Linux AppImage. That file contains the window and the fingering charts. It does not read sheet music, and it does not include oemer, ONNX, or model files. The usual way to run it is one Linux AppImage. That file contains the window and the fingering charts. It does not read sheet music, and it does not include oemer, ONNX, or model files.
## Run the AppImage ## Run the AppImage
```bash ```bash
chmod +x Recorder-Tab-Converter-0.2.3.AppImage chmod +x Recorder-Tab-Converter-0.2.4.AppImage
./Recorder-Tab-Converter-0.2.3.AppImage ./Recorder-Tab-Converter-0.2.4.AppImage
``` ```
If the file will not start because FUSE is missing: If the file will not start because FUSE is missing:
```bash ```bash
APPIMAGE_EXTRACT_AND_RUN=1 ./Recorder-Tab-Converter-0.2.3.AppImage APPIMAGE_EXTRACT_AND_RUN=1 ./Recorder-Tab-Converter-0.2.4.AppImage
``` ```
Open **Empty line**, or start from **Twinkle, opening** or **Ode, held note**. Drag any chart from C5 to D7, or drag **Rest** or **Space**, onto a line. Drag a placed item to move it, including onto another line. **New line** adds a row underneath. Plus and minus change the length. Remove takes an item off. **Shorter**, **Taller**, **Narrower**, **Wider**, and the corner grip change the box. **Save PNG** downloads every line. Open **Empty line**, or start from **Twinkle, opening** or **Ode, held note**. Drag any chart from C5 to D7, or drag **Rest** or **Space**, onto a line. Drag a placed item to move it, including onto another line. **New line** adds a row underneath. Plus and minus change the length. Remove takes an item off. **Shorter**, **Taller**, **Narrower**, **Wider**, and the corner grip change the box. **Save PNG** downloads every line.
@@ -30,7 +30,7 @@ From a checkout, one command:
That installs Node packages, builds the app, and writes: That installs Node packages, builds the app, and writes:
```text ```text
dist/Recorder-Tab-Converter-0.2.3.AppImage dist/Recorder-Tab-Converter-0.2.4.AppImage
``` ```
The AppImage is not committed. Keep it under 600MB. The AppImage is not committed. Keep it under 600MB.
@@ -49,4 +49,4 @@ The dev server listens on [http://127.0.0.1:3847](http://127.0.0.1:3847).
Baroque (English) fingerings are the first choice on the [Dolmetsch Online chart for recorders in C](https://dolmetsch.com/textfingeringchart.htm) (Brian Blood). The soprano is labeled in concert pitch: low C is C5, and the chart stops at D7. Double holes 6 and 7, forked F, and the second-octave thumb pinch are included. Alternate fingerings on that chart are not shown. Baroque (English) fingerings are the first choice on the [Dolmetsch Online chart for recorders in C](https://dolmetsch.com/textfingeringchart.htm) (Brian Blood). The soprano is labeled in concert pitch: low C is C5, and the chart stops at D7. Double holes 6 and 7, forked F, and the second-octave thumb pinch are included. Alternate fingerings on that chart are not shown.
Each chart is drawn foot-up: holes 7 and 6 at the top, then 5 through 1, then the thumb, with the mouthpiece at the bottom. A filled hole is closed. A treble staff under the holes is written one octave below the sounding pitch. Low C, labeled C5, sits on the ledger line below the staff. Sounding C6 is written C5, and sounding C7 is written C6. Length is a notehead, stem, flags, dots, and rests. Labels keep the sounding names. Each chart is drawn foot-up: holes 7 and 6 at the top, then 5 through 1, then the thumb. The tube ends there. A filled hole is closed. A treble staff under the holes is written one octave below the sounding pitch. Low C, labeled C5, sits on the ledger line below the staff. Sounding C6 is written C5, and sounding C7 is written C6. Length is a notehead, stem, flags, dots, and rests. Labels keep the sounding names.
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "recorder-tab-converter", "name": "recorder-tab-converter",
"version": "0.2.3", "version": "0.2.4",
"private": true, "private": true,
"description": "Arrange soprano recorder fingering charts by dragging them onto a line.", "description": "Arrange soprano recorder fingering charts by dragging them onto a line.",
"main": "electron/main.cjs", "main": "electron/main.cjs",
+1 -1
View File
@@ -502,7 +502,7 @@ export function Editor() {
</section> </section>
<ul className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground"> <ul className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
<li>Foot at the top, mouthpiece at the bottom</li> <li>Foot at the top. The tube ends at the thumb hole</li>
<li>Filled hole: closed</li> <li>Filled hole: closed</li>
<li>Empty hole: open</li> <li>Empty hole: open</li>
<li>One of a pair filled: half-hole</li> <li>One of a pair filled: half-hole</li>
+4 -8
View File
@@ -24,8 +24,8 @@ const TUBE = "#9deaf3";
const INK = "#1a1a1a"; const INK = "#1a1a1a";
/** /**
* Foot at the top, mouthpiece at the bottom. * Foot at the top. The tube ends at the thumb hole.
* The drawing is the reverse of a held recorder. Hole states are not changed. * Hole states are not changed.
*/ */
function Hole({ function Hole({
cx, cx,
@@ -83,7 +83,7 @@ export function FingeringDiagram({
const [h1, h2, h3, h4, h5, h6a, h6b, h7a, h7b] = fingering.holes; const [h1, h2, h3, h4, h5, h6a, h6b, h7a, h7b] = fingering.holes;
const value = noteValue(quarters); const value = noteValue(quarters);
const label = `${pitch}, written one octave lower, ${durationLabel(quarters)} on the treble staff. Foot at the top, mouthpiece at the bottom. ${fingeringProse(fingering)}. ${fingeringMarks(fingering).join(", ")}`; const label = `${pitch}, written one octave lower, ${durationLabel(quarters)} on the treble staff. Foot at the top. The tube ends at the thumb hole. ${fingeringProse(fingering)}. ${fingeringMarks(fingering).join(", ")}`;
return ( return (
<svg <svg
@@ -95,7 +95,7 @@ export function FingeringDiagram({
className="shrink-0" className="shrink-0"
> >
<path <path
d="M9 3 H33 V148 H44 V184 H9 Z" d="M9 3 H33 V150 H9 Z"
fill={TUBE} fill={TUBE}
stroke={INK} stroke={INK}
strokeWidth="1.4" strokeWidth="1.4"
@@ -114,10 +114,6 @@ export function FingeringDiagram({
<Hole cx={21} cy={118} r={4.7} state={h1} /> <Hole cx={21} cy={118} r={4.7} state={h1} />
<line x1="9" y1="130" x2="33" y2="130" stroke={INK} strokeWidth="1" /> <line x1="9" y1="130" x2="33" y2="130" stroke={INK} strokeWidth="1" />
<Hole cx={21} cy={140} r={4.5} state={fingering.thumb} /> <Hole cx={21} cy={140} r={4.5} state={fingering.thumb} />
<line x1="9" y1="156" x2="44" y2="156" stroke={INK} strokeWidth="1" />
<line x1="9" y1="166" x2="44" y2="166" stroke={INK} strokeWidth="1" />
<line x1="9" y1="176" x2="44" y2="176" stroke={INK} strokeWidth="1" />
<ellipse cx="26" cy="166" rx="3.2" ry="4.4" fill={TUBE} stroke={INK} strokeWidth="1.2" transform="rotate(-24 26 166)" />
<Staff pitch={pitch} /> <Staff pitch={pitch} />
<NoteOnStaff pitch={pitch} head={value.head} stem={value.stem} flags={value.flags} dots={value.dots} /> <NoteOnStaff pitch={pitch} head={value.head} stem={value.stem} flags={value.flags} dots={value.dots} />
</svg> </svg>
+2 -2
View File
@@ -1,8 +1,8 @@
import { quartersMatch } from "@/lib/duration"; import { quartersMatch } from "@/lib/duration";
/** Recorder drawing stays in a 48×188 box. The staff is added underneath. */ /** The tube ends just below the thumb hole. The staff is added underneath. */
export const CHART_VB_W = 48; export const CHART_VB_W = 48;
const RECORDER_VB_H = 188; const RECORDER_VB_H = 152;
/** Distance between two staff lines. One diatonic step is half of this. */ /** Distance between two staff lines. One diatonic step is half of this. */
export const STAFF_SPACE = 4.6; export const STAFF_SPACE = 4.6;