116 lines
2.4 KiB
Markdown
116 lines
2.4 KiB
Markdown
# Timing with at
|
|
|
|
Every step has a duration. By default, sounds emit at the very start of that duration. `at` changes *when* within the step sounds fire -- giving you sub-step rhythmic control without adding more steps.
|
|
|
|
## The Basics
|
|
|
|
`at` drains the entire stack and stores the values as timing offsets. Each value is a fraction of the step duration: 0 = start, 0.5 = halfway, 1.0 = next step boundary.
|
|
|
|
```forth
|
|
0.5 at kick snd . ;; kick at the midpoint
|
|
```
|
|
|
|
Push multiple values before calling `at` to get multiple emits from a single `.`:
|
|
|
|
```forth
|
|
0 0.5 at kick snd .
|
|
```
|
|
|
|
Two kicks: one at start, one at midpoint.
|
|
|
|
```forth
|
|
0 0.25 0.5 0.75 at hat snd .
|
|
```
|
|
|
|
Four hats, evenly spaced.
|
|
|
|
The deltas persist across multiple `.` calls until `clear` or a new `at`:
|
|
|
|
```forth
|
|
0 0.5 at
|
|
kick snd . ;; 2 kicks
|
|
hat snd . ;; 2 hats (same timing)
|
|
clear
|
|
snare snd . ;; 1 snare (deltas cleared)
|
|
```
|
|
|
|
## Polyphonic at
|
|
|
|
Deltas multiply with polyphonic voices. If you have 3 notes and 2 deltas, you get 6 emits — every note at every delta:
|
|
|
|
```forth
|
|
0 0.5 at
|
|
c4 e4 g4 note 1.5 decay sine snd .
|
|
```
|
|
|
|
6 emits: 3 notes x 2 deltas. A chord played twice per step.
|
|
|
|
## Arpeggios with at + cycle
|
|
|
|
Use `cycle` inside an `at` block to pick one note per subdivision:
|
|
|
|
```forth
|
|
0 0.33 0.66 at
|
|
sine snd [ c4 e4 g4 ] cycle note 0.5 decay .
|
|
```
|
|
|
|
C4 at 0, E4 at 0.33, G4 at 0.66. `cycle` advances per iteration of the at-loop.
|
|
|
|
If the list is shorter than the number of deltas, it wraps:
|
|
|
|
```forth
|
|
0 0.25 0.5 0.75 at
|
|
sine snd [ c4 e4 ] cycle note 0.3 decay .
|
|
```
|
|
|
|
C4, E4, C4, E4 — wraps to fill 4 time points.
|
|
|
|
## Generating Deltas
|
|
|
|
You rarely type deltas by hand. Use generators:
|
|
|
|
Evenly spaced via `.,`:
|
|
|
|
```forth
|
|
0 1 0.25 ., at hat snd . ;; 0 0.25 0.5 0.75 1.0
|
|
```
|
|
|
|
Euclidean distribution via `euclid`:
|
|
|
|
```forth
|
|
3 8 euclid at hat snd . ;; 3 hats at positions 0, 3, 5
|
|
```
|
|
|
|
Random timing via `gen`:
|
|
|
|
```forth
|
|
( 0.0 1.0 rand ) 4 gen at hat snd . ;; 4 hats at random positions
|
|
```
|
|
|
|
Geometric spacing via `geom..`:
|
|
|
|
```forth
|
|
0.0 2.0 4 geom.. at hat snd . ;; exponentially spaced
|
|
```
|
|
|
|
## Gating at
|
|
|
|
Wrap `at` expressions in quotations for conditional timing:
|
|
|
|
```forth
|
|
( 0 0.25 0.5 0.75 at ) 2 every
|
|
hat snd .
|
|
```
|
|
|
|
16th-note hats every other bar.
|
|
|
|
```forth
|
|
( 0 0.5 at ) 0.5 chance
|
|
kick snd .
|
|
```
|
|
|
|
50% chance of double-hit.
|
|
|
|
When the quotation doesn't execute, no deltas are set -- you get the default single emit at beat start.
|
|
|