Keeping SuperCollider evolving with minimal impact on users work

You just need to look at the number of upvotes to know that this not the case. I’m pretty sure this has been flagged by accident.

@scztt Can you unhide James’ post?

1 Like

I think the number of likes your post quickly received definitely tells that you are totally welcome, and before that, definitely part of the community. I decided to get myself involved more into SuperCollider’s ecosystem because I felt in debt with the people who spent countless hours developing it, allowing me to work and progress on artistic topics that I didn’t even expect to exist. I’m more than happy to discuss, learn and even disagree with those people, and again, so grateful SuperCollider exists.


This wasn’t flagged based on quality or value, only as off topic because it wasn’t related to this topic. I moved it to a separate topic, because this is a cool and interesting project that deserves discussion on it’s own.

In general, this discussion has become a bit sprawling and there’s a lot of tangents (my post was a bit tangential as well :no_mouth:) - this was a development topic with a very specific set of concerns mentioned by @Dindoleon in the first post, and it’s worth trying to stick to that so it doesn’t become unnavigable. I’m not going to go through and pull things apart any further, but one thing that might be useful for everyone:
If you want to reply to a post but your reply is a tangent / side discussion / not directly related to the topic at hand, you can click the right arrow button in the upper-left of the post editor window and choose “Reply as linked topic”. This will create a new topic, but link it to the post you’re replying to so that people have context. This REALLY helps organize topics, especially when they grow to a huge number of messages like this one.

(I’m less inclined to be hyper-organized about topics elsewhere, but Development topics are places where dev work is organized, and there’s a bit more need to keep things on task.)


@asynth Many people are happy to have your voice back in the discussion! Your new project looks great and many of the future users are on this forum (if you decide to release it :wink:). So please continue to share! I’m sure if you opened up a Topic for discussing SAPF+ there would be a pile on of questions and enthusiasm.

Edit: I see that Topic has already started (Missed scott’s message while i was posting this)

1 Like

Just to clarify, the discussion of maintaining a clean git history made passing mention of a source tree reorganization in 2010. I was looking in the history of complex numbers in SC and found the history severed at that point in time. << In that particular file’s history, you’ll also see the the “great reformat” (reformat with clang), and the history is contiguous.

The clang reformatting is a relevant case for this discussion because that was an example of a very contentious change in which lots of opinions were thoroughly considered, knowing that not everyone would be pleased, but was deemed necessary for the health of the project. The change itself was meticulously handled, and well I think, all things considered. Given the discussion lately, I think we can anticipate some similarly necessary decisions ahead…

To whoever asked (and then deleted the question?):
Yes, of course emojis can be variables.

let 🦕 = [1, 2, 3]
let 🪰 = 2
let 🖨️ = println
🖨️(🦕 * 🪰)

[2, 4, 6]

It was me, I just didn’t want to pollute the forum too much.

After using fonts with ligatures, and utf8 in code, I was thinking about the potential of having emoji (which is a type of ideogram, like in Chinese writing for instance) as part of the code.

EDIT: I think people on this forum were wondering about using music glyphs (accidentals etc) as code recently. Imagine creating a font that would mix fira code and bravura for this kind of thing.

Some things just work nowadays, the problem is there isn’t one good font with both things.

accStr1 :: Accidental
accStr1 = "♭" 
accStr2 :: Accidental
accStr2 = "♯" 
accStr3 :: Accidental
accStr3 = "♮" 
accStr4 :: Accidental
accStr4 = "𝄫" 
accStr5 :: Accidental
accStr5 = "𝄪" 
accStr6 :: Accidental
accStr6 = "𝄳" 
accStr7 :: Accidental
accStr7 = "𝄲" 

>>> accStr1 == Flat
>>> accStr2 == Sharp
>>> accStr3 == Natural
>>> accStr4 == DoubleFlat
>>> accStr5 == DoubleSharp
>>> accStr6 == QuarterFlat
>>> accStr7 == QuarterSharp

-- "𝄱" :: Accidental
-- "𝄰" :: Accidental
-- "𝄭" :: Accidental
-- "𝄬" :: Accidental

1 Like

His current vision is also very important! It could be SC4, or it could influence the concept of SC4. His opinion will be invaluable in concluding the long debate about the development of SC4.

The following would be cool:

let rests = [𝄼, 𝄻, 𝄽, 𝄾, 𝄿, 𝅀]
let notes = [𝅝, ♩, ♪]
let length = [½,⅓,⅔,¼,¾,⅕,⅖]

