A Song as Sheet Music

A tracker song is a grid of rows. Written music is beats and bars. notation turns one into the other, and follows the song as it plays.

const song = await loadJSON("songs/night_drive.json")
const page = showNotes(song, { channels: [3, 1] })      // the tune and the bass, a staff each

function onMouseDown() {
  page.play()                                           // the page plays the song itself, and follows it
}

function draw() {
  background("#0b1020")
  text(page.bar ? "bar " + page.bar : "Click to start the song", width / 2, height - 24, "white", 18, "centre")
}

A page that shows a song plays the song itself. page.play() hands the song to the sound library, which plays it with its own instruments, round and round, and the page follows. There is no playSong to write, and a Python scene needs no from synths import * for it.

As the song plays, the notes that are sounding light up and a line moves through the bar. Tap a bar and the song jumps there. Tap a note to hear it.

To do thisJavaScriptPython
Play it oncepage.play({ repeat: false })page.play(repeat=False)
Say what the song's synths areshowNotes(song, { patches: { tune: "bell" } })show_notes("tune.json", patches={"tune": "bell"})
Follow a song you started yourselfshowNotes(song, { follow: playSong("tune.json") })show_notes("tune.json", follow=play_song("tune.json"))

page.bar is the bar the song is in, counted from 1. It is 0 until the music has begun.

The song is our own JSON kind. A MOD or XM file is shown once the sound library has packed it into one; a file that has not been packed is refused, in plain words that say so.

Choosing what to show

JavaScriptPythonWhat it does
channelschannelsWhich channels to show, counted from 0, in the order you want the staves
instrumentsinstrumentsOnly these instruments, by number or name
drumsdrumsWhich instruments are drums, by number or name. Left out, an instrument called kick, snare, hat and the like is one
grandgrandtrue: the tuned channels together on a grand staff
rowsPerBeatrows_per_beatHow many rows make a beat, when the song's speed does not say it right
const written = await loadJSON("songs/night_drive.json")
showNotes(written, { grand: true, paper: "dark" })

How rows become written music

This is what notation does, and where it guesses.

  • A row is a fixed written length. Four rows are a beat (so a row is a sixteenth note) at a song speed of 6, eight at 3, two at 12. rowsPerBeat says otherwise. The tempo written is the tempo that results.
  • A note lasts until the next note on its channel, a note-off, a volume of nothing, or the end of its sample if the sample does not loop, and never more than two bars. A note let go a row before the beat is written to the beat, as a player would write it.
  • A bar is a time signature's worth of rows: 4/4 unless you say time.
  • Lengths that are not one note are written as notes tied together, split so that every beat (and the middle of a 4/4 bar) can be seen. Short notes are beamed a beat at a time.
  • The key is the one that leaves the fewest sharps, flats and naturals to write; key says otherwise. The clef of each channel is the one its notes sit best in, written an octave away (with a small 8) if they are very high or low.
  • A chord whose notes sound together is written as a chord. An arpeggio is written as its chord with a wavy line beside it, not as dozens of tiny notes. (In a song of the older format, version 1, a chord on a note is always an arpeggio, and is written that way.)
  • A note that is slid to is not a new note. Notes that slide or bend are written as the notes they start from: the slide itself is not shown.
  • Drums are instruments called kick, snare, hat, tom, crash and the like, or the ones you name in drums. A channel that is mostly drums gets a percussion staff, each drum in its own place, with crosses for cymbals.

What is not written

  • Slides, vibrato and other effects that bend a note.
  • Pattern loops.
  • Triplets, and other lengths that are not halves of halves: they are written to the nearest thirty-second.
  • Two rhythms at once on one staff. A staff has one rhythm, so a grand staff made of several channels takes the notes that begin together as a chord, and ends each where the next begins.