Two ways to make a patch play itself: inside the signal graph with pulses and counters, or outside it with forked Pharo processes — plus the TpSampler multisample player.

1. Two places time can live

Rhythm in Phausto can be generated in either of two places, and knowing which you are using explains most of the surprises.

Inside the DSP — a Pulse or counter is part of the signal graph. It is sample-accurate, runs on the audio thread, and keeps perfect time regardless of what the image is doing.
Outside the DSP — a forked Pharo process sends trig: or playNote:prefix:dur: messages. It is far more flexible, can use the whole language, but is only as accurate as Pharo's scheduler.

Use the first for steady rhythmic engines, the second for anything that needs decisions, randomness or live interaction. Most real patches use both.

2. Pulses, counters and time tools

Eighteen UGens are dedicated to generating and dividing time. The essentials:

ClassWhat it does
PulseA repeating pulse; set the interval with period:
PulsenA pulse with an explicit length as well as a period
SpulseA single, non-repeating pulse
PhImpulsifyConverts a gate into a one-sample impulse
PhTempoTempo as a signal, in BPM
PhBeatBeat clock derived from a tempo
PhSubBeatSubdivisions of the beat
PhCountUp / PhCountDownCounters, with looping variants
PhCycleCycles through a range
PhRamp / PhSweepLinear ramps over time
PhTimeElapsed time as a signal
PhSequencerStep sequencer with a trigger: input

A pulse becomes a rhythm the moment you feed it to something that responds to a trigger — an envelope, a drum model, a sampler:

"A djembe struck every 300 ms, entirely inside the DSP"
drum := Djembe new trigger: (Pulse new period: 0.3).
dsp := drum stereo asDsp.
dsp init.
dsp start.
dsp stop.

2.1 A modulated pulse

Because period: accepts a UGen, the tempo itself can be modulated — giving accelerating, decelerating or drifting rhythms that no external sequencer could produce as cleanly:

"Two pulse generators — the first has its period driven by an LFO"
pulse1 := Pulsen new period: (LFOTriPos new freq: 0.2; offset: 0.05; amount: 4).
pulse2 := Pulsen new period: 0.35.

"Two physical models, one triggered by each pulse"
djembe  := Djembe  new trigger: pulse1.
marimba := Marimba new
  trigger: pulse2;
  freq: (LFORandomPos new offset: 20; amount: 600; freq: (1 / 0.35)).

"Mix, chuck into reverb, make it stereo"
dsp := (djembe + marimba => GreyHole new) stereo asDsp.
dsp init.
dsp start.
dsp stop.

Note LFORandomPos driving the marimba's pitch at exactly the pulse rate (1 / 0.35): a new random pitch per strike, with no scheduling code at all.

3. Sequencing from Pharo

The other approach keeps the DSP simple and drives it with messages. This is where Phausto starts to feel like a live coding environment.

3.1 Labelling with symbols

playNote:prefix:dur: finds an instrument's frequency and gate by name, built from a prefix you supply. For it to work, those two parameters must be labelled to match. Passing a symbol to a setter does exactly that:

"Symbols set the parameter labels rather than fixing values"
synth := ElecGuitar new
  freq:    #ElecGuitarFreq;
  trigger: #ElecGuitarTrigger.

dsp := synth asDsp.
dsp init.
dsp start.
Number, UGen or symbol A number fixes a value at compile time. A UGen modulates it. A symbol turns it into a named runtime parameter. All three are accepted by every setter — see Parameters & Control.

3.2 A melodic pattern

"128 random MIDI notes between 28 and 76, one every 125 ms"
pattern := [
  dsp playNote: (Random new nextIntegerBetween: 28 and: 76)
      prefix: 'ElecGuitar'
      dur:    0.11.
  (Delay forMilliseconds: 125) wait
].

[128 timesRepeat: pattern] fork.

dsp stop.
method playNote: aMidiNN prefix: aString dur: aDuration

aMidiNN is a MIDI note number (middle C is 60), aString the label prefix, and aDuration the note length in seconds. The method converts the note number to hertz and performs the gate-on, wait, gate-off cycle for you.

