Welcome to %s forums

BrainModular Users Forum

Login Register

Log to Linear- any math head help

I need help on a Patch
Post Reply
23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 02 Apr 2018, 14:37

well its more a math question

I need a linear fader in my code going from 0 to 1 to control cutoff from lets say 20 to 20000 Hz.
linear scaling gives bad results as frequency work in a log fashion.
what i was using previously was transforming my lin01 to a pseudo log01 using

pow(x,5), rescaling to my output range (20-20k) = wanted cutoff.
getting the reverse by rescaling given cutoff to a 0.1 range, then using pow(x,1/5) to get the fader normalised value;

that kinda work but is not very good as the start of the fader is very slow to raise.

now i use this formula, wich is much more natural to me and seems coherant with motion i see on other vsts:

[c]cutoff = exp (log(20) + (fader * (log(20000) - log(20) ) )); // 20 and 20k being min-max, fader going from 0 to 1[/c]

however im not that good at math and i fail to find what is the inverse of above fonction, ie if i enter 20000 as cutoff via keyborad, how to get 1.0 on the fader if i enter 20, get 0.

any help would be greatly apprecied!

User avatar
oli_lab  
Member
Posts: 1263
Location: Brittany, France
Contact:

Unread post by oli_lab » 02 Apr 2018, 15:17

Hi !
I had a go with the mapper curve and I found out it should do for your purpose.
unfortunatly, I'm not able to upload anything with the uploader..

to get the log from a 0-1 fader, use the mapper curve in log/exp mode and set the coeef to anything < 1

to get the inverse, I mean to get the 0-1 value from a 20-2000 log scale, use another mapper curve with its coeff set to 1/coeff of the first one.
http://oli-lab.org

Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces

follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 02 Apr 2018, 15:35

ok thanks i ll check maybe that will hep figuring out, ideally its for some function inside a user module code, so i would like to avoid depend/wiring other modules but rather code a function
that return the inverve of the first one.
i managed to get something working finally but i feel my revert function is 'heavy for nothing' and could be simplified..

[q]
///////////////////////////////
double Lin01_to_Freq(double inval, double min_Hz, double max_Hz) ///inval in 0..1 range
{
return exp(log(min_Hz) + (inval * (log(max_Hz) - log(min_Hz))));
}
//////////////////////////////////////////////////////////////////////////////////////
double Freq_to_Lin01(double inval, double min_Hz, double max_Hz) ///revert function in val in 20Hz-20KHz
{
double max_octave = log2(max_Hz / min_Hz); //how much octave is max_freq compared to min freq
double octave = log2(inval / min_Hz); /// 'position' of incoming Hz value

double val01 = RE_RANGE_TO01(octave, 0, max_octave); /// re range: ((inval - inmin) / (inmax - inmin));
return val01;
}
/////////////////////////////

[/q]

User avatar
senso
Site Admin
Posts: 4424
Location: France
Contact:

Unread post by senso » 02 Apr 2018, 15:51

hi,
often in Usine I use simply x * x. It does the trick and it's fast.

in your case
let say 'fader' the fader position in the range [0..1]

cutoff = 20 + fader * fader * 19980; // power 2
or
cutoff = 20 + fader * fader * fader * 19980; // power 3


or if you want to have more tweak possibilities:

cutoff = 20 + power(fader,coeff)*19980;

with coeff in the range [2..4]

senso

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 02 Apr 2018, 16:03

yes thanks olivier gonna give a shot

User avatar
oli_lab  
Member
Posts: 1263
Location: Brittany, France
Contact:

Unread post by oli_lab » 02 Apr 2018, 17:35

Hi !
I reckon your question should have been placed in the sdk forum ;-)

this what I do in user module : for exemple here, I have a sample that is played at any speed,
if the speed is under normal speed, the cutoff of an external filter (i.e. another module) should be reduced, if the speed is above normal, nothing should be done. What I like in Usine is the "modular mindset", and I keep this in mind when making user modules, this is why the filter control output will be 0-1 and will be interfaced with a filter module via a mapper curve.
You'll find out that 20000kHz is way too high, 8000Hz is what you get with a Moog filter.


