Plainsong

A keyboard-first music editor that writes plain-text .track files — composed as single notes on a pitch×time sheet, played back at runtime by game-audio. Built for game leitmotifs, and it can sing.

Who this is for. This tutorial skips the obvious (there is a Play button) and focuses on the features you would otherwise never find: the isomorphic piano keyboard, record-driven composition, singing voices with phonetic lyrics, reusable leitmotifs, custom tunings, and the source-only cross-file features.

The whole document is a text file. Every visual edit reserializes it; the Source view lets you edit the text directly and an AI can edit either side. Nothing is hidden in a binary blob.

The Sheet

There is one canvas for everything. Each note is a horizontal line: Y = pitch (rounded to semitones), length = duration, color = instrument (hashed to a hue), and a sloped line means glide. The left pitch gutter is a mini piano keyboard — black keys shaded, every C labelled (C4, C5…).

Placing notes

ActionResult
Click empty gridPlaces a snap-length note at the snapped position, and auditions it
Drag on empty gridPlaces a note and sets its length live as you drag (draws it as a stroke)
Ctrl + drag on empty gridRubber-band multiselect — selects every note the box touches
Drag a note bodyMoves it (multi-note moves respect overlap rules)
Drag a note's right edgeResizes its duration
Ctrl + drag a noteDuplicates the selection and drags the copy
Click overlapping notesCycles the selection through the stacked notes under the cursor
Shift + click a noteToggles it in/out of the selection
The one collision to know: plain drag places a note; Ctrl+drag is the rubber-band select. If you meant to select and got a note, you forgot Ctrl.

Snap & stacking

The Snap combo in the toolbar quantizes placement: Off, 1, 1/2, 1/3 (triplet), 1/4 (default), 1/6 (triplet), 1/8. Hold Shift during any click or drag to override snap for free positioning — Shift also disables pitch rounding, so you can place microtonal pitches between the semitone lanes.

Notes on the same pitch that overlap in time are drawn in parallel sub-lanes so nothing hides behind anything else. Draw order is inactive → active → selected.

Keyboard reference

Everything is reachable from the keyboard. Shortcuts are suppressed while a text field is focused.

KeysAction
SpacePlay / Stop
Ctrl+Z · Ctrl+Shift+Z / Ctrl+YUndo / Redo
Ctrl+C · Ctrl+VCopy · Paste (at the playhead, keeping relative offsets)
Ctrl+DDuplicate selection (offset +0.5 beat)
Delete / BackspaceDelete selection
EscExit motif/instance editing, else clear the selection
/ Seek one beat back / forward (Shift: one bar) — also while playing
19Focus layer by index piano off
PageUp / PageDownFocus previous / next layer (wraps)
Ctrl++ · Ctrl+- · Ctrl+0Zoom in · out · reset (both axes together)
Ctrl+wheel · Shift+wheelZoom · swap scroll axis
Ctrl+N/O/S · Ctrl+Shift+S/ONew · Open · Save · Save As · Reload
Ctrl+T · Ctrl+WNew document tab · Close tab (asks before discarding the last unsaved one)
Ctrl+PageUp / PageDownPrevious / next document tab
Ctrl+Q · Ctrl+Shift+QQuit · Force-quit

Real zoom. Ctrl+wheel scales both pixels-per-beat and semitone height, so notes get physically bigger — not just horizontally stretched. Ctrl+0 resets height and re-fits the song horizontally.

Piano mode

Piano (on by default, toolbar toggle) plays the active sound from the computer keyboard. The layout is isomorphic and uses physical key positions, so it is independent of your keyboard layout. Two rules:

Up one QWERTY row = +1 semitone. Right one key = +3 semitones.

The F key is the base pitch (0). The grid below shows the semitone offset of every key before the octave shift:

1−11
2−8
3−5
4−2
5+1
6+4
7+7
8+10
9+13
0+16
Q−10
W−7
E−4
R−1
T+2
Y+5
U+8
I+11
O+14
P+17
A−9
S−6
D−3
F0
G+3
H+6
J+9
K+12
L+15
;+18
Z−8
X−5
C−2
V+1
B+4
N+7
M+10
,+13
.+16
/+19

When Piano is on, the toolbar shows Oct +N + to shift the whole keyboard by octaves. (The number-row layer-focus shortcuts are disabled while Piano is on, since those keys now play notes.)

Record-driven composition

Rec is on by default — every piano key you press writes a note at the insert line. Toggle Rec off in the toolbar to play without writing (trying out sounds, hunting for the next note). This is the fast way to compose:

Singing voices phoneme-synth

Any sound can become a voice that sings its notes' lyrics. In the sound designer, pick the Voice preset: none (synth), male, female, child, robot, or ghost. A voice sound ignores the harmonics/envelope below it — it is synthesized by phoneme-synth instead.

