Browse documentation
Docs/Language

Music Notation

Grid models can hold music. A score is an ordinary value: you write it as notation text, calculate with it, and see it engraved, played and edited in the Score surface. Scores exchange with…

Music Notation

Grid models can hold music. A score is an ordinary value: you write it as notation text, calculate with it, and see it engraved, played and edited in the Score surface. Scores exchange with Sibelius, Finale, Dorico and MuseScore through MusicXML.

# Inputs
input melody = raw"""key: G
time: 3/4
tempo: 116
| \mf d5/4( g4/8 a b c5) | d5/4 g4-. g4-. |]"""
input transpose_by = 0 VALIDATE BETWEEN -12 AND 12

# Derived calculations
tune = MUSIC_SCORE(melody)
performance = MUSIC_TRANSPOSE(tune, transpose_by)

# Final outputs
playing_seconds = MUSIC_DURATION(performance)
musicxml_export = MUSIC_TO_MUSICXML(performance)

See the complete example.

Score values

A score is a value of type music. IS music accepts it and its representation root is object. It holds a title block and parts. Each part is one staff of measures, and each measure holds notes, chords and rests with their durations, ties, slurs, tuplets, articulations, dynamics, lyrics and chord symbols.

Create a score in one of four ways:

Source Use
music"…" or <music>…</music> Notation written directly in the model.
MUSIC_SCORE(text) Notation held in another cell or an input.
MUSIC_FROM_NOTES(table, …) A table of pitches and durations.
MUSIC_FROM_MUSICXML(xml) A score exported from other notation software.

The literal forms are shorthand for MUSIC_SCORE. Use <music>…</music> for notation that spans several lines or contains double quotes. Hold notation that people edit in an input, and use raw"""…""" so backslash dynamics stay verbatim.

Every function that takes a score also accepts notation text, so MUSIC_DURATION("| c4/4 d e f |") works without a separate parse.

Notation text

Notation text has a header, then one or more parts.

title: Night Song
composer: A. Composer
key: e minor
time: 6/8
tempo: 1/8=132 "Andante"

part Flute abbr "Fl." clef treble
  | b4/8 e5 f#5 g5/4. | f#5/8 e5 d#5 e5/4. |]

part Cello clef bass program 42
  | e3/4. b2/4. | c3/4. b2/4. |]
Line Meaning
title: subtitle: composer: lyricist: copyright: Title block.
key: G, key: e minor, key: Bb major, key: F#m Opening key signature.
time: 3/4, time: common, time: cut Opening time signature.
tempo: 120, tempo: 1/8=144 "Allegro" Metronome mark, with an optional marking.
clef: bass Default clef for parts that do not name one.
swing: triplet, swing: 62%, swing: 2:1, swing: off Play pairs of eighth notes long-short. light, triplet and hard are named feels; a percentage is the share of each beat taken by its first half. Swing applies where the beat is a quarter or half note.

Parts

part <name> starts a staff. It accepts clef (treble, bass, alto, tenor, percussion, treble8vb, bass8vb, tab), abbr for the name on later systems, group to brace staves together, and program for a MIDI program. Two parts with the same name, such as a piano's two staves, are braced automatically.

A part named after an instrument takes that instrument's clef, abbreviation, playback sound, playable range and transposition. "Clarinet in Bb", "Violin 1" and "Horn 2 in F" all match, and instrument names the preset when the part name does not. Anything written explicitly wins over the preset.

duet = MUSIC_SCORE("key: F
part Clarinet in Bb
  | f4/4 a4 c5 bb4 | a4/1 |]
part Solo instrument cello
  | f2/2 c3/2 | f2/1 |]")

The presets cover the orchestra, wind band, saxophones, keyboards, tuned percussion, guitars and choir voices.

Transposing instruments

