Mora

A metaobject protocol for audio-visual livecoding.

Compose temporal patterns, sound, and visuals in Common Lisp. Inspect the objects behind a performance, and extend how they behave from inside the running system.

Mora
The language: terse temporal patterns inside a running, SBCL-first Common Lisp image.
Mora Studio
Its optional native editor and performance environment, with an OpenGL canvas.
Output
Sound through SuperDirt, native shader visuals, MIDI, and optional adapters.

A short form, a running pattern

One channel, one pipeline, five decisions.

Common Lisp
(d1! (>> (s "bd [hh hh] sn hh")
         (every 4 #'rev)
         (gain 0.9)))
  1. d1! Install this pattern on channel 1 now. Evaluating the form again replaces it.
  2. >> Thread the pattern through each step, from left to right.
  3. "bd [hh hh] sn hh" Mini notation: four slots per cycle. The brackets divide the second slot in two.
  4. (every 4 #'rev) Conditionally apply rev, which reverses the score, on every fourth cycle.
  5. (gain 0.9) Annotate each event with a gain value, without changing how many events there are.

The mini-notation string over one cycle

A rhythm is not a one-time instruction. It becomes a pattern that can answer future questions about time. Press Play to hear it, and edit the form: the diagram and the sound follow.

0 Time

Patterns are questions about time.

A Mora pattern is an object that answers one question: what events are visible in this span? Spans are half-open, including their start and excluding their end. Time is expressed in cycles, and positions such as 1/3 and 7/8 can remain exact Common Lisp ratios.

A cycle is a musical coordinate, not a fixed number of seconds. The transport maps cycles to physical time using tempo. Asking a pattern for its events does not itself send audio: playback also needs a running transport, a channel, a backend, and a working receiver.

(events-in *first-pattern* (span 1/3 7/8) )

Drag the window or its endpoints, or tap the track to move the nearer endpoint. With an endpoint focused, use the arrow keys.

Events visible in the span [1/3, 7/8)
Event Whole Visible part Attack in this span
hh [1/4, 3/8) [1/3, 3/8) No, it began earlier
hh [3/8, 1/2) [3/8, 1/2) Yes
sn [1/2, 3/4) [1/2, 3/4) Yes
hh [3/4, 1) [3/4, 7/8) Yes

A span query over *first-pattern*, bound to (s "bd [hh hh] sn hh") as in the getting-started guide. The window is half-open: it includes its start (filled endpoint) and excludes its end (open endpoint). An event cut by the window keeps its whole span, and only an event whose onset falls inside the window starts a new attack. This figure is drawn by the website to explain the idea; it does not run Mora.

Patterns and time

1/8 Objects

Evaluation leaves objects you can open.

When an expression is evaluated, selected parts of it remain available as CLOS pattern objects instead of disappearing behind an opaque result. Their structure can be inspected, and the way they answer queries can be extended by adding methods in the running image.

  1. 1 Source expression
    (defparameter *example-pattern*
      (>> (s "bd sn")
          (fast 2)))
  2. 2 Retained pattern objects speed-pattern instance (s "bd sn") pattern Inspectable now: pattern-summary, pattern-children
  3. 3 A query over a span (here, cycle 0)
    (query-cycle *example-pattern* 0)
    Arbitrary spans use the lower-level events-in protocol, whose methods can be extended
  4. 4 Events with values, spans, and provenance bd [0, 1/4) sn [1/4, 1/2) bd [1/2, 3/4) sn [3/4, 1)
  5. 5 Interpretation by an output backend For sample and synthesis output: timestamped OSC to SuperDirt in SuperCollider.
What evaluation leaves behind. The source is a convenient way to construct the composition, not the whole result. Retained objects remain available for inspection and answer later queries, so a changed method changes future answers. Already-dispatched sound is not rewritten. The forms are from the public framework example file.

Introspection

Inspect the retained objects: their class, structure, children, and their answers to any span.

Common Lisp
(defparameter *pattern* (>> (s "bd ~ sn hh") (fast 2)))

(class-of *pattern*)
(pattern-summary *pattern*)
(pattern-children *pattern*)
(events-in *pattern* (span 13/4 7/2))

Intercession

Define a pattern class, install an instance, then add a method. The same object answers future queries differently.

Common Lisp
(defpattern pulse (&key (factor 1))
  "An inspectable backbeat. Example: (pulse :factor 2)."
  (fast factor (s "bd ~ sn ~")))

(defparameter *live-pulse* (pulse :factor 1))

(d1! *live-pulse*)

(defmethod events-in ((self pulse-pattern) query-span)
  (declare (ignore self))
  (events-in (s "bd hh sn [hh cp]") query-span))

Live changes affect future queries. They do not rewrite OSC bundles already dispatched, frames already rendered, or sound that has already been heard.

What remains after evaluation

1/4 Common Lisp

Terse notation, inside a real Common Lisp.

Mora is embedded in Common Lisp, not a fixed vocabulary wrapped around an engine. Functions, variables, macros, exact ratios, classes, generic functions, and the inspector are all present in the same running image. A short phrase can grow into a new operator or instrument without leaving the language.

  1. Authored pattern program (>> (s "bd sn") (fast 2)) Constructs a temporal program.
  2. Mora's retained implementation objects A speed-pattern instance, events-in, applicable methods Interpret and expose that temporal program.
  3. CLOS implementation facilities Classes, generic functions, methods Supply the metalanguage in which Mora is built.
“Metaobject” is relative to a language level. Mora's pattern objects participate in implementing the pattern language; CLOS implements those objects. Mora opens selected parts of its implementation through a protocol written in CLOS, which does not require extending the CLOS metaobject protocol itself.
defpattern
Defines a named pattern class with a constructor and observation methods.
deftransform
Defines a reusable, inspectable transformation.
Methods on events-in
Change how a class of patterns answers temporal queries, without editing a central dispatcher.
define-scale, define-chord, define-voicing
Extend the musical vocabularies with your own scales, chords, and voicings.

Common Lisp and CLOS

3/8 Sound and image

Compose more than sound.

Mora's temporal language reaches shader programming. A visual operator is also a pattern, so temporal transformations act on it too. One channel form can carry audio, a shader chain, and an ordered chain of image processing, each with its own responsibility.

Visuals can follow the score's events, or respond to measured audio. Those are different sources of information, and Mora keeps them distinct.

Common Lisp
(d1! :audio (s "bd ~ sn [hh hh]")
     :viz (>> (osc :freq 36)
              (kaleid 6))
     :post (>> (mora.visual:pixelate :px 128
                                     :py 72)
               (mora.visual:ascii :characters " .:-=+*#%@")
               (mora.visual:edge-glow :amount .6
                                      :radius 1.5)))

Shader material renders in Mora Studio's native OpenGL canvas; sound needs SuperDirt. Omitting a facet in a later edit leaves it alone.

:post chain: pixelate, then ascii

  1. Source
  2. pixelate
  3.          ...---++++++---...                   ...---++++++---...                   ...---++++++---...                   ===%%%######%%%===                   ===%%%######%%%===                   ===%%%######%%%===                ...###+++------+++###...             ...###+++------+++###...             ...###+++------+++###...             :::%%%===++++++===%%%:::             :::%%%===++++++===%%%:::             :::%%%===++++++===%%%:::             ...###+++------+++###...             ...###+++------+++###...             ...###+++------+++###...                ===%%%######%%%===                   ===%%%######%%%===                   ===%%%######%%%===                   ...---++++++---...                   ...---++++++---...                   ...---++++++---...          then ascii

:post chain: ascii, then pixelate

  1. Source
  2.             ...::::::...                        ..:-=++++=-:..                      .:-+*##%%##*+-:.                    .:=+#%%@@@@%%#+=:.                  .:-*#%%%####%%%#*-:.                 .-+#%%#*+==+*#%%#+-.                .:=#%%#+------+#%%#=:.               .-+%@#+--------+#@%+-.               .-*%%*=--====--=*%%*-.               .=*%%*---+**+---*%%*=.               :=#%%+--=+**+=--+%%#=:               .=*%%*---+**+---*%%*=.               .-*%%*=--====--=*%%*-.               .-+%@#+--------+#@%+-.               .:=#%%#+------+#%%#=:.                .-+#%%#*+==+*#%%#+-.                 .:-*#%%%####%%%#*-:.                  .:=+#%%@@@@%%#+=:.                    .:-+*##%%##*+-:.                      ..:-=++++=-:..                        ...::::::...             ascii
  3. then pixelate
Order is part of the program. Post effects operate on the preceding image in written order, so ASCII after pixelation differs from pixelation after ASCII. This schematic is computed by the website from a simple image to show the idea; it is not a capture of Mora's renderer.

Sound, visuals, and listening

1/2 Mora Studio

A native place to perform.

Mora Studio is a native Common Lisp livecoding environment. The editor and the running language share one Lisp image, so a pattern, transform, or visual operator can be inspected and redefined while the session continues. It is one way to use Mora, not a requirement.

Structural editing
Paredit operations, Lisp-aware indentation, matching parentheses, multiple cursors, and a REPL.
Documentation where you type
Live completion, ghost argument hints, signature snippets, keyword popups, and contextual documentation.
Inline views and controls
Piano rolls, punch cards, and scopes beside the code; knobs and sliders you can perform or write into the score.
The running image
An inspector, macro expansion, definition navigation, and SLYNK for remote development.
On stage
Desktop fullscreen and the zen performance layout are independent; a performance layout can put the code over the visual canvas while you keep editing.
Requirements
A driver supporting OpenGL 4.1 core / GLSL 410, plus native GLFW, libffi, and font libraries. The language itself needs no GL window.

Meet Mora Studio

5/8 Samples

Your samples, without filenames on stage.

Select loops by musical and descriptive metadata. Build stems by role, use mini notation for variants and slices, change one stem lane while the others keep playing, and request explicit tempo and key matching where the optional live engine is available.

Common Lisp
(loops :bpm-range '(130 150)
       :mode :minor)

(d1! (stack
       (>> (part :drums 0)
           (cut 1))
       (>> (stem :type :melody
                 :n "<0 1 1>"
                 :p "0 ~ 2 3 4 ~ 6 7")
           (cut 2))))

Needs an imported sample collection with metadata, and the matching sound banks loaded in SuperDirt.

Optional listening tools add other ways to find material: learned search, and PHALAR pairing that ranks candidates against an anchor recording or a capture of the audible mix. They do not replace your judgment or the original metadata, and none of them is needed to write or hear a pattern.

Samples, stems, and matching

3/4 Start
7/8 Questions

Common questions.

Is Mora only for music?
No. Its temporal model can describe sound, visuals, and other outputs. Music is a major current application, not the definition of live coding.
Is it TidalCycles or Strudel in Lisp?
It shares a temporal and notational lineage, and much of the mini notation is the same, which is why the website can play examples by translating them to Strudel. Mora's implementation, extension model, editor, native visuals, and backend contracts are its own.
Do I need to learn all of Common Lisp first?
Small pattern forms are a practical entry point. Lisp becomes especially useful when you want abstraction, inspection, or a new operator. Studio's documentation and structural tools help, but they do not make the language's concepts disappear.
Do I need Mora Studio?
No. The pattern language can be used from SBCL without OpenGL. Studio provides the integrated native editor and canvas.
Is AI required?
No. Patterns, sound output, and many visuals need no ML model. Machine learning is an optional set of tools for discovery, listening, generation, and ranking.
Where do the sounds come from?
From SuperDirt: its sample banks, its synths, and any collections you load into it. Optional models and native components are installed separately and carry their own licenses.
Can I try it without installing anything?
Partly. The Play page translates pattern forms into Strudel so you can hear them in the browser. The full language, Mora Studio, visuals, and Lisp extension run in Common Lisp; the Learn page covers setup.
What does the name stand for?
Mora is not an acronym. The name was chosen for its temporal meaning.

Search the documentation

Results update as you type. Use the up and down arrow keys to choose a result and Enter to open it.