notation(...) — Timepoint Notation
Renders a fragment of staff-based notation directly inside an SVG element. Notes are spaced proportionally in time rather than rhythmically — the horizontal position of each notehead is what matters; durations are conveyed by extent lines, fermatas, and gaps. This style of notation is sometimes called timepoint notation or proportional notation; the same approach underpins works by Brown, Cardew, Lutosławski, and Penderecki.
A notation() cue can fire OSC on click and on playhead-pass, draw glisses
between noteheads (including across staves in multi-stave systems), and
carry articulations, dynamics, and per-note sample assignments.
For interactive creation and editing in the browser, see Notation — Session Layer.
Quick Start
Give an SVG element an id like:
notation(pitches:'~A4 ~C5 ~Eb5 ~G5')
Open in the browser → a treble clef and four noteheads render inside the element's bounding box, evenly spaced.
Syntax
notation(
pitches:'~Bb3 ~Eb5 ~G4 ~Eb3',
clef:treble,
keysig:Eb,
transp:Bb,
height:34,
spacing:22,
extent:120,
extentStyle:wavy,
boxed:1,
playhead:1,
click:1,
osc:/oscilla/notation/myUid/note,
uid:myUid
)
Parameters
| Key | Default | Description |
|---|---|---|
pitches (required) |
— | Space-separated list of pitches (see Pitch Syntax below) |
clef |
treble |
treble or bass |
keysig |
— | Major key for key signature (e.g. Eb, G, F#); biases enharmonic spelling and renders accidentals |
transp |
C |
Instrument transposition (e.g. Bb, Eb, F) — input pitches are sounding, the staff shows the written pitch |
height |
40 | Staff height in SVG units |
spacing |
18 | Horizontal gap between noteheads |
extent |
— | X-position where the cue's "extent line" ends (sustain bar past the noteheads); also dragable in edit mode |
extentStyle |
block |
block, thin, dashed, wavy, dottedTrill, arrowed |
boxed |
false |
Draw a rectangle outline around the whole fragment |
boxRadius |
0 | Rounded corners on the bounding box |
boxPadding |
6 | Padding from staff edges to the box |
glisses |
— | Array of gliss objects (see Glisses below) |
articulations |
— | Map of { noteIdx: ["staccato","accent",…] } — see Articulations |
dynamics |
— | Map of { noteIdx: "mf" } — see Dynamics |
playhead |
(auto) | When non-false, the playhead crossing each notehead emits OSC. As of v… playhead-trigger is on by default; the per-note Audio tab in edit mode lets you override per-note or per-stave. |
click |
1 | When non-false, clicking a notehead emits OSC and plays its assigned sample (if any) |
osc / oscaddr |
/oscilla/notation/<uid>/note |
OSC address; {i} is replaced with note index, {s} with stave index in multi-stave systems |
uid |
(derived from id) | Stable identifier used for persistence of edit-mode overrides |
Pitch Syntax
~A4 → A above middle C
~Bb3 → B-flat below middle C
~F#5 → F-sharp above the staff
~Db5-31 → Db5, 31 cents flat (microtonal)
~A4+50 → A4, 50 cents sharp (quartertone)
60 → MIDI note number (middle C)
The ~ prefix is the conventional mark for a pitch literal. Cents
deviation is appended as +N or -N; the renderer draws the cents
value as a small superscript next to the notehead.
Pitches in pitches: are interpreted as sounding pitches — the
actual frequency the player should hear. If transp: is set, the staff
displays the corresponding written pitch (transposed up or down by
the instrument's transposition interval).
OSC Output
Each notehead can emit an OSC trigger. Two sources:
- Click: clicking a notehead in the score (outside edit mode)
- Playhead-pass: the score's playhead crossing the notehead's x-coordinate
Default address pattern: /oscilla/notation/<uid>/note
Args (single-stave): [noteIndex, midi, freqHz, cents, noteheadStyle, pitchName]
Args (multi-stave): [staveIndex, noteIndex, midi, freqHz, cents, pitchName]
Custom addresses can use {i} (note index) and {s} (stave index)
placeholders:
notation(pitches:'~C4 ~D4 ~E4', oscaddr:/synth/note/{i})
To enable / disable click and playhead triggers per-note or per-stave, use the Audio tab in the edit-mode popup (see Notation — Session Layer).
Glisses
Glisses (portamenti, slides, trill lines, custom contour lines) connect
two noteheads, or a notehead to a free-floating point. Persistence is
tied to uid; in edit mode, shift-drag from a notehead to draw one.
Authored DSL form:
notation(
pitches:'~A4 ~G5 ~D4',
glisses:[
{ from:{index:0}, to:{index:1}, style:straight }
]
)
| Style | Description |
|---|---|
straight |
Plain line (default) |
wavy |
Sinusoidal vibrato line |
arrow |
Line ending in an arrowhead |
dotted |
Dotted line |
dashed |
Dashed line |
trill |
Trill (tr + line) |
portamento |
Curved bezier |
Glisses can include intermediate breakpoints (breakpoints:[{x,y},…])
to bend through specific points; in edit mode, dragging the midline of a
gliss creates a breakpoint.
For multi-stave systems, gliss endpoints carry a staveIdx as well as
index:
glisses:[
{ from:{staveIdx:0, index:3}, to:{staveIdx:1, index:0}, style:wavy }
]
Articulations
Articulation marks render above (or below) each anchored note. Multiple marks on one note stack vertically.
notation(
pitches:'~C5 ~D5 ~E5',
articulations:{ 0:["staccato","accent"], 2:["fermata"] }
)
Available marks (SMuFL Bravura glyphs):
staccato, staccatissimo, accent, accentStaccato, tenuto,
portato, tenutoAccent, marcato, marcatoStaccato, stress,
unstress, laissezVibrer, fermata, fermataShort, fermataLong,
fermataVeryLong, harmonic, snapPizz.
In edit mode, dblclick a notehead → Articulation tab to toggle marks across all selected notes.
Dynamics
A single dynamic sits below the staff at the anchored note's x-position.
notation(
pitches:'~C5 ~D5 ~E5',
dynamics:{ 0:"p", 2:"f" }
)
Available dynamics:
n (niente), ppppp, pppp, ppp, pp, p, mp, mf, f, ff,
fff, ffff, fffff, fp, pf, sf, sfp, sfz, sffz, rf,
rfz, fz.
In edit mode, dblclick a notehead → Dynamic tab.
Per-Note Samples
Each note can be assigned an audio sample to play on click and / or
playhead-pass. Samples are picked from the project's /audio directory
via the popup's Audio tab (see
Notation — Session Layer).
The sample is played through the same engine as audio(…) cues, so it
inherits gain and speed but currently bypasses FX routing.
Multi-Stave Systems
Piano, organ, and string-quartet layouts use notationSystem (see
session-layer docs) — multiple staves rendered as a single coordinated
group with one shared extent line and bounding box spanning every
stave. Cross-stave glisses use staveIdx in their endpoint addressing.
Multi-stave systems are usually created via the topbar + Notation
button, but can also be authored in the score svg as a JSON spec.
Examples
Simple progression:
notation(pitches:'~C4 ~D4 ~E4 ~F4 ~G4', height:32, spacing:24)
Bb clarinet (sounding pitches), with Eb major key signature:
notation(pitches:'~Bb3 ~D4 ~F4 ~Bb4', transp:Bb, keysig:Eb)
Microtonal cluster:
notation(pitches:'~A4 ~A4+33 ~A4+67 ~A4+100', height:36)
Sustained tones with extent line:
notation(
pitches:'~G4 ~Bb4 ~D5',
extent:200,
extentStyle:wavy,
spacing:30
)
Boxed cluster with playhead-trigger OSC:
notation(
pitches:'~C4 ~D4 ~Eb4 ~F#4 ~G4',
boxed:1,
boxRadius:4,
playhead:1,
oscaddr:/synth/cluster/{i}
)
Edit-Mode Behaviour
When the topbar 🎼 (notation edit) toggle is on, every notation() cue
gains drag handles and double-click affordances. Per-note overrides
(positions, notehead styles, articulations, dynamics, samples, OSC flags)
are persisted under the cue's uid in localStorage and (for session
cues) in notation-cues.json. The score svg itself is never modified.
See Notation — Session Layer for the full set of edit-mode interactions.
Tip: use ← → or ↑ ↓ to navigate the docs