Equal Distribution Between Sliders

Recall the Coll's icon

Hello Max folks,

I'm trying to create a system where the sum of n sliders' values is always equal to a specified range.

When I move slider A for example, I want sliders B, C, D, E to be affected also. If A increases, B, C, D, E decrease. If A decreases, B, C, D, E increase.

My coding skills are really poor, so I can't properly explain what I want to achieve. However. below I have a patch that demonstrates what I want to achieve.

Thanks in advance

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

simply invert? or make sure that the sum of all sliders remains the same?

Recall the Coll's icon

I don't know how to achieve it with the methods you suggested, because then there is another issue that arises, feedback. Slider A is affecting B, C, D, E but also:

B affects A, C, D, E

C affect A, B, D, E

D affects A, B, C, E

E affects A, B, C, D

Roman Thilenius's icon

that kind of feedback can be solved by using "set 0.7" (set 1 0.7 in the case of multislider); you would "set" the actual GUI slider but send the value to its aim directly from the calculation.

start the patch with the actual math and logic and only use numberboyes everywhere, that helps a lot.
you will see that you always need to set the sliders independetly first to establish a sum value before the common movement of the sliders can work. you also have to decide what should happen when a slider exceeds 100%.

there was a thread for that kind of stuff with an example here, about 10 or 12 years old, but i can not recall the keywords to find it back. it is not this one... https://cycling74.com/forums/balancing-mixer-patch-help-please

Roman Thilenius's icon

oh, and that wasnt a suggestion, it was a question what you wanted it to do. :)

Recall the Coll's icon

oh, and that wasnt a suggestion, it was a question what you wanted it to do. :)

My bad, I misunderstood.

I'm really lost and I don't know how to explain it better than the patch I attached.

What I need is to be able to have some sliders that affect each other each time one is moved.

The initial value for each slider is maxRange / numberOfSliders . For this example let's say we have 5 sliders and the maxRange = 100. Every one of them will have an initial value of 20.

For example if maxRange=100 and A increases from 20 to 60, then 40 would be the total sum of B, C, D, E. So, 40 / (numberOfSliders - 1) = 10

A = 20 + 40 = 60 //change

B = 20 - 10 = 10 //reaction

C = 20 - 10 = 10 //reaction

D = 20 - 10 = 10 //reaction

E = 20 - 10 = 10 //reaction

Now, if I increase C from 10 to 50, the sum of A, B, D, E will have to adjust to be equal to maxRange, so for this example the new values should be C = 10 + 40 = 50. The added 40 of C must be subtracted from the same of A, B, D, E, so 40 / (numberOfSliders - 1) = 10 and this will give:

C = 10 + 40 = 50 //change

A = 60 - 10 = 50 //reaction

B = 10 - 10 = 0 //reaction

D = 10 - 10 = 0 //reaction

E = 10 - 10 = 0 //reaction

Hope this illustrates my point better.

Roman Thilenius's icon


the first thing to do is to find the sum value - in your case we already know it, it is 100.

if you do not know the sum because the sliders can also be moved seperately (like in a DAW mixer) you can do something like that to find the sum and the fractions the sliders own of it:

the rest of my answer has been deleted and held back for now, because i noticed that i dont understand your last part (the rest is chrystal clear and you are almost there)

are you sure you want those 3 sliders go down to zero?

double_UG's icon
Max Patch
Copy patch and select New From Clipboard in Max.

.................................................

Source Audio's icon

your explanation is too complicated.

If I managed to understand it right, sum of all sliders

should equal max range.

manipulating any of them after they got

initialised affects the others.

But the question is in which priority ?

A = 20

B = 20

C = 20

D = 20

E = 20

if you now move C to 19, what then ?

or :

A = 5

B = 13

C = 65

D = 2

E = 15

if you now move D to 19, what then ?

you are talking ints , not floats.

in case of floats, one would subtract moved slider from 100.

and scale the others by calculated factor to have sum of 100.

P.S.

any slider should at any time be allowed to move between min and max, right ?

Recall the Coll's icon

the rest of my answer has been deleted and held back for now, because i noticed that i dont understand your last part (the rest is chrystal clear and you are almost there)

Please let me know which part.

are you sure you want those 3 sliders go down to zero?

Yeah

The slider that I move is supposed to force all others to change values and this doesn't happen in your patch.

your explanation is too complicated.

I'm trying really hard to explain it as simply as I can.

But the question is in which priority ?

If you move C, then C changes first and according to that change, A, B, D, E change accordingly.

you are talking ints , not floats.

My end goal is to have floats, but I thought working with ints would be easier for me to grasp what's going on with some examples and easier to explain to others here, in order to get help.

I assume that now that I've specified that I'm working with floats I guess it would be obvious, but I'm just clarifying just in case:

A = 20

B = 20

C = 20

D = 20