Always fork Without fork the loop blocks the UI process and the image freezes until it finishes. Forked blocks also compose: several running at once give you polyrhythm for free.

4. TpSampler

TpSampler is the multisample player from TurboPhausto. Point it at a folder of audio files and it exposes an index to choose between them and a trigger to fire them.

Folder rules The folder must contain only .wav or .aiff files — no subfolders, no stray files — and every file must have the same channel count. Files are indexed in sorted filename order. Sample folders such as TurboSamples and MoofLodSamples are in the Phausto repository.

4.1 Loading a folder

"Drag a folder into the Playground and Phausto writes the path string for you"
sp := TpSampler new pathToFolder: '/Users/you/Documents/TurboSamples/conga'.

"TpSampler is mono even when the files are stereo — send stereo to widen it"
dsp := sp stereo asDsp.
dsp init.
dsp start.

"Play it from the UI: tpSamplerTrigger fires, tpSamplerIndex selects"
dsp displayUI.

4.2 Algorithmic triggering

"Random samples at random intervals"
[128 timesRepeat: [
  dsp trig: 'tpSamplerTrigger'.
  dsp setValue: (Random new nextIntegerBetween: 1 and: 9)
      parameter: 'tpSamplerIndex'.
  (Random new nextIntegerBetween: 80 and: 310) milliSeconds wait
]] fork.

4.3 Melodic playback

A sampler is also an instrument: fix the index and play the same file chromatically. MIDI note 60 plays at the file's original speed, and other notes resample around it.

"Choose one sample, then play it as a pitched instrument"
dsp setValue: 8 parameter: 'tpSamplerIndex'.

[128 timesRepeat: [
  dsp playNote: (Random new nextIntegerBetween: 35 and: 78)
      prefix: 'tpSampler'
      dur:    0.1.
  110 milliSeconds wait
]] fork.

dsp stop.
dsp destroy.
MessageEffect
pathToFolder:Load a folder of samples
pathToFile:Load a single file instead
numberOfSamplesHow many files were found
sampleNamesSortedThe filenames, in index order
dsp trig: 'tpSamplerTrigger'Fire the current sample
dsp setValue: n parameter: 'tpSamplerIndex'Choose a sample by index
dsp playNote: n prefix: 'tpSampler' dur: sPlay it pitched to a MIDI note
Check what loaded sp sampleNamesSorted tells you exactly which file each index refers to. An index beyond the end of the folder plays the last available sample rather than failing.

5. Where to go next

DocumentWhat it covers
MIDI & Playing NotesMIDI-enabled DSPs, keyboards and controller mapping.
Parameters & ControlTriggering, sweeping and automating from code.
TurboPhaustoThe rack engine that wraps all of this for live coding.
Physical ModellingInstruments worth pointing a sequencer at.

6. Troubleshooting

My forked loop froze the image

It was probably not forked. A bare 128 timesRepeat: [...] runs on the UI process. Wrap it: [128 timesRepeat: pattern] fork — §3.2.

A forked loop keeps playing after I stop the DSP

The process is still alive and still sending messages. Stop it from the Process Browser, or guard the loop with a flag you can flip. Destroying the DSP under a running loop can raise errors on every iteration.

playNote:prefix:dur: does nothing

The instrument's frequency and gate are not labelled to match the prefix. Set them with symbols first — §3.1 — and confirm the resulting names with dsp traceAllParams.

TpSampler is silent, or loads nothing

Check the folder holds only audio files with a consistent channel count, and that the path is absolute. sp numberOfSamples returning zero means the folder was not read. See §4.

The sampler plays but only ever the same sound

tpSamplerIndex is not being set, or is being set outside the valid range — indices past the end fall back to the last file. Confirm with sp sampleNamesSorted.

My in-DSP pulse rhythm drifts against the forked one

They are driven by different clocks — the audio thread and the Pharo scheduler — and will never lock. Pick one source of time per rhythmic layer. See §1.