Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 19, 2018 20:51:17 GMT 1
All this time had the wrong idea about panning vs balance..sheesh. Thanks a lot for the link. Ok, it's balance then.
It confused the crud out of me too the first time I tried to do it too! Most people prefer Balance these days, but I'll add a stereo-pan option to my module pack with all the different laws and stuff, already got a mono-pan, so that would complete the set.
Random note: Got my EQ filters done today, still can't beat the old Biquad for efficiency when not modulating:
Not Modulating: RH Biquad(Peak): 0.082% TD EQ A(Peak) : 0.112%
Modulating: RH Biquad(Peak): 0.349% TD EQ A(Peak) : 0.213%
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 19, 2018 17:41:04 GMT 1
P.P.S. @rob - depending on what you decide to make, balance or pan -> I'll add the one you are not making to my module pack for completeness.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 19, 2018 17:18:19 GMT 1
Andrew, thanks for explaining.. I realize now balance is the wrong name in my module. Panning control with equal power should be it. Dave, that's what you want as well right? Uhmm, I tested your newest Panner module, it's still a balance control, stereo panning would mix left and right channels.
P.S. Stereo Balance seems to be the default in a lot of DAWs. I'm a dual-mono kinda man myself, 'grew up' on a crappy Mackie desk/mixer -> only mono channels so I got used to working that way.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 18, 2018 18:19:23 GMT 1
It's not actually SE that crashed btw, it was .NET. that "CLR20r3" is a .NET error, hence why I asked. Glad you got it sorted. I'm switchin from i5-2500 so I'm also looking forward to the CPU boost!
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 17, 2018 13:58:15 GMT 1
What version of .Net is installed?
P.S. you know Win7 doesn't officially support your 8700K right? That might or might not cause issues with wrong or overlapping drivers.
P.P.S. I'm also upgrading to the 8700K in about 6 weeks time, can't friggin wait!
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 17, 2018 13:48:13 GMT 1
Are you sure it's not the DAW sending a small DC signal to your plug? I can't see the actual level. P.S - some DAWs do that by default to prevent denormal numbers, and it seriously pisses me off 'cause it can interfere with sleep mode; preventing denormals should be the domain of the plugin! I checked in SE and no DC was present btw. As for c++ classes, I think any decent c++ programmer will have a royal fit if they saw my source code
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 17, 2018 13:29:51 GMT 1
After reading that thread again I think I might have stoked the fires of confusion a bit! I didn't fully explain tapers, laws and critically -> the difference between balance and pan. With balance you only adjust 1 side at a time, while the other side stays at unity. Easier to explain in code:
///simplest version - linear balance - exactly like CK Stereo Balance module
float pan = panKnob + 1.f;//knob -1 to +1 range (i.e SE -10/+10) (actual range is 0-2, hence the +1) float LevelLeft, LevelRight; if (pan <= 1.f) { LevelLeft = 1.f; LevelRight = pan; } else { LevelLeft = 2.f - pan; LevelRight = 1.f; }
outputLeft = InputLeft * LevelLeft;
outputRight = InputRight * LevelRight;
I suggested the pan laws because you can use them as tapers(knob curves) instead of laws. For the +3 dB Power or Sqrt Law you actually have to lower the gain by -3dB to make it a taper. So it actually becomes a 0dB Power or Sqrt taper I should really learn to explain things better, lol.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 17, 2018 10:34:54 GMT 1
I checked with the Impulse Response module, Peak = 1000Hz, Q = 3, Gain = 0. And yeah, Dave is right - it's not a flat wire.
That being said - comparing it to the EQ module I'm working on atm, mine passes the 'flat wire' test above but fails the complimentary symmetry test(RH Biquad passes that btw). The complimentary symmetry test is when you connect two of the same filters in series but with polar gains - like filter 1 = -6dB, filter 2 = +6dB; it should return a wire. P.S - not all filters will return a flat wire in the symmetry test, especially analog ones.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 17, 2018 10:25:18 GMT 1
I've rebuilt the module using Andrew his -3dB pan law suggestion ( all credits goto him ).
Lol, I can't even remember that, and don't always trust my math - I mix up the signs of stuff all the time
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 15, 2018 19:56:02 GMT 1
It actually looks like little boosts not cuts. @rob - maybe it's one of the approximations that is a tad-off around 1 or 0? I don't know much about biquads but if I where to guess - I'd look to see if there was an exp or pow in the code and check that first. twoifbysea - are you exactly sure your knobs are 0Volts? The readouts aren't very accurate, even 0.00001 Volt offset may produce what you're seeing. And what is the maximum deviation in dB? That analyzer doesn't show enough resolution, if the error is max +/- 0.25dB, you can safely ignore it - nobody is gonna hear that. Also note that increasing gain computation resolution will increase CPU in tandem. Random note1: Unless you have non-linear processing(distortion) before the out gain calculation, the input gain is redundant i.e. a waste of CPU. Random note2: Q in filters are kind of arbitrary in a way i.e. the numbers don't really make sense. Example: Biquad Lowpass Q = 0.7071 is exactly equivalent to a State variable filter with Q = 0.5!
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on Jun 1, 2018 16:39:26 GMT 1
Actually just have to clip the value coming back from the text entry - i.e. right to left. The left to right min/max values is set in stone when saving as VST(automation is normalized) so shouldn't be a problem.
void TD_FloatRescaler::onSetValueOut()//value being passed back by text entry { float clippedValue = min(max(OutLow,valueOut),OutHi);
valueIn = frescaler(OutLow,OutHi,InLow,InHi,clippedValue); }
twoifbysea - patchmem 'Out' modules are for outputs like VUs, LEDs, bar-graphs etc. The regular patchmems are for inputs from the user - like sliders & knobs.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 30, 2018 20:13:15 GMT 1
Cool beans! Btw, you might wanna clip the in/out values to make it end-user proof i.e. if a user inputs +100 into that list, there might be issues.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 30, 2018 17:59:05 GMT 1
I got the sub-controls version working, including bi-directional. Math was right, might be pin updates or something with your module. I ended up modifying the Float Scaler2 example from the SDK examples because I have no idea how GUI modules work(this was my first GUI side module) and the Scaler2 example was close to what I wanted to do(too lazy to type, lol). My formula looks a bit different but it is actually 100% the same, just rearranged - no idea why I wrote it like that, just copy n pasted it from my audio module.
Feel free to use/modify code(I'm not releasing the module):
.h class TD_FloatRescaler : public MpGuiBase { public: TD_FloatRescaler( IMpUnknown* host );
private: void onSetValueOut(); void onSetValueIn();
FloatGuiPin valueOut; FloatGuiPin InLow; FloatGuiPin InHi; FloatGuiPin OutLow; FloatGuiPin OutHi; FloatGuiPin valueIn; };
float frescaler(float in_min, float in_max, float out_min, float out_max, float in) { if ((in_min-in_max) == 0.f) //avoid divide by zero return out_min; else return out_min + ((out_max-out_min) * ((in_min-in) / (in_min-in_max))); }
.cpp TD_FloatRescaler::TD_FloatRescaler( IMpUnknown* host ) : MpGuiBase(host) { // initialise pins. valueOut.initialize( this, 0, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueOut) ); InLow.initialize( this, 1, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueIn) ); InHi.initialize( this, 2, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueIn) ); OutLow.initialize( this, 3, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueIn) ); OutHi.initialize( this, 4, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueIn) ); valueIn.initialize( this, 5, static_cast<MpGuiBaseMemberPtr>(&TD_FloatRescaler::onSetValueIn) ); }
// handle pin updates. void TD_FloatRescaler::onSetValueOut() { valueIn = frescaler(OutLow,OutHi,InLow,InHi,valueOut); }
void TD_FloatRescaler::onSetValueIn() { valueOut = frescaler(InLow,InHi,OutLow,OutHi,valueIn); }
Cheers
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 30, 2018 14:14:41 GMT 1
I PM-ed you the project plus source and SEM. What Dave wants is: - To have the option to either set what the knob (subcontrol) sends to patch mem value out(dsp), or set it thru Text-entry 3 (subcontrol). - When it's set thru the Text-entry 3 the correct value should be reflected by the position of the knob, so it works bi-directional. I'm not sure we can help with the second bit, as it goes back from value ( subcontrol 0-10v ) on the patch memory to animation position ( subcontrol 0-1v ). You answered it probably by suggesting a second module to work that out. This might suggest Jeff did not foresee this use-case, but is relevant ( I would want it too when building a VST with knobcontrols and value input ).
It's probably something to do with the order of pin updates or the math, I'll check it out. You really need two modules if you want to change both the display and the output - Jeff designed it that way, it might sound weird but it is actually more flexible. If you do something wrong with the sub-controls - it may change the output of the patchmem - but that's an error, SE doesn't guarantee to initialize to the correct value(this is correct behavior)! Say a EQ module takes on kHz values, but you want to display Hz, you change the subcontrols only. Say, like my EQ(personal project) half of the knob travel goes from 0.05kHz to 1Hz and the other half of the knob travel goes from 1kHz to 18kHz - i.e. - the knob response is curved - I do that with two Float Function modules, one subcontrol one DSP.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 30, 2018 12:14:02 GMT 1
Okay, now I'm even more confused - I plugged your original formula into a Float Function module(DSP one under conversion, not bi-directional), got wrong result, used my own formula - wrong result. This was just for re-scaling not the inverse. Don't think either of us is wrong(my formula works fine in an audio module) but there must be something fundamentally that we are missing about using floats.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 30, 2018 6:48:18 GMT 1
Andrew , thanks for pitching in. Tried it, but while testing several values I do still get wrong results. There's probably still something wrong in my module. Check what happens when inputting 12 in TextEntry 3, value out says 307 now instead of 13
Hmmm, I think I don't understand what your module is suppose to do in practical terms. Can you PM me the source code and maybe a actual use example(default skin plz)?
Think their might also be some confusion about how the module is used. Just to make sure - do you want to change only the display values? Or both the display values and output values(prom patchmem)? If you want to do the latter - you actually need two modules, like the Float Function module that has two(one sub-control/one dsp float).
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 29, 2018 17:12:22 GMT 1
In simpler terms, rescaling is the inverse of rescaling.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 29, 2018 13:35:37 GMT 1
I'm having trouble rewriting the rescale formula to go back from output to input ( should have paid more attention in school ). To be continued.. Original formula: y = ( x - oldmin ) * ( ( newmax - newmin ) / oldmax - oldmin ) + newmin Wrongly rewritten formula: x = y + oldmin * ( ( oldmax - oldmin ) + newmin ) / ( newmax - newmin ) In this rare case i.e. no powers or transcendental functions(i.e. linear addition and multiplication), you can calculate the inverse by simply substituting 'values'. I'm adding the descriptor "pin" to the formula - because "value" doesn't make much sense with bi-directional stuff for me.
Original formula:
pinY = ( pinX - pinOldmin ) * ( ( pinNewmax - pinNewmin ) / pinOldmax - pinOldmin ) + pinNewmin
Inverse via linear substitution:
pinX = ( pinY - pinNewmin ) * ( ( pinOldmax - pinOldmin ) / pinNewmax - pinNewmin ) + pinOldmin
It's almost like cheating.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 23, 2018 22:43:43 GMT 1
Think the only way around that is to have a custom Text Entry module which has an additional 'locked' text pin. It doesn't work with the Append Module because of the way GUI modules communicate. The only hack I could think of is to not use the append module and have an extra Text Entry for the 'locked' text. Adds a bit of clutter though.
|
|
Andrew
Developer
Posts: 110
Posts: 110
|
Post by Andrew on May 11, 2018 19:51:54 GMT 1
So far I have High Sierra running fine in Virtualbox and VMware workstation player, the later more smoothly btw. To be continued!
That sounds fun. Anything 'need to know' about working with Xcode/Clang? I know Clang is highly compatible with GCC 'cause it was the original compiler tied to Xcode but getting a new compiler up and running is always a PITA. Also thinking about an easy way to test modules after compile. I assume you have to move back to Windows->Save As AU->run on Mac -> test in GarageBand(free) or Reaper I presume.
|
|