TuttiCodeTuttiCode guide

Mixing: buses and master

Shared reverbs and delays on buses, sends from the voices, each voice's fader and pan, and the program's master chain - the same tracks Open in TuttiDAW makes.

A program can mix itself the way a studio project is mixed: buses for shared effects, sends from the voices into them, a fader and pan per voice, and a master that everything goes through. "Open in TuttiDAW" makes exactly these tracks.

Code What it is In the studio
bus(name) a shared effect track a return track inside the program's group
.send(bus, dB) how much of a voice goes to a bus the voice track's send knob
.mix({vol, pan, mute}) a voice's (or a bus's) mixer the track's fader, pan and mute
master the program's own bus the program group's devices and fader

These are TuttiDAW-only, like .fx: a program that uses them does not play on strudel.cc.

Buses and sends

Declare a bus with bus("name") on its own line and give it effects with .fx. A bus usually holds a "wet only" effect (Dry/Wet at 100%): the voices keep their dry sound and send some of it to the bus.

bus("verb").fx("Reverb:Large Hall", {dryWetBalance: 1})

drums: s("bd*2 [~ bd] sd ~, hh*8").bank("tr909")
keys: chord("<Cm7 Fm7>").voicing().inst("Electric").send("verb", -10)
lead: n("0 2 4 7").scale("C4:minor").s("triangle").send("verb", -18)
Open in /TuttiCode

.send(bus, dB) takes a level in dB: 0 is the most, -70 is off. Send from as many voices as you like, and from one voice to several buses:

bus("verb").fx("Reverb", {dryWetBalance: 1, decayTime: "3s"})
bus("echo").fx("Delay", {feedback: 0.4}).mix({vol: -6})

keys: note("<c3 e3 g3>").inst("Drift").send("verb", -10).send("echo", -20)
Open in /TuttiCode

A pattern moves the level - here the reverb opens up every other bar:

bus("verb").fx("Reverb", {dryWetBalance: 1})
keys: note("c3 e3 g3 e3").s("sine").send("verb", "<-24 -6>")
Open in /TuttiCode

A send to a bus the program does not declare is a warning, and the editor offers to add bus("...") for you.

Why buses? Two voices that share one reverb sound like they are in one room, and you change the room in one place. Strudel's .room() still works too: it gives that voice its own reverb.

A voice's fader, pan and mute

.mix() sets the voice's mixer: vol in dB (0 leaves it as it is, -6 is half as loud, -70 is silent), pan from -1 (left) to 1 (right), mute on or off.

bass: note("c2 ~ c2 g1").s("sawtooth").lpf(500).mix({vol: -3})
hats: s("hh*8").mix({vol: -12, pan: 0.4})
perc: s("~ rim").mix({pan: -0.4, mute: true})
Open in /TuttiCode

vol and pan can be patterns too. When a voice has both .pan() (Strudel) and .mix({pan}), the .mix value wins.

The master

master is the program's own bus: every voice and bus goes through it. Give it effects and a fader like any bus - a gentle compressor to glue the mix and a limiter at the end are a common start:

master.fx("Glue Compressor", {threshold: -12}).fx("Limiter")
master.mix({vol: -1})

drums: s("bd*4, ~ cp, hh*8").bank("tr909")
bass: note("<c2 g1 a1 f1>").ply(4).s("sawtooth").lpf(600)
Open in /TuttiCode

On this page the master is what you hear. In a project, a program lives in its own group track, so master is that group's chain; it feeds the project's master like any other track.

In the studio

Open the program in TuttiDAW and you get its group with one track per voice, the buses as return tracks inside the group, and the master chain on the group. The values the code sets belong to the code: change one by hand (a device param, a fader, pan or mute, or a device added, removed or moved on a bus or the master) and that voice, bus or master is detached from the code (Re-attach brings it back). Remove a bus from the code and its return track stays, marked "not in code".