the code will be :
for (i = 0; i < numOfAudiotInsOuts; i++) {
temp2 = std::abs(m_speed) * 5.0f; // ok
temp2 = (temp2 + m_varispeed_rec - 1.0f); // tenir compte de la vitesse de la tete d'enregistrement//sdkTracePrecision(temp);
temp2 = constrain(temp2, 0.0f, 1.0f);
m_filterControl = temp2;
sdkSetEvtData(filterControl, temp2);
}
now, inside the same module, I implemented a one pole filter (LP) to cut the artefact when slowing the playing, there I needed to directly control the cutoff :

/////////// filtering
tapOutOld = tapout;
m_smoothcurrentCoeff = smooth(map(m_filterControl, 0.0f, 1.0f, 10.0f, 19000.0f), SMOOTH, m_smoothcurrentCoeff);
cutoffFinal = m_smoothcurrentCoeff * inv_samplerate;
computeCoeff();
//1 pole LP filter
audioBuffer1 = (tapout + audioBuffer0)*p - audioBuffer1[i] * f;
//gain compensation alla Moog
audioBuffer1[i] = k*(audioBuffer1[i] - (audioBuffer1[i] * audioBuffer1[i] * audioBuffer1[i]) * 0.1666666667f);
audioBuffer0[i] = tapout;
tapout = audioBuffer1[i];
sdkSetEvtArrayData(audioOutputs[i], j, tapout);
}
http://oli-lab.org

Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces

follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 02 Apr 2018, 19:58

found descent solution by waiting that ll do the job..
the problem i face using pow/coeff based functions (wich i think the the mapper is using too internally) is that while they are good and cpu more efficient, and doing the job for load of cases, they remain approximations, i really needed the 'real' way log frequencies behave for several case where i need the precise math output.
for ex if i plot the 'real' log behaviour, (fader01, output 20-20k) (blue-black curves) and a coeff based approximation, here using pow(x,5) (red curve) , it is a not bad approximation globally,
but if we look closer, zooming x and x axis, for the first part of the fader 0..0.33, it is really off 'tuning', its too low to raise, at 0.25 its only delivering 30 Hz when it should be more around 110 Hz so thats nearly 2 octaves off.. so was really looking for the inverse fonction of that exp(log(min_Hz) + (inval * (log(max_Hz) - log(min_Hz)))); that kill my brain^^
Image

in case some would need too, the best i got for now as the invert is:

log2(Hz/ min_Hz) / log2(max_Hz / min_Hz);

but if there is better optimized im taking

User avatar
oli_lab  
Member
Posts: 1263
Location: Brittany, France
Contact:

Unread post by oli_lab » 02 Apr 2018, 23:16

good on you 23fx23 !
Now we have a matter for the "suggestions and improvement" forum !
we need an extra mode in the mapper curve module, don't we ?
:)

by the way, the black g(x) is a pretty good approximation. but it looks like pow() is slower than exp() so the f(x) is the one to go.

"log2(Hz/ min_Hz) / log2(max_Hz / min_Hz);"
do you mean Log10 ? as it is working wonder in usine when doing
log10(Hz/ min_Hz) / log10(max_Hz / min_Hz);

very interesting indeed !

cheers
http://oli-lab.org

Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces

follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 03 Apr 2018, 00:53

haha yeah i should suggest that as an extra curve template indeed, lt *could* be useful. it is somehow kinda what the notes to frequency does but if we could adapt for wanted ranges in out would be more modular,
yes G(x) was in fact math correct but expressing in octaves, like 20Hz + 10 octaves = 20480 Hz wich makes it more complex if need to specify min-max of arbitrary hertz

23fx23
Member
Posts: 2545
Contact:

Unread post by 23fx23 » 03 Apr 2018, 01:03

ho sorry i didn't see your edit before answering, in the code i was using log2, binary log
http://en.cppreference.com/w/cpp/numeric/math/log2

but maybe it can work too with log10, didn't try yet, and maybe there is and even simpler formula^^

Post Reply

Who is online

Users browsing this forum: No registered users and 69 guests