I need to crossfade between subsequent values of a Select Ugen, when the index changes.
So it is not like SelectX, where a crossfade is always between subsequent indices, but on change, one crossfades into the new value.
The solutions I’ve come up with fail badly when a change is faster than the crossfade, because the internal Selects switch in the middle of the transition.
A simple multiplexer selects between N channels according to an index signal K, and can be implemented by multiplying the Kth channel by 1, all other channels by 0, and adding them together. To add a crossfade you can slew the binary signals that envelope each of the input channels. This handles the case where the index signal is suddenly switched between 3 or more signals faster than the crossfade can keep up.
If the slew produces a linear ramp, sin(x pi / 2) will convert it to an equal-power fade.
Now the problem is that this is very inefficient by comparison. For what I do, it doesn’t work – it builds too slowly and eats too many cycles while running.
How many channels you got? The algorithm I’ve described will always be click-free but if you make certain assumptions about index signal changing slowly then I can imagine ways to optimize it without needing a ugen.
Another way might be to stick to the original crossfade idea, but use sample and hold on the index to choose a new index only when a crossfade has completed. This would essentially pause index changes during crossfades.
Best,
Paul
In terms of efficiency, I am still stuck. I think that a UGen more similar to Select that does the slewing internally, only for those values that are nonzero and does an internal mul/add might be worth a try.
what if for every change of index you start a new synth,
which only reads the new channel of interest and fades it in,
and fades out the previous one?
that would trade more language side administration for
much less server CPU load.
also, timing would be quantized to blocksize borders
(for the fadeout triggers at least, fadeins could use OffsetOut)
Normally, this would be the best! But in this case, I need to have the whole thing as a single UGen tree. A new UGen will be the best, I think, and generally useful as well.