MXXX: Getting parameters to match when they're being fed the same Multiparameter value

Official support for: meldaproduction.com
RELATED
PRODUCTS

Post

Code: Select all

$eNqlV11T2zoQfedXaHxfaWPrw5ZnCB1IgcsMaXMTCtxHNRaJBsXKteVC+uvvyo6NE4PJTJ2HKOs90tnV2ZVy8uVlpdEvmeXKpEMv+Ox7SKZzk6h0MfQK+-iJe19Oj07GDw8PubQWzDn6Cxw9NDKpzYzWgL1IxU8tk6EH6FFm8tzAjGOTyKGHaXI+MHPbenG7WcOLs1Ros-DQ1Y-rmfotMcxJQn4ccdzYLkS+ATvn-nGEYw-dqPSpXONmOltrZa3MnFsAUB+H+2ZAEvAdi5eby+-n2syfnBWMsMC40FZNRCZWErzzEYQh1vk2grs6GxGPogB7pycNdUd681tmaLYyxi5TmecA+ewzD92rNDHPVWx-izQF2CSTj0rDApA1+GVUatGlFov8HBhTSOGLyzjxgX0cxywMvcF7bnTfbbA3eWbmQMZkPmo2A5CXSutyMFuaZ4jSZHdCFzIvbbdLNS-zOWjhA-Qd4sxUIkv39x3xoY7kUEf6geOgsw0gzJ8iTfxGkdttnKrF0k5EKvV7cuH+G3LBMXlHLzOp5dzKZKKLhQJl+MfgOSuyzBRpMlrCdku9rQKYffs4BZT+eT1Al4XW30B0Q+9GrRSsjID2jsFDDyXnf2HhZoLZbuWdWSvmT1V9XYrctiJ-FTYEsc1AUFVOTbNKiTFPZ0spkq9Si01pejPwKQQuctlea+Y2aClUOqmRjWUm5yZNRLbZrlW9-ThNtcud0cVKlureibsxNIP8DdC4rOXTk3uV2OUYHEyRzSVqF0qtpNplUGMGpY5co9vtDKd7Bh99lY8CTGUdudpnJIwY5zHBHBJ9BZTWQ+-iv0Jo5RpFgD6hi39QWDa1i0RZs22M30y2ErrqdTD31DxXu7DzspLGSCoN5NEAyiGT+dLoBNK6lnW-qqgE21E1w-kGPaost2hdU3dqqselEKciXYAn9VBjr9Y7h1yUxBuRwnhLoqzYP5imHcFSrGW7WzU5pXEYUB5hn5PQycM5Ns3hR6ps-uCOC5giFetbcwVmZ-D2uyeGxjzoGmnZUqFt0yCsn8hDm9JG-JatD8zJ61ODGSeMURKFIeN94ACzGgLKeZ2mDxJ2uAZBTEJCYoZxb5y4xbWGMhbSXooNw4DHjALLMOjNB46DfX4Y0z4E6SYQs+igZJCoZofjwxBvbDUhjEbRAVDWSR+JaBD5vDeBNUMa0IMExWgngZSFvQjeSSCN+UGLhc32MooPQ3T1x-oTEHVlFxLq+yQiLIz7oTW7kAdRbw6iruwiEjC4N-GIxr36e6OAIx5A+WL4wLnUB20IcnLY7sZd-fH+9MVd2cUf7BWrrpSld8l-ULZOd2rWrdmdebsnWseSwzF4Nrfql4SjEy79qP2jugmZrHVlhvXcwVY14JGwcmGyzbWVq+v00aCzwi7dZQ6cxkJpN3B2931-fw9fQHMER7mESKpzoyTeXtPxydZoClNDlPD66E-O+iMYtf7NnB79D2D7zjM=
Jason @ Melda Production

Post

I'm thinking about getting MXXX Core because it's on sale right now. It's way over my head, but I still really want it. So I figured that this would be an interesting thread. And it IS.
However, my brain caught on fire while trying to understand all of this.

But I'm still going to buy it! :ud:

Post

@ jmg8 Good stuff - how did you work out the Transformation Shape?
DarkStar, ... Interesting, if true
Inspired by ...

Post

Nice. Looks like a 0.02dB tolerance. That's WAY closer than I got after at least a few attempts

