Hmmm, I don’t know, I didn’t mean to drift so far off topic, it’s not ideal…
I did realise that by writing NamedControl.new(name, values, spec: ControlSpec.new(...))
a little more concisely, and generating a name
array if values
is an array, the notation:
{var freq = R.ctl(\freq, [193, 195], 110, 220, 'exp')
;var amp = R.ctl(name: \amp, default: 0.1, minval: 0, maxval: 0.2, warp: 'amp') // with keywords
;SinOsc.ar(freq, 0) * amp}
makes a spiffy Ui with three nicely named controls.
(Also that it makes a kind of sense to write freq
&etc. twice, since the control names need to be freq:1
and freq:2
or such, but the variable name is freq
, and these are not the same…)
Baby steps…
Also, more off-topic drift below…
If a basic difficulty is that SC has lot’s of different kinds of Sound objects that don’t “compose” (in the maths sense) then…
I wonder if SC could move towards a more Kyma-ish “unified Sound object model” incrementally, starting from where it already is, without breaking anything along the way.
That is, if a Sound
object could be placed in the class hierarchy (where?) and people could slowly teach it how to compose (in the maths sense) different kinds of sound structures?
Maybe starting with rather simple things where the current notations are considered non-ideal.
For instance, if u
is a UGen graph (which is a Sound) and if f
is a Soundfile (which is also, obviously, a Sound) to make the composite Sound that mixes them together the nice notation would be u + f
.
But that’s not really the standard SC notation?
A Soundfile would be a sort of BracketedSound
, one that needs to do some initial “before” work and some final “after” work.
u + f
would be a little like 0.1 + SinOsc.ar
, in that the left hand side would be lifted to compose with the right hand side, which has more structure.
I.e. the idea is not to add lot’s of eccentric syntactic sugar, but to make it a proper semantic relation, the kind SC already has in some cases, but not very uniformly.
Soundfile is more complicated to lift than than Float because there are two distinct ways to do it.
Either load the file into a Buffer or stream it from disk.
But usually we just decide on one or the other by looking at the size of the SoundFile?
So the SoundCompiler could do the same thing.
There could be a parameter, say SoundCompiler.soundFileMaxLoadBufferSize
, so people could tune things?
But also any existing approaches would still just work, so it’s not essential that it be perfect for all use cases, just acceptable for most.
Also, if r
is a filter (which is a Sound processor) then the nice notation is r(u + f)
, i.e. as we write r(u)
.
And so on.
Initially {...}.compileSound.play
could be the notation for making a sound.
Eventually, in the distant future, if it worked out, {}.play
could defer to this, since it’d be completely backwards compatible?
SC could borrow as much “structure” from Kyma as seems sensible.
If f1
and f2
are SoundFiles, to play one and then the next write the nice notation is f1 ++ f2
(also r(f ++ u)
&etc.).
But perhaps no-one wants that particular way of composing Sounds and it just doesn’t get implemented.
Sound could just accumulate things people actually want over a possibly very extended time frame.
(Some Patterns are Sounds so perhaps some people would want to write r(p + (f ++ u))
where p
is a Pattern, or maybe no one will…)
I’m definitely not the correct person to try and design the fundamentals of this (though I would like to help) because firstly I just don’t know enough of SC (I know a rather narrow part of it moderately well) and secondly I have no experience of this kind of “surgery” on a big object system.
But perhaps it could be a nice “community” project.
It’d need to be something like that, since it would be lots of work, and it’d perhaps need to tinker with the SCClassLibrary.
If the “interface” for what something needs to do to be a Sound
were made very clear, then it might be workable as a distributed project, there’d be a kind of “logical” criteria for if an implementation of a thing was correct or not.
(This is kind of how classes work in Haskell, which I know a little better. Classes come with set of rules, which aren’t checked by the compiler, but which instances need to follow. Sometimes there are multiple “correct” ways to write an instance, but at least anyone can look at an instance and see if it follows the rules or not. The rules are written in comments, and are things like: to be a Functor then map id x == x
, to be a Monoid then x + zero == zero + x == x
and so on. There could be these kinds of rules for what it means to be a Sound so that there would be a way of saying if someone has made a mistake and what would count as a correction.)
On the other hand I know there are already many, many different approaches to this kind of higher level “composable sound” problem, so perhaps it’s both too late and unnecessary to try and make a shared model for it.
Also partly I do think it’s nice having so many different “schools” within SC!
I really don’t know…