Scores are always stored at sounding (concert) pitch, so every calculation, playback and MUSIC_TRANSPOSE works on the notes you hear. A transposing part also publishes its written pitch and written key: the clarinet above is written in G major, a tone higher than it sounds. Use transpose <semitones> [steps] on a part for an instrument without a preset; transpose -2 is a B-flat instrument, and the diatonic steps default to the usual spelling.

MusicXML keeps the same convention: export writes written pitch with a <transpose> element, and import reads one back to sounding pitch.

Notes and rests

A note is a letter, an optional accidental, an octave and a value: c4/4 is middle C as a quarter note.

Written Meaning
c d … b Pitch letter.
# ## b bb n Sharp, double sharp, flat, double flat, natural.
4 Scientific octave. C4 is middle C.
/1 /2 /4 /8 /16 /32 /64 /0 Whole to 64th note; /0 is a breve.
. after the value Augmentation dot. c4/4. is a dotted quarter.
r/4 Rest.
R Rest for the whole measure.
[c4 e4 g4]/2 Chord.

Octave and value carry forward: c4/8 d e f is four eighths. Pitches are written as they sound; the 8vb clefs place them an octave higher on the staff. Accidentals are written as heard. The engraver shows or cancels them against the key signature and earlier notes in the measure.

Marks

Written Meaning
c4/4~ c4/4 Tie.
c4/8( d e f) Slur from the note before ( to the note before ).
-. -> -- -^ -! Staccato, accent, tenuto, marcato, staccatissimo.
-fermata -trill -mordent -turn Fermata and ornaments. Playback plays a trill with the note above in the key, a mordent with the note below, and a turn around the note.
-trem1 -trem2 -trem3 Tremolo strokes: repeated eighths, sixteenths or thirty-seconds.
[c4 e4 g4]/2-arp Rolled chord, played from the bottom up.
\8va \8vb \15ma \15mb then \loco Ottava line from the next note until \loco. Pitches stay as they sound; the staff shows them an octave (or two) away under the line.
\ped then \* Sustain pedal pressed at the next note and released at the note after \*. A second \ped while the pedal is down retakes it. Notes ring until the release.
c4/2 \gliss g4/2 Glissando line from the note before \gliss to the next note.
cue{ c5/8 d e f } Cue notes: written small and not played.
\p \mf \ff \sfz Dynamic on the next note.
\< \> then \! Crescendo or diminuendo wedge from the next note, ending at the note after \! or at the next dynamic. Playback ramps the loudness to that dynamic, or by one level when none follows.
"Glo-" after a note Lyric syllable; a trailing - joins it to the next syllable, and a trailing _ holds it with an extender line under the notes that follow.
%G7 %F#m7/A Chord symbol on the next note.
^"dolce" Text above the next note.
3{ c4/8 d e } Triplet. 5:4{ … } gives an explicit ratio.
g{ d5/16 } Grace note before the next note.

Measures and changes

| separates measures. || is a double barline, |] a final barline, |: and :| repeat signs, and :|: a back-to-back repeat. key, time, clef and tempo inside a measure change the signature from that measure on:

| c4/1 | key Eb major time 3/4 eb4/4 f g | clef bass c3/2. |

break system or break page inside a measure forces a new system or page after it. Without one, the Score surface breaks systems where they fill.

Drum kits and tablature

A part named Drums or Drum Set (or any part with clef percussion) is a drum kit. Write each instrument at its staff position, as if in treble clef; cymbals and hi-hats get cross noteheads, and playback uses the kit's sounds:

Position Instrument Position Instrument
f4 Bass drum g5 Closed hi-hat
c5 Snare drum b5 Open hi-hat
a4 Floor tom d4 Pedal hi-hat
d5 Mid tom f5 Ride cymbal
e5 High tom a5 Crash cymbal
part Drums
  | [f4 g5]/8 g5 [c5 g5] g5 [f4 g5] g5 [c5 g5] g5 |

clef tab writes a fretted part as tablature. Write the pitches as they sound; Grid chooses the string and fret for each note in the lowest position, and gives chord notes separate strings. Guitar and bass guitar use standard tuning; tuning lists other open strings from lowest to highest:

