Object naming scheme

33 views
Skip to first unread message

Johannes Taelman

unread,
Apr 20, 2015, 11:12:34 AM4/20/15
to axolot...@googlegroups.com
I'd like to discuss the naming scheme of the objects.
The current object library needs a clean-up, but before doing this effort I'd like to get your input on how to deal with it.

Currently it's a hierarchy, to sort things in categories. The category is then also part of the name.
For example, there are three (actually even more) "square"  objects:
lfo/square -> square wave low frequency oscillator
osc/square -> square wave audio frequency oscillator
I could also add
math/square -> y=x*x

Multiple varieties with exactly the same name (homonyms) but different input types can be defined, and auto-promoted when a connection is made, like "math/square" can exist for different input types.
The weakness of this that it can lead to in-determinism when (multiple) feedback connections are present.

Arguments currently are just an extension of the name, like "osc/saw sync" is "osc/saw" with the addition of a sync input. It's needed to have such variations rather than including all possible additions by default to minimize screen clutter.

It has already evolved over time, but there is still room for improvement:

* It lacks true arguments, say adding a constant 5 should be "math/+ 5". But then I'd love to give clear feedback to the user if it is going to work as expected. "math/+ 5" is fine for both integer, fractional and audio data types, while "math/+ 5.5" does not make sense for integer data.

Adding meta-objects that have code (perhaps javascript) that emits the final object based on object arguments is an option. Possibly this code will emit multiple (homonym) objects to deal with different data types. 
Some sort of guiding to select arguments would be appropriate. Otherwise it becomes like command line wizardry. Typing arguments directly should be possible too, it's quick for advanced users, and easy to copy.

Using anonymous arguments like in pd and max can be confusing, for example  "counter 2 1 4". Key-value pair arguments like Jitter introduced in Max can get long : [jit.op @op * @val 0.5].
I guess using formal key-value pairs is the best definition, and allowing to just use one parameter as argument when there is only one key defined by the meta-object is a shorthand.
Or auto-associating parameters to keys based on their text, even recognizing units?
I'm just dreaming now :
"lfo/square 2Hz sync"
"lfo/square 120bpm sync"
"lfo/square sync 500ms"
"lfo/square sync 0.5s"
all completely equivalent to
"lfo/square freq=2 sync=true"
So the value is auto-associated with the frequency key, because other keys do not take input that can be converted into frequency, and the "sync" key is a boolean that defaults to false, but is true when listed in the arguments.

(this object would not get a frequency parameter knob, since frequency is already specified).

Can you find corner case examples where this scheme would get confusing?

* I think some objects deserve to be in the root, without category in their name
especially some in math, like math/+ etc
also mux/mux ...
also mix/mix ...
Should they still go in a category in the hierarchical object tree, but having the category as part of the name is totally redundant. But how to keep it consistent?

* adding "symlink"-like entries in the categories could help finding objects (indicated by their name in italic?) when a single object deserves to sit in multiple categories, while avoiding the impression of duplicate objects.

* Sometimes the only reason for an argument is a different range or scaling of parameters
examples: ctrl/dial bp, ctrl/dial p
this could become one object with a switchable range/scaling on parameters.
Also "mix/mix 2 g" versus "mix/mix 2 sq"
Currently there is no variety of mixers with bipolar gain setting, but they would be useful too.
This may be a configuration option for each channel individually? I think that 'd make sense for a mixer. Object name arguments? Or a parameter setting?

A design goal is that it should be possible to recreate a patch from a screenshot. I try to avoid "inspector" panels like in Max, since you don't get a good overview. It's not always possible : sub-patches or scripts for instance. But when a parameter is configurable to different scaling it should be visually clear too what it is.
I also 'd avoid using nameless icons for an object. It's hard to figure out how to create another instance of an object by only the look of it.
Keeping object representations compact is critical too, when a patch starts to span multiple screen pages, the overview is lost.

Replicating PD/Max nomenclature is not a goal, they're so different that converging to their naming standard would increase confusion. And the ~ character is awkward to type on different keyboard layouts.

Other aspects, like parameters, deserve a similar discussion but in a separate topic...

tim vets

unread,
Apr 21, 2015, 12:48:24 PM4/21/15
to axolot...@googlegroups.com


