Sunday, January 13, 2008

Psytrance in Csound. 4 - Score Macros

Something is bugging me a little bit. So far, I've been auditioning only one bar of music and it's hard to get a good view of the soundscape in one bar. Four bars would be more in context with this project. Csound has a simple provision for macros. Here's what I did:

;=== SCORE ===

f 1 0 8192 10 1

t 0 150

#define KICK #
; p1 p2 p3 p4 p5 p6
; start dur freq level reverb
i 1 0 .5 44 .8 .01
i 1 1 .5 44 .8 .01
i 1 2 .5 44 .8 .01
i 1 3 .5 44 .8 .01
#

#define BASS #
; p1 p2 p3 p4 p5 p6
; start dur pitch level reverb
i 2 0.50 6 5.09 .8 .04
i 2 1.50 6 6.09 .8 .04
i 2 2.50 6 5.09 .8 .04
i 2 2.75 6 6.07 .8 .04
i 2 3.50 6 6.09 .8 .04
#

$KICK.
$BASS.
b 4
$KICK.
$BASS.
b 8
$KICK.
$BASS.
b 12
$KICK.
$BASS.

e

Listen (psy4-1.mp3) or Download Code & WAV (psy4-1.zip)

The b in the score creates a beat offset in the macro code that follows. So instead of 0, 1, 2 and 3, after "b 4" it turns the start times into 0+4, 1+4, 2+4 and 3+4.

Now it's starting to sound like a song!

Psytrance in Csound. 3 - Bass

So I'm happy enough with the kick, let's start building the groove. Next, I'll add a simple bassline to build the foundation of the track. I'm thinking something simple and typical: a filtered sawtooth with a touch of reverb. For the sake of saving space, I'll leave out the portion of the code that has already been used for the kick.

;=== ORCHESTRA ===


instr 2

p5 = 32768*p5
klvl expseg 1, .050, .5, .450, 0.00003
aosc vco p5*klvl, cpspch(p4), 1, .5, 1
kcut linseg 1, .030, .1
afilt moogladder aosc, 5000*kcut, .4
al,ar freeverb afilt, afilt, 0.8, 0.35, sr, 0
al = afilt+al*p6
ar = afilt+ar*p6
outs al, ar

endin


;=== SCORE ===


; instr start dur pitch level reverb
i 2 0.50 6 5.09 .8 .04
i 2 1.50 6 6.09 .8 .04
i 2 2.50 6 5.09 .8 .04
i 2 2.75 6 6.07 .8 .04
i 2 3.50 6 6.09 .8 .04

Listen (psy3-1.mp3) or Download Code & WAV (psy3-1.zip)

About the code... I used an exponential envelope for the amplitude, and the 0.00003 comes from the fact you can't use 0 in exponential envelopes in Csound. If you divide 1 by 32768 (to get the smallest 16-bit value) you get 0.0000305... in other words, 0.00003 is a "practical zero". Another thing I like about Csound is the ability to control filter frequencies with ultimate precision. In this case, the envelope takes the cutoff from 5000 to 500 in 30ms. In the score, note the long 6-beat duration of each note, to allow the reverb to come through.

It all sounds nice enough, but why not fatten it up a little? Let's add two more oscillators, detuned slightly.

;=== ORCHESTRA ===


instr 2

p5 = 32768*p5
klvl expseg 1, .050, .5, .450, 0.00003
aosc1 vco p5*klvl, cpspch(p4), 1, .5, 1
aosc2 vco p5*klvl, cpspch(p4)*1.01, 1, .5, 1
aosc3 vco p5*klvl, cpspch(p4)*0.99, 1, .5, 1
aoscall = aosc1+aosc2+aosc3
kcut linseg 1, .030, .1
afilt moogladder aoscall, 5000*kcut, .4
al,ar freeverb afilt, afilt, 0.8, 0.35, sr, 0
al = afilt+al*p6
ar = afilt+ar*p6
outs al, ar

endin

Listen (psy3-2.mp3)
or Download Code & WAV (psy3-2.zip)

I could improve it even further by adding random detuning to the oscillators, or by adding more oscillators, plus effects like chorus or delay, adding pitch tracking to the filter, etc. Maybe later, but we'll stick with that for now.

Psytrance in Csound. 2 - Kick

The common Psytrance kick is simple: a sweeping sine wave that starts high and quickly decays to a low pitch. When made in a sound editor like Sound Forge, it starts as a sine wave at a low frequency around 50-60 Hz, maybe even lower. Pitch shifting is applied to the first few milliseconds of the waveform until the kick feels right. The only problem with this process is that these shifts are performed almost randomly until the very last one. If the kick doesn't feel right, you have to undo and redo these shifts until you find the right combination of decay times and shifting amounts. Trying to duplicate the result is nearly impossible because of this haphazard method.


