MSF Generator Modulation Question

Official support for: meldaproduction.com
RELATED
PRODUCTS

Post

MeldaProduction wrote: Sat Jul 27, 2019 8:58 pm I must say I don't really understand the example you mentioned
Well, never mind about my example. I realized there is a fundamental flaw. I wanted to have run-time selection of the MIDI influencer (mod wheel, pressure, CC74, etc.), so I was going to associate an MP with a MIDI source and use that to set the depth. However, doing so would negate the MPE-ness of pressure and CC74 (i.e., the per-note-ness), and maybe have some other unwanted side effects as well - all that irrespective of the fact that the modulation amount calculation doesn't work as I assumed it does in the first place.

What I really could use here is the ability to select the mod source (Mod Wheel, Env 1, LFO 2, Constant, et. al.) via an MP. We can alter the depths of the mod grid slots, but not the mod source.

Post

MeldaProduction wrote: Sat Jul 27, 2019 8:58 pm As for the multiplication, I don't really know how else to explain that, so an example will be best I think.
A1 = 1, depthA1 = 1, A2 = 0.2, op = mul
output = depthA1 * (A1 * (1 - depthA2) + A1 * A2 * depthA2)
depthA2 = 1 (hence maximum) => output = depthA1 * (A1 * 0 + A1 * A2 * 1) = depthA1 * A1 * A2
depthA2 = 0.5 => output = depthA1 * (A1 * 0.5 + A1 * A2 * 0.5) = blend between A1 and A1 * A2
depthA2 = 0 => output = depthA1 * (A1 * 1 + A1 * A2 * 0) = depthA1 * A1 = no change to the A1
OK, now we're getting close to something comprehesible (although a real-life example might be very helpful). But I'd like to ask you to rewrite the forumla "output = depthA1 * (A1 * (1 - depthA2) + A1 * A2 * depthA2)" as follows to make it clearer.

Call the slot current values A1, A2, etc. Call the depth values D1, D2, etc. Call the between-slot operators (Mul, Add, Max, etc.) @12, @23, etc. Finally, don't assume we know the operator precedence story, even if it's just like C++ - supply parens throughout.

Is the formula so rewritten now:

output = D1 * ((A1 * (1 - D2)) + ((A1 @12 A2) * depthA2))

and please confirm the parens are correctly placed as well - they probably are not.

Now, having the two slot formula down. Can you give us the three slot formula? This stuff is far from obvious, but a comprehensible formula may help enormously.

Post

Sorry, but those formulae have got me confused.

And what would they be if the Operator were "Add" or "Max"?

And what happens for a Constant? Is its value always 1 and its Depth set by the slider? Or ...?
DarkStar, ... Interesting, if true
Inspired by ...

Post

DarkStar wrote: Sun Jul 28, 2019 9:58 pm Sorry, but those formulae have got me confused.

And what would they be if the Operator were "Add" or "Max"?
Exactly. Further, which "*" corresponds to Mul in Vojtech's forumla:

output = depthA1 * (A1 * (1 - depthA2) + A1 * A2 * depthA2)

Maybe it could be better expressed where the grid operation (Mul, Add, Max, ...) is expressed as a function call:

output = A1 * Mul(some-formula, some-other-formula)

or something like that - that way there's no mystery about operator precedence (the order in which multiplications, additions, etc. get executed).

DarkStar wrote: Sun Jul 28, 2019 9:58 pm And what happens for a Constant? Is its value always 1 and its Depth set by the slider? Or ...?
Constant is always 1. The depth of the grid slot can be set directly or via an MP. The effect of the depth - well that's the question this thread is trying to get an answer to.

Post

OK, enlightenment - of sorts.

Consider a practical real-life scenario. We are modulating filter cutoff (not that that matters). We have an envelope in the A1 slot. For simplicity, assume the envelope is just a gate: 0 for a delay amount, full on until note-off. So, by itself, the output of the modulator will be 0, the A1 depth (D1), then 0 at note off - in other words: [0, D1, 0]. All very straighforward.

