In the two previous posts, I’ve shown how a house beat in SuperCollider works. At the end of every eight bars, this house beat includes a riser — a buildup sound used to increase tension prior to a transition. This is the most complex sound in the beat, so I’ve saved it for last.
Here’s the beat again:
And here’s the riser:
Next, here’s the code:
As usual, starting off with
creates a callback function and registers it under the name “riser.”
The callback function takes three keyword arguments —
amp plays its usual role in defining the amplitude, or volume, of the function.
endPan play the same roles they play in the synth hat code
in the previous post.
In the previous two posts, we’ve seen
a tight, quick envelope well-suited to drum synthesis.
Env object has many other methods, each of which generate different types of envelopes,
This code uses
Env.pairs, which is the most flexible option.
takes an array of two-element arrays.
These pairs each represent the time and level of a point in the envelope.
The envelope can have any number of points,
and you can also pass in a symbol or string to specify the type of curve you want the envelope to have.
With that in mind, let’s look at the envelope code.
Two of the envelopes use a linear curve; the third is exponential. The first one lasts three and a half seconds, the second one lasts a little over three seconds, and the third lasts for four seconds. The first envelope starts with a level of zero, goes up, and then goes back down to zero again. The third envelope likewise ramps down from fifty to one. The second one is the exception; it starts at 55 and ramps up to 1760.
As you might guess,
env2 is a pitch envelope.
A common technique with risers in dance music is to build up from a low frequency to a high one,
and that’s what happens here.
If you’ve been following along with the previous posts,
you won’t be surprised to learn that the top frequency of 1760 represents a high octave of the note A,
and the bottom frequency of 55 repesents a low octave of A.
Here’s the code which uses this envelope to create a sound running through these frequencies.
This is one half of the riser sound. To make it easier to understand, I took out the other half for this recording:
That rise in pitch is what the code is doing right now.
Saw is a SuperCollider unit generator or UGen,
an object in SuperCollider which generates sound.
In this case, it generates a sawtooth wave,
a classic element of subtractive synthesis since the 1960s.
By invoking its
we modulate it at audio rate.
So first we pass in the frequency we want with
which simply means we’re going to take the control output of the pitch envelope
which runs from 55 to 1760,
and supply those values to
freq over time.
Then we pass
env1.kr as the value for the
mul keyword argument.
This means we’ll use
env1 as an amp envelope.
doneAction of 2 is equal to the value of
and means that SuperCollider will free up the
Saw UGen’s memory once it’s done playing this sound.
The code multiplies the amp envelope by 0.8 to tone the volume down a bit,
and the whole thing gets multiplied by
which allows us to make further volume modifications elsewhere in the code, if we need that.
If we don’t, multiplying by
amp does no harm,
since its default value is 1.
Now, as I said, I took out half of the riser sound so that we could understand that part.
That part, named
riser in the code, does an actual rise in pitch.
The next part adds texture.
Here’s what that other half sounds like.
And here’s the code.
As before, we’re just passing
mul to a
Saw sawtooth wave UGen,
but the results are very different.
Or actually, the results with
mul are virtually the same;
the only differences are that we make the UGen quieter,
by damping it down by a factor of 0.6 instead of 0.8,
and we don’t dispose of it with
The reason for that is the code we pass to
freq needs the
Saw.ar to stick around until
env3 is done,
env3 lasts four seconds, while
env1 (the amp envelope controlling
mul) lasts 3.5 seconds.
We could shorten
env3 to 3.5 seconds as well if we needed to,
but in practice, it doesn’t cause any problems.
mul is clear.
What’s going on inside
freq is a little more unusual:
In the same way that calling
Saw.ar gets SuperCollider to give us the audio output of a sawtooth wave generator,
SinOsc.ar gets us the audio output of a sine wave generator.
Passing only one argument to
SinOsc.ar means we’re just defining the frequency of the sine wave,
and that frequency is a slow envelope that, over 4 seconds, starts at 50 and goes down to 1.
However, we then call
This is actually a method on UGen itself, the superclass,
which scales the output of the UGen to fit within the range of frequencies defined.
So our sine wave actually starts at 19.9 kHz and scales down to 30 Hz,
which is almost the lowest frequency a human being can hear.
Will any ear ever hear this frequency?
Because we’re not feeding it into any audio output;
we’re simply using it to generate the
freq argument for our
What’s going on here?
We’re using our
SinOsc as an LFO.
At the start of its frequency envelope, it’s oscillating at 19.9 kHz,
which is way too fast to really qualify as an LFO —
it stands for low-frequency oscillator, after all —
and instead basically performs FM synthesis, modulating the sawtooth wave very quickly.
As it slows over the course of four seconds, however, it enters LFO territory.
So you get a transition in texture over those four seconds.
I wish I could say I thought of this myself,
but it’s an idea I stole from a Microkorg preset.
The Microkorg version didn’t go into FM territory,
but the idea was the same.
There are a few more lines of code which add just a little special sauce to this sound.
Pan2.ar turns mono sounds into stereo sounds,
pos argument (for “position,” i.e., pan position) is the control rate information from a
over four seconds,
Those values are -1 and 1, respectively,
which in this context stand for a signal panned all the way to the left
and a signal panned all the way to the right.
In other words, we make the sound move across the stereo spectrum.
FreeVerb adds some reverb to the sound,
just to give it a bit of presence.
And that’s how we get the end result.