NamedControl: a better way to write SynthDef arguments

I think the end to the debate is to use whichever is appropriate to the situation.

The premise of this whole thread – that argument syntax fails a few use cases, therefore it is always inadequate for every use case – was overstated from the get-go.

My ongoing practice is to use argument style for single-value arguments, and NamedControls for arrayed arguments. I agree that NamedControls are clearer for arrays. I don’t feel any particular need to pick a side.

hjh

3 Likes

My point is that this all could have been presented as “here’s a usage that I find congenial, maybe you’ll like it too,” but it was presented as “this is better (implying that the other way is worse) and y’all should make the switch, and I can’t understand why people aren’t switching” – all of which traces back to verbiage in the first post, and is extraneous to the technical arguments. So there’s extra junk in the post (which probably just reflects over-enthusiasm), and then when somebody says uh, wait up, some of this reads more judgy than you think, the reply is, no no, you should focus on the technical arguments. (In that case, the original post could have begun by sticking to the technical.)

I could write a post about patterns, comparing them to routines, pointing out some technical advantages and finishing with “you can make up your own mind.”

Or I could write a post entitled “Patterns: SC’s best sequencing framework,” expressing hope that users would switch to them, and evaluating routines’ advantages to be insignificant.

I would expect the latter format to ruffle some feathers, and it would be disingenuous afterward to (use jokes to) declare the feather-ruffling parts to be off-limits for criticism.

Framing the topic as “better-than / worse-than” places the two approaches in a competitive, rather than complementary, relationship. I found it a bit strange to speak of this “debate… [that] will never end” when… it’s not actually a debate. Is it? If so, why? Users can decide for themselves how to use the given resources. But this manufactured “debate” is a consequence of the initial framing; I disagree with both the framing and the “debate” labeling.

hjh

2 Likes

Muting the thread now, goodbye.

hjh

1 Like

@smoge the issue for me is about staying in the moment - when I am making music I am often on a tear - trying to get something working right now.

I am often in the middle of writing a graph when I realize “Oh I need a control for this” - having to jump back up to the argument declarations and then jump back is a context switch and I just want to type right where I am.

Likewise when I want to change a hardcoded value, I just don’t want to have to type on two non-contiguous lines!!

I’ve made. a lot of little tweaks to the language that let me just keep moving forward whether I planned properly or not - for me that’s the musical mindset, the present point (the cursor location) is where I am! JMC after sc became interested in a concatenative style for just this reason.

I think that needing to declare all variables at the top of a function is a pretty lame limitation in sclang. If we could simply declare anywhere, for vars or args that might be the best of both worlds.

1 Like

I put soysauce in my oatmeal

For readability purposes, I strongly prefer having all arguments at the top and variables mixed in the code.

For vars I regularly resort to storing variables in an event (however, one has to be careful not to reuse/overwrite existing keys in the event or things might go wrong in non-obvious ways)

(
var v = ();

v[\myvariablename] = 42;
)

1 Like

This is really interesting, but I can’t figure out how it would work. It is possible that @nathan or somebody else that knows this syntax post an example of dynamic number of channels with NamedControl please?

1 Like

Yes, the word “Dynamic” threw me off. Thanks for the examples. Very useful!

The minval and maxval are supposed to work like a clip ? Because we I do something like:

Ndef(\a, {SinOsc.ar(mul:1/8)*SinOsc.ar(\f1.kr(1,spec:ControlSpec(0.01, 20)),0, mul: 0.125, add: 0.5)}).play;
Ndef(\a).set(\f1, 10);
Ndef(\a).set(\f1, 25);
Ndef(\a).set(\f1, 40);

I can go beyond the limits defined in the controlspec.

If they do not work as clipping, what is their function? Assume that all the inputs will be in the range of [-1,1] and the map them into the new defined range?

For clipping values, in this case I should use .clip?

The spec parameter on controls is purely metadata - generally, you can use it to construct UI controls for a Synth. Clipping is generally better done on the language side, by limiting the values you send to a synth - though if you want to clip in the Synth obviously this works fine as well.

~def = SynthDef(\specTest, {
  Out.ar(
    \out.kr(0), 
    SinOsc.ar(\freq.kr(spec:[20, 2000])) * \amp.kr(spec:[0, 1])
  )
}).add;

~synth = Synth(\specTest);

~view = View().minHeight_(100).layout_(HLayout());
~def.specs.keysValuesDo {
    |name, spec|
    ~view.layout.add(HLayout(
        StaticText().string_(name),
        Slider().action_({
            |slider|
            ~synth.set(name, spec.map(slider.value))
        })
    ))
};
~view.front;
Ndef(\x,{ \test.kr(spec:[-5,10]) }).gui;
or
Ndef(\x,{ \test.kr(spec:ControlSpec(-5,10)) }).gui;

should set the gui slider from -5 to 10 - right ?
but it’s range is set from -0.25 to -100 !

with

Ndef(\x).addSpec(\test, [-5,10] );
or 
Ndef(\x).addSpec(\test, ControlSpec(-5,10) );

the sliders range is set correctly from -5 to 10

so what am i missing ?

(i use sc 3.14.0-dev on linux)

I’m not totally sure, but an Ndef can contain multiple Synths - I think by default it MAY not pull it’s specs from the SynthDef (sadly even in a trival case like this) given that there could be e.g. multiple synths with \test controls that have different specs. So it might be that Ndef:addSpec is somewhat decoupled from the individual SynthDef specs? I recall working around this in local code of mine to just pull the specs directly from the source SynthDef when I want to generated controls.

A reasonable workaround here if you want to use Ndef:gui is just to make a new addSynthDefSpecs method that basically finds the SynthDefs for that Ndef, iterates over the specs for that SynthDef, and sets them on the Ndef via addSpec. Check Ndef(\x).inspect to poke around and find where the SynthDef’s / SynthDesc’s are stored, I can’t recall :upside_down_face:.

see this issue: MainFXGui ignores specs from NamedControl · Issue #22 · supercollider-quarks/JITLibExtensions · GitHub