How to draw frequency separation in a parametric equalizer - math

I'm trying to do something similar to this parametric equalizer, in regards to the frequency axis only, i.e. the values along the middle line:
This appears to be the standard format for equalizers but I can't work out the formula to do this.
i.e. The values for the first set of frequency lines are 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
but the spacing reduces as you go up to 100
From there, it goes 100, 200, 300, 400, 500.. to 1000 and the spacing resets at 100 then reduces at each interval up to 1000
The same pattern repeats to the max, which in this case is 20,000
How is this done? Is it logarithmic?

With the help of this video I was able to work out a formula to plot the frequency axis as a logarithmic scale.
int factor = 10;
for(int i = 10; i <= FREQ_MAX; i+=factor)
{
fx = (float) ((float) (Math.log10(i) - Math.log10(PEQ.FREQ_MIN))/(Math.log10(PEQ.FREQ_MAX)-Math.log10(PEQ.FREQ_MIN)) * getMaxCanvasWidth());
canvas.drawLine(fx, 0, fx, getHeight(), paintLinesThick);
if(isDisplayedFreq(i))
{
paintText.setTextAlign(Paint.Align.LEFT);
canvas.drawText(getFreqAsFormattedLabel(i), fx + (getMaxCanvasWidth() / 120f), (getHeight() / 2f) + (getHeight() / 50f), paintText);
}
if(i >= (factor*10))
{
factor *= 10;
}
}

Related

Math problem trying to make a progressbar in project zomboid

I am making a mod for project Zomboid and I cant seem to figure out a math problem, so the value I am getting ranges from 0 to 1 and I want my progress bar to start at the max width and then descend as the value is increasing.
The first one was easy I got a value between a 100 and 0 so how do this with a value starting at 0?
I tried searching this on google but I am really bad at math and could not find an answer.
function panel:render()
self:drawRectBorder(30, 30, self:getWidth() - 1, 50, 1.0, 1.0, 1.0, 1.0);
--print((bt_core.player:getBodyDamage():getOverallBodyHealth() / 100) * self:getWidth());
self:drawRect(31, 31, (bt_core.player:getBodyDamage():getOverallBodyHealth() / 100) * self:getWidth() - 3, 48, 1, 0, 0, 1);
self:drawRectBorder(30, 110, self:getWidth() - 1, 50, 1.0, 1.0, 1.0, 1.0);
print(bt_core.player:getStats():getFatigue());
if bt_core.player:getStats():getFatigue() == 0 then
self:drawRect(31, 111, self:getWidth() - 3 , 48, 1, 0, 0, 1);
else
self:drawRect(32, 111,bt_core.player:getStats():getFatigue() / (self:getWidth() - 3) , 48, 1, 0, 0, 1);
end
end
To get variable in range 100..0 from variable in range 0..1, you can use y = 100 - x*100
So you have a value 0..1 and you want to map it to 100..0.
Multiplying your value with 100 gives you 0..100.
To invert this you subtract that from 100. 100-0 is 100, 100-100 is 0...
local newVal = 100 - val * 100
or
local newVal = 100 * (1-val)

What is the fast way to constraint an float angle in a range?