Now, we then want that envelope to be modulated by velocity. So we put Velocity in the A2 slot.

The envelope depth is controlled by the A1 depth value, D1, and the amount of velocity influence is controlled by D2. If D2 is 0, velocity does not influence the envelope at all - just what we had before: [0, D1, 0]. If D2 is 1 (velocity influence of 100%), we want velocity to completely influence the modulator output. If velocity is minimum, the envelope will be flat. If velocity is max, then the output will be [0, D1, 0].

If D2 is 0.5 (velocity influence of 50%), then we get a combination of effects. We get half the envelope on its own and the other half influenced by velocity. So, we get this: [0, ((D1 * 0.5) + (D1 * V * 0.5)), 0].

Now, this is exactly what Vojtech's original formula produces:

output = depthA1 * (A1 * (1 - depthA2) + A1 * A2 * depthA2)

The problem in understanding it is that it's optimized by factoring depthA1 out of it, eliminating one multiplication. If makes a whole lot more sense (well, at least maybe a little bit more sense) written this way:

Output = (A1 * D1 * (1 - D2)) + (A1 * A2 * D1 * D2)

This gets you exactly described above with the envelope/velocity example. It all makes sense.

What remains a huge mystery is what happens if we add a third slot, although I cannot conceive of a real-life use case. Also mysterious is how all this plays out if the operator is other than Mul, even for the simple two-slot case.

Post