On Monday, April 20, 2015 at 5:12:34 PM UTC+2, Johannes Taelman wrote:
I'd like to discuss the naming scheme of the objects.
The current object library needs a clean-up, but before doing this effort I'd like to get your input on how to deal with it.

Currently it's a hierarchy, to sort things in categories. The category is then also part of the name.
For example, there are three (actually even more) "square"  objects:
lfo/square -> square wave low frequency oscillator
osc/square -> square wave audio frequency oscillator
I could also add
math/square -> y=x*x

Multiple varieties with exactly the same name (homonyms) but different input types can be defined, and auto-promoted when a connection is made, like "math/square" can exist for different input types.
The weakness of this that it can lead to in-determinism when (multiple) feedback connections are present.

Arguments currently are just an extension of the name, like "osc/saw sync" is "osc/saw" with the addition of a sync input. It's needed to have such variations rather than including all possible additions by default to minimize screen clutter.

It has already evolved over time, but there is still room for improvement:

* It lacks true arguments, say adding a constant 5 should be "math/+ 5". But then I'd love to give clear feedback to the user if it is going to work as expected. "math/+ 5" is fine for both integer, fractional and audio data types, while "math/+ 5.5" does not make sense for integer data.


cut off the .5 automatically?

Adding meta-objects that have code (perhaps javascript) that emits the final object based on object arguments is an option. Possibly this code will emit multiple (homonym) objects to deal with different data types. 
Some sort of guiding to select arguments would be appropriate. Otherwise it becomes like command line wizardry. Typing arguments directly should be possible too, it's quick for advanced users, and easy to copy.

Using anonymous arguments like in pd and max can be confusing, for example  "counter 2 1 4". Key-value pair arguments like Jitter introduced in Max can get long : [jit.op @op * @val 0.5].
I guess using formal key-value pairs is the best definition, and allowing to just use one parameter as argument when there is only one key defined by the meta-object is a shorthand.
Or auto-associating parameters to keys based on their text, even recognizing units?
I'm just dreaming now :
"lfo/square 2Hz sync"
"lfo/square 120bpm sync"
"lfo/square sync 500ms"
"lfo/square sync 0.5s"
all completely equivalent to
"lfo/square freq=2 sync=true"
So the value is auto-associated with the frequency key, because other keys do not take input that can be converted into frequency, and the "sync" key is a boolean that defaults to false, but is true when listed in the arguments.

(this object would not get a frequency parameter knob, since frequency is already specified).

Can you find corner case examples where this scheme would get confusing?

not really, but there could be quite some variations to take into account, e.g. 1000Hz == 1kHz == 1k == 0.001MHz?

* I think some objects deserve to be in the root, without category in their name
especially some in math, like math/+ etc
also mux/mux ...
also mix/mix ...
Should they still go in a category in the hierarchical object tree, but having the category as part of the name is totally redundant. But how to keep it consistent?

in the case of mux: I see there's nothing but 'mux'-es in that category, so it might not be necessary at the moment to have the category at all, but in the 'mix' category there is also 'mix/xfade', so there it does make sense to have the 'mix/' prefix.
My opinion: keep these categories as is. it doesn't require any extra typing to create mux/mux 2 anyway, and also, there might be some other object appearing in the mux/catogory sooner or later...?
Do the category prefixes have to be shown in the object names?

* adding "symlink"-like entries in the categories could help finding objects (indicated by their name in italic?) when a single object deserves to sit in multiple categories, while avoiding the impression of duplicate objects.


It can't be avoided that you have to learn what to look for (i.e. what's the name of the object that does what you need, or that for example you don't look in the 'sel/' category but in 'math/' if you need an object that triggers when its input value becomes equal to some x ([sel] in pd, but not in axoloti, rather 'math/=='...right?)), and I don't think symlinks would help a lot in that respect.
Another observation/suggestion: when I type '*' in the object browser, it also give me stuff like dist/soft, presumably because it has '*' in the description (not in the name or args), that might be confusing...?

* Sometimes the only reason for an argument is a different range or scaling of parameters
examples: ctrl/dial bp, ctrl/dial p
this could become one object with a switchable range/scaling on parameters.
Also "mix/mix 2 g" versus "mix/mix 2 sq"
Currently there is no variety of mixers with bipolar gain setting, but they would be useful too.
This may be a configuration option for each channel individually? I think that 'd make sense for a mixer. Object name arguments? Or a parameter setting?

