NRT and Supernova

Hi there -

I am curious about using Supernova to render multiple audio files at the same time.

I’m not entirely sure this is possible, based on what I know about Supernova - but I was hoping the more-knowledgeable here would have some ideas.

My understanding is that if you start Supernova and dispatch your synths via a ParGroup, the server will distribute your synths across several cores. Presumably, this is an scsynth routing solution - and the NRT rendering would be handled via sclang.

I’d like to start somewhere simple - would it be difficult to simply render 5 sine tones on 5 cores at the same time?

I appreciate the help, cheers!

NRT starts its own server instance - so using scsynth here should be fine- you can have multiple nrt scsynth instance run at once.
Sclang can help kick off nrt or format scores, but once the nrt process is running, sclang has nothing to do with it.
Hope that helps
Josh

/*
Josh Parmenter
www.realizedsound.net/josh
*/

No, it isn’t – supernova is a full replacement for scsynth. It isn’t a wrapper around scsynth.

Supernova NRT would produce only one file, just like scsynth. The commandline interface supports only one output path.

If the 5 files don’t have any interdependencies, then you could run them in separate scsynth processes. If they do have dependencies (like, file 2 is a filtered version of file 1’s signal), then they’d have to be in series, not parallel (which could be done in the same process, or separately with the file 2 process running after file 1 is complete and reading from file 1).

hjh

Thank you - but just to clarify here:

You mean that they are “supernova processes”, right? I think I’m still confused here.

If I understand correctly:

sclang parses some messages to “kick off” the NRT in the form of a score, those messages usually activate synths stored on sclang - but supernova could be used in place of sclang without too many major differences.

The big difference is that the processes must be “parallel” - so all signals that modulate or control each other must be kept within a single ParGroup, where it will operate on a single core.

So, if I wanted to create 5 simultaneous renderings of sine wave tones, outputting 5 .wav files - I could write something to execute 5 NRT scores at the same time, but give each instance its own ParGroup. supernova would manage distributing these instances over the available cores and I would not have much say in the matter…

Is this all correct?

So, something like the following code should be using the benefits of parallel processing…although, I’m getting an error when running it:

*** ERROR: in main(): boost::interprocess::bad_alloc
SynthDef("sine",
	{|freq, out, gate=1|
		Out.ar(out, SinOsc.ar(freq, mul: 0.1)*Linen.kr(gate, doneAction:2));
}).store;

Server.supernova;
Score.program = Server.program;

Task({
4.do{|i|
var server, chans = 2, duration = 100, pattern1, pattern2, nrtScore;
Date.getDate.postln;


pattern1 = Pbind(
	\instrument, \sine,
	\freq, Pwhite(0, 10000, inf),
	\stretch, 1,
	\dur, Prand([0.1, 0.05, 1], inf));

nrtScore = PparGroup(pattern1, inf).asScore(duration: duration, timeOffset:0.11);

	nrtScore.recordNRT(outputFilePath: "/Users/bd/Desktop/"++i++".flac",
	headerFormat: 'flac',   //this allows longer files..?
	sampleFormat: 'int16',
	oscFilePath: "/Users/bd/Desktop/"++i++".txt",
	duration:duration,
    action: {
		(Date.getDate).postln;
		"NRT done".postln;

});

	};
}).play;

NRT workflow is that sclang creates SynthDefs and also creates a Score (the messages), and then a NRT server process (not language process) is launched to read the SynthDefs and score from disk. (SynthDefs may be embedded in the Score too.) Then the server process runs all the DSP and writes the output file.

Supernova is a server process, not a language process. In theory it may be used in place of scsynth (I suppose just a typo here).

It’s very easy to get confused about what ParGroup does. Evidence of that confusion is that these paragraphs contradict each other – in the first paragraph, the immediate children of a ParGroup run in series (one core); in the second, they are distributed among cores. (The right answer is the second.)

Also – “I could write something to execute 5 NRT scores at the same time” – the only way to do this is to run 5 NRT processes (which your example does). But be aware in this case that ParGroup then becomes irrelevant! If you are running multiple server processes at the same time, the OS will put them on different cores to whatever extent is possible – including scsynth. (If you were thinking “scsynth has only one DSP thread” – there is no way to share one DSP thread across multiple separate processes. If you run 5 scsynths, then you have 5 DSP threads, and the OS will parallelize them.)

So if the 5-processes approach is what you want, then you can just use scsynth, no problem. Multiple scsynths on the same machine have always been parallel (this has been suggested before as a way to parallelize – you lose the unified signal flow of supernova, but avoid supernova’s little quirks).

Btw, NRT in supernova is not at all well tested, and may simply not work. In that case, “5 scsynths” may be the only way to go.

hjh

1 Like

This is very interesting - thank you for taking the time to explain all this. It is not something I’ve seen discussed elsewhere.

It sounds like it is a very clear-cut case to use multiple scsynths to render multiple processes separately - but this does makes me a little bit uncertain about what, if any, benefits supernova would have in this context. You mention “unified signal flow” - but I’m not sure what that means with regards to parallel processes and threads.

I would love to confirm if NRT in Supernova simply does not work also - if anyone else has tried to use it. My example above does throw an serious-looking error message, but was able to render a few files fairly easily (more trouble with longer renders, though)

Thanks again!

It should work in general. I have personally fixed some bugs in Supernova regarding to NRT processing. If you find that something does not work, please file a bug report on GitHub!

1 Like

If the signal chains are 100% independent of each other, then supernova has no benefits over scsynth in this case.

Parallel DSP also needs to be able to handle cases such as:

frequency LFO (sample-hold noise e.g., something with randomness)
| | | | |_ oscillator 1
| | | |_ oscillator 2
| | |_ oscillator 3
| |_ oscillator 4
|_ oscillator 5

The oscillators do not depend on each other, and could run in parallel. But they all depend on the LFO. So you have to guarantee that the LFO finishes before any one of the oscillators begins. In supernova, this would be modeled like:

SynthDef(\lfo, { |out| Out.kr(out, LFDNoise3.kr(12).exprange(200, 1000)) }).add;

g = Group.new;
p = ParGroup(g, \addToTail);  // head/tail doesn't matter yet lol

~lfoBus = Bus.control(s, 1);
~lfo = Synth(\lfo, [out: ~lfoBus], target: g, addAction: \addToHead);  // NOW it matters
~oscs = Array.fill(5, {
	Synth(\default, [freq: ~lfoBus.asMap], p)  // order doesn't matter in pargroup
});

sc-pargroup

The LFO is outside the ParGroup – before it – and the oscillators are marked for parallel processing by making them immediate children of the ParGroup. It can get more complex – a ParGroup can contain regular Groups, in which case, you would have parallel series of synths, where each series remains in order.

Supernova has benefits in this case (but that isn’t the case in your code example). It would be possible, using temporary audio files, to use multiple scsynths for these cases as well – but, considerably more difficult than ParGroups – so much more difficult that it wouldn’t even be worth trying.

BTW I had said before that it wasn’t possible to write multiple output files in NRT. That isn’t strictly true. There is only one “output file path,” but it should work to allocate recording Buffers, prepare them for recording, and use DiskOut. Users normally don’t do this “by hand” because you can just turn on recording (which does all of that for you) – but the components of recording are available, and could (should?) be possible to replicate in NRT.

Actually it does! I wasn’t at the computer and couldn’t try it last night.

No error for your code example in Linux. Which OS are you using?

hjh

2 Likes