Note Mapping & Visual Alignment Reference
Core Variables
numNotes— count of valid scale notes in the selected rangeposition— normalized hand Y coordinate (0.0 = top, 1.0 = bottom)invertedPosition = 1.0 - position(0.0 = bottom, 1.0 = top)
Fret Boundary Lines (NoteFretOverlay.swift)
Drawn at the edges of each note zone:
y_boundary(i) = 1.0 - (i / numNotes) for i in 0...numNotes
i spans from y_boundary(i) down to y_boundary(i+1)
Note Labels (NoteFretOverlay.swift)
Placed at the center of each zone:
y_label(index) = 1.0 - ((index + 0.5) / numNotes)
Position-to-Note Mapping (MIDIRouter.swift)
circleRadiusOffset = 14.0 / screenHeight
adjustedPosition = source.position.y - circleRadiusOffset
invertedPosition = 1.0 - adjustedPosition
floatIndex = invertedPosition * numNotes
rawIndex = Int(floatIndex)
index = max(0, min(rawIndex - 1, numNotes - 1))
rawIndex - 1 shift is intentional — removing it makes alignment worse.
The 14pt radius offset ensures the pitch boundary aligns with the dot center, not its bottom edge.
Tracking Dot Dimensions (ContentView.swift)
- Outer glow: 70x70pt (RadialGradient, purely visual)
- Core circle: 28x28pt (filled + stroked)
- Radius for offset math: 14pt
Velocity from X Position (MIDIRouter.swift)
clampedX = clamp(x, 0.0, 1.0)
curve = pow(clampedX, 1.5)
velocity = 20 + curve * 107 // range: 20-127
Modulation from Fingers (MIDIRouter.swift)
ccValue = UInt8(fingerCount / 5.0 * 127.0)