Question for Vojtech: If a modulator row has a depth of zero, is there optimization that bypasses the processing for that row (at least if there's only one slot used or two slots with the Mul operator)? Since we cannot alter the modulation source at run time (set it to Off, in particular), it would be nice to avoid unnecessary processing at least.

I'd still love to have the ability to set the modulation source on the fly, however.

Post

I am not sure that the equations that Vojtech posted are absolutely correct. :-o .

So I have gone back to first principles. Given that the "Mul" operation is a Dry/Wet control then I think that the calculation is as follows:
-- given that valueA1 =1, depthA1 = 100%, valueA2 = 0.2, depthA2 = 70%
-- the output from A1 can be considered as the "Dry" value and the value coming from A2 the Wet value

-- A2depth is 70%, that is 70% wet and (1 - 70% =) 30% dry
-- A1's contribution = valueA1 x (1 -depthA2) = 1.0 x 30% = 0.30
-- A2's contribution = valueA2 x depthA2 = 0.2 x 70% = 0.14
-- the output from the A2 stage is 0.30 + 0.14 = 0.44

Here it is in a pic (with stage A3 added too):
Image >>> https://i.imgur.com/tXm419E.png

The formula I have used is, for stage A2:
OutputA1 = (valueA1 * depthA1)
OutputA2 = (OutputA1 * (1 - depthA2)) + (valueA2 * depthA2)
For stage A3, it would be
OutputA3 = (OutputA2 * (1 - depthA3)) + (valueA3 * depthA3)

You might like to try out the attached MS Excel spreadsheet to see how the outputs differ for a two stage "Mul". Here are some examples:
Image >>> https://i.imgur.com/mziNm7f.png

Phew!

Meanwhile, if you are using "Mul" in the Per-voice Modulators, go carefully.
You do not have the required permissions to view the files attached to this post.
Last edited by DarkStar on Thu Aug 01, 2019 8:01 am, edited 1 time in total.
DarkStar, ... Interesting, if true
Inspired by ...

Post

Vojtech posted this: Output = D1 * (A1 * (1 - D2) + A1 * A2 * D2)

dmbaer proposed this: Output = (A1 * D1 * (1 - D2)) + (A1 * A2 * D1 * D2)

My revised version would be: Output = (A1 * D1 * (1 - D2)) + (A2 * D2).

I cannot see any reason why the contribution to the Output from A2 should be affected by the value or depth from A1.
DarkStar, ... Interesting, if true
Inspired by ...

Post

DarkStar wrote: Wed Jul 31, 2019 3:38 pm Vojtech posted this: Output = D1 * (A1 * (1 - D2) + A1 * A2 * D2)

dmbaer proposed this: Output = (A1 * D1 * (1 - D2)) + (A1 * A2 * D1 * D2)

My revised version would be: Output = (A1 * D1 * (1 - D2)) + (A2 * D2).

I cannot see any reason why the contribution to the Output from A2 should be affected by the value or depth from A1.
First of all, my version of the formula is mathematically identical to Vojtech's version. I just added some parens, rearranged the terms and un-factored the initial D1 multiplication. But both versions produce the exact same output values.

Second, the "mix" Vojtech alluded to earlier is not a mix of slot1 and slot 2. It's a mix of slot1 and (slot1*slot2). So, A1 gets involved in the calculations for slot 2. If you think about the real-life scenario of an envelope modulating filter cutoff and that being optionally further modulated by velocity, it turns out this is precisely what you'd want.

I put together a test rig. It's a modulator (modulating semitones - not that that matters but just so it can be easily found) in which slot 1 has an envelope that's just a gate: 1 sec. delay of 0, full value until note off, then 0. Be sure and hold a note down long enough to get to the sustain segment.

Slot 2 might be Velocity in real life. To get more accuracy, I made the modulator be MIDI key number with a transfer curve that gets you: C1 = 0, C2 = .25, C3 (middle C) = .5, C4 = .75 and C5 = 1 - this is sufficiently accurate but not to several decimal places.

My testing was informal and just was done observing the modulation line displays in the modulator grid. But the results I observed are consistent with the original formula (either version).

Code: Select all

$eNqVll1z2joQhu-5FRrlNgmS8RcztjtNIG2mIXAwTdtLgRfwVJYYSc5Af-0Z2YEQoODeeCzpeXdXq7W80ad1wdErKJ1LEWN6SzACMZNZLhYxLs38JsSfklY0SGUpsgc2M1JtNBiTi4VGVzGmGF194XLKuJ6waTW+L5UCYUYKNJjHXowHMkMjJaccCtSDQmLUz3IjVZr-gRhTnwbXIfH2Z-tMb2JMKeleh46L0df-vq80K1a8Cotg9DROVzw3BiqcxpgS72jaibHjdjEasPXTw-COy9nv2mXHwWhQcpOPmGIFGFD6XnLOVhqyyvzLNiGh5wQdHydRWk5HvFzk4i0HSVQP04+5OOkqBQ4zA1mtiDG57uCtXm9f0EPJ+TMrIMZDPcs5Z0YqVJnUvx9FFdbhMkY-q-lfMX63eBDR1XeRayn6gk057O3SLr1IXlqL5Jb47ungk2gw7F2lUORGCtDoXpbCVOoerMzSviXRmGznHYxqT7UHrWYkxn3xiuoBjfE32GC0JjG+scqJYkLPpSqYyaUgqP-8Mhr30-4kxl3cPlynSTSSuTDogbOFvosxdamlDicJRmu7KyekJPCJ7wddjDYxviG3hNBu4AeuS0OfeOfEvueFrkurZ6U+6YpWNK0ActvthsTpOJ4XUtfS7aP422OSRO0POU2idMlWgNJJf7TdPKnUHw90N7F70aeYo0pt7RXvz79UyamjP1G35L1uT8a376gV9cUrRT3grMqN1yGhS32MvkqeVclyQtf1nMC3k2mpDaucVFUBheTyb2mxdmvzThPWqdlOE7ZTs24T1q1Zrwnr1azfhPVrNmjCBjUbNmHDpBXVV7X9IHcJp5cTvlMlrejpYUjRE4iF-fhtkRzQFeFcJDoXCfci4V0k-ItEcJEIzxNjJjJZ0MOrav8mC6skbsGtxGkqcXaSTlNJZydxm0psNX+DjZ4xDg12846+y5zmMrunF+BylpvGLg-4AwPOPxrYj+AQbb2bsl2MLhWcQ3IzW96ByM4wA5n9WALwM8gkL6YKAvcMcqeAmSVxziD99cpGbH829Az2LA0M5-Nj4gvPM6jvgaO1zzOTv0Ld16H9Qf2jkOpje7EdTRTYHqPu7+r75p4ZWEi1eTRQPIq5bCfRW9d4rKqbHnuAn0e1O3uW++5taGqFxsyA-UhtqIOqqXOSaFiaAerlesXZZsDWeVEWb7fajzwzy0ESpbJUM0AjBfOcG1BvLaZ1skXaW3OtqH2qE9ZJ6398rIEH

Post

DarkStar wrote: Wed Jul 31, 2019 3:35 pm The formula I have used is, for stage A2:
OutputA1 = (depthA1 * valueA1)
OutputA2 = OutputA1 * (1 - depthA2)) + (valueA2 * depthA2)
You don't have the parens right in OutputA2. However if you meant to write it:

