mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-26 04:47:35 +00:00
Render wideband spectrum with OpenGL primitives
This commit is contained in:
+142
-28
@@ -30,6 +30,7 @@ type
|
|||||||
FPoints: array of TPoint;
|
FPoints: array of TPoint;
|
||||||
FGLTex: GLuint;
|
FGLTex: GLuint;
|
||||||
FDirty: Boolean;
|
FDirty: Boolean;
|
||||||
|
FGLBackgroundDirty: Boolean;
|
||||||
FSampleRateHz: Double;
|
FSampleRateHz: Double;
|
||||||
FRefLevel: Double;
|
FRefLevel: Double;
|
||||||
FRange: Double;
|
FRange: Double;
|
||||||
@@ -51,10 +52,14 @@ type
|
|||||||
function ComputeSpectrumWDSP(const Samples: array of SmallInt;
|
function ComputeSpectrumWDSP(const Samples: array of SmallInt;
|
||||||
Count: Integer): Boolean;
|
Count: Integer): Boolean;
|
||||||
procedure CloseWDSPAnalyzer;
|
procedure CloseWDSPAnalyzer;
|
||||||
procedure DrawCPU(W, H: Integer);
|
function BuildSpectrumPoints(PlotW, H: Integer): Boolean;
|
||||||
|
procedure DrawCPU(W, H: Integer; IncludeSpectrum: Boolean = True);
|
||||||
procedure PaintCPU(C: TCanvas);
|
procedure PaintCPU(C: TCanvas);
|
||||||
procedure PaintGL(C: TOpenGLControl);
|
procedure PaintGL(C: TOpenGLControl);
|
||||||
procedure ColorToGL(AColor: TColor; out R, G, B: GLFloat);
|
procedure ColorToGL(AColor: TColor; out R, G, B: GLFloat);
|
||||||
|
procedure DrawSpectrumGL(PlotW, H: Integer);
|
||||||
|
procedure DrawHamBandGL(PlotW, H: Integer; F1, F2: Double; AColor: TColor);
|
||||||
|
procedure DrawHamBandsGL(PlotW, H: Integer);
|
||||||
function SourceFreqToBin(FreqHz: Double; BinCount: Integer): Integer;
|
function SourceFreqToBin(FreqHz: Double; BinCount: Integer): Integer;
|
||||||
function FreqToX(FreqHz: Double; W: Integer): Integer;
|
function FreqToX(FreqHz: Double; W: Integer): Integer;
|
||||||
function GridStepHz(W: Integer): Double;
|
function GridStepHz(W: Integer): Double;
|
||||||
@@ -123,6 +128,7 @@ begin
|
|||||||
SetLength(FWDSPPixels, WB_WDSP_PIXELS);
|
SetLength(FWDSPPixels, WB_WDSP_PIXELS);
|
||||||
FGLTex := 0;
|
FGLTex := 0;
|
||||||
FDirty := True;
|
FDirty := True;
|
||||||
|
FGLBackgroundDirty := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TWidebandView.Destroy;
|
destructor TWidebandView.Destroy;
|
||||||
@@ -139,6 +145,7 @@ procedure TWidebandView.SetTheme(const T: TAppTheme);
|
|||||||
begin
|
begin
|
||||||
FTheme := T;
|
FTheme := T;
|
||||||
FDirty := True;
|
FDirty := True;
|
||||||
|
FGLBackgroundDirty := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWidebandView.SetSampleRateHz(AHz: Double);
|
procedure TWidebandView.SetSampleRateHz(AHz: Double);
|
||||||
@@ -180,6 +187,7 @@ begin
|
|||||||
FSourceStartHz := SourceStartHz;
|
FSourceStartHz := SourceStartHz;
|
||||||
FSourceEndHz := SourceEndHz;
|
FSourceEndHz := SourceEndHz;
|
||||||
FDirty := True;
|
FDirty := True;
|
||||||
|
FGLBackgroundDirty := True;
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -218,7 +226,10 @@ begin
|
|||||||
W := Max(1, W);
|
W := Max(1, W);
|
||||||
H := Max(1, H);
|
H := Max(1, H);
|
||||||
if (FBitmap.Width <> W) or (FBitmap.Height <> H) then
|
if (FBitmap.Width <> W) or (FBitmap.Height <> H) then
|
||||||
|
begin
|
||||||
FBitmap.SetSize(W, H);
|
FBitmap.SetSize(W, H);
|
||||||
|
FGLBackgroundDirty := True;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWidebandView.SetBitmapSize(W, H: Integer);
|
procedure TWidebandView.SetBitmapSize(W, H: Integer);
|
||||||
@@ -560,11 +571,42 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWidebandView.DrawCPU(W, H: Integer);
|
function TWidebandView.BuildSpectrumPoints(PlotW, H: Integer): Boolean;
|
||||||
|
var
|
||||||
|
X, Y, Bin, N, TopH: Integer;
|
||||||
|
DB, InvRange, SrcHz, Nyq: Double;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
N := Length(FData);
|
||||||
|
if (N <= 1) or (PlotW <= 0) or (H <= 0) then Exit;
|
||||||
|
TopH := Max(1, H - 1);
|
||||||
|
InvRange := 1.0 / Max(1.0, FRange);
|
||||||
|
SetLength(FPoints, PlotW);
|
||||||
|
Nyq := FSampleRateHz * 0.5;
|
||||||
|
if Nyq <= 0.0 then Nyq := 61440000.0;
|
||||||
|
for X := 0 to PlotW - 1 do
|
||||||
|
begin
|
||||||
|
SrcHz := FSourceStartHz +
|
||||||
|
X / Max(1, PlotW - 1) * (FSourceEndHz - FSourceStartHz);
|
||||||
|
if (SrcHz < 0.0) or (SrcHz > Nyq) then
|
||||||
|
DB := -200.0
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Bin := SourceFreqToBin(SrcHz, N);
|
||||||
|
DB := FData[Bin];
|
||||||
|
end;
|
||||||
|
Y := Round((FRefLevel - DB) * InvRange * TopH);
|
||||||
|
Y := EnsureRange(Y, 1, TopH);
|
||||||
|
FPoints[X] := Point(X, Y);
|
||||||
|
end;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWidebandView.DrawCPU(W, H: Integer; IncludeSpectrum: Boolean);
|
||||||
var
|
var
|
||||||
C: TCanvas;
|
C: TCanvas;
|
||||||
X, Y, Bin, N, TopH, PlotW, ScaleX: Integer;
|
X, Y, TopH, PlotW, ScaleX: Integer;
|
||||||
DB, DBMin, InvRange, StepHz, FreqHz, SrcHz, Nyq: Double;
|
DB, DBMin, InvRange, StepHz, FreqHz: Double;
|
||||||
begin
|
begin
|
||||||
EnsureBitmap(W, H);
|
EnsureBitmap(W, H);
|
||||||
C := FBitmap.Canvas;
|
C := FBitmap.Canvas;
|
||||||
@@ -614,27 +656,8 @@ begin
|
|||||||
DB := DB - 20.0;
|
DB := DB - 20.0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
N := Length(FData);
|
if IncludeSpectrum and BuildSpectrumPoints(PlotW, H) then
|
||||||
if N > 1 then
|
|
||||||
begin
|
begin
|
||||||
SetLength(FPoints, PlotW);
|
|
||||||
Nyq := FSampleRateHz * 0.5;
|
|
||||||
if Nyq <= 0.0 then Nyq := 61440000.0;
|
|
||||||
for X := 0 to PlotW - 1 do
|
|
||||||
begin
|
|
||||||
SrcHz := FSourceStartHz +
|
|
||||||
X / Max(1, PlotW - 1) * (FSourceEndHz - FSourceStartHz);
|
|
||||||
if (SrcHz < 0.0) or (SrcHz > Nyq) then
|
|
||||||
DB := -200.0
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Bin := SourceFreqToBin(SrcHz, N);
|
|
||||||
DB := FData[Bin];
|
|
||||||
end;
|
|
||||||
Y := Round((FRefLevel - DB) * InvRange * TopH);
|
|
||||||
Y := EnsureRange(Y, 1, TopH);
|
|
||||||
FPoints[X] := Point(X, Y);
|
|
||||||
end;
|
|
||||||
if FFillSpectrum then
|
if FFillSpectrum then
|
||||||
DrawSpectrumGradient(FPoints, PlotW, H);
|
DrawSpectrumGradient(FPoints, PlotW, H);
|
||||||
C.Pen.Color := TColor($0040FF80);
|
C.Pen.Color := TColor($0040FF80);
|
||||||
@@ -645,7 +668,10 @@ begin
|
|||||||
|
|
||||||
C.Font.Color := FTheme.Text;
|
C.Font.Color := FTheme.Text;
|
||||||
C.TextOut(6, 4, 'Wideband');
|
C.TextOut(6, 4, 'Wideband');
|
||||||
FDirty := False;
|
if IncludeSpectrum then
|
||||||
|
FDirty := False
|
||||||
|
else
|
||||||
|
FGLBackgroundDirty := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWidebandView.DrawRuler;
|
procedure TWidebandView.DrawRuler;
|
||||||
@@ -716,6 +742,90 @@ begin
|
|||||||
B := ((AColor shr 16) and $FF) / 255.0;
|
B := ((AColor shr 16) and $FF) / 255.0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TWidebandView.DrawSpectrumGL(PlotW, H: Integer);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
R, G, B: GLFloat;
|
||||||
|
ATop, ABot: GLFloat;
|
||||||
|
begin
|
||||||
|
if not BuildSpectrumPoints(PlotW, H) then Exit;
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
if FFillSpectrum then
|
||||||
|
begin
|
||||||
|
R := FTheme.SpecGradR / 255.0;
|
||||||
|
G := FTheme.SpecGradG / 255.0;
|
||||||
|
B := FTheme.SpecGradB / 255.0;
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
for I := 0 to PlotW - 1 do
|
||||||
|
begin
|
||||||
|
ATop := 0.44;
|
||||||
|
ABot := 0.02;
|
||||||
|
glColor4f(R, G, B, ATop);
|
||||||
|
glVertex2f(FPoints[I].X, H - FPoints[I].Y);
|
||||||
|
glColor4f(R, G, B, ABot);
|
||||||
|
glVertex2f(FPoints[I].X, 0);
|
||||||
|
end;
|
||||||
|
glEnd;
|
||||||
|
end;
|
||||||
|
|
||||||
|
glColor4f(0.25, 1.0, 0.50, 1.0);
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
for I := 0 to PlotW - 1 do
|
||||||
|
glVertex2f(FPoints[I].X, H - FPoints[I].Y);
|
||||||
|
glEnd;
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWidebandView.DrawHamBandGL(PlotW, H: Integer; F1, F2: Double;
|
||||||
|
AColor: TColor);
|
||||||
|
var
|
||||||
|
X1, X2: Integer;
|
||||||
|
R, G, B: GLFloat;
|
||||||
|
begin
|
||||||
|
X1 := FreqToX(F1, PlotW);
|
||||||
|
X2 := FreqToX(F2, PlotW);
|
||||||
|
if (X2 <= 0) or (X1 >= PlotW) then Exit;
|
||||||
|
X1 := EnsureRange(X1, 0, PlotW - 1);
|
||||||
|
X2 := EnsureRange(X2, 0, PlotW - 1);
|
||||||
|
if X2 <= X1 then Exit;
|
||||||
|
ColorToGL(AColor, R, G, B);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glColor4f(R, G, B, 0.34);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex2f(X1, 0);
|
||||||
|
glVertex2f(X2 + 1, 0);
|
||||||
|
glVertex2f(X2 + 1, H);
|
||||||
|
glVertex2f(X1, H);
|
||||||
|
glEnd;
|
||||||
|
glColor4f(R, G, B, 0.46);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex2f(X1, H - Min(H, 15));
|
||||||
|
glVertex2f(X2 + 1, H - Min(H, 15));
|
||||||
|
glVertex2f(X2 + 1, H);
|
||||||
|
glVertex2f(X1, H);
|
||||||
|
glEnd;
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWidebandView.DrawHamBandsGL(PlotW, H: Integer);
|
||||||
|
begin
|
||||||
|
DrawHamBandGL(PlotW, H, 1810000, 2000000, TColor($003B8F5A));
|
||||||
|
DrawHamBandGL(PlotW, H, 3500000, 3800000, TColor($004D8F3B));
|
||||||
|
DrawHamBandGL(PlotW, H, 5258500, 5403500, TColor($00688F3B));
|
||||||
|
DrawHamBandGL(PlotW, H, 7000000, 7300000, TColor($00808D34));
|
||||||
|
DrawHamBandGL(PlotW, H, 10100000, 10150000, TColor($008F7834));
|
||||||
|
DrawHamBandGL(PlotW, H, 14000000, 14350000, TColor($008F5D34));
|
||||||
|
DrawHamBandGL(PlotW, H, 18068000, 18168000, TColor($008F4934));
|
||||||
|
DrawHamBandGL(PlotW, H, 21000000, 21450000, TColor($008C3E58));
|
||||||
|
DrawHamBandGL(PlotW, H, 24890000, 24990000, TColor($007A3E8C));
|
||||||
|
DrawHamBandGL(PlotW, H, 28000000, 29700000, TColor($005B4B9A));
|
||||||
|
DrawHamBandGL(PlotW, H, 50000000, 51990000, TColor($003C729A));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TWidebandView.UploadBitmapToGL;
|
procedure TWidebandView.UploadBitmapToGL;
|
||||||
var
|
var
|
||||||
X, Y, I: Integer;
|
X, Y, I: Integer;
|
||||||
@@ -767,9 +877,9 @@ begin
|
|||||||
SetBitmapSize(W, H);
|
SetBitmapSize(W, H);
|
||||||
NeedUpload := True;
|
NeedUpload := True;
|
||||||
end;
|
end;
|
||||||
if FDirty then
|
if FGLBackgroundDirty then
|
||||||
begin
|
begin
|
||||||
DrawCPU(W, H);
|
DrawCPU(W, H, False);
|
||||||
NeedUpload := True;
|
NeedUpload := True;
|
||||||
end;
|
end;
|
||||||
if FGLTex = 0 then
|
if FGLTex = 0 then
|
||||||
@@ -797,9 +907,13 @@ begin
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
PlotW := Max(1, W - WB_DB_SCALE_W);
|
||||||
|
DrawSpectrumGL(PlotW, H);
|
||||||
|
DrawHamBandsGL(PlotW, H);
|
||||||
|
FDirty := False;
|
||||||
|
|
||||||
if (FMarkerHz >= FViewStartHz) and (FMarkerHz <= FViewEndHz) then
|
if (FMarkerHz >= FViewStartHz) and (FMarkerHz <= FViewEndHz) then
|
||||||
begin
|
begin
|
||||||
PlotW := Max(1, W - WB_DB_SCALE_W);
|
|
||||||
X := EnsureRange(FreqToX(FMarkerHz, PlotW), 0, PlotW - 1);
|
X := EnsureRange(FreqToX(FMarkerHz, PlotW), 0, PlotW - 1);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|||||||
Reference in New Issue
Block a user