Parse SynthDef for transmission to server

Hey! I am trying to write another client application to control the server and want to send a SynthDef to it. I’ve seen that a special .scsyndef file is needed for this purpose, which is created when calling writeDefFile on the SynthDef.

I’d like to parse the string into this format without sclang. What encoding is needed here if any and/or are there any other suggestions on how to transmit a definition to the server? Is there actually a way to just send the normal SynthDef syntax with an OSC command, either directly or saved to a file?

I mean - I’ve seen posts like these (Encrypted SynthDef) and really can not wrap my head around it. It is suggested that the SynthDef should just be parsed as binary - so naively I tried a few String to binary converters online, but none delivers the same result like the function .asBytes in the SC IDE. Am I missing something here?

It’s very important for this kind of task to define the input and output carefully.

What are the string’s contents? This isn’t stated in the post.

The output of the SynthDef builder is described in the documentation: Synth Definition File Format | SuperCollider 3.12.2 Help

hjh

Thank you very much for your answer! Now that I studied the page, I can clearly see how the binary format of the .asBytes output translates. However - would anybody experienced maybe be willing to help on this providing a little hands-on example how a SynthDef like this little example would be parsed to this output, if I wanted to do it manually?

SynthDef.new(\test, {
arg freq = 440, amp = 0.1;
var env, sig;
env = Env.perc().ar(Done.freeSelf);
sig = SinOsc.ar(freq!2);
sig = sig * env * amp;
Out.ar(0, sig);
});

I was afraid that this might be what you meant :grimacing:

I’m sorry to have to say this, but, if your goal is to build SynthDefs outside of sclang, without using sclang, then to take sclang code as the input is, IMO, not a good approach.

The process that the code goes through, to become a binary synthdef, is:

  • Lexing: The code is split up into tokens.
  • Parsing: The tokens are analyzed into a syntax tree explaining the structure of each expression.
  • Compilation: The syntax tree is translated into interpreter bytecodes, which are placed into a Function object.
  • Execution: The new Function is evaluated.

^^ These steps are all implemented in C++, not visible in the class library. But, if you want your client to run sclang SynthDef code, then you would have to handle these. lnihlen’s Sparkler project could help you with lexing and parsing, but not with compilation or interpreting.

  • SynthDef.new: A SynthDef object is initialized, and then the synthdef function is evaluated.
    • Any UGens that are created within this function are added into the current SynthDef object, keeping track of the source for each input.
    • Optional: Then, an optimization pass removes unused chains and collapses certain combinations of math operators into a smaller number of UGens.
    • Optional: Then, a topological sort rearranges the UGens into what is usually a depth-first order, as much as possible.
  • Now the SynthDef object is ready to be written out.

I suspect here that you might have mistaken SynthDef code for a static structure. The code is not an object to be parsed. It represents a process by which a particular SynthDef is built. It has to go through the process, step-by-step.

If the goal is to support sclang’s way of writing a SynthDef, then you essentially have to replicate all of sclang in your other client. This would be a massive waste of time (because there is already a functioning sclang interpreter). Don’t do that.

You’d be better off to figure out how to represent the UGen graph in your client’s language. In a first attempt, it would be enough to handle UGen objects’ inputs and outputs (optimization and topological sorting are not strictly necessary).

There are some other clients that build SynthDefs – if I recall correctly, ScalaCollider and hsc (Haskell-SC) do. These projects, plus the SC class library SynthDef and UGen classes, would give you more insight and tips.

hjh

Okay, thank you very much for these insights! I am trying to build the SynthDef out of vvvv.
This is the procedure I am doing so far:

  1. Build the SynthDef as a string (with removed tabs, line breaks and spaces) + the .writeDefFile method at its end
  2. Save it to disk as a .scd file
  3. Use sclang command line to run the file
  4. Send the binary file to the server once it is created
  5. Delete both files after successfull SynthDef addition

Are there tips how to improve this for now?