From the looks of that curve, I need to learn a few things about curve creation as well. Were those somehow defined rather than clicked? What was the process to create it?

That's definitely close enough for most static cases, but the more complex issues come into play as the ranges change. Unfortunately, unless the transformation curve itself is dynamic, it doesn't appear to be possible to optimize it for anything other than a single static range.

Shifting to -24dB range, for instance, widens the variance to 2dB, but it also goes out of calibration when pushed the other direction. As far as I can tell, It doesn't appear to matter what range you start with. No matter how well the curve is dialed in, changing the range in any direction will decrease accuracy.
Last edited by Annabanna on Mon Jul 30, 2018 8:57 pm, edited 3 times in total.

Post

sirmonkey wrote:I'm thinking about getting MXXX Core because it's on sale right now. It's way over my head, but I still really want it. So I figured that this would be an interesting thread. And it IS.
However, my brain caught on fire while trying to understand all of this.

But I'm still going to buy it! :ud:
Can't speak for core as I haven't used it, but you can also do the entire suite on subscription which is quite a good deal. Don't let me put you off. It's phenomenal stuff. I just have a life long habit of finding new and interesting ways to break things.

This will get resolved more comprehensively at some point... so far just about everything else I've run into has thanks mainly to help on this board.

Post

@jmg8, It would be quite helpful if you could share any best practices for creating such a graph as you appear to have done so much more quickly and accurately than my attempts.

It works quite well in the simplest static case. Unfortunately, when the range changes as it necessarily does when more than 1 controller is involved, accuracy deteriorates, and in the case of more complex control structures, those errors compound dramatically. Again, this is not just an MXXX issue. The same is happening in any plug where controllers are used.

It's very clear to me that this can only be properly addressed on the dev side for many reasons. The obvious tediousness of brute force fixes aside, the best any of these methods achieve on the user end is to distort the curve by introducing lots of vertices. By definition, these brute force attempts merely reduce a smooth curve to a low poly approximation. Since users do not have direct access to algorithmic methods to define curves, it can only truly be addressed fully on the dev side.

I do truly believe that if more folks measured some of the actual outputs, and evaluated those measurements according to the most common sense case benchmark of a user naturally expecting a parameter to have the value he had selected for it, the benefit of doing so would be obvious, accuracy would increase for all affected plugs, and control would be more intuitive as parameters and therefore plug behavior would match common sense user expectations. That's a lot of benefits for a lot plugs for one behind the scenes option with absolutely no downside that I can see at all. Sure, other modular systems may have a similar limitation, but isn't the goal to always be better?




The SIMPLEST fix:
I actually don't even think it's that difficult to address. In the case presented, for instance, if I knew how, I'd just hack into the plugin code, and change the Threshold range to 24 rather than 80dB, and every single other compound issue mentioned would just magically fix itself. That might seem like it's limiting the range of the threshold, but the fact is, for any case where you're attempting to match two parameters, the range is already limited to the smaller of the two.

If, for instance, there were a checkbox that said something like "Match range interpretation for same units" or "Match same units to smallest range" or "Match same units to first parameter range" or something like that that only affected multiple parameters using the same units, but with different ranges, this would already be solved. Nothing would be negatively affected. All existing patches would still work, and any other parameters with different units would be unaffected.

To clarify, this simple option would, for the ceiling/threshold case cited (and all other similar cases for all Melda plugs with controllers) not only perfectly match them at the full 24db range, but also for all other restricted ranges as the percentage values would simply be based on the newly matching innate ranges. Every case, static, and dynamic just automatically matches because the core mismatch is addressed at the source. It almost couldn't be simpler to fix perfectly while still allowing perfectly smooth curves on the dev side of the equation. Whole other can of compounded complexities on the user side.




A much more powerful fix:
That's the simplest fix. A more sophisticated option that opens up all kinds of other possibilities would be to allow the restriction of innate ranges. That way, setting any two parameters with the same units to the same range automatically matches their curves perfectly AND MIS-matching them according to ratios always perfectly matches those ratios. For instance, if the innate range of the threshold is set to 48, and the innate range of the ceiling is 24 (which is the first parameter), then ANY value entered on the MP will result in that exact value for the ceiling, and EXACTLY double that value for the threshold. As you can see, it also allows for common sense behavior to extend BEYOND the smallest of the two ranges.

