Guide

Framework examples

A section-by-section walk through examples/mora-framework-intro.mora, a file of small framework demonstrations.

The example file examples/mora-framework-intro.mora contains small, generic demonstrations of patterns, transformations, layers, shader construction, ordered image processing, and inspection. This page walks through each section of the file and explains what each form does.

Before you start

Open the file in Mora Studio and evaluate one form at a time. The file begins by stating its prerequisites and selecting the mora package:

Common Lisp
;;; MORA: SMALL FRAMEWORK EXAMPLES
;;; Evaluate one form at a time in normal Mora Studio.
;;; Sound requires SuperDirt and its bd/sn/hh banks. Shader examples require
;;; Studio's native renderer.

(in-package :mora)

The forms deliberately replace the contents of channel 1 as you go. Evaluate them in order and listen or look after each one.

Tempo, mini notation, transformation, and stopping

Common Lisp
;;; Tempo, mini notation, transformation, and explicit stopping.
(bpm 140)

bpm sets the tempo directly. Mora’s time is measured in cycles, a musical coordinate that the transport maps to physical time using tempo and beats per cycle. With four beats per cycle, 140 BPM corresponds to 7/12 cycles per second; Mora exposes BPM so that musicians do not need to make that conversion. See Patterns and time.

Common Lisp
(d1! (s "bd [hh hh] sn hh"))

d1! immediately assigns live channel 1. s builds a sample pattern from a mini notation string: space-separated elements form a sequence within the current cycle, and [hh hh] subdivides its containing slot. See Mini notation.

Common Lisp
(d1! (>> (s "bd [hh hh] sn hh")
         (every 4 #'rev)
         (gain 0.9)))

Re-evaluating d1! replaces the channel’s composition. >> threads a pattern through transformations and clauses from left to right. every is a conditional-application transform; here it conditionally applies rev, which reverses the score in time. (gain 0.9) is a parameter annotation: each existing event keeps its multiplicity while receiving the parameter. See Pipelines and composition and Transformations and groove.

Common Lisp
(d1! (silence))

Assigning (silence) stops the channel. (d1!) with no pattern is not a stop command, and hush is the session-wide tool when you intend to silence the whole session.

Independent voices

Common Lisp
;;; Independent voices, using ordinary sample patterns.
(d1! (stack
       (s "bd ~ bd ~")
       (s "~ sn ~ sn")
       (>> (s "hh*8")
           (gain 0.45))))

stack plays its patterns as simultaneous voices. In the strings, ~ is a rest and * marks repetition, a faster local occurrence. Only the hh layer passes through >> to receive a gain annotation, so the annotation applies to that layer alone.

stack polyphony is distinct from parameter merging. A parameter annotation joins values onto existing events; stack adds voices. Pipelines and composition explains the difference.

Shader construction and ordered image processing

Common Lisp
;;; Generic shader construction and ordered image processing.
(d1! :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)))

This channel form has two facets:

  • :viz selects visual material for the channel form. The visual DSL constructs CLOS operator objects: osc is a generator, and kaleid composes with it through >>. Emission produces GLSL with cached compiled programs. A visual operator is also a pattern, so temporal transforms can act on it.
  • :post supplies an ordered image post-processing chain. Post effects operate on the preceding image in the written order: here pixelation, then ASCII rendering, then edge glow. ASCII after pixelation is different from pixelation after ASCII.

The form has no :audio facet. An omitted facet is left alone, so a visual or post-only edit need not replace an audio pattern already running on the channel.

Supplying an explicit :post chain replaces the renderer’s legacy built-in post effects. It does not replace the underlying visual object or geometry. See Shader composition and Ordered post-processing.

Bypassing post-processing

Common Lisp
;;; Bypass post-processing without replacing the visual source.
(d1! :post (mora.visual:post-chain))

An explicit empty chain deliberately bypasses post-processing, including the renderer’s legacy effects, while the :viz source keeps running. Three cases are distinct:

Form of :postMeaning
OmittedPreserves the installed post policy.
nilRestores the renderer’s legacy treatment.
An empty chain, (mora.visual:post-chain)Bypasses post effects, including legacy effects.

Inspecting a pattern without sound

Common Lisp
;;; Inspect an ordinary temporal pattern without dispatching sound.
(defparameter *example-pattern*
  (>> (s "bd sn")
      (fast 2)))

This stores a pattern in an ordinary Lisp variable without assigning it to a channel, so nothing is dispatched. (fast 2) changes the pattern’s rate.

Common Lisp
(query-cycle *example-pattern* 0)
(mora.core:pattern-summary *example-pattern*)
(mora.core:pattern-children *example-pattern*)

query-cycle asks for the events in cycle 0. pattern-summary and pattern-children are structural observation operations: they expose the retained pattern objects and their structure for inspection and tools. A query does not send audio; the object remains available for later queries. See What remains after evaluation.

Source references

Repository-relative paths in the Mora source where these mechanisms are implemented.

  • examples/mora-framework-intro.mora
  • src/mini/d-bang-bangs.lisp
  • src/visual/emitter.lisp
  • src/visual/post-model.lisp
  • src/visual/post-backend.lisp
  • src/core/pattern.lisp

Documentation

Search the documentation

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