In Csound we can control these sweeps one by one, and tweak them until we find the right kick. In fact, the very makeup of the kick could be automated -- I'm not going there, but it's definitely possible. So I started with a simple architecture: three envelopes controlling the pitch of a sine wave. One for the main downward sweep (a small one of an octave or two spanning the full length of the kick), another for the initial decay of the wave, and the last one (a quick "thunk") for impact. This is what I came up with:

;=== ORCHESTRA ===

sr = 44100
kr = 44100
ksmps = 1
nchnls = 2

instr 1

p5 = 32768*p5
k1 linseg 1.5, .200, .5
k2 linseg 2, .060, 1
k3 linseg 4, .010, 1
akick oscil p5, p4*k1*k2*k3, 1
al = akick
ar = akick
outs al, ar

endin


;=== SCORE ===

f 1 0 8192 10 1
t 0 150

; instr start dur freq level
i 1 0 .5 44 .8
i 1 1 .5 44 .8
i 1 2 .5 44 .8
i 1 3 .5 44 .8

e

Listen (psy2-1.mp3) or Download Code & WAV (psy2-1.zip)

To briefly explain the code... I like notating levels and other parameters from 0 to 1, hence the p5 conversion in the first line. k1 sweeps the pitch from 1.5 octaves above the base pitch down to an octave below. It's a more dramatic sweep than you'd normally find in your common kick, but I like it like that. k2 adds a 60ms 2-octave sweep for the decay and k3 adds a 10ms 4-octave sweep for the attack. In the score file, I have one bar with 4 kicks for testing, each one an eighth-note long (half a beat). I picked 44Hz for the base frequency because it's "related" to A (440Hz, although a low A is 55Hz), so we'll keep this song in A. Some producers like to offset the kick perfectly to the 3rd or 5th of the key of the song, or pitch the kick by ear, but I'll keep it like this for now.

It's getting there, but it's missing a few things. The attack needs a little more bite, so I'll add another envelope for that. There's no dynamic control, that's why there's a click at the end of each kick, so I'll add an amplitude envelope too. Finally, a touch of reverb, gated to the duration of the kick, to add a bit of air. To make the amount of reverb more dynamic in the future, we'll add p6 to the score to control the wet/dry mix.

;=== ORCHESTRA ===

sr = 44100
kr = 44100
ksmps = 1
nchnls = 2


instr 1

p5 = 32768*p5
k1 linseg 1.5, .200, .5
k2 linseg 2, .060, 1
k3 linseg 4, .010, 1
k4 linseg 4, .002, 1
klvl linseg 0, .0002, 1, .030, .8, .080, .7, p3-.1102, 0
akick oscil p5*klvl, p4*k1*k2*k3*k4, 1
al,ar freeverb akick, akick, 0.8, 0.35, sr, 0
al = (akick*(1-p6))+(al*p6)
ar = (akick*(1-p6))+(ar*p6)
outs al, ar

endin


;=== SCORE ===

f 1 0 8192 10 1
t 0 150

; instr start dur freq level reverb
i 1 0 .5 44 .8 .01
i 1 1 .5 44 .8 .01
i 1 2 .5 44 .8 .01
i 1 3 .5 44 .8 .01

e

Listen (psy2-2.mp3) or Download Code & WAV (psy2-2.zip)

I like it. Next I'll add a simple bassline to go with it and create macros in the score to save on typing.

Psytrance in Csound. 1 - Intro

I recently read something about one of BT's tracks, All That Makes Us Human Continues, being completely written in Csound. It's amazing that all the nuances in the song were, at one point, nothing but hundreds of lines of code. That re-sparked my interest in Csound, so I decided to put a little more time into it.

I'm a hands-on kind of guy and decided that, if I'm going to put time into something as complex as Csound, I might as well make music with it. I've been listening to a lot of Psytrance, mainly Infected Mushroom's IM The Supervisor and other Israeli stuff like Hypersonic and Injection.

The Psytrance kick is the foundation of the genre, and the Infected Mushroom website has a nice little tutorial on how to create your own kicks in editors like Sound Forge. I made over a dozen kicks using their method, which seemed a little haphazard to me. If I could have more control over the pitch shifting described in the tutorial, I could design the perfect kick for each song. That's where I made the connection: Csound and Psytrance are made for each other!

In this article (and its following chapters) I'll narrate the steps of this experiment and post the Csound code. Keep in mind I'm new to Csound AND Psytrance, so don't expect breathtaking results. I just hope to have a finished song at the end of this madness.

So, let's start with the kick... in the next article.