This solution fixes not only everything mentioned in this thread, but also makes it incredibly simple to preserve all kinds of ratios in all kinds of static cases, and opens up a whole new world of correlation options in more complex cases that used to involve strings of nested kludges, but are now a click away. The simplest implementation I can think of is just some version of double clicking or something like that on a parameter to open up a simple slider that allows the user to set a restricted innate range. The plug simply uses that new user restricted range as the innate range, and bases all percentage values on it.

I can only blame my own communication skills if the benefits of what I'm saying aren't immediately obvious. It's not a small thing. It addresses and improves, and simplifies all sorts of things that extend well beyond the scope of this thread. It makes a number of currently difficult common tasks effortless, and it allows the behavior of all sorts of aspects of all sorts of plugs to mimic basic user expectations... and does so with zero detriment to those who chose not to engage the option. If it is not clear, please specify what is not clear. I will provide graphs, charts, whatever is necessary. This is not a small thing. It has the potential to be a major step forward in both user experience and utility.

Even the simplest fix mentioned would greatly improve the accuracy of all plugs with controllers and mismatched ranges from the common sense perspective of a user's natural expectation that values are what they told them to be. The more sophisticated fix also greatly simplifies all kinds of things that are currently quite cumbersome, and does so without restricting the usable range of any plugins. Both do so with no downside.





In the meantime:
Of course, there is no such option currently, and it's throwing off quite a few aspects of every project I'm working on. The only path I can see forward at this point is to either create completely separate control structures per parameter (doubling, tripling, or more the complexity of each plug), or to just brute force it to death by creating a dynamic version of your curve. To do that, I believe i need to take what you've done, and do it again separately for a number of different ranges using the same points so that the correction graph itself morphs to adapt to the contour that fits each individual range. Doing so separately for every dB within a 24dB range should work well enough.

Obviously, tweaking 24 such graphs could be quite tedious, so any tips you can share about best practices for creating such a graph quickly and tuning it accurately would be greatly appreciated.

I'm also not exactly sure the best way to handle such automation. Would it be better to use banks to do this? Playing around with bank interpolation today to familiarize myself with any options there.

Post

Firstly I must say, that I do not agree with you on this topic. I have already explained and do not wish to go round in circles.
But one last time, I will explain.
Also after this post, I will try to create some step by step tutorial as to how I created the curve.


MPs should display percentages if they are controlling more than one parameter (yes even if the two parameters share the same unit values)
The option to display first parameter value applies ONLY to the first parameter (yes even if the other parameters share the same unit values)
Just because two parameters share the same unit values does not mean they should be able to be linked. They can have very different sweet spots. So typically 50% will be around the sweet spot. For a gate this sweet spot could be around -48db but maybe for an EQ bands gain it could be 6db, some only go positive some only negative, some both, they can have different min and max values and very different transfer curves. This is so we get a sensible range with a central sweet spot.
It is not reasonable to expect them to behave in the same way, just because they share the same unit values.

Remember the MP sends to the parameter a percentage, NOT the value. Then the parameter sends its value back to the MP for display purposes only. however, this is only relevant for the first parameter.
Jason @ Melda Production

Post

Unfortunately, I cannot work out how to take a screenshot of a selected area without it closing the pop-up windows i have open.
So I will do the step by step, just using text.