Four voice knobs fine-tune the timbre, each seeded from the preset with a reset:

KnobRangeWhat it does
Formant0.5 – 2.0Shifts the vocal tract size (smaller = more childlike/chipmunk)
Tilt0.0 – 1.0Spectral tilt — brightness vs. darkness of the voice
Breath0.0 – 1.0Breathiness mixed into the tone
Vibrato0.0 – 1.0Pitch vibrato depth

Lyrics & phonemes

Each note carries a Lyric (in the note inspector), written in phonetic symbols. New notes on a voice sound default their lyric to la so they always sing something. The lyric is drawn right on the note in the sheet.

The phonetic alphabet:

Vowels

aeiou@äöü

Voiced

mnlrjq (ng)

Noise

sc (sh) fx (ach) zw (v)

Plosives

ptkbdg

A lyric can hold more than one syllable: spaces separate words and ' separates syllables within a wordhal'lo du sings a two-syllable word and then another word, all sharing the note's duration. A leading ' ties the note to the previous note on the same sound: the run is sung as one legato phrase (syllables flow into each other), drawn as a small tie arc between the notes in the sheet. Without it every note starts a fresh phrase.

Because lyrics live on ordinary notes, a sung line inherits everything else notes have: glide, volume ramps, layer effects, motif reuse. Auditions sing too — placing or pitch-dragging a voice note sings its lyric instead of falling back to the synth.

Leitmotifs

A motif is a named, reusable group of notes — the core feature for game music. Compose it once, drop transposable instances wherever it recurs, and vary it at runtime in the game.

  1. + Motif in the library creates one and drops you into edit mode: the song fades out and you place the motif's notes in the sheet exactly like normal notes (inside a labelled Motif: name box).
  2. Esc, clicking the motif again in the library, or clicking a layer tab leaves edit mode.
  3. Place on layer drops an instance at the playhead. Instances render as a ♪ chip outlining their span — drag to reposition and transpose, double-click to edit that instance's overrides.
  4. The instance inspector sets its sound, start, transpose, and tuning. If the instance's sound is a voice, empty motif-note lyrics fill with la — so a leitmotif can sing.
Per-instance overrides & trim. Double-click an instance's ♪ chip (or hit Edit notes in sheet in its inspector) to enter instance editing: drag this placement's notes and the changes are stored as overrides on the instance — the motif itself stays untouched, other placements keep playing the original. Delete resets selected notes back to the motif. The inspector lists every override field by field (× removes one) and sets Trim (from/count) to keep only a contiguous range of the motif's notes; trimmed notes render faded while editing.

Custom tunings

Beyond 12-TET, define your own scales. In the Tunings library: + Tuning creates one; the inspector sets:

Assign a tuning per layer with the Tun combo on each layer card, and set that layer's Root frequency in Hz. Motif instances can override tuning too. Deleting or renaming a tuning cascades to everything that referenced it.

Layers & effects

Layers are mix groups, not composition containers — you compose in the sheet with the active sound, and which layer a note belongs to is just an attribute. New documents start with one layer; the concept only surfaces when you need it.

Each layer card (above the grid) has: name (click to focus, Shift/Ctrl+click to toggle active for editing), M mute, S solo, Vol, Pan, Tun, Root. Inactive layers render faded and non-interactive.

The layer inspector adds the runtime semantics that the game switches:

Move a note to another layer with the Layer combo at the top of the note inspector.

Loop region, playhead & audition

Sound designer

Selecting a sound opens a full synth editor (non-voice sounds):

Source view & cross-file playback

Toggle Source to open a live text editor beside the sheet. Every visual edit reserializes it; every text edit reparses live (errors show in red and block playback). It is the only place to reach the source-only features:

Files open as document tabs in the top bar (Ctrl+PageUp/PageDown to cycle). Drop a .track file to open it; drop an audio file (WAV/MP3/OGG/FLAC) to attach it as a clip on a new layer; drop a .mid to import it (below). External changes auto-reload unless you have unsaved edits.

MIDI import

Drop a .mid / .midi file onto the window — or use Import MIDI in the toolbar — to convert a Standard MIDI File into a new song in its own tab. The conversion (from game-audio) carries over:

The first tempo wins — later tempo changes are dropped with a warning in the status bar. The imported song pulls its instruments from the shared bank via @import sounds/all.track, so provide that bank next to where you save (or remap the sounds) for playback; until then the sheet still shows every note, colored by instrument. Save as .track like any song.

Audio export

Export Audio in the toolbar renders the whole song to a .wav or .mp3 file — pick the extension in the save dialog. Everything is synthesized offline exactly as it plays, so the export is shareable and usable anywhere, not just in a game running game-audio. The .track file stays the editable source; the audio file is the baked result.


Plainsong is free software. Source: gitlab.com/porky11/plainsong. The runtime is game-audio.