The code below draws a logarithmic grid with DrawGrid(). It seems the vertical lines are ok. When I use the function SetPositionHzValue() the resulting position seems ok (it uses the same logic as the DrawGrid() and seems to match the grid). But how to convert this 0 - 1.0 normalized value, that uses the display width linearly, to an actual Hz value? Why is the function GetPositionsHzValue() wrong?
To complicate things, the display has a start frequency (20 Hz in this case) and an end frequency (44100 Hz in this case).
procedure TAudioBezierCurves.DrawGrid(Bitmap32: TBitmap32);
var
GridPosition: Integer;
GridPositionF: Double;
i: Integer;
Base: Double;
LogOffsetValue: Double;
LogMaxValue: Double;
begin
GridPosition := 0;
Base := 1;
if GridFrequencyMin = 0 then begin
LogOffsetValue := 0;
end else begin
LogOffsetValue := Log10(GridFrequencyMin);
end;
LogMaxValue := Log10(GridFrequencyMax) - LogOffsetValue;
repeat
for i := 2 to 10 do begin
if Base * i < GridFrequencyMin then begin
Continue;
end;
//* This gives the % value relative to the total scale
GridPositionF := (Log10(Base * i) - LogOffsetValue) / LogMaxValue;
GridPositionF := GridPositionF * Bitmap32.Width;
GridPosition := Trunc(GridPositionF);
Bitmap32.VertLineS(GridPosition, 0, Bitmap32.Height - 1, GridColor);
end;
Base := Base * 10;
until GridPosition > Bitmap32.Width;
end;
procedure TAudioBezierCurve.SetPositionHzValue(AValue: Double);
var
LogOffsetValue: Double;
LogMaxValue: Double;
begin
if AValue = 0 then begin
Self.Position := 0;
end else begin
if Parent.GridFrequencyMin = 0 then begin
LogOffsetValue := 0;
end else begin
LogOffsetValue := Log10(Parent.GridFrequencyMin);
end;
LogMaxValue := Log10(Parent.GridFrequencyMax) - LogOffsetValue;
//* This gives the % value relative to the total scale
AValue := (Log10(AValue) - LogOffsetValue) / LogMaxValue;
Self.Position := AValue;
end;
end;
function TAudioBezierCurve.GetPositionsHzValue: Double;
var
AValue: Double;
begin
AValue := Self.Position;
AValue := Power(AValue, 2);
Result := AValue * (Parent.GridFrequencyMax);
Result := Result - (AValue * Parent.GridFrequencyMin) Parent.GridFrequencyMin;
end;
EDIT: Ok, almost ok now. So it seems the correct function is:
AValue := Power(AValue, 10);
But still not perfect. Changing the display range to min. 0 to 44100, for simplicity, results that setting to the upper value 44100 is ok, the function GetPositionsHzValue() report 41100. But calling setting the position value to 20, GetPositionsHzValue() reports 0. Trying to decrement the position all is fine until 44085, but 44084 value is reported as 44085 and this difference increases with smaller values. Going from lower values, it's 0 until 39, 40 results 1.
CodePudding user response:
In function GetPositionsHzValue, line "AValue := Power(AValue, 2);" where does the value of "AValue" come from?
Maybe you should do something like you did in "SetPositionHzValue(AValue: Double);". AValue should be a parameter, not a local variable.
CodePudding user response:
Found the solution, it should be:
function TAudioBezierCurve.GetPositionsHzValue: Double;
var
AValue: Double;
begin
AValue := Self.Position;
AValue := AValue * Log10(Parent.GridFrequencyMax) (Log10(Parent.GridFrequencyMin) * (1 - AValue)); //* Results "min." at 0
Result := Power(10, AValue);
end;