How to plot a SynthDef?

I just recently resumed my attempts at learning SuperCollider, and I am trying to make the leap from playing functions directly to using SynthDefs. There seems to be one critically important ability (for a learner at least) that I seem to have lost while making this leap: the ability to See What I Compute.

How do I graph the output of a Synth created from a SynthDef?

There are two or three ways you can introspect the output or internal state of a Synth - the most easy and straightforward is to use the poll method:

SynthDef(\foo, {
	var lfo = SinOsc.kr(1/10);
	lfo.poll(1, "lfo");
}).add.play;

I built a slightly more accessible tool to graph control values of a Synth - you’re welcome to try it out. I’ve been working on a bigger SynthDef introspection library to solve exactly this problem in a much more open-ended and automatic way, but that’s a long way off from being complete…

(You’ll need to include this or add it to and extension folder)

Example (you can reset min and max values by clicking on them):

~bus = Bus.control(s, 1);
SynthDef(\foo, {
   var cutoff, sig;
   sig = LFSaw.ar(120);
   cutoff = SinOsc.kr(1/10).range(100, 400);
   Out.kr(~bus, cutoff);
   sig = LPF.ar(sig, cutoff);
}).add.play;

~bus.debugScope();
1 Like

You can also use get.

From the Synth help file:

(
SynthDef("help-Synth-get", { | out, freq = 440|
    Out.ar(out, SinOsc.ar(freq, 0, 0.1));
}).add;
)
x = Synth("help-Synth-get");
x.set(\freq, 220 + 440.rand);
x.get(\freq, { arg value; ("freq is now:" + value + "Hz").postln; });
x.free;

BTW the reason why we can have { ... }.plot but not SynthDef(...).plot is:

  • When plotting a function, we can assume that the function’s return value (which is a network of UGen connections) is the signal that you want to plot.

  • If it’s a SynthDef, there is no guaranteed, reliable way to know what signal to plot. SynthDefs use Out.ar to write the signal to a bus. To plot, we would need to know which bus. There is a loose convention that SynthDefs should have an out argument for the output bus number. But if the user said outbus or bus or audioOutputBus, how would SynthDef:plot know this? (Worse, a lot of new users take a shortcut and write Out.ar(0, ...) in which case it would be impossible for a hypothetical SynthDef:plot method to isolate the signal from other things playing at the same time.)

poll is one workaround.

Another is to write a RecordBuf into the SynthDef (temporarily, delete it later), then plot the buffer’s contents.

s.boot;

b = Buffer.alloc(s, 44100, 1);

(
// hack the default synthdef
SynthDef(\default, { arg out = 0, freq = 440, amp = 0.1, pan = 0, gate = 1;
	var z;
	z = LPF.ar(
		Mix.new(VarSaw.ar(freq + [0, Rand(-0.4, 0.0), Rand(0.0, 0.4)], 0, 0.3, 0.3)),
		XLine.kr(Rand(4000, 5000), Rand(2500, 3200), 1)
	) * Linen.kr(gate, 0.01, 0.7, 0.3, 2);
	RecordBuf.ar(z, b, loop: 0, doneAction: 2);  // <<-- inserted
	OffsetOut.ar(out, Pan2.ar(z, pan, amp));
}, [\ir]).add;
)

a = Synth(\default);  // will stop by itself

b.plot

b.getToFloatArray(wait: -1, timeout: 5, action: { |data| d = data; "done".postln });

d[0..500].plot;

hjh

1 Like

@scztt
Hi Scott, your debugScope is so damn useful, I use it regularly in development and have suggested it to students and friends. How about making a Quark of it? I would happily do that if you don’t have time, but I would like to know what you think about it, and correctly credit you.

And through time I’ve made little changes to your method, mainly to improve display using Layouts. You’ll find my version as a comment to your gist

I think this a fantastic idea. I think I did some initial sketches for a broader “server debugging” quark, that used this as a starting point, but it didn’t go to far. I’ve actually fallen out of using it a little because I mostly debug with the NodeSnapshot quark in my day-to-day work, but if it were cleaned up a little it would fit right in as an additional tool for that Quark as well.

I’m going to try to find some time in the next week to do some basic clean-up and Quark-ification of it. From there, you (or anyone else) are welcome to add functionality - maybe it can become a basis for some more diverse debugging tools, or maybe it just gets a bit easier for students to install and use :slight_smile:

1 Like