Transport, tempo, mute and solo, looping and global transforms — the moves you make while the music is already running, and the handful of behaviours that will surprise you on stage if you meet them for the first time there.
1. Two objects you can drive
Depending on your backend you will be sending performance messages to one of two objects, and confusing them is the most common source of “that method does not exist”.
| Object | What it is | Get it with |
|---|---|---|
Performance | Coypu's singleton. Holds every running Sequencer, keyed by instrument name. Always present | Performance uniqueInstance |
| A Phausto engine | EcoPhausto, TurboPhausto and friends — a Phausto rack that fronts a Performance with the same vocabulary | EcoPhausto new |
"driving Coypu directly — works with any backend"
p := Performance uniqueInstance.
p freq: 132 bpm.
p play.
"driving a Phausto rack, which forwards to the same Performance"
EcoPhausto start.
ep := EcoPhausto new.
ep bpm: 132.
ep playFor: 128 bars.
EcoPhausto new answers a Phausto engine, not a Performance. It
happens to understand bpm:, play, mute: and the rest
because it forwards them. Reach the real Performance underneath with
ep tpPerf, and the DSP with ep tpDsp, when you need something the
facade does not expose.
Everything below works on either object unless stated. Examples use p for the
Performance and ep for an engine.
2. Transport
| Message | Effect |
|---|---|
| play | Start the transport. Runs for about four days at 120 BPM — effectively indefinitely |
| playFor: n | Run for n steps, then stop |
| playCyclicFor: n | Run for n cycles, resolving Mondo alternations each time round |
| stop | Halt immediately |
| resetAllSequencers | Return every Sequencer to its first note |
p play.
p stop.
"or a fixed length — `bars` converts, so this is 128 bars"
ep playFor: 128 bars.
play resets every Sequencer first, so a performance always begins from the top
of each pattern. It also refuses to start a second transport if one is already running,
which prevents the doubled-tempo effect you get from two clocks on the same Performance.
stop is immediate
There is no fade and no wait for the end of the bar. In a live context, mute first, let the
bar finish, then stop — §4.
2.1 Cyclic playback
playCyclicFor: is the transport for Mondo
patterns. Instead of advancing one step at a time it asks each Sequencer for the events
falling inside each cycle, which is what allows alternations and subdivisions to resolve.
'bd <sd cp> bd sd' asMondoSounds to: #drums.
p playCyclicFor: 64.
Step-based patterns still work under cyclic playback, so you can mix the two notations in one Performance.
3. Tempo
Coypu's clock is expressed as the duration of one step, not as BPM — but you rarely have to
think in those terms, because bpm converts for you:
p freq: 132 bpm. "the idiomatic form"
p bpm: 132. "equivalent"
ep bpm: 132. "on a Phausto engine"
A step is a sixteenth note, so 132 bpm answers (60/132)/4 seconds.
Tempo changes take effect on the next step — the transport re-reads the value every time
round rather than caching it, which is what makes smooth live tempo changes possible.
p freq: 90 bpm. "drop it"
p freq: 140 bpm. "lift it"
freq: repeatedly gives you an accelerando with no special support needed.
4. Mute and solo
| Message | Effect |
|---|---|
| mute: aKey | Silence one instrument |
| mute: anArrayOfKeys | Silence several at once |
| muteAll | Silence everything |
| solo: aKey | Silence everything except this one |
| solo: anArrayOfKeys | Isolate several |
| unmute: / unsolo: | Restore — but read §4.1 first |
| restore | Return to the last snapshot |
| temporarySave | Take a snapshot without changing anything |
p mute: #kick.
p mute: #( #kick #snare #bleep ).
p solo: #bass.
"the symbol shorthands read better live"
#kick mute.
#bass solo.
#bass unsolo.
4.1 How restore really works
unmute: ignores the key you give it
Both unmute: and unsolo: discard their argument and call
restore, which reinstates the entire snapshot taken when you last
muted or soloed. p unmute: #kick therefore brings back every muted part, not
just the kick. This is the single most surprising behaviour in Coypu.
The mechanism is a single backup slot. mute:, muteAll and
solo: each snapshot the Performance before changing it; restore
puts that snapshot back. There is no per-key memory and no stack of states.
To bring back one part and leave the others silent, re-send it instead of unmuting:
"restores everything — probably not what you meant mid-set"
p unmute: #kick.
"brings back only the kick"
16 downbeats to: #kick.
p temporarySave takes a snapshot without muting anything, so you can set up a
state you like, experiment freely, and p restore back to it.
5. Looping
loop: caps the transport's step counter, so the whole Performance wraps after a
fixed number of steps instead of running on:
p loop: 64. "everything wraps every 64 steps"
p unloop. "release it"
This is a global constraint, not a per-part one — every Sequencer still wraps at its own length as well, but the transport itself returns to zero at the loop point. Use it to pin a phrase while you rebuild something over the top.
unloop sets the maximum to SmallInteger maxVal rather than
removing the limit, and a plain play runs for roughly four days at 120 BPM.
Neither is a constraint you will meet in a set.
6. Global transforms
These act on every Sequencer in the Performance at once — large, dramatic gestures.
| Message | Effect |
|---|---|
| transpose: n | Shift every part by n semitones |
| rhythm: aRhythmOrSeq | Give every part the same gates, keeping its own notes and sounds |
| swap: keyA with: keyB | Exchange two parts' Sequencers |
| remove: aKey | Take a part out entirely |
p transpose: 3. "everything up a minor third"
p rhythm: 16 tresillo. "every part onto the tresillo"
p swap: #kick with: #snare. "exchange two parts"
"the symbol form of swap"
#kick swapWith: #snare.
rhythm: is the big one
Putting an entire arrangement onto one rhythm — every drum, bass and lead hitting together —
is an enormous gesture, and a very easy way to mark a section change. Follow it by
re-sending individual parts to peel them back off.
7. Editing while it plays
This is the point of the whole system. The transport reads the Performance dictionary on every step, so replacing an entry takes effect at the next step with no rebuild and no gap:
"evaluate this line while the transport is running"
16 claveSon to: #conga.
"then this one — the part changes at the next step"
16 rumba to: #conga.
The same is true of the tempo, the notes, the sample indices and the effect parameters. Nothing in Coypu requires stopping.
, or use two instrument names pointed at the same sound —
see Rhythms: Basics §6.
8. Shaping a set
A skeleton for a live session, using nothing not already covered:
"--- soundcheck -------------------------------------------"
p := Performance uniqueInstance.
p performer: PerformerSuperDirt new.
p freq: 128 bpm.
16 downbeats to: #bd.
p play.
"--- build ------------------------------------------------"
16 claveSon to: #cp.
16 quavers to: #hh.
(16 tumbao notes: #( 36 43 36 41 )) to: #bass.
p temporarySave. "snapshot the groove"
"--- breakdown --------------------------------------------"
p solo: #bass.
p freq: 124 bpm.
"--- drop -------------------------------------------------"
p restore. "everything back"
p transpose: 5.
32 jungleKick to: #bd.
"--- out --------------------------------------------------"
p mute: #( #cp #hh ).
p stop.
temporarySave overwrites the one backup slot, and so does every
mute: and solo:. If you want to return to a groove later, take the
snapshot immediately before the move you intend to undo — §4.1.
10. Troubleshooting
unmute: brought back parts I wanted to stay silent
It restores the whole snapshot and ignores the key. Re-send the one part you want instead — §4.1.
The tempo sounds doubled
Two transports are running on one Performance. play guards against this, but a
forked loop started by hand will not. p stop and start once.
A Phausto engine does not understand a Performance message
The facade exposes a subset. Reach the Performance itself with ep tpPerf — §1.
Mondo alternations never advance
You are on play or playFor:, which step rather than cycle. Use
playCyclicFor: — §2.1.
Everything stopped when I changed the Performer
performer: mutes the Performance on the way in and out. Choose the backend
before building patterns — see Setup §4.
My parts drifted out of alignment and never came back
Their lengths have no common multiple worth waiting for. Either match the lengths or use
loop: to force a shared wrap point — §5.