Structure and Spectra


You need SuperCollider and SuperClean to run this code on your machine.
I made a page on my site to help you do just that:

danielmkarlsson.com/superclean-installparty

(
thisThread.randSeed = 9099;
~a = {arg snd, degree;
    var b = Pbind(*[
        type: \cln,
        snd: snd,
        mi1: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mi2: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mi3: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mi4: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mi5: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mi6: Pseg(Pwhite(0.05, 2.5), Pexprand(3.0, 9.0), \wel, inf) / Pexprand(1/4, 4.0),
        mia: Pkey(\mi1) + Pkey(\mi2) + Pkey(\mi3) + Pkey(\mi4) + Pkey(\mi5) +Pkey(\mi6), 
        dur: 1/8,
        degree: degree,
        scale: Scale.major(\wcSJ),
        octave: Pdup(inf, Prand((2 .. 5), inf)),
        frq: Pfunc{|ev|ev.use{ev.freq}},
        sustain: Pseg(Pwhite(1/6, 1/2), Pwhite(4.0, 16.0), \wel, inf),
        amp: (Pseg(Pexprand(0.3, 0.9), Pexprand(8.0, 32.0), \wel, inf) 
            / Pkey(\frq).expexp(43, 4186, 1, 3)
            / Pkey(\mia).linlin(0.075, 600, 1, 3)).trace,
        pan: Pxshuf([Pexprand(0.1, 0.4, 1), Pmeanrand(0.1, 0.9, 1), 1.5 - Pexprand(0.6, 0.9, 1)], inf),
    ]);
    Pseq([b], inf);
};
Pdef(0, ~a.(\fm0, 0)).play;
Pdef(1, ~a.(\fm1, 1)).play;
Pdef(2, ~a.(\fm2, 2)).play;
Pdef(3, ~a.(\fm3, 3)).play;
Pdef(4, ~a.(\fm4, 4)).play;
Pdef(5, ~a.(\fm5, 5)).play;
Pdef(6, ~a.(\fm6, 6)).play;
Pdef(7, ~a.(\fm7, 7)).play;
Pdef(8, ~a.(\fm8, 8)).play;
Pdef(9, ~a.(\fm9, 9)).play;
Pdef(10, ~a.(\fma, 10)).play;
Pdef(11, ~a.(\fmb, 11)).play;
Pdef(12, ~a.(\fmc, 12)).play;
Pdef(13, ~a.(\fmd, 13)).play;
Pdef(14, ~a.(\fme, 14)).play;
Pdef(15, ~a.(\fmf, 15)).play;
Pdef(16, ~a.(\fmg, 16)).play;
Pdef(17, ~a.(\fmh, 17)).play;
Pdef(18, ~a.(\fmi, 18)).play;
Pdef(19, ~a.(\fmj, 19)).play;
Pdef(20, ~a.(\fmk, 20)).play;
Pdef(21, ~a.(\fml, 21)).play;
Pdef(22, ~a.(\fmm, 22)).play;
Pdef(23, ~a.(\fmn, 23)).play;
Pdef(24, ~a.(\fmo, 24)).play;
Pdef(25, ~a.(\fmp, 25)).play;
Pdef(26, ~a.(\fmq, 26)).play;
Pdef(27, ~a.(\fmr, 27)).play;
Pdef(28, ~a.(\fms, 28)).play;
Pdef(29, ~a.(\fms, 29)).play;
Pdef(30, ~a.(\fmt, 30)).play;
Pdef(31, ~a.(\fmu, 31)).play;
r.stop;
r = {
    loop{
        32.do{|i|Pdef(i).reset;};
        [2, 4, 8, 16, 32, 48, 64, 80].wchoose
        ([1, 15, 5, 11, 7, 8, 13, 3].normalizeSum).wait;
    }
}.fork;
Routine{
    5400.wait;
    32.do{|i|Pdef(i).stop;};
}.play
)

A while back I did a record called Towards a Music for Large Ensemble on a label called Fönstret. This music is called Structure and Spectra. It was released on Tokinogake. This piece has the same starting point for me as that previous one. I’ll start us off by describing that point and then I’ll casually walk us through the code.

I used to play electric guitar in bands when I was growing up. It was a big deal for me. It shaped the way I think about music in a profound way. Long story very short, I am still to this day often trying to get the feeling I got from playing in bands as a teenager. Or maybe it’s more that I’m trying to understand what that feeling means? Anyway, here we all are, having arrived in the future and I’m using a computer to make music instead of an electric guitar. I am a composer of various kinds of computer musics and I have been graciously invited by Thorsten to include some code and some text in this zine that you are reading now.

