Log to Linear- any math head help
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!
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!
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.
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
Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces
follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social
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]
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]
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
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
Olivier Sens
www.brainmodular.com
www.brainmodular.com
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);
}
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
Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces
follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social
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^^

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
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^^

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
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
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
Win11 Ryzen9/32GB RAM - RME MADIFACE - SSL alpha link 4-16 - OSC capable interfaces
follow OLI_LAB adventures on Mastodon
@olivar_premier@mastodon.social
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
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
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^^
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^^
Who is online
Users browsing this forum: No registered users and 78 guests
