One of the reason I'm into Supercollider for my audio programming adventures at the moment, is that it conveniently correlates with my current day job, which mostly consists of object oriented programming in Ruby.
Being both somewhat inspired by SmallTalk, they share a couple of nice features, one of them being code organization in classes.
One of my first "larger" Supercollider projects is a "variable length looper" that allows live recording of sound sources into an array of buffers, and manipulating them with patterns afterwards (I've explored that here and here a bit in video format).
The code for this quickly became unwieldy and called for more separation of concerns, but it somehow all revolved around an array of buffers:
Being both somewhat inspired by SmallTalk, they share a couple of nice features, one of them being code organization in classes.
One of my first "larger" Supercollider projects is a "variable length looper" that allows live recording of sound sources into an array of buffers, and manipulating them with patterns afterwards (I've explored that here and here a bit in video format).
The code for this quickly became unwieldy and called for more separation of concerns, but it somehow all revolved around an array of buffers:
~buffers = ~num_buffers.collect { Buffer.alloc(s, s.sampleRate * 10.0, 1); }; ~num_buffers.collect { ~rec = Synth(\rec, [\bufnum, ~buffers[bufnum]]); }
etc. etc.
Now one of the problems I faced was that I wanted to further develop this project without being dependent on a sound generator like a synth etc. I wanted to work on it on the go, with a couple of samples. That sounded like a generalization worthy to extract from here. So I looked deeper into OOP with Supercollider.
Now one of the problems I faced was that I wanted to further develop this project without being dependent on a sound generator like a synth etc. I wanted to work on it on the go, with a couple of samples. That sounded like a generalization worthy to extract from here. So I looked deeper into OOP with Supercollider.
Writing a Buffer Collection Abstraction
In short, most of the technique required is written up in the guide, but for me the most surprising part was this:
Class definitions are statically compiled when you launch SuperCollider or "recompile the library." This means that class definitions must be saved into a file with the extension .sc, in a disk location where SuperCollider looks for classes.
On MacOS, that's usually under /Users/username/Library/Application Support/Supercollider/Extensions, for other platforms just look up what `Platform.userExtensionDir;` spits out for you, and put your definitions there.
Coming from MaxMSP and PD, this seemed a bit arbitrary - why make this a hardcoded requirement? But then I reconsidered: my RubyGems, or global npm packages all live in defined spots on my hard drive, why not Supercollider classes? After all, there's also a point to make when sharing code: If I were to share a SC project with others including some of my abstractions, all I'd have to tell them is to take my definitions and put them into this specific folder. Or even better, just take my SC extensions Github Repo and clone it there.
So, long story short, I developed a variable buffer collection class, or VBufferCollection, and was able to swap it in immediately.
Even better, I was able to unit test it for the three scenarios (allocate empty buffers, take a directory and load all containing files, or define an array of file paths). The result, for now, can be found here:
https://gist.github.com/julianrubisch/1f71a921f8b503158a3d9f8a0e750d4c
I'm certainly going to develop that further, and report back.