The casual code walkthrough begins here. This block of code can be run inside of a program called SuperCollider to hear the piece. You also need a little framework called SuperClean which makes using SuperCollider fun and easy. In SuperClean I implemented the 32 “classic” six operator FM algorithms that Yamaha popularized way back when. Each of the 32 algorithms has its own SynthDef with it’s own default values for harmonic ratio, modulation index, envelope, curvature and carrier amplitude level. These defaults can be overwritten any time but what I often end up doing is keeping a subset of these parameters at their default values to retain some of the unique instrument characteristics. This is the case in this piece of music. I’m only messing around with the modulation indexes out of all of the FM synth specific parameters. The other parameters stay at their default values. The only duration present in the piece is an eighth note. The modulation index, amplitude, sustain and pan values create the perception of a more complex rhythmic material. I thought about accents and ghost notes here. The scale is the Major scale but it has a little bit of a salty tuning. It is a tuning called Wendy Carlos Super Just. There is a nice Wikipedia article on that tuning in case you would like look more closely at that. I chose it because it has a flavour that I like. It’s a little different than say five limit just intonation. Try it.

Which octave an instrument is in changes each time the block is reevaluated by the fork below which has a loop in it. The scale degrees are tied to the instruments, that’s from 0 to 32. The octave parameter helps to diffuse this parameter connection enough so that it’s a fairly rare occurrence that it can be heard across a part boundary. This connection is meant to act only in a subtle way on a listener’s pattern recognition. I adjust the amplitudes of each individual synth sound according to its frequency and modulation index. In other words, the high pitch noisy stuff gets turned down a tad so as not to be too harsh. The top part of the code block is a Pbind factory and the skinnier part below are the Pdefs which contain the two unique parameters synth name and scale degree. This factory style is nice because is decreases code duplication by a very large amount. Below that is the fork loop combo which contains the weighted choice of how long the parts should be. This construction is new for me and I am fascinated by it. It has an interesting interaction with the top line where it reads: thisThread.randSeed = 9099 This line is what makes the piece deterministic despite the generative composition process. Change that number and You have a new, unique, yet determinate unfolding of this music. The Pdefs do not reset as would have been the case with Pseed or if they had been stopped with Pdef(0).stop before being started again. It seems to me that these instruments have been set on a path by the initial seed which will always yield a determinate result even while being subjected to a “soft reset” by the fork loop combo. Musically I hear this as the parts gaining perceived difference. I know that in this music there is always only a major scale, but I still end up hearing it as the other modes; Dorian, Phrygian, Lydian, Mixolydian, Aeolian and Locrian. Just the slow continuous change in the amplitude, sustain modulation index values would not have given me this sense. It’s the abrupt change that does it. It measures out time by dividing it into parts. The last little bit of plumbing in the form of a Routine is what makes the piece finite, or, end after 5400 seconds, which is 90 minutes. I like music of long duration. You could comment out this part if you want to listen for a longer duration. The casual code walkthrough ends here.

I’ll close this out with just a couple quick things. When I was in my lower teens it was rare to meet grownups that I felt understood me and who wanted to support my desire to devote my life to creating, let’s say “less common”, music. Once I hit the rough equivalent of high school I found a guitar teacher that I felt understood where I was coming from. He showed me a lot of music that I had never heard before. One piece of music that made a big impression on me was a piece called Music for 18 Musicians by a composer called Steve Reich. Later on in my life as I went on to study composition the meaning of that early injection of American Minimalism started to become more complicated as I came into contact with other, let’s say, “schools of thought”. 18 really broke out of “New Music” and made an incredible splash. I think that the amount of success it enjoyed really was a bothersome anomaly for the folks who thought of themselves as “New Music Proper”. I always liked the piece. I still think It’s super dreamy and that it has this unique transcendant quality to it. This piece that I have made is in a strange way a kind of homage to 18. All eighths and all Major scale all the time. What else could it be?

Last little personal note before I go. When I was somewhere in my preteens a kid on the other side of the little village I grew up in had a Commodore 64 and we would play games and mess around with speech synthesis on that thing in his basement. It was loads of fun. I remember he had magazines which had code printed in them. They were simple programs which were meant to teach you programming Basic, but they could still be hundreds of lines of code. Getting them all punched into the computer without any errors was very difficult. Ever since I saw that as a kid I always thought the idea of code printed out in a magazine was very appealing. I am very happy and grateful to finally be able to scratch that strange itch here.

You can just copy this code from my site if you want though. No need to punch it all in by hand. I really like how this potentially infinite piece of music is contained in a 2kb file. I have a bunch more code and other resources on my site if you would like to check it out. Thank you for spending your time reading this thing I wrote and please get in touch with me through my site if you want to talk to me. I think getting email from people who are into music is nice.