Maybe to reduce the list in the object browser you can put the arguments in parenthesis or so?
insted of:
wav/play3
wav/play3 fn stereo
wav/play3 fn
wav/play3 stereo
you could have:
wav/play3 (fn, stereo)
for selecting you could do:
select 'wav/play3 (fn, stereo)' by clicking or up/down arrows on keyboard,
then browse the variations by left/right arrows (wav/play3, wav/play3 stereo, wav/play3 fn stereo, wav/play3 fn... consecutively)
but I guess this is not necessary if the number of variations is limited, and people may also find it easier to just scroll in one dimension...

gr,
Tim

Mark Harris

unread,
Apr 22, 2015, 3:39:25 PM4/22/15
to axolot...@googlegroups.com
Have you looked at Reaktor?, its got some quite nice ideas... and manages to keep the number of objects to a small menu. (so can be directly selected)

I think the variations are probably the main issue (for explosion of types) 

Reaktor tackles this in 3 ways

a) variations like mix 2/mix 4  
you can dynamically add inlets  (using the ... 'button') ... this is not always possible, just when it makes sense.
b) variations like   math/+1  
you just have +  , but you can attach a constant to an inlet ( which gives code optimisation possibilities as it knows its a constant)
c) types variations -  are determined by connection, i.e. you attach an audio connection, then it changes.

I wonder if something like this would be possible, even if it had limitations 
e.g.

- add inlets, its only needed on some objects types, so doesnt need to be implement on everything (it isn't in Reaktor)

- constants, easy to implement a constant object, for many types  (I think), the trick is ensuring the generated code uses a constant, so its optimised correctly

- type variations - this almost is just 'two stage' object selection, when you put an object on the canvas if it has inlet type variations, then these are shown with a 'variable' colour,
then when you add a connection, this narrows down the choices of matching objects, and inlet/outlets are now colour correctly.
(actually I think Reaktor will convert types, but I don't necessarily think thats a great idea)


This way you can really have objects just named Mixer  + ,  -, so the menu is pretty small.

I know requires more intelligence in the editor, and also keeps it graphical/visual (which I think is sometimes missing in Max)
perhaps not the next step, as may be a bit too much coding...
but perhaps some of these are easier than others?  (e.g. constant values?) 



On Monday, April 20, 2015 at 5:12:34 PM UTC+2, Johannes Taelman wrote:

Mark Harris

unread,
Apr 23, 2015, 7:02:35 AM4/23/15
to axolot...@googlegroups.com
further thinking on this... I think adding constants and list params could be really useful, so (a) and (b)... and Ive some ideas on how to ensure the code produced is no less optimal that the current 'hardcoded' approach.
so may have a go at this next week ( I have some time first week of may) if you like the idea, I'll put in a branch as it'll be experimental  ... and I may need to ask a few questions.

(c) I think is probably difficult, and requires a lot of code changes in areas I'm completely unfamiliar with...

I did however think of an alternative.
currently we have different objects for different types e.g. dial b/dial p
another approach would be to only ever have 1 of each type (say dial), and that some parameters would be kind of 'type free' *1,  *2

inside the code of the object there would then be two possibilities for these parameters:

- automatic type conversion. (known to be sub-optimal but in some cases 'acceptable')
- code checks parameter types and can have variations depending on type produces different code. *3

the idea is this shifts the 'burden' of typing to object creators (who will I suspect know Axoloti better/deeper) and away from the user/musician/patcher
(this can also be true in the constant case, where special cases could be coded... using the compiler to optimise/prune dead code branches)

combined with (a) and (b), this means, users would only be faced with objects that have different functional uses, rather that objects which only different by number of inlets, constants, types

I think all the above could be made compatible with existing objects, however it might be an idea to do early on,  so new objects can make use of the newer functionality
(and also important existing objects could start to be migrated)

thoughts?
btw: is this 'on-topic' , I think this is what you meant, but I'm now 100% sure :) 

Mark



*1 ok, they may be typed still, to give an indication of 'optimal type'
*2 choice, we could make this only for k-rate types, not audio/control, at least initially, to simplify.
*3 slight complication for UI elements, as these would need to change UI objects potential when you connect an inlet

Johannes Taelman

unread,
Apr 23, 2015, 9:53:48 AM4/23/15
to Mark Harris, axolot...@googlegroups.com
On Wed, Apr 22, 2015 at 9:39 PM, Mark Harris <ma...@technobear.com> wrote:
Have you looked at Reaktor?, its got some quite nice ideas... and manages to keep the number of objects to a small menu. (so can be directly selected)

I have never used Reaktor...
 
I think the variations are probably the main issue (for explosion of types) 

Reaktor tackles this in 3 ways

a) variations like mix 2/mix 4  
you can dynamically add inlets  (using the ... 'button') ... this is not always possible, just when it makes sense.

Sometimes variations are not just linear extensions of the number of inlets, but different variations of an object exist. For instance a sine oscillator could optionally have a phase reset, frequency modulation, pitch modulation, phase modulation. Not necessarily presenting all inlets when you need the last inlet when they have an order.
But yeah I can see the convenience of extending a mixer with one channel.
 
b) variations like   math/+1  
you just have +  , but you can attach a constant to an inlet ( which gives code optimisation possibilities as it knows its a constant)

