As part of a project that has been torturing me with its lack of existence since 2013, I need to learn Supercollider and Overtone. This is what brought me to Clojure in the first place. I’ll be blogging about that project plenty, but enough of that for now.

So I’ve been translating Supercollider code from Eli Fieldsteel‘s very excellent YouTube Supercollider tutorial series into Clojure for use with Overtone. It’s the domain-specific knowledge that gets you. I can’t be productive in Overtone until I understand how Supercollider works. So I’ve got to start with Supercollider, but keep my chops up in Clojure. Hence, this exercise.

Tutorial 3 talks about composing Ugens together to define and control synths in Supercollider. Yesterday and today I translated the final pulseTest synth into Clojure. What I’ve got sounds almost like the example code run from the Supercollider IDE, but something’s off with the ampHz Ugen. It seems to be pulsing at about half the speed, and occasionally I get a very loud low-frequency boom when I kick off the synth. I’d appreciate anyone who can spot my error or help me track down the cause. Here’s what I have:

(defsynth pulsetest "A super awesome synth that almost works the same as it would in SC"
  [ampHz 4
   fund 40
   maxPartial 4
   width 0.5]

  (let [amp1 (* 0.75 (lf-pulse:kr ampHz 0   0.12))
        amp2 (* 0.75 (lf-pulse:kr ampHz 0.5 0.12))

        freq1 (round 
                ; http://doc.sccode.org/Classes/UGen.html#-exprange explains
                ; that it uses a LinExp ugen to do the work. Here, we do the
                ; same manually 
                (lin-exp:kr :in    (lf-noise0:kr 4) 
                            :dstlo fund 
                            :dsthi (* fund maxPartial)) fund)
        freq2 (round 
                ; see above
                (lin-exp:kr :in    (lf-noise0:kr 4) 
                            :dstlo fund 
                            :dsthi (* fund maxPartial)) fund)

        freq1 (* (+ 1 (lf-pulse:kr 8)) freq1)
        freq2 (* (+ 1 (lf-pulse:kr 6)) freq2)

        sig1  (* amp1 (pulse:ar freq1 width))
        sig2  (* amp1 (pulse:ar freq2 width))

        sig1  (free-verb:ar sig1 0.7 0.8 0.25)
        sig2  (free-verb:ar sig2 0.7 0.8 0.25)]
    (do
      (out 0 sig1)
      (out 1 sig2))
    )
  )


Here is the SC version:

 

(
SynthDef.new(\pulseTest, {
        arg ampHz=4, fund=40, maxPartial=4, width=0.5;
        var amp1, amp2, sig1, sig2, freq1, freq2;
        amp1 = LFPulse.kr(ampHz,0,0.12) * 0.75;
        amp2 = LFPulse.kr(ampHz,0.5,0.12) * 0.75;
        freq1 = LFNoise0.kr(4).exprange(fund, fund * maxPartial).round(fund);
        freq2 = LFNoise0.kr(4).exprange(fund, fund * maxPartial).round(fund);
        freq1 = freq1 * (LFPulse.kr(8)+1);
        freq2 = freq2 * (LFPulse.kr(6)+1);
        sig1 = Pulse.ar(freq1, width, amp1);
        sig2 = Pulse.ar(freq2, width, amp2);
        sig1 = FreeVerb.ar(sig1, 0.7, 0.8, 0.25);
        sig2 = FreeVerb.ar(sig2, 0.7, 0.8, 0.25);
        Out.ar(0, sig1);
        Out.ar(1, sig2);
}).add;
)

 

And that’s how far I am. I’m going to proceed to another tutorial for now. I’m also going to find a theme and plugin that makes this code look a little nicer.

You can track my progress at the git repo I have set up for this project.

I was about to write another post about my journey with Supercollider and Overtone, and I probably will right after this, but I had a thought about learning to code that I thought merited its own post.

Learning the syntax and semantics of a programming language, especially a modern one like Ruby, is indeed achievable within the context of a bootcamp. But the real challenge of programming isn’t learning how to talk to computers. It’s learning how computers talk to each other (roughly layers 3-6), how programs talk to each other (layer 7 when it comes to network, plus a bunch of other concepts and markup languages and, as you get more advanced, OS-specific API knowledge), and the general ecosystem in which your programs live (sysadmin/tech support background helps here).

There’s a blog post that pretty accurately captures all the extra stuff you pick up as a web developer, but it tries to sell you more bootcamps and classes. I can’t vouch for the content of those classes, but I can tell you from experience that this isn’t a problem you have to throw money at. Linux is free and will run on equipment you would have retired.

This “extraneous” knowledge amounts to several years of active computing experience. You just have to spend a couple years messing around with computers, trying to run Arch and get everything done, stopping to troubleshoot esoteric problems, etc. Somebody with an IP address in China logs in and deletes your home directory for lulz. You grieve the years’ loss of writing, recordings, and other personal data. You learn iptables, set up denyhosts, start using SSH keys, change the way you structure your network, and start backing up your data (ask me how I know!).

Or you can take some classes, I suppose. I chose the former route.

Either way, as far as I can tell, there’s no shortcut. Until you get this contextual knowledge, you’re gonna struggle. You know a language, but have nothing to talk about for lack of any frame of reference. It’s like learning the words in Spanish for “fruit”, “dress”, and “bathroom” but being from an alien planet where they don’t eat, wear clothing, or defecate.

I think the main problem with a lot of these training courses, and the culture of learning to code, is that they gloss over this part of the journey. People get frustrated, conclude that they’re just not smart enough for the craft, and give up.

I think that’s the wrong conclusion. You just have to realize that on your way to true competence, you’re gonna have to take on some pretty massive side quests as part of the grind. You probably have what it takes. This is just a very long game.

And when you’ve mastered the “basics”, there’s a whole other level to get at. For a professional software developer, it should be a given that they know their network, they know how OS’s work, they know how various flat-file and database storage systems work, they know a couple markup languages and a couple Layer 7 protocols, and a ton of other miscellaneous stuff I’m forgetting. Taking all that stuff as a given, here’s my frontier.

Keep learning. We practice a deep craft.