feat(waterfall): палитры Inferno/Turbo + gamma, разрешение до 4096, HiDPI

- SPECTRUM_PIXELS 1024→4096 + настройка display_pixels (лимит точек
  анализатора, SetDisplayResLimit); web-зеркало остаётся 1024 —
  max-децимация в SnapshotPixels
- палитры водопада Classic/Inferno/Turbo + регулятор gamma (в LUT),
  настройки wf_palette/wf_gamma, страница Waterfall → группа Rendering
- GL-водопад переведён на общий LUT/AGC-уровни базового класса
  (убраны дубли ColorForDB/UpdateLevels)
- явные glViewport в GL-вьюхах умножаются на PixelScale (HiDPI),
  текстура водопада — в физической ширине

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 16:11:58 +03:00
co-authored by Claude Fable 5
parent 4733ddab58
commit 092a202f5f
10 changed files with 397 additions and 263 deletions
+62
View File
@@ -47,6 +47,8 @@ type
SpecAvgMode: Integer; SpecAvgTimeMS: Double) of object;
TOnWaterfallParamChange = procedure(WfDetector, WfAvgMode: Integer;
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double) of object;
TOnWfRenderChange = procedure(Palette: Integer; Gamma: Double;
ResLimit: Integer) of object;
TOnGridParamChange = procedure(RefLevel, Range, GridStep: Double) of object;
TOnAudioDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
TOnAudioInDevChange = procedure(DevIndex: Integer; const DevName: string) of object;
@@ -119,6 +121,9 @@ type
FWfAGCOffset: TFlatFloatSpinEdit;
FChkWfAGC: TFlatCheckBox;
FChkWfNF: TFlatCheckBox;
FCmbWfPalette: TFlatComboBox;
FWfGamma: TFlatFloatSpinEdit;
FCmbWfRes: TFlatComboBox;
FEdRefLevel: TFlatEdit;
FEdRange: TFlatEdit;
FCmbGridStep: TFlatComboBox;
@@ -289,6 +294,7 @@ type
FOnWebSettingsChange: TOnWebSettingsChange;
FOnDisplayChange: TOnDisplayParamChange;
FOnWaterfallChange: TOnWaterfallParamChange;
FOnWfRenderChange: TOnWfRenderChange;
FOnGridChange: TOnGridParamChange;
FOnAudioDevChange: TOnAudioDevChange;
FOnAudioInDevChange: TOnAudioInDevChange;
@@ -378,6 +384,8 @@ type
procedure FireDisplayChange;
procedure FireWaterfallChange;
procedure FireWfRenderChange;
procedure OnWfRenderCtlChange(Sender: TObject);
procedure FireGridChange;
function GetSpecAvgTimeMS: Double;
@@ -423,6 +431,7 @@ type
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
procedure LoadXvtrSettings(const X: TXvtrSettings);
procedure LoadWfAGCNF(AGC, NF: Boolean);
procedure LoadWfRender(Palette: Integer; Gamma: Double; ResLimit: Integer);
procedure LoadADCSettings(Dither, Random: Boolean);
procedure LoadWebSettings(Enabled: Boolean; Port: Integer;
const BindAddr, User, Pass: string);
@@ -435,6 +444,7 @@ type
property OnVHFCalChange: TOnVHFCalChange read FOnVHFCalChange write FOnVHFCalChange;
property OnDisplayChange: TOnDisplayParamChange read FOnDisplayChange write FOnDisplayChange;
property OnWaterfallChange: TOnWaterfallParamChange read FOnWaterfallChange write FOnWaterfallChange;
property OnWfRenderChange: TOnWfRenderChange read FOnWfRenderChange write FOnWfRenderChange;
property OnGridChange: TOnGridParamChange read FOnGridChange write FOnGridChange;
property OnAudioDevChange: TOnAudioDevChange read FOnAudioDevChange write FOnAudioDevChange;
property OnAudioInDevChange: TOnAudioInDevChange read FOnAudioInDevChange write FOnAudioInDevChange;
@@ -492,6 +502,10 @@ const
GRID_STEPS: array[0..4] of Double = (5.0, 10.0, 20.0, 30.0, 40.0);
GRID_STEP_NAMES: array[0..4] of string = ('5 dB','10 dB','20 dB','30 dB','40 dB');
WF_PALETTE_NAMES: array[0..2] of string = ('Classic', 'Inferno', 'Turbo');
DISPLAY_RES_VALUES: array[0..2] of Integer = (1024, 2048, 4096);
DISPLAY_RES_NAMES: array[0..2] of string = ('1024 px', '2048 px', '4096 px');
FPS_VALUES: array[0..12] of Integer = (5, 10, 15, 20, 25, 30, 40, 50, 60, 75, 80, 90, 100);
FPS_NAMES: array[0..12] of string = ('5 fps','10 fps','15 fps','20 fps','25 fps','30 fps',
'40 fps','50 fps','60 fps','75 fps','80 fps','90 fps','100 fps');
@@ -1093,6 +1107,19 @@ begin
FChkWfNF.Font.Name := UI_FONT;
FChkWfNF.Font.Size := 9;
FChkWfNF.OnChange := OnWfAGCNFChkChange;
Grp := MakeGroupPanel(FPageWaterfall, 'Rendering', MARGIN, 614, 650, 170);
MakeLbl(Grp, 'Palette:', PAD, R1 + 5, LW);
FCmbWfPalette := MakeCombo(Grp, CX, R1, CMB_W, OnWfRenderCtlChange);
for i := 0 to High(WF_PALETTE_NAMES) do FCmbWfPalette.Items.Add(WF_PALETTE_NAMES[i]);
FCmbWfPalette.ItemIndex := 0;
MakeLbl(Grp, 'Gamma:', PAD, R1 + STEP + 5, LW);
FWfGamma := MkFloat(CX, R1 + STEP, SPW, 1.0, 0.3, 3.0, 0.05, OnWfRenderCtlChange);
FWfGamma.DecimalPlaces := 2;
MakeLbl(Grp, 'Resolution:', PAD, R1 + 2 * STEP + 5, LW);
FCmbWfRes := MakeCombo(Grp, CX, R1 + 2 * STEP, 130, OnWfRenderCtlChange);
for i := 0 to High(DISPLAY_RES_NAMES) do FCmbWfRes.Items.Add(DISPLAY_RES_NAMES[i]);
FCmbWfRes.ItemIndex := High(DISPLAY_RES_NAMES);
end;
// ---------------------------------------------------------------------------
@@ -2310,6 +2337,41 @@ begin
GetWfAGCOffset);
end;
procedure TSettingsForm.FireWfRenderChange;
var
ResV: Integer;
begin
if FLoading then Exit;
if not Assigned(FOnWfRenderChange) then Exit;
if (FCmbWfRes.ItemIndex >= 0) and (FCmbWfRes.ItemIndex <= High(DISPLAY_RES_VALUES)) then
ResV := DISPLAY_RES_VALUES[FCmbWfRes.ItemIndex]
else
ResV := DISPLAY_RES_VALUES[High(DISPLAY_RES_VALUES)];
FOnWfRenderChange(Max(0, FCmbWfPalette.ItemIndex), FWfGamma.Value, ResV);
end;
procedure TSettingsForm.OnWfRenderCtlChange(Sender: TObject);
begin FireWfRenderChange; end;
procedure TSettingsForm.LoadWfRender(Palette: Integer; Gamma: Double; ResLimit: Integer);
var i: Integer;
begin
FLoading := True;
try
if (Palette >= 0) and (Palette < FCmbWfPalette.Items.Count) then
FCmbWfPalette.ItemIndex := Palette
else
FCmbWfPalette.ItemIndex := 0;
FWfGamma.Value := EnsureRange(Gamma, 0.3, 3.0);
FCmbWfRes.ItemIndex := High(DISPLAY_RES_VALUES);
for i := 0 to High(DISPLAY_RES_VALUES) do
if DISPLAY_RES_VALUES[i] = ResLimit then
begin FCmbWfRes.ItemIndex := i; Break; end;
finally
FLoading := False;
end;
end;
procedure TSettingsForm.FireGridChange;
begin
if FLoading then Exit;