1. Open the transfer curve window (making sure to arrange the windows in such a way that you can see the target parameters)
2. Work out how many anchor points to use. In this case 0db to -12db is 13 steps (at 1db increments)
3. Right-click in the window and snap x to grid. Then using the little magnet type symbol you can set the grid resolution, choose 13.
4. Now create 12 points and snap them one to each X grid point.
5. Next type in the MP -1db. You can see that it correctly sets the value of the first parameter, now we need to match the second parameter to this. So open the transfer window and move the relevant point up and down until the second parameter reads as -1db (in this example the point to move will be the 12th point from the left) If needed you can zoom into the graph to achieve a higher resolution.
6. When the point has been set correctly, right click on the point and lock it (so as not to accidentally move it)
7. simply repeat this for all points.
In my curve, I actually doubled the resolution by also adding points in between each point. But I could have gone even further and done four times the resolution (but I couldn't be bothered)

Hope all that made sense, feel free to ask any questions.
Jason @ Melda Production

Post

To capture pop-up windows, drop-down menus etc, PrtScn works here, then I paste into MS Paint and crop / annotate the pic as necessary.
DarkStar, ... Interesting, if true
Inspired by ...

Post

I see what you mean now about controller ranges behaving non-linearly.

The ceiling control behaves linearly whereas the threshold control does not which tells me it's not some sort of log vs linear units translation (since they both have the same units). This would seem to indicate that there is a hidden (and inaccessible?) translation curve being imposed on the threshold. Assumedly, this would be to emphasize the more commonly used portion of the range, though it would also appear to be one of the root causes of complications when trying to gain more accurate control.

Is this an accurate assessment?

If so, is there any setting or control anywhere to force linear interpretation by the parameter?

Post

Yes. That is an accurate assessment.
Unfortunately no, there is no setting to force linear.
Jason @ Melda Production

Post

Annabanna wrote: ...Can't speak for core as I haven't used it, but you can also do the entire suite on subscription which is quite a good deal. Don't let me put you off. It's phenomenal stuff. I just have a life long habit of finding new and interesting ways to break things....
MXXX Core works exactly like MXXX, but you can only use the plugins that you've bought. I actually have the Mastering Bundle, as well as several additional plugs. I have only scratched the surface on most of them, so I have plenty to experiment and learn with.
So I'll be getting MXXX Core in about 5 minutes (literally). Then, to get on topic, I will load the presets posted here, and see if my cranium doesn't start smoking again while trying to understand everything.

Good luck to the O.P. ! I suppose Vojtek will chime in here once he notices this thread (or whenever he actually has some time!)

Post

You're right. I was missing an important piece of the puzzle.

I'm not entirely sure, but it seems like a solid educated guess at this point that the hidden transformation curve is static, and always applies to the full range. This would explain why correction curves always shift when the range does... because the correction curves are being applied to the restricted range which keeps shifting while the hidden transformation is being applied to the entire range which does not shift.

If that is correct, I think I've got an accurate picture now. Please let me know if I have misunderstood anything. If that's the discrepancy with which you disagreed, I fully understand, if not I'm not at all clear which part of the following you would disagree with:




I'd like to invite everyone to step back from the specifics of this thread for a moment, shake the etch-a-sketch, and join me on a little thought experiment.

Let's pretend for the moment that there was a little checkbox on controllers (modulators and MP's) just like there is for "invert." Let's pretend that when this button is pressed, the following things happen automatically:

1) Values the user enters for multiple parameters always match exactly in cases where that is possible and configured to do so.

2) Locking two values together becomes trivial, and is always accurate for any interpolation.

3) Locking values in any ratio becomes trivial, and is always accurate for any interpolation.

4) Locking values with any chosen offset becomes trivial, and is always accurate for any interpolation.

5) Locking values related by some basic compound operations (Y=2x+3) becomes trivial, and is always accurate for any interpolation.

6) It becomes possible to predict precise outcomes of compound behaviors with zero margin of error.

7) Many tasks that formerly required nested or chained controllers are now trivialized, and the outcomes are always accurate for any interpolation.

8 ) Even for relatively simple tasks, plugin behavior becomes more intuitive, and matches the common sense behavior any new user would expect.

9) Nothing changes at all for anyone not checking the box. They will WANT to check it once they understand what it does, but they are under no obligation to change anything.

10) Nothing breaks, and all existing patches function exactly as before.






I've spent most of the day working this out now, and I'm relatively sure I have a rather straight-forward way to accomplish everything on that list with a simple button click from users, and relatively minor code modification on the dev end, but it's going to take a bit of a paradigm shift, and the introduction of some new terminology to communicate this properly. If one or more of the following terms already have existing names, please let me know, and I will modify this post to use those names instead as the goal here is clarity.

Speaking of clear, If I haven't made this clear, I LOVE this product, and the support on this forum. I want it to be the best it can be for me, and for the community.


Let's start with the definitions:

MAX RANGE: This is the range set by the developer. It sets the lower and upper bounds for possible values of the parameter. Users can never expand or shrink this range, or set values outside it. In the threshold example, the max range is -80dB to 0dB.

OPERATING RANGE: This is the range according to which all incoming controller values are interpreted. In the current configuration, the operating range is the same as the max range. In the threshold example, an incoming controller value of 0% produces a value of -80dB, and an incoming controller value of 100% produces a value of 0dB specifically because the operating range is -80dB to 0dB.

