I tend to get this question (or variations of it) a lot:
“What’s the best language for an aspiring audio programmer to learn?”
There are, as far as I can tell, two correct answers to this.
- Well, it really depends on what you want to do.
- C++
When I began my foray into taking audio programming seriously as a thing I intended to learn and master – I avoided C++ despite getting answers similar to that above.
Everything I “knew” (which wasn’t really anything), and was told is that C++ is a hard language to learn and work with. While there are various opinions on this, all I really understood was that once I got past the basic syntax of C++ I had no idea what the heck was going on.
It also wasn’t just because things like pointers and function pointers aren’t that prevalent/accessible in higher level languages.
So invariably I’d start some sort of project – like a VST plugin – and hit a wall that I couldn’t get past, either math or code related. I never really understood why, and it was consistently frustrating.
Today, I get to sit next to some brilliant software developers and ask them questions while I go through an “advanced” C++ course – and the answer to “why is C++ so hard?” really hit me.
So if you’ve ever found yourself in that spot of wanting to create something truly mesmerizing, but getting stuck consistently – I think I can help you out.
It’s Not about Syntax
If you go to one of the literally hundreds of thousands of programming tutorials on the web today – especially “beginner” ones – you really learn one thing: syntax.
By that I mean, how the language is written.
Once you learn the basics of a few languages you come to realize that most of their parts are, largely, very similar. You have odd anomaly’s like Python’s use of white space, but each language generally has bits like these that might be named something different:
- A dynamically sized array (like a “list” or “vector”)
- An object that can store key, value pairs
- Some sort of special loops, like C#’s “foreach”
- etc.
Early on, learning said languages is mostly learning the quirks and differences for the specific one you’re learning.
Once you get it, you’re well on your way to making some very fun cool things – perhaps inefficient fun cool things, but fun cool things nonetheless.
So you’d assume, if you didn’t know any better, that you just need to learn the syntax of C++ and how object oriented programming works and you’d be good to go. From there it would just be time and experience to “get good” at it, whatever that means.
But that’s where you’re wrong, and where I’ve learned that low-level language (like C and C++) really get vastly different than everything else.
For once, the syntax isn’t really the important part. The syntax is the baby step where – if you don’t know any better – you say you’re really “learning” C++. It’s not that I think you aren’t – but it’s more like you’re learning how to form a sentence instead of why you form it in such a way.
Re-read that last sentence. It’s what I’ve found that differentiates “high” and “low” level languages.
Why it’s Different
If I spell it out for you, the fundamental difference – and why you find it so hard – is this:
With C++ you really need to know what and why you and the computer are doing what you’re doing.
This can be thrown in contexts of “efficient operations” or “garbage collection” or “memory management” or whatever – but it all boils down to the same idea at the end of the day.
In C#, for example, if you had no idea about passing references or copies of objects (and there’s a good chance you have no idea what I’m talking about right now) that’s entirely fine for the most part. You don’t need to know, because the language and machine make inferences about what you’re doing and handles that for you.
But in C++, it’s not. So you need to know when, why, and how you pass a reference or a copy of an object. On one hand, it’s super trivial – but for someone new, it’s not. Even for someone with experience, if you don’t handle a minor operation like that correctly over and over, you can bring a system down.
Nothing in C++ ever comes right out and says “It’s a really good idea for you to learn and understand how the computer handles memory when you instantiate a vector vs an array”, it’s usually only alluded to in unhelpful ways by people who are more experienced.
“You know, you really should use an array here – I don’t know why you’re using a vector. A vector is overkill and vastly inefficient for this operation.”
OK – but… if you don’t know why that’s remotely important, you also don’t have to determine the size of your vector. Yay, less to immediately think about! It’s more familiar to “high level” programming! Woohoo!
But, that’s really the wrong way to go about writing your program. It’s vastly important to ask “Well, why is it more efficient? How does the computer handle these objects in memory? Does that matter for the thing I’m working on?”
Which means you have to dig further than you normally do and use your brain for things besides syntax. Also, unless you have someone walk you through how through how to view actual bytes in memory, or even a disassembly window – it’s hard to wrap your brain around all of it on your own.
Why does any of that matter? Because you can do so much in C++, you can mangle memory and the language syntax the way you want it to be mangled. For example, for those that don’t know, if you wanted to you can make the plus operator (+) do any other kind of arithmetic you want. A plus operator that does division? If you want that, sure!
But if you don’t know what the machine is actually doing to make that happen, you’re usually going to shy away from it and not take advantage of that sort of thing when you could use it. That’s going to make your life extremely difficult whenever you work with a team or another programmer who does understand these things – because you’ll need to get up to speed.
The best way I’ve found to handle this mentally is – instead of being intimidated by the mountain of information – get fascinated with the quirks of the machine. Don’t try and memorize the rules of how many bytes a generic type holds, because if you use the language enough then you’ll likely do that eventually. Instead, find things like – “Huh, did you know that when a vector gets dynamically resized that it actually DOUBLES the potential amount of information it can hold? So unless you specifically declare the size, a single vector could get HUGE and still be pretty empty if you have a lot of information stored.”
But you wouldn’t know that last part, if you didn’t run across how a vector works. It also starts to explain one reason why, in a large system, a vector could be a horrible idea to use when compared to an array.
Thankfully there’s plenty of content – paid and free – online that can address this sort of thing now. Handmade Hero, for example, is a great place to start. I also enjoy Jon Purcell’s C++ courses.
You Can Get Past This
The one thing I want to constantly tell you is – you can do it.
I am, and I’m a pretty average human. There’s no reason that, if you want to, you can’t excel at something like audio programming with C++ no matter how hard it seems. It’s just working at it consistently that will get you through.
Don’t be intimidated, find something intriguing and get fascinated by it. Now that you know why it can be hard, you’re in a much better position to make it easier on yourself. Soon, you’ll know something a lot of people are freaked out by – and you can be proud of yourself for that, and then bring them along too!
Copyright 2016-2021, NIR LLC, all rights reserved.