part Guitar clef tab
  | [c3 e3 g3 c4 e4]/2 e2/4 g3 |
part Bass Guitar clef tab tuning b0 e1 a1 d2 g2
  | b0/2 e1 |

-s and a string number plays a note higher up the neck: e4/4-s2 is the open first string's E fretted on the second string, and -s3 on the third. String 1 is the highest. On a chord the number places the highest note, and the notes below it take the next strings down:

part Guitar clef tab
  | e4/4 e4/4-s2 [c4 e4]/2-s2 |

A note too low for the chosen string moves to the next string that reaches it. A position that is not part of the kit, or a pitch the strings cannot reach, is reported as a finding. MusicXML export writes the tuning and each note's string and fret, and import keeps a tuning that is not standard and any note placed away from the lowest position.

Voices

// starts the next voice of the same measure, up to four voices on one staff. Each voice fills the measure on its own, and ties and slurs stay within their voice. The first and third voices are stemmed up and the second and fourth down:

| e5/4 d5/8 c5 d5/4 e5 // c5/4 b4/8 a4 b4/2 |

Lines starting with # are comments.

Findings

Notation errors, such as an unknown token or an unclosed chord, make MUSIC_SCORE return #VALUE! with the line and column. Measures that are too long or short, parts of different lengths, pitches outside the MIDI range, and notes outside an instrument's playable range are warnings. The Score surface lists them, and MUSIC_CHECK returns them as a table, including errors in text that does not parse:

findings = MUSIC_CHECK(melody)

Functions

The complete signatures are in the function catalog.

Function Returns
MUSIC_SCORE(text) A score parsed from notation text.
MUSIC_FROM_NOTES(notes, [time], [key], [tempo], [title]) A score from rows of pitch, quarters, lyric and part. Notes crossing a barline are split and tied.
MUSIC_FROM_MUSICXML(xml) A score imported from MusicXML.
MUSIC_TRANSPOSE(score, semitones, [part]) The score transposed with correct spelling, key signatures and chord symbols.
MUSIC_PART(score, part) One part, by name or number.
MUSIC_MEASURES(score, from, [to]) An excerpt, keeping the key, time, clef and tempo in force.
MUSIC_CONCAT(score, …) Scores joined end to end; parts match by name.
MUSIC_SET_TEMPO(score, bpm, [beat_unit]) The score with a new opening metronome mark.
MUSIC_TEXT(score) Canonical notation text.
MUSIC_TO_MUSICXML(score) A MusicXML 4.0 document.
MUSIC_NOTES(score) A table of sounding notes: part, measure, beat, pitch, MIDI number, length, start and lyric.
MUSIC_MIDI_EVENTS(score) A table of MIDI note events with timing in seconds and velocity.
MUSIC_CHECK(score) A table of findings.
MUSIC_DURATION(score) Playing time in seconds.
MUSIC_MEASURE_COUNT(score) Number of measures.
MUSIC_PARTS(score) Part names.
MUSIC_KEY(score, [measure]) Key in force, such as G major.
MUSIC_TIME_SIGNATURE(score, [measure]) Time signature in force, such as 3/4.
MUSIC_TEMPO(score, [measure]) Metronome mark in force.
MUSIC_TITLE(score) Title.
MUSIC_RANGE(score, [part]) Lowest and highest pitch.

Note tables feed ordinary analysis. For example, count the pitches that sound in the first measure:

notes = MUSIC_NOTES(tune)
opening_bar_notes = COUNTIF(CHOOSECOLS(DROP(notes, 1, 0), 2), 1)

MusicXML import keeps up to four voices on each staff and splits a multi-staff part, such as a piano, into braced staves. It warns when it skips a fifth voice. Export writes every part and voice, with grand-staff braces.

The Score surface

Create a Score surface and point [source].bind at a cell that holds a score. It engraves publication-style notation: shared proportional spacing across the system, beams grouped by beat, key-aware accidentals, ledger lines, ties, slurs, tuplets, grace notes, articulations, dynamics, lyrics, chord symbols, tempo marks, repeat barlines, braces and brackets.