However, the musical symbols supported by the operating system are not sufficient, and we should use special fonts such as “Bravura” for this. To make this possible, the IDE should support multiple fonts in an SCD document.

Sorry if this muddies the thread.

But amid all the very exciting talk of how to move things forward I just want to express deep gratitude to all the developers, past and present, for everything you have been doing for years and years. I have for the past decade used SC daily in my work alongside several other (prominent commercial) pieces of software, and SC is the one that always works (and remains stable) where others break or crash or simply are incapable of doing the task at hand (and not just in the audio domain!). I can only imagine how tedious/frustrating/painstaking/etc it can be to maintain such a sprawling ecosystem, and every day – with no exaggeration – I am so grateful that you put your skills and dedication and passion towards keeping all of our practices and pieces alive.

(And that said I eagerly look forward to breaking changes that improve the long term health and well-being of the project and the developers.)


Let me second that!

Here’s just another little voice on the future of SC, not from a computer musician but from an acoustician/voice scientist. Sorry if I am barging into a dev group but this discussion is great. I have been programming for signal analysis and voice synthesis since the 1980’s, in assemblers, Fortran, C, C++, Pascal, Matlab and probably a few more. I do not consider myself a professional programmer; it is just a tool that is necessary for the research work. And I have never been as productive as I am with SuperCollider.
So here is why I love SuperCollider 3:
• The language is elegant and tolerant and OOPy. Never a blue screen.
• The turnaround time is typically one second. Ideal for prototyping.
• There is only one type of source file (.sc), no header files that need to be included.
• No other files are generated for a compile/link/run cycle.
• I don’t need to keep track of a lot of supporting libraries and their versions.
• Execution speed is perfectly adequate for everything I do. Just code carefully.
• Great access to the internals; easy to override when necessary. I’m happy to let others implement primitives.
• Cross-platform, except my dozen custom UGens which are a necessary headache to maintain.
• A very helpful community
• A great library of extensions

While I understand that many of you on the dev team would like something more industrial-strength, with name spaces, type checking and so on, that’s really not the raison-d’être of SC, as I see it. Those of us who are programming by necessity (and who do not need to supply user-proofed self-contained applications) love its accessibility and flexibility and relative simplicity.
And here are a few things that I would love to see in the way of new SC3 features:
• On errors, jump to the offending place in the source code.
• An API for reading and writing also non-signal chunks in .wav and .aiff files (for embedding metadata). But I guess that’s for the libsndfile team?
• An API for system clipboard access, for text, images, and signals.
• Some way of writing SynthDefs with existing UGens such that the whole synth becomes demand-rate, evaluated only on an audio-rate trigger. Maybe not possible?
• A mechanism for bundling an SC app into a single executable (ideally with refactoring to remove unused classes). Or,
• The ability to distribute quarks without requiring the user to have Git installed (I do have a bunch of end users).

On occasion I have tried to return to doing things in C/C++ (UGens), but I find today’s Visual Studio quite intimidating and vastly overqualified for the things I need to do, with a morass of switches and options at every turn. Every module compiled requires dozens of source and header and project files for the make, link, compile, and debug phases. Every module gives rise to at least one directory tree; every project becomes a jungle. When I rebuild a C++ project there is a torrent of messages and warnings, most of which can be ignored.

Please let’s not try to make SuperCollider do all those things. It’s great already and very useful to very many people. Thanks to you all.


You can definitely save non signal chunks in wav and aiff files. Just needs to be in a float format:

a = Array.fill(1000, { 25000.0.rand2 });

b = Buffer.loadCollection(s, a, 1);

b.write("/tmp/test.wav", "wav", "float");

c =, "/tmp/test.wav");

c.loadToFloatArray(action: { |array| array.postln });


I think the comment was about having more control over the soundfile header.


It could be possible using a meta-data library like Python and Haskell have bindings for it. Is that what you are talking about?

From one simple/minimal Wave parser haskell library (not a good one btw):

