[NS TUTORIAL SERIES 1-7] SuperCollider Client- vs. Server-side Programming I
Articles,  Blog

[NS TUTORIAL SERIES 1-7] SuperCollider Client- vs. Server-side Programming I


Hey there, creative coders! This is Benjamin
D. Whiting, and welcome back to the SuperCollider segment of Null-state’s Interactive Digital
Art tutorial series. Last week we covered arrays in SuperCollider, both as ways of collecting
data, as well as a means for multichannel expansion. This week we’re going to discuss
a bit about how SuperCollider works under the hood, with emphasis on the distinction
between client-side and server-side programming. Let’s get started! Before we dive into the distinction between
client- and server-side programming, it’s important to understand just what I mean when
I refer to SuperCollider. SuperCollider is often described, by myself included, as a
programming language centered around synthesis, digital signal processing, and algorithmic
music composition, but it’s a bit more complex than that. It is actually a suite of applications
that includes the following: scide, the editor that we boot into every
time we launch SuperCollider, sclang, the programming language that we’ve
been covering in this tutorial, and scsynth, the sound-generating server that
takes OSC messages and produces audio or control rate output Of these three components, scide is generally
considered to be the least essential for working in SuperCollider. In fact, some people choose
to eschew it altogether and use dedicated text editors — typically with plugins aiding
in the creation of SuperCollider code — when working in the language. This was a particularly
common scenario before the contemporary IDE was introduced back in version 3.5, and updated
several times with helpful features. I myself dabbled in using the Sublime Text SuperCollider
package back in the 3.6 days, but as of 3.7 swiftly switched back to using the IDE as
I find features such as the floating windows with argument defaults an indispensable part
of the programming process. Conversely, scsynth is often regarded as the
most important component of SuperCollider, as it’s what is responsible for the output
of audio (which is by far the most common application for which the language is utilized).
It uses compiled SynthDef code to determine what audio and/or control rate data is generated
and responds to OSC messages to determine the scheduling and termination of actions,
along with the setting of arguments in SynthDefs with control data, the allocation of memory
for buffers, and a host of other operations. There is an alternative to scsynth that ships
with SuperCollider on macOS and Linux (and on earlier 32-bit releases for Windows) called
Supernova. In a nutshell, it works much like scsynth but allows for the use of more than
one CPU core. One must explicitly program this into one’s code, however, and as we will
not be engaging in anything particularly CPU intensive for the time being, we will be sticking
with scsynth. Finally, sclang is also an important component,
as it is the “language” part of the suite itself which is interpreted into either machine
language (for SynthDefs) or OSC messages (for everything else) when addressing scsynth.
It houses a wealth of powerful algorithmic composition tools. It is also capable of implementing
control structures, routines, streams, and other kinds of functionality ubiquitous in
higher-level programming languages. That said, sclang is technically optional. One can make
use of any OSC-capable language to communicate with scsynth: Python is a popular alternative.
(One can even control scsynth directly from Max if one so desires.) Depending on the language
used, however, it can be rather tricky to compile SynthDef code readable by scsynth,
so even if other languages are used for interfacing with scsynth SynthDefs are still often coded
in sclang. There are alternatives to sclang created with scsynth specifically in mind.
Overtone (based on Clojure) and TidalCycles (based on Haskell) are two popular examples.
The opposite is technically also true in that one can bypass scsynth altogether and use
sclang to interface with and control other sound-generating languages; using SuperCollider’s
powerful algorithmic composition tools along with Max/MSP is an option. Now that we’ve covered scsynth and sclang
in some detail, let’s investigate how they talk to each other. First, it’s imperative
to discuss what is meant by the client-server model. Some of you may already know, or at
least have guessed, that it’s a computer networking term, and you’d be right on the money. To
illustrate what is meant for those who may not be immediately familiar with this concept,
let’s look at the model though a more generic lens. Clients and servers both depend on network
communication to function effectively. Servers provide, or “serve,” functionality and resources
to devices connected to them via a network; these devices are its “clients.” Servers can
provide their services to more than one client at a time. For instance, NAS, or Network-Attached
Storage, relies on a central hub serving one or more clients requesting data storage. Clients,
on the other hand, do not typically share their resources, and are dependent on servers
for services to be fulfilled. Returning to a NAS system, computers that access it, while
connected to the network, do not open themselves up for others to access whatever internal
storage they may possess. Both scsynth and sclang behave as server and
client, respectively. Ever wonder why we’ve selected something called “Boot Server” each
episode before working with sound? We need to launch scsynth before any sound can be
generated. Until we boot it, the only components that are running are sclang and scide. Client-side
code will still work — for example, last episode we were able to initialize and fill
arrays with objects like simple numbers. Sound generating code, on the other hand, is handled
exclusively by the server. The server remains active on the network, listening for byte
code to tell it what kinds of sounds to produce, and OSC messages, to tell it how and when
to produce those sounds. “Hold the phone!” you might interject. “What
do you mean when you say its ‘active on the network?’ Is this not all happening on the
same machine?” Even if nothing is leaving your personal computer,
a network connection is still being used for interapplication communication of machine
code and OSC messages. By default, sclang sends its instructions out over the loopback
IP address, “127.0.0.1”, where scsynth is listening over port 57120, using the User
Datagram Protocol (UDP). Incidentally, a connection via TCP, or Transmission Control Protocol,
is also possible, but typically not necessary or even recommended unless you’re dealing
with connections outside of one’s Local Area Network (and even then UDP is generally reliable
enough for most situations). On the flip side is sclang, which, as mentioned
earlier, is considered a “client” in relation to scsynth. Sclang interprets SuperCollider
code and passes it along to scsynth, either in the form of compiled SynthDef code for
desired sound production templates, or interpreted OSC messages to schedule said templates and
provide further context as to how they are to be instantiated. It has the capability
to further structure how and when communication with the server is handled, using processes
that run completely independently of scsynth. Sclang is also capable of accepting incoming
network connections, though as it is not a server it is quite exclusive as to the kinds
of processes it opens up for remote access. (There is a very handy Quark called OpenObject
that can be used to open the interpreter up for manipulation by other OSC-enabled applications
and languages, though such a decision is not without its risks.) For this model to work both the client and
server have their distinct roles to play, very little of which are interchangeable.
These can be summed up as follows: Server-side programming is responsible for:
SynthDef code generating audio rate and control rate data;
Instancing SynthDefs into individual Synth nodes on the server, and the freeing of said
nodes; Dynamically setting parameters, or arguments,
that have been programmed into SynthDefs to be modulatable;
Allocating buffers in memory to store data (including digital audio), and the real-time
storage of data into said buffers; Ordering and reordering Synth nodes to affect
signal flow; Creating groups of Synth nodes to further
organize and affect signal flow; and Bussing audio and control rate data between
Synth nodes and to and from hardware inputs and outputs. Client-side programming includes the following:
The use of control structures (such as if/then statements, cases, switches, and the like)
to determine conditions that would trigger other actions;
The use of routines or streams to structure a schedule of actions based on either the
receipt of input triggering a new action or the passage of time (I’m specifically avoiding
using the term event as event means something quite specific in SuperCollider);
Variables; Functions;
Patterns (which are special classes facilitating algorithmic music composition);
sclang class creation; Graphic User Interfaces (GUIs); and
Much more! … except for what’s listed under Server-side programming To avoid long hours of desperate debugging
and frustration, it is imperative that the roles of each, along with what kind of code
constitutes client and server side programming, is understood early on when learning the language.
The client-server model is a large part of what makes SuperCollider so powerful, but
it is also arguably a big reason — possibly the biggest reason — why the language has
the reputation of possessing an intimidating learning curve. We will cover the distinction
in much greater depth next episode, but for now I invite you to revisit episode 6 — the
episode on Arrays — and to compare the code being evaluated before booting the server
to the code being evaluated after booting the server. It should serve to provide some
intuitive understanding of the difference between each before diving into it in greater
detail. This wraps up our exposition of client- and
server-side programming. Next week we will be examining common mistakes when coding in
each, like the placement of conditional statements within SynthDefs, along with strategies for
mitigating the limitations of both sides in order to facilitate getting SuperCollider
to behave like you want it to behave. In the meantime, please don’t forget to hit that
like button and subscribe to this channel to show your support for more interactive
digital music and art content from us at Null-state. Also, make sure to check out our Facebook
page and webpage to stay up-to-date on all of our upcoming events, workshops, and concerts;
the link is in the description below. See you next time!

Leave a Reply

Your email address will not be published. Required fields are marked *