I’m trying to solve following problem.
Module has a lot of knobs and one switch ‘Mode 1’ <-> ‘Mode 2’. On switch from ‘Mode 1’ to ‘Mode 2’ I would like to save all knob values for ‘Mode 1’, load values for ‘Mode 2’ and adjust knobs accordingly. Same backwards.
Adjusting param.value doesn’t work - knobs are not redrawn.
I assume I can make custom Widget child and override step() function, which will update widget value from param value and call redraw. But is there easier option?
I am trying to change a knob value programatically (Rack v1.dev.46f9577)
If I call params[…].setValue(…) from the process() method the redraw works.
If I try to do the same from the onSampleRateChange the redraw doesn’t take place (if I drag the knob it will jump to the set value).
Is this expected?
A related question: calling configParam crashes if called in the onSampleRateChange. It didn’t a few days ago. Should we avoid using it outside the Module constructor?
I can’t reproduce the bug when you call Param::setValue from onSampleRateChange. My question though is why would you ever want to do that?! Regardless, I tested it and it works as expected.
Yes. Only call config* functions from the Module constructor.
Ok, what would be the proper way to modify properties such as the max/min values or the display Base/Multiplier/Offset?
There are no setter method so the only chance is directly accessing them.
I’m thinking of panels that can change some of their properties depending on e.g. a context menu option. Say, e.g. I leave the user an option to decide whether to use samples instead of millisecs for a knob.
But I also want the new value to be consistent with the previous one, so I have to change the knob value in the onSampleRateChange method.
Does it make sense to you?
Don’t modify the parameter limits, just rescale in the DSP code. E.g.
float x = params[...].getValue();
if (mode)
x = rescale(x, 0, 1, -1, 1);
But why would you want a knob to change its position based on the unit? The unit of measurement is a display setting. The DSP code should only care about the absolute measurement.
I don’t think your users want to care about samples. They think in terms of milliseconds, not samples.
Ok, but even keeping everything in ms, the problem of allowing a non-uniform mapping in the range 0-1s with varying sampling rate remains. The new display feature is very useful, but the values should be consistent with the DSP engine, otherwise it gets confusing for the user. I see the same issue with the clock of SEQ-3, for instance, where the BPM value ranges from 2^i where i ranges -2 to 6 but no hint is given to the user.
I’m sorry, but I really need to stress this detail: how are we going to handle display values in cases such as the SEQ-3 clock knob?
I’m wondering if other developers have found their own neat way to get this right, otherwise I believe that a solution should be found before v1 is out.
Just my 50 cents.
Yes, I was fiddling with this and came to the same conclusion. Obviously in this case you don’t need the value of the engine sampling rate for displaying the value.
So I figured out that this is not exactly my case: in SEQ3 the upper limit is 3840BPM, i.e. one step lasts Fs/64 samples. In my case I’d like to get down to generating 1 random value per sample, keeping the same nonlinear mapping, and keeping the user informed with a meaningful display value.
The solution I figured out so far needs to know the sampling rate to init the knob display multiplier and base, so it’s not feasible if sampling rate changes.
Solution1: display value = Fs^(x-1) --> with x in [0,1] allows to range from 1/Fs to 1
Solution2: display value = x^2 --> with x in [0,1] allows a nonlinear map (not perfect though for musical stuff), but the APIs do not allow x to be the displayBase.
I guess there’s no way around this with the current APIs.
BTW: the intent is to make a random generator useful for BPM stuff but also to generate noise getting to a rate of Fs or close to it.