[source]
bind = "minuet"      # cell holding the score
edit = "melody"      # optional: the notation-text input to edit

[layout]
view = "page"        # page | panorama
zoom = 100

[playback]
enabled = true
audio = "renders/minuet.wav"       # optional: where Render audio writes
soundfont = "sounds/orchestra.sf2" # optional: a sample library for Render audio
  • Page view breaks systems onto pages with a title block. Panorama lays the whole score on one line.
  • Play previews the score with the browser's audio from the selected measure, following tempo marks, swing, dynamics and hairpins, ties, articulations, ornaments, tremolos, rolled chords and the sustain pedal. The preview plays the same notes at the same moments as rendered audio and exported MIDI. The playhead follows the music. Choose a slower or faster playback tempo without changing the score.
  • Mixer opens a strip for each part with a volume slider, Mute and Solo. The preview follows it at once, and Render audio applies the same mix to the file.
  • Parts shows the full score or one part.
  • Concert pitch appears when a part transposes. Transposing parts are shown at written pitch by default; the toggle shows every part as it sounds. Instruments that transpose only by octaves, such as piccolo, guitar and double bass, keep their written octave in both views.
  • Notes outside an instrument's playable range are drawn in red.
  • When one part is shown, runs of empty measures become multi-measure rests with the count above. [layout].multirests turns that on or off, and [layout].spacing (0.5 to 2.5) tightens or loosens the horizontal spacing.
  • Scores of up to 200,000 notes and rests are engraved. A long score draws only the pages near the part you are looking at, so scrolling stays quick.

Document setup

The page view lays the music out for a sheet of paper. Without any setup it is A4 portrait with a 7 mm staff and 14 mm side margins:

[layout]
page = "a4"                /* a4 | a3 | letter | legal | tabloid */
orientation = "portrait"   /* portrait | landscape */
staff_size = 5             /* staff height in millimetres, 3 to 10 */
margin = 12                /* side margin in millimetres, 5 to 40 */
hide_empty_staves = true

A smaller staff puts more measures on a system and more systems on a page, which is how a full score fits its staves; parts usually keep 7 mm. With hide_empty_staves, every system after the first leaves out the staves that only rest in it, as a conductor's score does. The two staves of a piano, harp or organ stay together, and a staff stays when a tie, slur or line continues into the system.

Rendered audio and the Media surface

Render audio turns the performance into a WAV file in the model's Files, at [playback].audio or renders/<cell>.wav. Grid renders it on the runtime: repeats and endings, tempo changes, dynamics, ties, grace notes and articulations, with each part voiced by its instrument family and placed across the stereo field. The file is 16-bit PCM at 44.1 kHz stereo; scores longer than about six minutes step down to mono and then to 22.05 kHz so the file stays within the Media surface's 64 MiB limit, and scores longer than 25 minutes are refused. Rendering an unchanged score again leaves the file untouched, and overwriting a different file asks first.

Sample libraries

Rendered audio can play recorded instruments instead of the built-in sounds. Put a SoundFont 2 file (.sf2) in the model's Files and name it in [playback].soundfont; Render audio then plays each part with the library's samples for its instrument, and the drum kit with the library's kit. A part whose instrument the library lacks keeps the built-in sound, and the status line names those parts. The mixer, the stereo placement of the parts and the hall reverb apply either way, and the same score, mix and library always produce the same file.

Grid reads the library's samples, loops, key and velocity splits, tuning, volume envelopes, panning and hi-hat cut-offs. It does not apply a library's filters, modulators or vibrato settings, so a library that depends on those sounds brighter and plainer than in a full sampler. Libraries up to 512 MiB are read; compressed (SF3) libraries are refused. The browser preview always uses its own synthesizer, so use Sound: Rendered audio to hear the library.