-- | This datatype defines an INFO chunk and our internal representation of it. It is
-- actually defined very clearly in section 2-14 of the Spec and we have tried to mirror
-- that representation here. The spec says the following:
-- > An INFO list should contain only the following
-- > chunks. New chunks may be defined, but an application
-- > should ignore any chunk it doesn't understand. The
-- > chunks listed below may only appear in an INFO list.
-- > Each chunk contains a ZSTR, or null-terminated text
-- > string.
-- Manipulations of that data structure should adhere to that specification.
data WaveInfo = WaveInfo
   { archiveLocation       :: Maybe String
   , artist                :: Maybe String
   , commissionedBy        :: Maybe String
   , comments              :: Maybe String
   , copyrights            :: Maybe [String]
   , creationDate          :: Maybe String
   , croppedDetails        :: Maybe String
   , originalDimensions    :: Maybe String
   , dotsPerInch           :: Maybe String
   , engineers             :: Maybe [String]
   , genre                 :: Maybe String
   , keywords              :: Maybe [String]
   , lightness             :: Maybe String 
   , originalMedium        :: Maybe String 
   , name                  :: Maybe String
   , coloursInPalette      :: Maybe String
   , originalProduct       :: Maybe String
   , subject               :: Maybe String
   -- TODO make sure we output our name
   , creationSoftware      :: Maybe String 
   , sharpness             :: Maybe String 
   , contentSource         :: Maybe String
   , originalForm          :: Maybe String
   , technician            :: Maybe String 
   deriving (Show)

FluCoMa uses the HISStools one by Alex Harker. Simple, to the point, complete, free, BSD3. fun :slight_smile:

Nice. It seems an elegant project indeed.

But to value the cohesion of the project, we cannot forget that scsynth works perfectly well in non-realtime mode. We can do all sorts of things using scsynth -N , which will be available in the language. Including sound analysis and all kinds of things.

I’m having some fun with functional algorithms for dsp in haskell, since c++ makes me dizzy and confused. c++ not very fun for me ))

1 Like

My 2c on ‘users work’. scsynth has currently no way of allocating the correct memory structures for UGens, instead relying on the SynthDef sent to them. Rather than addressing this issue when thinking about extending the UGen APIs, i.e. making scsynth aware of the number of arguments and pre-filling the structure with a sensible default (e.g. zeroes, what would have to be taken into account then in UGen evolution), it’s far less work (a magnitude less work) to just quickly “patch” the system.

Current example: RandID was until now only a global setting per SynthDef; now discussion comes along, it would be nice (agreed) to be able to use multiple RandIDs; how to do it? Add another UGen argument “force” to the UGen; no problem for 99% of users because you can break the binary API if you co-evolve scsynth and sclang; 1% of users (me) will have to deal with the fact that the (different) client would now have to produce two different synth-defs depending on which version of scsynth is running. This is not to accuse anyone, just saying, this is simply how do-ocracy works.

1 Like

This should perhaps be discussed again!

1 Like

I think everyone would agree that it would be good not to risk crashing, but adding the workaround would be probably more work than anyone would be willing or capable of doing. So I can only point out the issue, but I won’t be able to present the PR that implements the workaround.

I wonder if a simpler (and actually better) solution is to store the size of the data structure, such that instead of

bool fire = ZIN0(1) > 0

you then write

bool fire = num_ugen_args >= 2 && ZIN0(1) > 0

Ugens do know the size of their inputs and outputs (numInputs and numOutputs). It is therefore possible to add new (optional) UGen inputs; the UGen only needs to check the number of inputs, just as in your example above.

FWIW, I was unable to crash it by mismatching scsyndef and plugin versions.

  1. Using the develop branch, create a synthdef:
    SynthDef(\randID, {;,
  2. Switch to topic/MultipleRandIDs, make, sudo make install.
  3. Relaunch SC, boot the server – no crash during GraphDef loading.
  4. x = Synth(\randID); – no crash.

^^ That is using new RandID plug-in code, which expects two inputs, with a SynthDef produced by the old library code, providing one input. x.trace shows just one input. I don’t have time at the moment to doublecheck the ZIN, ZIN0 macro set, but this test does suggest that ZIN0(1) isn’t guaranteed to crash when there is no input 1 – which is a significant finding because the question seems to assume that it will necessarily crash. (Perhaps it would have crashed at some point in the past.)

I also tried the other direction – using the topic branch:

SynthDef(\randID2, {, 0);,

Then switch back to develop, rebuild, reinstall, and run the synth. Again, no crash. (In this case, the struct for RandID would be defined without enough space for the second input that exists in the SynthDef.)

So it would be worth investigating: Has the code changed to handle this situation more safely? Because I can’t reproduce the problem in this case. (Or, maybe it’s fine for control rate inputs but mismatched audio rate inputs might crash.)