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:

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