Lay patterns and sounds out on tracks as a song #334

New page Songs. Patterns, Instruments, Architecture, Keyboard, Home, _Sidebar and Development follow it.
admin committed 2026-10-06 16:28:46 +02:00
1 parent 340046d1c1
commit dd4bdc1795
8 files changed
+151 -16

No files matched your search

+15 -5
@@ -148,8 +148,10 @@ src/core/time.ts the global clock: one scaled step a frame, shared by the
src/core/music/ time (ticks, 480 to the quarter, tempo and meter, a position as bar, beat and tick), sequence
(the notes of a window of playing time, across the seam of a loop — a pure rule), Scheduler
(#332: plans the notes ahead on the audio clock through a host, so it is measured with a clock
of the test's own), pattern (#333: a pattern's notes, grid, meter, tempo and loop, held to
their rules, and the sequence it plays)
of the test's own; a song's sound items as clips, taken up mid-way where the playhead
lands, #334), pattern (#333: a pattern's notes, grid, meter, tempo and loop, held to
their rules, and the sequence it plays), song (#334: tracks and items held to their rules,
the sequence a song plays, the level of a track's bus, an item cut at a tick)
src/runtime/ GameRun (one run: start, tick, `Load scene` — shared by Play and a released game, #266),
World, Entity, System interface, Input tracker, CollisionSystem (the editor run's detection),
solids (what `Move` collides with and how it slides — one-way solids let it through unless
@@ -206,8 +208,10 @@ src/viewport/ WorldViewport (the drawing of a world or a holder, the ba
SoundLibrary + pitchWorklet (the AudioWorklet that plays a way with a Pitch through
core/soundfx/pitchPlayer, a phase vocoder, #317; a note of an instrument is one voice
of what reaches its Output, each way with its own file, #331; a voice can start and be released
at a second of the audio clock, #332), music (the scheduler on the library's clock, its
notes played by the project's instruments: the Pattern tab's player, #333, and `__gm.music`) + musicTimer
at a second of the audio clock, #332; a clip of a song from a second into its sound until
its end, a bus per track of a song with its level and pan, #334), music (the scheduler on
the library's clock, its notes played by the project's instruments and its clips by
the library: the player of the Pattern and Song tabs, #333/#334, and `__gm.music`) + musicTimer
(the Web Worker whose interval is the scheduler's beat, #332), ShaderLibrary, ParticleLibrary,
particles (one ParticleContainer per source), tilemap (one container per layer),
shaderPicture (the picture a shader is laid over when it shades a camera's frame, #299, or
@@ -342,7 +346,13 @@ src/editor/pattern/ PatternEditor (header: Play, Grid; plays through the sche
PianoRoll (keys, ruler, notes and velocity lane in one widget, the gestures and keys) +
rollView (its geometry: rows, hits, bands) + rollEdit (what a gesture does to the notes)
src/editor/music/ timeView (the time axis: ticks to pixels, zoom, the lines of bars, beats and grid) + TimeRuler
(bars, loop, start and playhead) — for the piano roll and the song tab (#334)
(bars, loop, start and playhead) — for the piano roll and the song tab — + transport (one
piece plays at a time: a song or a pattern, #334)
src/editor/song/ SongEditor (header: Play, Grid; plays through the scheduler, sets the tracks' buses and
follows edits, #334), SongTimeline (heads, ruler and lanes in one widget, dropping assets
in, the gestures and keys) + songView (its geometry: tracks, items and their ends, the
parts of a head) + songEdit (what a gesture does to the items) + songActions (deleting
tracks and items, shared with the inspector and Delete)
src/editor/tile/ TileEditor (header + kind), TileCanvas (every tile of the block and a sample map, animated),
PictureStrip (the pictures as animation steps; its reorder maths is `dropIndex` in ui/sortable),
TilePalette (the tiles as a grid of pictures in the tilemap panel, #139)
+1 -1
@@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun
# has and the web server's container has not (SKIP there)
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
php tests/php/releases.test.php # the release store (#266), the same way
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1799 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1817 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result
+1
@@ -24,6 +24,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
| [Sounds](Sounds) | Uploading a sound, what the asset says, `Play sound` and `Stop sound`, sound FX (gain, pitch, EQ, mix, delay) and how long a voice rings on, what a pause and a stop do to a voice |
| [Instruments](Instruments) | The instrument asset: Notes, Sample, Parameters, Sound FX, Envelope and Output, triggers, zones and layers, the keys of the Instrument tab, `Play note` |
| [Patterns](Patterns) | The pattern asset and its piano roll: drawing, moving and lengthening notes, the grid, the ruler with start and loop, velocities, playing it in a loop |
| [Songs](Songs) | The song asset: tracks with volume, pan, mute and solo, pattern and sound items laid out, moved, cut and split, playing it in a loop |
| [Animations](Animations) | Animation assets, the Animation tab, how they run |
| [Curves](Curves) | Easings drawn by hand, the Curve tab, using one on a key or a `Lerp` |
| [Tiles](Tiles) | The tile asset, plain tiles and the two autotile kinds, the pictures as animation steps, the Tile tab |
+3 -3
@@ -1,7 +1,7 @@
An **instrument** (**+ → Instrument**, #331) makes a note a sound. It is a node graph like a
[sound FX](Sounds#sound-fx): **Notes** nodes bring the note in, a **Sample** plays a sound for it,
the effects of a sound FX shape it and the **Output** is what is heard. It is the first piece of
the music tools planned in #330: a [pattern](Patterns) (#333) plays one, and a song (#334) will.
the music tools planned in #330: a [pattern](Patterns) (#333) plays one, and a [song](Songs) (#334) lays patterns out.
A behavior plays one with **Play note**, and the tab plays it from its keys.
Instruments are listed under **Instruments** in the asset panel, patterns under **Patterns**.
@@ -194,7 +194,7 @@ different instruments, `Play note` warns.
The **scheduler** (#332) plays notes of instruments in time, on the clock of the sound rather than
the game's, so a slow frame or a busy page never moves a note. The Pattern tab plays a
[pattern](Patterns#playing) with it, a song (#334) will, and the check scripts drive it directly
[pattern](Patterns#playing) with it, the Song tab a [song](Songs#playing), and the check scripts drive it directly
(`__gm.music`).
- **Ticks.** Musical time is counted in ticks, **480 to the quarter note** as in MIDI files: a
@@ -227,6 +227,6 @@ the game's, so a slow frame or a busy page never moves a note. The Pattern tab p
## Not yet
No oscillators or 8-bit sources (#329), no songs (#334), no swing. An Envelope
No oscillators or 8-bit sources (#329), no swing. An Envelope
shapes notes of an instrument only, not a sound played through a sound FX. Notes can not be played from an `.mid` file or a MIDI
keyboard.
+1 -1
@@ -8,7 +8,7 @@ without it, before anything else those keys do ([Behaviors](Behaviors)) ·
under the pointer ([Scene editing](Scene-editing), [Behaviors](Behaviors)) · `Ctrl+V` import an image from
the clipboard as a texture when nothing copied fits the tab (ignored while a text field has focus) · Animation tab: `Ctrl+C` copy
the picked keys, `Ctrl+V` paste them at the playhead (while keys are copied this takes `Ctrl+V`
there, so an image is pasted from another tab), `Ctrl`+drag duplicate keys · Pattern tab: `Space` play/stop, `Ctrl+C`/`Ctrl+V` copy the picked notes and paste them where playing starts, `Ctrl+D` duplicate them behind themselves, `Ctrl+A` pick all, `↑`/`↓` a semitone (`Shift` an octave), `←`/`→` a grid step (`Shift` a bar), `Alt` while drawing, moving or lengthening leaves the grid ([Patterns](Patterns#drawing-and-editing)) · `Tab` / `Shift+Tab` cycle fields (in the Game tab with no field focused, Tab is a game key like any other, and the key field of `On key down` takes it too) · lists: `↑`/`↓` move,
there, so an image is pasted from another tab), `Ctrl`+drag duplicate keys · Pattern tab: `Space` play/stop, `Ctrl+C`/`Ctrl+V` copy the picked notes and paste them where playing starts, `Ctrl+D` duplicate them behind themselves, `Ctrl+A` pick all, `↑`/`↓` a semitone (`Shift` an octave), `←`/`→` a grid step (`Shift` a bar), `Alt` while drawing, moving or lengthening leaves the grid ([Patterns](Patterns#drawing-and-editing)) · Song tab: `Space` play/stop, `Delete` the picked items (else the picked track), `Ctrl+C`/`Ctrl+V` copy the picked items and paste them where playing starts, `Ctrl+D` duplicate them behind themselves, `Ctrl+E` split them where playing starts, `Ctrl+A` pick all, `↑`/`↓` a track, `←`/`→` a grid step (`Shift` a bar), `Alt` while moving or sizing leaves the grid ([Songs](Songs#laying-out-and-editing)) · `Tab` / `Shift+Tab` cycle fields (in the Game tab with no field focused, Tab is a game key like any other, and the key field of `On key down` takes it too) · lists: `↑`/`↓` move,
`←`/`→` fold, `Enter` activates · number
fields: drag to scrub (`Shift` x10, `Alt` x0.1, snapping to the grid of that increment, so a
step-1 field lands on whole numbers), `↑`/`↓` step, shown with at most three decimals and without trailing zeros
+6 -6
@@ -1,6 +1,6 @@
A **pattern** (**+ → Pattern**, #333) is a stretch of notes for one [instrument](Instruments),
drawn in a piano roll. It is the second piece of the music tools of #330: a song (#334) will lay
patterns out on tracks, and several songs and tracks can use the same pattern.
drawn in a piano roll. It is the second piece of the music tools of #330: a [song](Songs) (#334)
lays patterns out on tracks, and several songs and tracks can use the same pattern.
Patterns are listed under **Patterns** in the asset panel, the instruments under **Instruments**.
A new pattern is empty: four bars of 4/4 at 120 BPM, drawn on a 1/16 grid, with no instrument yet.
@@ -15,7 +15,7 @@ The notes and the loop are the pattern's own data; everything else is a row in t
| **Length (bars)** | 1 to 256 bars. A note starting at the end or behind it is kept, drawn faint, and not played; a note reaching past the end is cut off there. |
| **Grid** | What a note is drawn and moved on: 1/1 to 1/32, and the triplets 1/4T to 1/32T. The tab's header has the same choice. |
| **Beats per bar**, **Beat** | The meter, any one: 3/4, 6/8, 7/8. It only says where the bars and beats of the ruler are; the notes are kept in ticks, so a pattern changed from 4/4 to 6/8 keeps every note where it was. |
| **Tempo (BPM)** | 20 to 400, quarter notes a minute, for hearing the pattern in its tab. A song will play it at its own tempo. |
| **Tempo (BPM)** | 20 to 400, quarter notes a minute, for hearing the pattern in its tab. A song plays it at its own tempo. |
A note is a start and a length in ticks (480 to the quarter note, see
[Playing in time](Instruments#playing-in-time)), a note number (60 is C4) and a velocity from 0 to 1.
@@ -121,8 +121,8 @@ Its notes fade out in 10 ms; with **Let ring** a note of an instrument with an
naming no sound it stops everything, patterns included, and its `voice` takes a `playback`. The end
of the run stops every pattern.
This is a step ahead of songs: a song (#334) will play several patterns on tracks, and a game will
play a song (#336). A pattern has no tempo input in the game yet, and nothing tells a graph that a
This is a step ahead of songs in a game: a [song](Songs) plays several patterns on tracks in the
editor, and a game will play a song (#336). A pattern has no tempo input in the game yet, and nothing tells a graph that a
pattern played once has ended.
Measured (2026-10-06, e2e 64): a bar of quarters at 150 BPM played by `Play pattern` in a game was
@@ -131,6 +131,6 @@ once it was gone by itself after its bar.
## Not yet
No notes of other patterns in the background (ghost notes, with the song, #334), no lanes for
No notes of other patterns in the background (ghost notes), no lanes for
pitch bend or an instrument's parameters (automation, #337), no swing. The computer keyboard does
not play notes in this tab as it does in the Instrument tab, and there is no step input.
+123
@@ -0,0 +1,123 @@
A **song** (**+ → Song**, #334) lays [patterns](Patterns) and [sounds](Sounds) out on tracks along
one time axis. It is the third piece of the music tools of #330, after the instrument (#331) and the
pattern (#333). Several songs and tracks can use the same pattern: an edit to it is heard everywhere
it lies.
Songs are listed under **Songs** in the asset panel. A new song has four empty tracks, 120 BPM in
4/4, and items snap to the bar.
## What a song says
The tracks, the items and the loop are the song's own data; everything else is a row in the
inspector.
| Row | What it does |
|---|---|
| **Tempo (BPM)** | 20 to 400, quarter notes a minute. The song plays every pattern at this tempo; the tempo set on a pattern is only for its own tab. |
| **Beats per bar**, **Beat** | The meter of the ruler. Items are kept in ticks, so a change only moves the bar lines. |
| **Grid** | What items snap to: **Bar** (the default), or one of the grids of a pattern, 1/1 to 1/32 and the triplets. The tab's header has the same choice. |
One tempo and one meter hold for the whole song. A change of tempo within a song would come with
automation (#337).
### Tracks
A track has a name, a **volume** from -60 to +6 dB, a **pan** from -1 (left) to 1 (right), **mute**
and **solo**. While any track is soloed, only the soloed ones are heard. Each track is heard on a bus
of its own: a change of volume, pan, mute or solo reaches what is sounding on it at once, not only
the next note. A song keeps at least one track. There are no effects on a track yet, that needs the
master bus of #325.
### Items
An item lies on a track, from a start for a length, both in ticks (480 to the quarter note). A track
takes both kinds, mixed.
| Kind | |
|---|---|
| **Pattern** | Plays the pattern's notes. Longer than the pattern, it repeats it; it plays the whole pattern, the loop set on its ruler is for editing. **Transpose** moves every note by semitones (-48 to 48). **Instrument** plays it with another instrument; empty, the pattern's own. |
| **Sound** | Plays the sound as a clip, at its own speed whatever the tempo. Longer than the sound, it repeats it. A **Sound FX** sends it through an effect. |
Every item has a **volume** from -60 to 0 dB on top of its track's. An item whose pattern or sound
has been deleted stays, drawn red as *missing*, and plays nothing.
An item cut back from its left end keeps what it plays where it was: it starts that far into its
pattern (in ticks) or its sound (in seconds). A split does the same with the right-hand part.
## The Song tab
Down the left are the **heads** of the tracks: the name, **M** (mute, orange when on) and **S**
(solo, yellow when on), below them the volume (the line marks 0 dB) and the pan (the line marks the
middle). Under the last track, **+ Track** adds one. Along the top is the **ruler**, as in the
Pattern tab. Between them are the **lanes** with the items: a pattern blue with its notes drawn
small, every round it plays; a sound green with its waveform, from where it starts in it. A picked
item has a white edge; a picked track a lit head and lane.
The header has **Play** (it turns into **Stop**), the **Grid**, **Fit** and on the right the number
of tracks and items. **Fit** shows the whole song across.
What is picked goes to the inspector: an item shows its pattern or sound, its volume and the rows of
its kind, a track its name, volume, pan, mute and solo. Both have a button to delete them.
### Laying out and editing
| Do this | And this happens |
|---|---|
| Drag a pattern or a sound from the Assets panel onto a lane | A frame shows where it lands; let go and it lies there, on the grid line before the pointer, as long as the pattern or as the sound at the song's tempo, picked. |
| Drag an item by its body | It moves along the grid and to the track under the pointer, the other picked items with it. |
| Drag an item by its right end | It takes the length to the grid line nearest the pointer, the other picked items lengthen by as much. |
| Drag an item by its left end | It is cut back (or pulled out again) at the front; what it plays stays where it was. It can be pulled out no further than the start of what it plays. |
| Hold `Alt` while moving or sizing | Off the grid, on the tick. |
| Drag on empty lanes | A band; the items it touches are picked. With `Shift` they are added. |
| Click an empty lane | Picks its track. |
| `Shift`-click an item | Adds it to the pick or takes it out. |
| Right-click an item | Deletes it; dragging on with the right button deletes every item it passes. |
| Double-click a pattern item | Opens the pattern in the Pattern tab. |
| Click **M** or **S** in a head | Mutes or solos the track. |
| Drag along a head's volume or pan | Sets it; while the song plays it is heard as it moves. |
| Right-click a head | *Add track above*, *Add track below*, *Move up*, *Move down*, *Delete track*. |
Every drag is one undo step, and so is every key below that changes the song.
| Key (the lanes focused) | |
|---|---|
| `Space` | Play or stop. |
| `Delete`, `Backspace` | Delete the picked items; with none picked, the picked track and what lies on it. Never the song itself. |
| `Ctrl+C`, `Ctrl+V` | Copy the picked items; paste them where playing starts, on the tracks they came from. The copy works for every song of the project. |
| `Ctrl+D` | A copy of the picked items right behind them, moved by whole grid steps, picked in their place. |
| `Ctrl+E` | Split the picked items where playing starts; the right-hand parts are picked. |
| `Ctrl+A` | Pick every item. |
| `↑` / `↓` | The picked items a track up or down. |
| `←` / `→` | The picked items a grid step earlier or later, with `Shift` a bar. |
| `Esc` | Pick nothing. |
The ruler, zoom and scrolling work as in the [Pattern tab](Patterns#the-ruler): a click sets where
playing starts, a drag the loop, a right-click offers *Loop bar N* and *Loop the whole song*; the
wheel scrolls, with `Shift` across, on the ruler or with `Alt` it zooms the time. With no loop set
the whole song is the loop: up to the bar after its last item, and at least four bars.
## Playing
**Space** or **Play** plays the song round its loop from where playing starts, through the
scheduler (#332), every note and clip planned ahead on the clock of the sound. Started inside a
sound item, the clip starts that far into its sound; so it does again after every jump back to the
start of the loop. At the end of the loop a clip is faded out in 10 ms, a note gets its release
(see [Envelopes](Instruments#envelopes)), echoes ring on. An edit while it plays is heard from the
next window on, without starting over; a track's volume, pan, mute and solo at once.
The editor plays one piece at a time: playing a pattern stops the song, and playing the song stops
a pattern. Playing goes on while another tab is open; it stops when another song is shown in the
tab, when the song is gone and when a project is opened.
Measured (2026-10-06, e2e 65 on the CI's Windows machine): a sound clip on the first track and a
pattern at bar 3 on the third, at 120 BPM, were planned 4 s apart, the pattern's notes 1 s apart,
each on the bus of its track; a track turned down to -6 dB was set to 0.501 on its bus, and muting a
track while the song played set its bus to 0.
## Not yet
A game cannot play a song yet: that is #336 (a pattern it can, see
[Playing one in a game](Patterns#playing-one-in-a-game)). No automation (#337), no markers in the
ruler (with game sync, #338), no effects on a track (#325), no song inside a song, no held note
(drone) as an item. A pattern item cannot be made into a pattern of its own (*make unique*); for a
variation, duplicate the pattern in the Assets panel and pick it on the item.
+1
@@ -15,6 +15,7 @@
- [Sounds](Sounds)
- [Instruments](Instruments)
- [Patterns](Patterns)
- [Songs](Songs)
- [Animations](Animations)
- [Curves](Curves)
- [Tiles](Tiles)