Sc3 vs Supriya as Python scsynth front-ends?

Has someone here used or at least tried both and can give a brief overview of what’s supported in one vs the other? Both “sc3” and Supriya are Python front-ends for scsynth that have seen reasonably recent development efforts. The latter has more issue filed with its github tracker, but most are self-filed by the main dev to keep track of enhancements they want to make, so that’s not too illuminating.

The most obviously named attempt at this, called supercollider · PyPI has apparently been abandoned by its dev, a couple of years ago.

There’s also FoxDot, I see, but it seem to want to go in a slightly different direction as it appears to have its own idea of how the higher-level composition should be done. On that angle, there’s also “scamp” that can use both scsynth, albeit somewhat indirectly and its own fluidsynth-based synthesizers. Actually, looking at the FoxDot tutorial, it also uses some sclang bootstrap code, probably more of it than scamp. Neither of these latter two projects has an actual SC synthdef compiler (graph builder) of their own, it seems. The abandoned “supercollider” python package didn’t have one either.

I haven’t tried either, but from a quick look at the examples, sc3 looks more elegant and pythonic to me.

For example, making a SynthDef:

Supriya:

builder = supriya.synthdefs.SynthDefBuilder(
    amplitude=1.0,
    frequency=440.0,
    gate=1.0,
    )

with builder:
     source = supriya.ugens.SinOsc.ar(
         frequency=builder['frequency'],
         )
    envelope = supriya.ugens.EnvGen.kr(
        done_action=supriya.DoneAction.FREE_SYNTH,
        envelope=supriya.synthdefs.Envelope.asr(),
        gate=builder['gate'],
        )
    source = source * builder['amplitude']
    source = source * envelope
    out = supriya.ugens.Out.ar(
        bus=0,
        source=source,
        )

synthdef = builder.build().allocate()

sc3:

@synthdef
def sine(freq=440, amp=0.1, gate=1):
    sig = SinOsc(freq) * amp
    env = EnvGen(Env.adsr(), gate, done_action=2)
    Out(0, (sig * env).dup())

Apparently, Supriya requires 3 seperate steps to build a SynthDef. sc3, on the other hand, can do everything in a single step (using a decorator).

3 Likes

Author of Supriya here. That sc3 decorator technique is clever. I should look into it…

Supriya’s in a place where most of what I wanted to implement is done, and I’m now going through and writing documentation for everything, tightening up the API, and adding more test coverage.

It’s definitely more verbose than other projects out there. Didn’t write it with live-coding in mind. Have generally followed a “nail down the model and tests first, add syntactic sugar later” approach.

Lucas (author of sc3) can correct me, but I think sc3 intends to reproduce the structure and spirit of sclang inside Python. Supriya doesn’t, and I’ll be the first to admit that I barely know how to use sclang :sweat_smile:.

My goal building Supriya was so that I could build large applications on top of it. Wanted something with little-to-no-magic, high unit-testability, tight parity between realtime and non-realtime APIs (e.g. write codepaths that perform RT or NRT agnostically), asyncio integration (e.g. async osc, servers, clocks), Sphinx integration, etc. Definitely makes it way more verbose, maybe even enterprisey :laughing:.

1 Like

OK :laughing: decorator implemented and merged, and the README updated. The example in Supriya now looks like this, including all the imports:

import supriya
from supriya.ugens import EnvGen, Out, SinOsc
from supriya.synthdefs import Envelope, synthdef

@synthdef()
def simple_sine(frequency=440, amplitude=0.1, gate=1):
    sine = SinOsc.ar(frequency) * amplitude
    envelope = EnvGen.kr(envelope=Envelope.adsr(), gate=gate, done_action=2)
    Out.ar(0, [sine * envelope] * 2)

server = supriya.Server().boot()
synth = server.add_synth(simple_sine)
synth.release()
server.quit()

We’re effectively doing the more verbose version with the SynthDefBuilder under the hood. Unlike the sc3 version, you have to explicitly add the SynthDef to the server. Also unlike the sc3 version, parameter rates and lags are arguments to the decorator rather than annotations (e.g. @synthdef("ar", ("kr, 0.5), "ir")) because using non-type-hint annotations will break the Python static analysis tooling.

I’m also using keyword arguments for all the UGen args because I simply cannot remember the positional order, and no-one else should have to either :laughing:.

2 Likes

Yes, sc3 is the sclang (base) library in python, and is a port of all the basic abstractions developed in sclang by contributions and creativity of many people. The license is different from supriya, sc3 is GPLv3 and being a derivative project it will be that way forever. It is also a lightweight zero-dependency library and a less canonical but more efficient implementation overall (following sclang’s). It also works out of the box on Windows too and is not finished and could be improved in many ways (since there are no backguard compatibility issues).

Actually that is optional, you can pass the same data as arguments to the decorator:

@synthdef(rates=[0.02, 0.02], variants={'low': {'freq': 110}})
def test(freq=440, amp=0.1, pan=0, gate=1):
    ...
2 Likes