The postfix drum automaton

An experimental programmable drum machine

Programming the machine

Language syntax

Each of the eight tracks is programmed using a custom stack-oriented programming language. The language operates over a Stack of numbers. A Stack is a data type which you can add to the top of ('push'), and remove from the top of ('pop').

To evaluate a program, the interpreter executes each word in the program in order:

  • Numbers are pushed to the stack.
  • Operations are executed and can pop zero or more numbers from the stack. The result of the operation is pushed to the stack.
  • return stops the program executing.
  • if <expression> then only executes <expression> if the number on top of the stack is non-zero.
An example [click to expand]

Given the initial stack [] and the program 1 2 +, the interpreter would execute the following steps:

  1. Push 1 to the stack: [1]
  2. Push 2 to the stack: [1, 2]
  3. Execute the + operation, which pops two numbers from the stack and pushes the sum: [3]
A more complicated example [click to expand]

Given the initial stack [] and the program 1 if 0 return then 2, the interpreter would execute the following steps:

  1. Push 1 to the stack: [1]
  2. Execute the if operation, which pops the top number from the stack and checks if it is non-zero. Since it is, the interpreter runs the code up to the then block: 0 return. This pushes 0 to the stack and exits: [0]
  3. Since we've returned early, the code after the then block is not executed, so 2 isn't pushed to the stack.

The drum machine

Internally, the drum machine has a clock, which increments 24 times per beat. The number of beats per minute (BPM) is configurable.

On each increment, each track's program is called, with the current clock value passed as the only item on the stack.

24 times per beat is too fast for most music, so the built in operations 4n and 8n, and 16n are provided, which return early unless the current clock value is for a quarter note, eighth note, or sixteenth note. Most patterms will start with one of these operations.

Built-in Operations

These operations are built into the interpreter itself.

OpDescription
+Adds two numbers
-Subtracts the number on the top of the stack from the number below it
*Multiplies two numbers
/Divides the number on the top of the stack by the number below it
=Returns 1 if the two numbers are equal, 0 otherwise
!=Returns 1 if the two numbers are not equal, 0 otherwise
<Returns 1 if the number on the top of the stack is less than the number below it, 0 otherwise
>Returns 1 if the number on the top of the stack is greater than the number below it, 0 otherwise
modReturns the remainder of the division of the number on the top of the stack by the number below it
rndReturns a random number between 0 and 1
rrngReturns a random number between the two numbers on the stack
dupDuplicates the number on the top of the stack
swapSwaps the two numbers on the stack
dropRemoves the number on the top of the stack

Custom Operations

These operations are defined in the language itself, and can be used in patterns. You can define your own.

NameBody
4ndup 24 mod 1 != if drop 0 return then 1 - 24 / 1 +
8ndup 12 mod 1 != if drop 0 return then 1 - 12 / 1 +
16ndup 6 mod 1 != if drop 0 return then 1 - 6 / 1 +