For example, I have an angle with value 350 degree, and I want to constraint it in a range with max positive offset of 30 and a max negative offset of 40.
As a result, the angle value should be in a range of (310, 360) and (0, 20). If the computed angle value is 304, the angle value should be constrainted to 310, and if the computed angle value is 30, the angle value should be constrainted to 20.
I have already implemented a method, but it's not efficient enough(Most of the effort is to solve the issue when the angle value is near 360~0 ). What is the fast way to achieve this please?
Function:
// All values are in the range [0.0f, 360.0f]
// Output: the angle value after constraint.
float _KeepAngleValueBetween(float originalAngle, float currentAngle, float MaxPositiveOffset, float MaxNegativeOffset).
For example:
KeepAngleValueBetween(350.0f, 302.0f, 30.0f, 40.0f)
result: 310.0f
KeepAngleValueBetween(350.0f, 40.0f, 30.0f, 40.0f)
result: 20.0f
KeepAngleValueBetween(140.0f, 190.0f, 45.0f, 40.0f)
result: 185.0f
I couldn't come up with a solution that doesn't use if. Anyway, I handle the problem around 0/360 by translating the values before checking if currentAngle is in the desired range.
Pseudo code (Ok, it's C. It is also valid Java. And C++.):
float _KeepAngleValueBetween(float originalAngle, float currentAngle, float MaxPositiveOffset, float MaxNegativeOffset) {
// Translate so that the undesirable range starts at 0.
float translateBy = originalAngle + MaxPositiveOffset;
float result = currentAngle - translateBy + 720f;
result -= ((int)result/360) * 360;
float undesiredRange = 360f - MaxNegativeOffset - MaxPositiveOffset;
if (result >= undesiredRange) {
// No adjustment needed
return currentAngle;
}
// Perform adjustment
if (result * 2 < undesiredRange) {
// Return the upper limit because it is closer.
result = currentAngle + MaxPositiveOffset;
} else {
// Return the lower limit
result = currentAngle - MaxNegativeOffset + 360f;
}
// Translate to the range 0-360.
result -= ((int)result)/360 * 360;
return result;
}

how to multiply Polynomials coefficients

Hello i want to know the idea of multiplying two Polynomials this function
it used to multiply the two Polynomials
i want to know what is happened in this function to the coefficients in this code
mul(poly((10, 20, 30)), poly((1, 2, 3))).coefs == (10, 40, 100, 120, 90)
how did (10, 40, 100, 120, 90) come out ?
mul() stands for the multiplying function
poly() stands for the Polynomials function
When you multiply polynomial A of Nth power with polynomial B by Mth power, you'll get resulting polynomial C of (N+M) power, which has N+M+1 coefficients. Kth coefficient of result:
C[k]{k=0..N+M} = Sum(A[i] * B[k - i]){find proper range for i}
example for N = 3 and M = 3:
C[5] = A[3]*B[2] + A[2]*B[3]
I hope that implementation of such a simple formula with cycle is not problem in any programming language.
Lets assume your coefficients are stored in two an arrays A[], B[] in with coeff[0] being the zero-th degree term and store the result in C.
// degree of result
int deg=A.length+B.length-2;
int C[] = new int[deg+1];
// initialise to zero
for(i=0;i<=deg;++i) {
C[i]=0;
}
for(i=0;i<A.length;++i) {
for(j=0;j<B.length;++j) {
C[i+j] += A[i] * B[j];
}
}

Linearly Scale Between RGB values

Is there an easy mathematical relationship for scaling between two distinct RGB (3-tuple) values. Say I want to scale from red to green (1,0,0) to (0,1,0). Or say the values are more complex how do I linearly scale from (22,183,19) to (199, 201, 3)?
Here's a simple algorithm that will generate an array of RGB tuples that represent a linear transition. I noticed you had javascript tags in your profile, so I went with that. I chose to use the max distance between any pairs to determine the number of steps rather than using a fixed number of steps (but obviously that's trivial to change).
function generateLinearTransition(start, end) {
var rDiff = end.r - start.r;
var gDiff = end.g - start.g;
var bDiff = end.b - start.b;
var steps = Math.max(Math.abs(rDiff), Math.abs(gDiff), Math.abs(bDiff));
var rStepSize = rDiff / steps;
var gStepSize = gDiff / steps;
var bStepSize = bDiff / steps;
var tuples = [start];
var current = start;
for (var i = 0; i < steps; i++) {
current = {
r: current.r + rStepSize,
g: current.g + gStepSize,
b: current.b + bStepSize,
};
tuples.push({
r: Math.floor(current.r),
g: Math.floor(current.g),
b: Math.floor(current.b)
});
}
tuples.push(end);
return tuples;
}
var a = {
r: 22,
g: 183,
b: 19
};
var b = {
r: 199,
g: 201,
b: 3
};
var results = generateLinearTransition(a, b);
for (var i = 0; i < results.length; i++) {
var current = results[i];
console.log("(" + current.r + "," + current.g + "," + current.b + ")");
}
As an aside, your example of (1,0,0) and (0,1,0) are both essentially black, so there won't be much transition there. If you used (255,0,0) (red) and (0,255,0) (green), respectively, you'd get a longer transition.
Here's a working example.
You could find the difference between each value in each tuple by substracting one from the other, divide each of those differences by the number of "steps" to get an incremental delta for each value, per step, and then at each step add that delta.
For example, to scale from (22, 183, 19) to (199, 201, 3) in, say, 4 steps:
199 - 22 = 177; 177 / 4 = 44.25
201 - 183 = 18; 18 / 4 = 4.5
3 - 19 = -16; -16 / 4 = -4
So at each step, you'd add 44.25 to the first value (r), 4.5 to the second value (g), and -4 to the third value (b). So you'd go from (22, 183, 19) to (66.25, 187.5, 15) to (110.5, 192, 11) to (154.75, 196.5, 7) to (199, 201, 3).
Basically, treat each component separately, and scale linearly from one to the other, and combine.

Math Function For Getting An Increasing/Decreasing Percentage

Is there a function or set of functions in php that will help me solve line 1 of this problem:
Noofdays factorial (for 5days) = 5+4+3+2+1
BasicValue = 200/ 15 =13.3
DailyDosage= Daynumber x basicValue
Decreasing dosage for 200 milligram prescription example: Day1 - 67, Day2 - 53, Day 3 - 40,Day 4 - 27, Day 5 - 13
Where 200 Needs to be a variable and NoofDays needs to be a variable.
1+2+...+n = n⋅(n+1)/2, if that's what you are asking.
Not really sure about what you are having problems with here. But the below seems to do what you want.
$currentDay = 4;
$noOfDays = 5;
$milligram = 200;
$basicValue = $milligram / array_sum(range($noOfDays, 1,-1));
$dailyDosage = round($currentDay * $basicValue);
factorial would be 5*4*3*2*1 = 120, not (sum) 5+4+3+2+1 = 15.
$Noofdays = 5;
$totalAmount = 200;
$dayThreeAmount = calculateDosage(3, $Noofdays, $totalAmount);
function calculateDosage($day, $totalDays, $totalAmount)
{
return ($totalAmount / ($totalDays * ($totalDays+1) / 2)) * ($totalDays - $day + 1);
}
I'm assuming sum is what you wanted...
EDIT: Doh, divide not multiply...

Resources