This commit is contained in:
2026-03-05 22:14:28 +01:00
parent 77364dddae
commit 04b68850d0
25 changed files with 374 additions and 8447 deletions

View File

@@ -1,18 +1,57 @@
# The Prelude
# Preludes
You can define words in any step and they become available to all other steps. But as a project grows, definitions get scattered across steps and become hard to find and maintain. The **prelude** is a dedicated place for this. It is a project-wide Forth script that runs once before the first step plays. Definitions, variables, settings — everything in one place. Press `d` to open the prelude editor. Press `Esc` to save and close. Press `D` (Shift+d) to re-evaluate it without opening the editor.
Cagire has two levels of prelude: a **project prelude** shared by all banks, and **bank preludes** that travel with each bank.
## Bank Prelude
Each bank can carry its own prelude script. Press `p` to open the current bank's prelude editor. Press `Esc` to save, evaluate, and close.
Bank preludes make banks self-contained. When you share a bank, its prelude travels with it — recipients get all the definitions they need without merging anything into their own project.
```forth
: bass pulse sound 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width . ;
: pad sine sound 0.5 gain 2 spread 1.5 attack 0.4 verb . ;
```
Every step in that bank can now use `bass` and `pad`. Share the bank and the recipient gets these definitions automatically.
## Project Prelude
The project prelude is a global script shared across all banks. Press `P` (Shift+p) to open it. Use it for truly project-wide definitions, variables, and settings that every bank should see.
```forth
c2 !root
0 !mode
42 seed
```
## Evaluation Order
When preludes are evaluated (on playback start, project load, or pressing `d`):
1. **Project prelude** runs first
2. **Bank 0 prelude** runs next (if non-empty)
3. **Bank 1 prelude**, then **Bank 2**, ... up to **Bank 31**
Only non-empty bank preludes are evaluated. Last-evaluated wins for name collisions — a bank prelude can override a project-level definition.
## Keybindings
| Key | Action |
|-----|--------|
| `p` | Open current bank's prelude editor |
| `P` | Open project prelude editor |
| `d` | Re-evaluate all preludes (project + all banks) |
## Naming Your Sounds
The most common use of the prelude is to define words for your instruments. Without a prelude, every step that plays a bass has to spell out the full sound design or to create a new word before using it:
The most common use of a bank prelude is to define words for your instruments. Without a prelude, every step that plays a bass has to spell out the full sound design:
```forth
pulse sound 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width .
pulse sound c2 note 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width .
```
Repeat this across eight steps without making a new word and you have eight copies of the same thing. Change the filter? Change it eight times.
In the prelude, define it once:
In the bank prelude, define it once:
```forth
: bass pulse sound 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width . ;
@@ -20,22 +59,8 @@ In the prelude, define it once:
Now every step just writes `c2 note bass`. Change the sound in one place, every step follows.
A step that used to read:
```forth
pulse sound c2 note 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width .
```
Becomes:
```forth
c2 note bass
```
## Building a Vocabulary
The prelude is where you build the vocabulary for your music. Not just instruments but any combination of code / words you want to reuse:
```forth
;; instruments
: bass pulse sound 0.8 gain 400 lpf 1 lpd 8 lpe 0.6 width . ;
@@ -49,11 +74,11 @@ The prelude is where you build the vocabulary for your music. Not just instrumen
: loud 0.9 gain ;
```
By using the prelude and predefined words, steps become expressive and short. The prelude carries the design decisions; steps carry the composition.
Steps become expressive and short. The prelude carries the design decisions; steps carry the composition.
## Setting Initial State
The prelude also runs plain Forth, not just definitions. You can use it to set variables and seed the random generator:
The project prelude is the right place for global state:
```forth
c2 !root
@@ -61,18 +86,18 @@ c2 !root
42 seed
```
Every step can then read `@root` and `@mode`. And `42 seed` makes randomness reproducible — same seed, same sequence every time you hit play.
Every step can then read `@root` and `@mode`. And `42 seed` makes randomness reproducible.
## When It Runs
## When Preludes Run
The prelude evaluates at three moments:
Preludes evaluate at three moments:
1. When you press **Space** to start playback
2. When you **load** a project
3. When you press **D** manually
3. When you press **d** manually
It runs once at these moments, not on every step. This makes it the right place for definitions and initial values. If you edit the prelude while playing, press `D` to push changes into the running session. New definitions take effect immediately; the next time a step runs, it sees the updated words.
They run once at these moments, not on every step. If you edit a prelude while playing, press `d` to push changes into the running session.
## What Not to Put Here
The prelude has no access to sequencer state. Words like `step`, `beat`, `iter`, and `phase` are meaningless here because no step is playing yet. Use the prelude for definitions and setup, not for logic that depends on timing. The prelude also should not emit sounds. It runs silently — any `.` calls here would fire before the sequencer clock is running and produce nothing useful.
Preludes have no access to sequencer state. Words like `step`, `beat`, `iter`, and `phase` are meaningless here because no step is playing yet. Use preludes for definitions and setup, not for logic that depends on timing. Preludes also should not emit sounds — any `.` calls here would fire before the sequencer clock is running.