Closed miguel-negrao closed 10 years ago
Hi Miguel,
that would be nice indeed. In the GUI it is done so easily, so why not in code. I have two ideas: 1 - starting an array with a number (integer) would replicate every unit that comes after it by that number, and increase all i/o buses by one. Syntax would be like this:
UChain(*[0,0,totalDuration+5,
[\groupIn, [\bus, 20]],
[ numChan, [ \highPass, [ \freq, [\envelope, [\env, env]] ] ] ],
[\output, [\numChannels, numChan]]
]);
2 - a bit harder to make, but easier on the eyes; every Unit would have a possible \numChannels key. If it is not defined by the def (like in case of \output) it would render itself into an array of U's when not 1. I.e.:
UChain(*[0,0,totalDuration+5,
[\groupIn, [\bus, 20]],
[ \highPass, [ \freq, [\envelope, [\env, env]], \numChannels, numChan ] ],
[\output, [\numChannels, numChan]]
]);
The latter would need to be dealth with within U, perhaps pointing to a temporary MultiU or UArray, which would need to be unpacked by the UChain (or not).
Btw in the example you gave the GUI will automatically create a MassEditU GUI for the whole group of highPass. This happens always if more then one U's of the same def are placed next to each other.
Hi Wouter,
Option 1 seems fairly easy to implement. Option 2 is more work but would be quite more convenient, so I would vote for number 2 (but well, this is a do-ocracy... :-) ). I think in this case the MassEditU gui is not very usefull because most often you want the exact same settings for all the channels, and that's not doable with the range sliders.
For my own phD library I have a similar issue. I have a class MUChain which makes n copies of a uchain. I made a special gui for it which just presents one slider together with a button to open a plot to see the underlying values (in case they are changed by code or from umods) and another button to update the plot or not (to save cpu) . This was done by subclassing MassUEdit and changing
massEditSpec = argSpec.spec.immEditSpec( values );
Then I had to also subclass ArrayControlSpec and change the makeView method.
+ Object {
immEditSpec { |...args|
^this.massEditSpec(*args)
}
*immEditSpec { |...args|
^this.massEditSpec(*args)
}
}
+ ControlSpec {
asImmArrayControlSpec { ^ImmArrayControlSpec.newFrom( this ) }
immEditSpec { |inArray|
^this.asImmArrayControlSpec.default_( inArray );
}
}
The gui for this
UChain(ImmU([U(\sine), U(\sine)])).gui
looks like
Perhaps we could subclass MassEditU to MultiChannelU and do something similar ? Although, I just tested and doing UChain(MassEditU([U(\sine), U(\sine)])).prepareAndStart only plays one sine, so it's not actually functional to play multiple things at the same time...
Hi Miguel,
ah ok, but if the single value thing is hard to do from MassEdit, that is what actually needs to be fixed. I was thinking along the line of having a second fader squeezed in the space of the range slider, which would be a normal fader. Moving that fader would move the center of the range-slider, double clicking or moving it to one of the outer bounds would flatten the range. That way both multi-value and single value unit sets could be edited from the same gui. Haven't gotten to implementing this yet, but it would be much simpler and more convenient, as both modes of editing would be available in a single GUI.
on topic; thinking about option 1 a bit more that may actually be my favourite. We could invent a simple multichannel expansion syntax, which would also allow for example arrays and maybe small functions to set individual parameters of the multiple U's. This could be implemented via MassEditU, where we could make a new *generate method perhaps which could be called internally by UChain at creation. MassEditU already has some things built-in to intelligently know if an arg is meant to be an array, or is in fact an array of args that should be spread among the units.
ok, just added a mean slider to the mass edit gui. The upper part of the range slider now acts as a mean slider. Moving it moves the whole range, double clicking sets the range to a single value.
Ok, just pulled, the new mean slider is quite nice ! :-)
The way I understood option 1 was that the the units would be generated in the UChain#new method but would be concatenated with the rest of the list on both sides, such that after creation time they would just be a number of perfectly normal repeated units. That would mean that after creation time you wouldn't be able to easily set the value of them by code with .set for instance (would have to select them out of the array first). Is this what you are proposing ?
My ClusterBasic class also does "intelligently know if an arg is meant to be an array, or is in fact an array of args that should be spread among the units.", just in case it's usefull. See expandArray in https://github.com/miguel-negrao/Cluster/blob/master/ClusterBasic.sc
The way I see it, for this specific situation, what I would be after would be that the array of units would really behave in every way as if they were really just one unit, indeed as if the synthdef had a 'numChannels' argument which was changing the the structure of the synthdef internally (just wrote about that on the list today :-) ). What about having this be a special type of U ( UX ? as in U x 8) which would create n synths internally and then would set the in/out controls accordingly. In the args it would have all the u_i_ar_j_bus, u_o_ar_j_bus, with j in [0, (n-1)], but then internally it would smartly pass the right parameters to each synth, so : u_i_ar_1_bus would be passed to u_i_ar_0_bus of synth number 2 u_i_ar_2_bus would be passed to u_2_ar_0_bus of synth number 3 etc
Maybe this would be too convoluted... just brainstorming... :-)
Currently I do stuff like:
It would be nice if there was a special syntax or class to automate this, and if the guis for those multiple copies would present them as if they were just one, since if we think of this as just one fx, then you want all those units to have the same settings.