Stem events file

The file in which StemDeck keeps a set’s events: planned movements of the stems, placed on the beat grid. A person can edit it, a program can write it (stemdeck-prepare-events does). This page is format version 1.

Where it lives

Beside the set’s first stem file, in the same folder:

<first stem file name without its extension>.a3events.json
  • Song/drums.wav, Song/bass.wav, … gives Song/drums.a3events.json.

  • An NI Stems file drops the whole .stem.mp4: Song.stem.mp4 gives Song.a3events.json.

  • One file per set; all four stems are in it. It travels with the library, to any deck host. There is no file when a set has no events (StemDeck deletes it when the last event goes).

Layout

UTF-8 JSON, one object:

{
  "version": 1,
  "events": [
    {
      "stem": 1,
      "beat": 64.0,
      "shape": "orbit",
      "bars": 4,
      "reversed": true,
      "seed": "1311768467463790320",
      "active": true,
      "origin": "prepared"
    }
  ]
}

Field

Type

Meaning

version

integer

the format version, here 1

events

array

at most 512 events (see Limits)

Per event, all eight fields are required:

Field

Type

Meaning

stem

integer, 0 to 3

the stem, in the set’s order (the first stem file is 0). An event with another number is skipped when the file loads (that event only)

beat

number

where the event starts, in beats of the deck’s grid counted from the grid’s first beat (the track’s one); a decimal, negative before the one. There is no time in the file: a grid corrected by hand moves the events with the music

shape

string

orbit, ping, rise or scat

bars

number

how long the movement runs, in bars: 0.5, 1, 2, 4 or 8. Any other value, and anything that is not a finite positive number, plays as 4

reversed

boolean

true: ORBIT runs the other way round. ping, rise and scat ignore it in this version

seed

string of decimal digits

decides the random course of scat, so a prepared track scatters the same way every time. Other shapes keep it but do not use it

active

boolean

false: the event is kept but does not fire (shown dimmed)

origin

string

hand (placed or recorded by the DJ) or prepared (written by a preparation tool)

The seed is a string

A seed is an unsigned 64-bit number. JSON numbers are read as 64-bit floats by most tools, which lose digits above 2^53, so the seed is written as a string ("seed": "42", not "seed": 42). A reader accepts only digits, at most 2^64 - 1; anything else makes that event invalid.

One event per slot

A slot is one stem at one beat. Two events on the same slot (within a millionth of a beat) cannot exist: the second one in the file is dropped when the file is read. Events are kept sorted by beat, then stem.

Limits

  • At most 512 events per set. Further events in a file are dropped. When the list is full, recording refuses a new event (LIST FULL).

  • A set without a beat grid has no events: the app neither records nor fires any.

Versions

version is 1. A reader that knows version n treats a file as follows:

File

What StemDeck does

missing

the track has no events

valid, version 1

loads it; an event with an unknown shape or origin, a missing field, a bad seed or a stem outside 0 to 3 is skipped, the rest are kept

not valid JSON, no version or events, wrong types

damaged: plays the track plain, writes nothing

version above 1, however large

newer: plays the track plain, writes nothing

A damaged or newer file is never overwritten, not even after the DJ places or records something: that change then lives in memory only, and the strip says FILE DAMAGED or NEWER FILE. (NOT SAVED is for a good file whose write failed.) Move the file away to start a new one. If you edit the file by hand, keep a copy: an event that is invalid is skipped when the app loads the track, and the next save of that track writes the file without it. A valid file is written whole, atomically, so a power cut leaves the old file or the new one.

origin: hand and prepared

hand marks what the DJ made. prepared marks what a tool wrote. stemdeck-prepare-events replaces its own prepared events when it runs again, keeps every hand event as it is and does not put a prepared event on a slot a hand event holds. StemDeck itself writes hand, and a DJ’s edit in the app (a nudge, ACTIVE) turns a prepared event into a hand one. Without --replace the tool leaves a file that already has events untouched.