i think thats exactly the discussion which has to be made.
what is programming? what is contemporary music?
i went way to far on the programming part and got stuck with making music. but where do these meet?
i often get reminded when reading these threads that i have no idea of programming.
The advantage to system building is that you can build it up up over a long period of time. I have had a lot of success with this approach…and a lot of failure. The nice thing is I keep the successes and throw out the failures. I have some sound processing modules THAT I MADE OVER 20 YEARS AGO and still use in almost every performance today. I will probably make something next week that goes in the garbage next month.
This being said, I am not really making pieces. I am mostly an improviser who is building a language over time. My dissertation is called “Laptop Improvisation in a Multidimensional Space.” It isn’t about composition, as I decided a while back that the instrument, at least in my hands, is better at improvisation than at composition. My compositions tend to not be in the form of SC programs, although some of them are. I have found SC to be very bad for distribution of “pieces” even while it is great at composing.
The balance between creating good music and making good code is constant. SC, because of its idiosyncrasies, shall we say, tends to attract people who like to code and might find code attractive. Therefore we need to learn to see the forest through the trees. It is a constant struggle that we all need to be aware of.
I have some great success stories - I’ve built instruments over the last few years that felt at the time like way-too-big engineering nightmares, but after diligent attention and care (I’m talking a period of a month or two, not years…) they matured into very flexible, exciting things. I’ve built abstractions that let me work out ideas with a ton of fluidity and speed, and let me make great sounds all afternoon without any “engineering-y” work to be done at all.
But there are some caveats here:
I also have FOLDERS full of half-baked ideas, buggy implementations, and “musical systems” (though this particular kind of thing I, like nathan, gave up on years ago). The amount of wasted time is immense, though these days I tend to be quite selective about what I spend my time on engineering-wise.
I have 15+ years of professional software development experience, including large-scale work on systems… a fair amount more complex than any of my SuperCollider patches. This is a VERY particular and i think relatively unusual perspective to have in the SC community.
If I’m thinking of “success stories”, a few commonalities:
1. Small, simple, well-designed things that solve a specific problem I run into all the time.
The payoff with these can be fantastic, because the cognitive load of having to deal with some gotcha or clumsy way of doing something in sclang takes attention and energy out of every studio session. These are the equivalent of those hooks and fasteners you hang cables on in your studio - you shouldn’t spend ALL your time just re-cabling your setup, but if you trip over cords every day it’s worth spending a day or two solving the problem.
But, caveat: My ability to remember and use these nice little abstractions is limited: I probably have 15-20 of these in my core rotation, built up over many years. More than this and I simply won’t remember how they work, how to use them, or how to fix them if I find a problem. I have the energy and attention to care for a small menagerie of these animals, but definitely not a large one. And finally: your practice changes, so a useful thing now may not be useful in a few years.
I have have maybe 5-6 things like this. These took a LOT of time to build, and still take some effort to maintain. But, they are at a level of abstraction of a good VST plugin - they have reasonable parameters, flexible behavior, they sound good / work well, and I can throw them in something with no parameters or setup and they start working immediately.
All of these that I would consider successes started with code-jam style development - I’d see an opportunity that felt useful enough to really solve and not just hack around on. I’d spend a weekend or a week building a quick-and-dirty prototype, and make music with it. If it works well, sounds good - like really good, game-changer good - then I’ve made time to properly tackle the problem, make the code solid. This has meant REAL development: not just hacking around to make it a bit better, but really thinking about myself as the user, thinking about how I want to use it and what would make it better for me.
Usually when I reach a critical mass of “I really want it to do this!”, I’ll put in a well-defined chunk of work into it - e.g. a weekend or two - and then leave it alone for a while. The best things tend to grow like an onion, adding thing layers onto what was there before. I also have lots of things that never made it out of the first code jam phase, but these were often learning experiences - and one weekend for a failed experiment plus some learning is relatively low cost for me.
How big do your files get? I’ve always found that after 1000 or so things start to become unmanageable, particularly if the code needs to be executed it a particular order.
About 500 LOC for a standard 5-minute composition. I almost always have just two parenthesized blocks, one for SynthDefs and one for Routines, which take up about 50/50. Having many executable regions is a bad idea in any context other than live coding.
My code is not very software-y, it’s mostly data. The bulk of it is UGen graphs and manually sequenced rhythms and pitches.
Ah, unfortunately that simply isn’t possible for the genre of work I’ve been doing - Jellyfish 2023 - new work - it needs: osc sources between unity and mediapipe, several helper synths to wrap the mediapipe stuff, the audio, osc mapping functions, osc maps content, osc senders, and gui helpers for some of those things. Even if I simplified it there is easily several thousand lines.
Perhaps a one file approach works well for a particular style of music? And in general, if such considerations should be reflected in ‘opinionated advice for supercollider beginners’?
D’n’b producer Cylob used to have a big “do-everything” system in SC2.
Around 2005, I started writing all of my compositional code into Proto objects. Now here, I suppose saying this will trigger several standard rants about “prototypes are awful in SC” but I derive a lot of benefit from this. My live set up loads a lot of scd files but very, very few global variables (master and reverb mixer channels, a one-key hook for control mapping, and a tempo fader, that’s about it).
Now… this might not help beginners that much. But, for example, a few weeks ago when I was preparing for a duo jam, I wanted some vocals to adapt to the tempo and key. So I wrote a Proto process (which includes all buffer loading and unloading, mixing framework management etc.) and a factory object including a small database of audio files and metadata. Then, in the show:
// this loads everything -- \twist is the database key
/make(voxBP:tw(set:\twist));
// and this says "play a different section, on the downbeat, every 8 bars"
/tw = "1";
/tw..section = "[*]::\seq("1234")";
/tw = (main.rest*7);
It is more weight up front to put all of that into a Proto, but what I get out of that is a package that Just Works, and then I don’t have to fight with it again. 18 years of this working method (the live-coding dialect is more recent though), without significant design changes – I’m satisfied that this is working reasonably well.
The complexity level that Jordan is talking about would definitely benefit from objects, whether standard objects or the types of Proto that I’ve been using.
I absolutely needed to write classes to build the piece I’m working on now! Beyond that its just a joy when developer-me succeeds in providing user-me a pleasant interface! I spent a couple years using vanilla SC before venturing into writing my own classes, and it took a couple years of that before the system became (somewhat!) productive. I have my classes and pieces all in a giant git repo so if I change the classes one day and break old pieces it should be straightforward to wind things back (famous last words!).
Here ~a does not equal ~b because by the time the server has synced the current executing file has changed.
Now this just flat out doesn’t work with executeFile, which I think is better than sometimes working and sometimes not (just spent half an hour trying to fix this).
Yesterday I had said that nowExecutingPath might not be set in context of a thread. AFAICS that’s not true – whenever a thread is awakened, the thread’s executingPath populates nowExecutingPath, and when it yields, nowExecutingPath should be reverted.
The problem here is that load-ing a different file within a thread needs to update the thread’s executingPath, but it doesn’t. (I have a bit of a hacky fix, but it’s probably not a good one… will log it shortly.)
This probably explains the sync problem that you ran into.
I suppose that I can apologize for being unaware of that bug. However, I get a slight feeling that some of the energy in that post is going toward proving me wrong, where a better focus would be solving the problem… just noting it, I won’t go further into that.
The infrastructure is there for a thread to remember where it’s executing. It’s just not consistently updated, which IMO is not realizing the spec properly.
TBH here… in my live setup file, I have var path = thisProcess.nowExecutingPath and then I use path throughout. That was a while ago. I don’t remember if I had tried using thisProcess.nowExecutingPath, and it broke, and then I tried to work around it – or maybe I just assumed “this isn’t going to work in a thread” and preemptively worked around it.
(Now, the path infrastructure doesn’t exist for functions – so, scheduled functions don’t have any awareness of the path in which they were defined. I don’t think this is a big problem because standalone functions don’t persist their status in the way that routines do, and if you really need it, the workaround isn’t difficult.)
Good article. Taking inspiration from cool pieces of hardware is great, as it helps you to think about problems in a general way.
I got pretty overwhelmed when starting out with SuperCollider and I was not new to programming or synthesis or music production.
So my tip is more for casual self-learners, that just want to hack something together to make sick tunez after work, rather than the lucky few that get to invest much more time.
My tip is (especially if you feel overwhelmed): you don’t have to go ‘all in’ on Supercollider, when starting out.
Instead of synthesis exclusively in SuperCollider, you could record VSTs and explore triggering samples from within SuperCollider
Just explore midi sequencing and CC
If understanding Groups and Busses is not quite sticking yet, consider just routing out to a DAW (or quarks as mentioned above).
There are many other ideas for using Supercollider in a limited way. The point is not to sweep difficult concepts under the rug, but to try and learn them incrementally while still getting your hands dirty writing code and enjoying the new capability. As ideas get more ambitious, there’s more motivation to take on the trickier concepts.
For programmers: one thing I did was cherry pick problems from coding sites like code wars or exercism and solve them in sclang. That was a fun way to explore the language and get a feel for it. Instead of just wishing it had feature x from lang y.
You mentioned Synth secrets, which I quite like. There’s also this old nord modular book - you’re probably aware of it, though I’m not sure if it’s a good addition to your article.
I experienced something similar. I was losing motivation to write supercollider code after writing code all day at work. My productivity increased once I stopped caring about the usual things when developing in a professional context.
My music code doesn’t need to scale, it doesn’t need to be readable or maintained by anyone else, it doesn’t need to be DRY, etc etc. It just needs to sound good! If I were collaborating, then ok sure, I would have a different approach.
Just discovered this lately. Certainly a lot of very useful recommendations! Some of them with a strong opinion – I might not agree with – but that’s ok.
I especially like the emphasis on practice, keeping things technically clean and simple and – at the end – LISTENING to the results. Having said that, sometimes curiosity inevitably leads you to things that are not simple …
One side-remark concerning the Amplitude UGen you are mentioning in the collection of SuperCollider Tips: it’s not only the default settings, it’s mathematically wrong in more than one regard – a bad bug, as Julian described it (my example of June 4, 2020 is clearer than my first post). However, Amplitude is still of practical usage:
I can only partially confirm what you have been experiencing. Indeed, I’ve developed several classes for miSCellaneous_lib that I have never used musically in serious projects (E.g.: Sieve / Psieve patterns, ironically, I know that others did use them). However, I’ve used several classes intensely over a long period of time: VarGui is serving my GUI needs since 2007 or so for all of my projects. I’ve used it in combination with PLx Pattern classes for Pattern-based granulation very often.
What also happens quite often is that classes turn out to be useful with a delay of several years. I’ve used PbindFx – which took me three years to develop – for the first time in a larger project last year.
Yes so true. That’s my preference - for curiosity to lead me towards complexity, rather than racing towards it, as I have in the past. I guess there are some parallels there with premature optimization.
Edit: And yes your miSCellaneous_lib is super cool and very useful! Thank you.