Export MIDI writes a Standard MIDI File beside it (renders/<cell>.mid): a conductor track with the title, tempo, time and key signatures, then one track per part with its name, instrument program and notes, repeats written out and hairpins and accents in the velocities. Percussion-clef parts use MIDI channel 10. Open it in a sequencer or another notation program.

After rendering, Sound chooses between the quick browser preview and the rendered file; the rendered file plays at the written tempo. When the score, the mix or the sample library changes, the surface says the rendering is out of date until you render again. The surface remembers the file it rendered: after a reload Sound offers it again while the music still matches.

Bind a Media surface to the same file for its waveform, spectrum, annotations and selection inputs:

kind = "media"
[source]
asset = "renders/minuet.wav"

The two surfaces follow each other. While the Media surface plays that file, the Score surface follows it with its playhead, and choosing a note moves the Media playback to that measure. While the Score surface plays the rendered file, the Media surface's cursor follows and its own player stays silent, so the file is never heard twice. The link stays in the browser; playback position is never written to the model.

Keyboard note entry

When edit names the writable input the score is parsed from, click a note and type. Each change rewrites that note's notation and the model recalculates.

Key Action
A–G Insert a note after the selection, in the nearest octave. On a transposing part the letter is read at the pitch shown.
↑ ↓ Move the note by a step in the key.
⌘/Ctrl + ↑ ↓ Move the note by an octave.
Alt + ↑ ↓ On tablature, move the note to the next string up or down at the same pitch.
1–8 64th, 32nd, 16th, eighth, quarter, half, whole, breve.
. Toggle a dot.
+ - N Sharp, flat, natural.
T Toggle a tie to the next note.
S > Toggle staccato or accent.
R or 0 Insert a rest.
Delete Turn a note into a rest, or remove a rest.
← → Select the previous or next note.
Shift + ← →, or Shift-click Extend the selection to a range within one part.
⌘/Ctrl + A Select the whole part.
⌘/Ctrl + C X V Copy, cut or paste.
Esc Leave note input, then clear the selection.
Space Play or pause.

With a range selected, the step, octave, string, accidental, value, dot, tie and articulation keys change every note in it in one write, and Delete turns the notes into rests so the rhythm stays. Copy puts the selection on the clipboard as notation with every value written out; tuplets, grace notes and cue notes keep their groups. Paste inserts it after the selection, or in place of an empty measure. Cut leaves rests. Only notation is accepted from the clipboard.

Mouse note entry

Note input turns clicks on the staff into notes. Choose a Value (and the dot), then:

  • Click a rest to write a note of that value at the height you click. What is left of the rest is filled with rests; in an empty measure a quarter note is followed by a quarter and a half rest.
  • Click a note to move it to the clicked line or space. In a chord the nearest note moves.
  • Shift-click a note to add a chord note at that height, or to remove the one already there.

The pitch takes the key signature's accidental and is read as shown: written pitch on a transposing part, and the displaced octave under an ottava line.

Import MusicXML loads a score from other notation software into the notation input. Choose a .musicxml, .xml or compressed .mxl file; Grid stores it under imports/ in the model's Files, converts it to notation text, and shows the title, parts and measures before anything changes. Load replaces the input's text, after which the score is edited like any other. Voices, ties, tuplets, grace notes, dynamics, hairpins, repeats and endings, lyrics, chord symbols, transposing instruments, ottava lines, pedal marks, glissandi, tremolos, cue notes, system and page breaks, and tablature tunings and string choices carry over; other layout and engraving details from the other program do not.

Editing needs the score to come directly from the input: bind MUSIC_SCORE(melody) or an excerpt of it with MUSIC_PART or MUSIC_MEASURES. A transposed or imported score is shown read-only, with the reason.

In Grid Views

A score placed in a Grid View shows through the Score surface:

SURFACE Practice
  Score minuet edit melody
  show performance
END

Score accepts edit, view, zoom, playback, audio, soundfont, multirests, spacing, page, orientation, staff size, margin and hide empty staves phrases.