CONTROLLER RANGE: This is the range set by the user on a MP or Modulator. It is limited by the bounds set by the max range. In the threshold example the user could constrict the output of an MP to only produce threshold values between -12B and 0dB, but all they are actually doing is restricting the MP to output values between 49.6% and 100%. The operating range, and the interpretation of those values at the parameter level remains unchanged.




Everything in this thread, and a great many other issues, complications, errors, and unpredictable plugin behaviors can all trace their roots to the following two items:


1) Hidden transformation curves that cannot be neutralized by the user.

2) That coupling of the operating range to the max range. (get ready for the pardigm shift)





First, the hidden transformations. I understand their use. I use them personally, I always toss up a rough mix first, then use gain plugs to set the faders at unity so I can maximize the useful range. I get it. It's a useful feature, and I wouldn't ever suggest changing it for the typical daily use cases.

That being said, it is the exact opposite of useful in just about every situation that involves anything beyond the basic use case. It's actually one of the core reasons so many things are unnecessarily complex, and never produce accurate results.

Let's just step back for a moment, and look objectively at something. If a user sets a value, they expect the value to be what they set. If there is a mismatch because an AI stepped in and determined according to it's machine learning algorithm that the user was actually trying to do something a bit different, and the value could be further optimized, then it's fair not to call that mismatch an error. If the value differs because the user has mismatched units, is attempting to do something out of range, or is otherwise trying to do something UN-intuitive, it's also fair to say that mismatch is not an error.

If, on the other hand, the user is trying to do something intuitive, and the value he enters keeps being overridden by constantly varying degrees according to factors which are arbitrary to his use case, and which render the results to be consistently inaccurate with no remedy, it seems fair in such a case to refer to such mismatches as "errors." I'm regularly seeing 4dB errors in simple cases, and have seen errors exceed 10dB in compound cases. In addition, there are a number of operations which would be quite simple without them, but which are exceedingly difficult if not impossible with them. More on that later.





The second core issue is the coupling of the operating range to the max range. The issues in this thread along with several others occur in large part because the user is telling the plugin to use one range (the controller range), yet is is using another for it's interpretation (the operating range). In the current configuration, the operating range is always effectively the same as the max range.

What would it look like if they were allowed to be decoupled, and the operating range were instead then coupled to the controller range? Well, first, let's clarify what that means.

In the threshold example, the max range is always -80dB to 0dB. Again, the max range is set by the developer, and can never be changed. In the current paradigm, that is also the operating range in that incoming controller values of 0% are interpreted as -80dB, and incoming controller values of 100% are interpreted as 0dB.

Lets say the user (via an MP or Modulator) sets the controller range for the threshold parameter to -12dB to 0dB. Since controllers only ever work in percentages, and the controller range hasn't changed, what's actually happening is that the controller has simply limited it's output to a range of 49.6% to 100%.

If the operating range were decoupled from the max range, and instead coupled to the controller range, things would work quite differently. In this case, the controller would no longer be sending a range of 49.6% to 100%, but would instead be sending a range of 0% to 100%. Once that value hits the parameter, however, since the operating range has now changed to match the controller range, the 100% controller value still produces a parameter value of 0dB, but the 0% controller value now produces a parameter value of -12dB.

But wait... nothing has changed, so what's the point? Done the old way or the new way, setting the controller to the bottom of it's range produces the same parameter value: -12dB. Yes. That much was always intuitive. It's everything else that wasn't.... and everything else changes.





To get the full picture, we need to combine both. So, back to our thought experiment. You click the little red pill button and what happens?

1) It turns off the invisible and otherwise un-bypass-able transformation curve for the parameter allowing linear control.

2) It decouples that parameter's operating range from the max range, and couples it instead to the controller range.





Dude, you sure type a lot a gibberish. Mind getting to the point?

If I must. How about a compare and contrast. With and without the magic button. Let's say you want to:


1) Lock two values together.

OLD WAY: Good luck if there's a range mismatch, hidden transformation curve, or both. Best case scenario, you might be able to create dozens of static curves, and animate between them which would involve thousands of data points. There will always be errors, so all that effort is just to minimize the errors.

NEW WAY: Just match the ranges, and press the magic button. No errors. Ever.