E = 20

if you now lift C to 19, what then ?

The difference from old C to new C is 1. 1 / (numberOfSliders - 1) = 0.25

C = 19

A = 20.25

B = 20.25

D = 20.25

E = 20.25

A = 5

B = 13

C = 65

D = 2

E = 15

if you now move D to 19, what then ?

The difference from old C to new C is 46. 46 / (numberOfSliders - 1) = 11.5

A = 5 + 11.5 = 16.5

B = 13 + 11.5 = 24.5

C = 19

D = 2 + 11.5 = 13.5

E = 15 + 11.5 = 26.5

I think I just thought of another requirement from this system I forgot to mention. When a subtraction of an affected slider gives a negative number, it clips at 0 and the remainder is shared to other sliders. For example:

A = 5

B = 13

C = 65

D = 2

E = 15

If C moves to 75

The difference from old C to new C is -10 / (numberOfSliders - 1) = -2.5

A = 5 - 2.5 - 0.16 (remainder from D/3) = 2.34

B = 13 - 2.5 - 0.16 (remainder from D/3) = 10.34

C = 75

D = 2 - 2.5 = 0 (because it clips at 0 but has remainder -0.5. This -0.5 will be split to A, B, E, so 0.5 / 3 = -0.16 for each)

E = 15 - 2.5 - 0.16 (remainder from D/3) = 12.34

Source Audio's icon

You will face more problems when some

sliders allready are at zero and you need

to subtract the list further to accomodate

new sum

And another question is if all sliders can receive input at same time, like from a list or a preset, which would add to the complexity

Roman Thilenius's icon

"And another question is if all sliders can receive input at same time"

yeah, like from loading presets or applying plug-in automation. i rembember having quite some fun with that back in the days. and as you say, it only works with float.

@Recall the Coll

what is still unclear is this:

"C = 10 + 40 = 50 //change

A = 60 - 10 = 50 //reaction

B = 10 - 10 = 0 //reaction

D = 10 - 10 = 0 //reaction

E = 10 - 10 = 0 //reaction"


if A is 60 and B is 10, they should not be lowered by the same absolute value, but by the same fraction. (unless you want something different than i thought.)

Roman Thilenius's icon

ok, apart from the logic and math problem and all the possible different implementations one might want i shall give you the next missing building block for the "feedback" thing.



Source Audio's icon

In case only 1 slider changes at a time,

one would index sliders which are still > 0. ,

separate currently moving one, and spread sum match

factor within the rest of them.

it is a job for vexpr, because number of sliders in general

as well as non zero group is dynamic.

In case of list input for all sliders, one can ignore

current sliders state and simply scale list input to mantain sum.

Wil's icon

I did this with multislider

a while back

using some old code I found

have to stop the stack overflow

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

the results are a bit strange, though. bet the live object is doing that. :)

Recall the Coll's icon

You will face more problems when some

sliders allready are at zero and you need

to subtract the list further to accomodate

new sum

If:

A = 7

B = 13

C = 65

D = 0

E = 15

and C moves from 75 then each slider is expected to decrease by 2.5 (-10 / (numberOfSliders - 1) = -2.5). Maybe there should be a mechanism to check if the lowest value is reached (in this case 0) and then calculate and distribute the remainder.

C = 75

D = 0 //remainder 2.5 / 3 = 0.83 extra decrease for the remaining sliders

A = 7 - 2.5 - 0.83 = 3.67

B = 13 - 2.5 - 0.83 = 9.67

E = 15 - 2.5 -0.83 = 11.67

And another question is if all sliders can receive input at same time, like from a list or a preset, which would add to the complexity

I always work with [coll] for my presets. So I could output a preset from [coll], put it in [zl.reg] and then send it to [iter], so I change only 1 at a time. I assume that this will be useless, since it would be hard to predict/calculate the outcome of many sequential changes. You can easily calculate 3 sliders. But I'm planning on working with a variable slider number with a maximum of 32, so it will get pretty insane.

For now I don't care much about presets, my main focus is to having a working system.

Recall the Coll's icon

if A is 60 and B is 10, they should not be lowered by the same absolute value, but by the same fraction. (unless you want something different than i thought.)

I need them to by lowered by the same absolute value.

ok, apart from the logic and math problem and all the possible different implementations one might want i shall give you the next missing building block for the "feedback" thing.

Thanks for that. However it seems pretty scary when I imagine I have will have to scale that up to 32 sliders :D

Recall the Coll's icon

In case only 1 slider changes at a time,

one would index sliders which are still > 0. ,

separate currently moving one, and spread sum match

factor within the rest of them.

it is a job for vexpr, because number of sliders in general

as well as non zero group is dynamic.

In case of list input for all sliders, one can ignore

current sliders state and simply scale list input to mantain sum.

I have no idea how to do these. Any chance you could provide an example?