OutputA1 = (depthA1 * valueA1)
OutputA2 = OutputA1 * ((1 - depthA2) + (valueA2 * depthA2))

then if I'm not mistaken, that's another version of the same formula Vojtech provided and I rearranged into an equivalent version.

Post

:dog: :Oops: OutputA2 = (OutputA1 * (1 - depthA2)) + (valueA2 * depthA2)

I had intended for the outmost pairs of (...) to separate the "Dry" and the "Wet" signals
I'll fix my earlier post
DarkStar, ... Interesting, if true
Inspired by ...

Post

dmbaer wrote: Wed Jul 31, 2019 7:03 pm First of all, my version of the formula is mathematically identical to Vojtech's version. I just added some parens, rearranged the terms and un-factored the initial D1 multiplication. But both versions produce the exact same output values.

Second, the "mix" Vojtech alluded to earlier is not a mix of slot1 and slot 2. It's a mix of slot1 and (slot1*slot2). So, A1 gets involved in the calculations for slot 2. If you think about the real-life scenario of an envelope modulating filter cutoff and that being optionally further modulated by velocity, it turns out this is precisely what you'd want.
Yep, after posting, I saw that your formula was a reworked version of VojTech's :).
a mix of slot1 and (slot1*slot2)
That's the bit I'm struggling with. Off to think about it.

Using your formula, i think that we get (blue is "Dry", red is "Wet"):
Output from stage A1: = (1 * (1-1)) + (1 * A1 * 1 * D1), that is (A1 * D1)
Output from stage A2: = (Out1 * (1 - D2)) + (Out1 * A2 * D2)
Output from stage A3: = (Out2 * (1 - D3)) + (Out2 * A3 * D3)

We can simply those to:
Output from stage A1: = 1 * ( (1-1) + (1 * A1 * 1 * D1) ), that is (A1 * D1)
Output from stage A2: = Out1 * ( (1 - D2) + (A2 * D2) )
Output from stage A3: = Out2 * ( (1 - D3) + (A3 * D3) )

It is beginning to make a bit more sense. ;)
DarkStar, ... Interesting, if true
Inspired by ...

Post

Also, I see that if the stage's Amount is 1 (or is a Constant), then it has no effect.

For example:
Output from stage A2: = Out1 * ( (1 - D2) + (A2 * D2) )
when A2 =1
Output from stage A2:
= Out1 * ( (1 - D2) + (1 * D2) )
= Out1 * ( (1 - D2) + (D2) )
= Out1 * 1
DarkStar, ... Interesting, if true
Inspired by ...

Post

Huaaaaaa :o mathematical topic :D, I'm not going to contribute here :D :D.
Anyways did you reach some interesting concensus? :D
Vojtech
MeldaProduction MSoundFactory MDrummer MCompleteBundle The best plugins in the world :D

Post

Yep, the consensus is that I misunderstood, but still don't get it fully :oops: :bang:
DarkStar, ... Interesting, if true
Inspired by ...

Post Reply

Return to “MeldaProduction”