2) Lock two values according to a ratio.

OLD WAY: It is possible under very select circumstances depending on the ranges involved, which direction the ratio goes, etc. Too many issues to get into... but that's kind of the point. Let's also not forget that if there are range mismatches, imposed curves, etc, you will then ALSO need to deal with all the issues from the first example to correct that. Again, you will never get perfect results in such a case. Your best hope is to minimize errors.

NEW WAY: Change the ranges according to whatever ratio you want via the same controller, and press the magic button. No errors. Ever.



3) Lock two values with an offset.

OLD WAY: I don't even remember how to do this. I just remember it being a pain. I think I did something like routing the MP through a modulator, and back to MP. I do remember it took over an hour to work out, and I STILL had all the problems associated with the mismatched ranges, imposed curves, blah, blah, blah. Again, always errors, just a matter of how much work you want to put into minimizing them.

NEW WAY: Change the ranges so the upper and lower bounds of 1 are offset by the chosen value from the upper and lower bounds of the other. Press the magic button. No errors. Ever.


4) Lock two values according to compound operations. (Y=2x+3)

OLD WAY: I feel your pain. Best of luck.

NEW WAY: Set one range to be x number of times larger (multiplication/division), and then offset the upper and lower bounds vs the other range (addition/subtraction). Press the magic button. No errors. Ever.





I know these are very technical examples, but I'd suggest they're very INTUITIVE examples. Here's why. Math works precisely because we can predict it. We can do amazing things when the tools we have behave predictably. it encourages us to go further and do more. What all of these examples have in common is that thee plugin behaves exactly as any user would expect it to, and they can reliably predict it's behavior.

So let's get super NON technical. Say you're a brand new user and on your very first day, all you want to do is to get two parameters to track together... like me a couple weeks ago. If you are so frustrated that the plug will not ALLOW you to do such a simple and intuitive thing, it can be endlessly discouraging... and that's not even getting into the compounded complexities of trying to do various operations.

Perhaps most importantly, it reduces all kinds of things whose current flow chart resembles a bowl of spaghetti down to a few mouse clicks by addressing the core issues directly and allowing intuitive and predictable behavior rather than piling kludge on top of kludge on top of kludge....

We all get used to things being the way they are, but imagine for a moment that you're a new user. You try doing things the old way, then you press the magic button and try again. I have one question:

Would you ever UNpress the button again?





I'm oversimplifying a few things for the sake of brevity (believe it or not), and I've thought of a few other variations on how exactly the implementation might work, where exactly in the UI the ability to change the operating range should be, etc. This is not meant to be an exact blueprint for what should be. It is meant to be an invitation to dive into this range decoupling/recoupling paradigm shift and work out the details collectively.... or to tell me that I have lingering misconceptions. Both are welcomed.

Post

I re-read this thread. Well... Honestly, I re-skimmed it. And I partly get the issue. So...
The type of "error" you're getting seems to be an unpredictable amount of db change across different ranges of multiparameter settings, right? At least in part, that seems to be important. Don't tune out yet, even if I'm a bit slow!
But I'm smart in some ways. And I usually have some idea of how to ask decent questions.

Question 1. Why does what you're trying to do require such precision? Is the problem mainly gain change?

Question 2. Can you post a piece of music, and then describe how exactly that you want to make it sound better, in a way that you currently can't?

Post

sirmonkey wrote:
Question 1. Why does what you're trying to do require such precision? Is the problem mainly gain change?

Question 2. Can you post a piece of music, and then describe how exactly that you want to make it sound better, in a way that you currently can't?
1) It's a problem that pops up in all kinds of parameter pairings. Why would anyone ever bother giving a parameter a specific value if they DIDN'T care if it had that value? If that were the case, why not just have a giant knob with no numbers on it? Some things may work just fine that way. Quite a few things don't. Mastering limiters tend to rank rather high on the scale of things that don't work fine that way.... which is why I chose the limiter module for the example.

2) No, but it's a universal concept. Hack all your plugins to randomly shift any of their parameters by 4dB or more, do a mix, and get back to me. If that doesn't strike you as a problem, it seems highly unlikely that I could explain it any better. Ask any ME to work with his precision tools under those same conditions, and he'd have a stroke.

If you truly want to understand any of it, forget anything else, and read my last post.

Post Reply

Return to “MeldaProduction”