Separate constants exclude the possibility to show real world units like Hz, semitones, bpm, time corresponding with its value, unless there is some sort of upstream logic in the patcher and inlet types get a real-world unit conversion tag. Hmmm annotating inlet types with real-world unit types is interesting but also brings new challenges:

A "ctrl/dial" object directly connected to the pitch inlet of an oscillator (without pitch control now), could show the frequency in various ways. Next level is when multiple "ctrl/dial" objects connect to a multiplexer object in turn connected to the oscillator. The multiplexer object could propagate the conversion tag of the oscillator to its inlets. Next step is doing math on the real world values when there is a math/+1 between the dial and the oscillator rather than a multiplexer. But this gets too crazy...

"Math/+" and "Math/+1" are abstract unit operations. And +1 is a compile-time constant so I'm deviating from Mark's point here...

Back to the point, as a design pattern I generally try to make objects not too atomic. Ultimately an sine oscillator has a pitch-to-phase conversion, a phase accumulator and a table lookup, and could be composed out of more primitive objects. But I think that would expose too much details to users.
Not that I aim in the opposite direction, like replicating stompboxes or Eurorack look and feel, as such metaphor would struggle to expose the power of digital.
 
c) types variations -  are determined by connection, i.e. you attach an audio connection, then it changes.

Perhaps the object promotion mechanism matching connected input types almost supports this already.
An "unimplemented in this variation" inlet type could be added, and when connected the object will get promoted to a variation that implements the inlet.
But this increases the screen size of object, unless it has a way to hide unconnected inlets.
 
I wonder if something like this would be possible, even if it had limitations 
e.g.

- add inlets, its only needed on some objects types, so doesnt need to be implement on everything (it isn't in Reaktor)

- constants, easy to implement a constant object, for many types  (I think), the trick is ensuring the generated code uses a constant, so its optimised correctly

Compile-time generating widgets in the gui are called "attributes". For integers that is AttributeInstanceSpinner. There is currently no implementation for fractionals.
 
- type variations - this almost is just 'two stage' object selection, when you put an object on the canvas if it has inlet type variations, then these are shown with a 'variable' colour,
then when you add a connection, this narrows down the choices of matching objects, and inlet/outlets are now colour correctly.
(actually I think Reaktor will convert types, but I don't necessarily think thats a great idea)

'variable' color for each input?
Would the first-stage object have an implementation too?
Or would that make a patch non-runnable? If so, it must be clear to the user that it's an error and hint how to solve it.
If it has a default 2nd stage object, it'd better already show its inlet/outlet types

This way you can really have objects just named Mixer  + ,  -, so the menu is pretty small.

Having really small mix, +, -, mux objects would be nice but I'm also hesitant to deviate them from generic object look and feel.
 
I know requires more intelligence in the editor, and also keeps it graphical/visual (which I think is sometimes missing in Max)
perhaps not the next step, as may be a bit too much coding...
but perhaps some of these are easier than others?  (e.g. constant values?)

I committed a compile-time constant integer object.
My feelings:
* be careful with conversion from integer to fractional, may overflow/wrap. Maybe limit adjustment range to -64 to 64 "kindergarten integers"?
* the control is grayed out when "live", but there must be a visually clear indication that it is going to be grayed out.
but both are not specific for this object...

More later...
Reply all
Reply to author
Forward
0 new messages