mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(display): скорость водопада с max-hold накоплением + MSAA спектра
- настройка Speed (wf_speed_div 1/2/4/8, Waterfall→Rendering): замедление накапливает кадры max-hold'ом в SetWaterfallData — короткие посылки (CW) не выпадают из строки; двойная децимация MainForm убрана (EffectiveWfInterval, CPU-путь не быстрее полукадровой) - настройка Anti-aliasing (spec_msaa 1/2/4/8, дефолт 4x, Spectrum→Rendering): MultiSampling на GL-контроле спектра; смена в рантайме пересоздаёт контекст → ResetGLCache обнуляет текстурные кэши без glDelete Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+44
-28
@@ -163,9 +163,6 @@ type
|
||||
// переехало в TRadioController (нужно headless-load в DoConnectDevice).
|
||||
// Снимок последнего кадра спектра/водопада для web переехал в TRadioController
|
||||
// (FSpectrumBuf/FWaterfallBuf) — нужен headless-демону.
|
||||
// Waterfall frame timing
|
||||
FWaterfallFrameInterval: Integer;
|
||||
FWaterfallFrameCounter: Integer;
|
||||
FAgcLineCounter: Integer;
|
||||
// ---- Splitter ----
|
||||
FSplitterDrag: Boolean;
|
||||
@@ -588,7 +585,9 @@ type
|
||||
procedure ApplyWaterfallParams(WfDet, WfAvgMode: Integer;
|
||||
WfAvgTimeMS, WfHigh, WfLow, WfAGCOffset: Double);
|
||||
procedure ApplyWfRenderParams(Palette: Integer; Gamma: Double;
|
||||
ResLimit: Integer);
|
||||
ResLimit, SpeedDiv: Integer);
|
||||
procedure ApplySpecMSAA(Samples: Integer);
|
||||
function EffectiveWfInterval: Integer;
|
||||
procedure ApplyWfAGCNF(WfAGC, WfNF: Boolean);
|
||||
procedure ApplyADCSettings(Dither, Random: Boolean);
|
||||
procedure ApplyWebSettings(Enabled: Boolean; Port: Integer;
|
||||
@@ -845,8 +844,6 @@ begin
|
||||
FController.FFMRptOffsetHz := RPT_DEFAULT_2M;
|
||||
FController.FFMRptAutoActive := False;
|
||||
FController.FFMCTCSSAutoActive := False;
|
||||
FWaterfallFrameInterval := 2;
|
||||
FWaterfallFrameCounter := 0;
|
||||
FController.FDevConnected := False;
|
||||
// Spectrum grid settings defaults
|
||||
FController.FSpecRefLevel := -20.0;
|
||||
@@ -1010,8 +1007,6 @@ begin
|
||||
// OpenGLContextEx (QOpenGLWidget-бэкенд) работает и в нативном Wayland,
|
||||
// старая X11-заглушка больше не нужна
|
||||
FUseOpenGLSpectrum := HasOpenGLSpectrumSwitch;
|
||||
if FUseOpenGLSpectrum then
|
||||
FWaterfallFrameInterval := 1;
|
||||
if FUseOpenGLSpectrum then
|
||||
FSpecView := TSpectrumViewOpenGL.Create
|
||||
else
|
||||
@@ -1037,7 +1032,7 @@ begin
|
||||
FSpecView.SpecGridStep := FController.FSpecGridStep;
|
||||
// TX overlay: ширина окна = TX_SAMPLE_RATE из движка (фикс 192k)
|
||||
FSpecView.TXSpanHz := WDSPEngine.TX_SAMPLE_RATE;
|
||||
FSpecView.WfFrameInterval := FWaterfallFrameInterval;
|
||||
FSpecView.WfFrameInterval := EffectiveWfInterval;
|
||||
FSpecView.PAMaxPower := FController.FPAMaxPower;
|
||||
FWidebandView := TWidebandView.Create;
|
||||
|
||||
@@ -1475,6 +1470,8 @@ begin
|
||||
FSpecView.WfAGCOffset := FController.FWfAGCOffset;
|
||||
FSpecView.WfPalette := FController.FWfPalette;
|
||||
FSpecView.WfGamma := FController.FWfGamma;
|
||||
FSpecView.WfFrameInterval := EffectiveWfInterval;
|
||||
ApplySpecMSAA(FController.FSpecMSAA);
|
||||
FSpecView.ResetWfAvgBuf;
|
||||
if Assigned(FWidebandView) then
|
||||
FWidebandView.SetFillSpectrum(FController.FWidebandFill);
|
||||
@@ -2211,6 +2208,7 @@ begin
|
||||
PbSpectrum := TOpenGLControl.Create(Self);
|
||||
TOpenGLControl(PbSpectrum).AutoResizeViewport := False;
|
||||
TOpenGLControl(PbSpectrum).DoubleBuffered := True;
|
||||
TOpenGLControl(PbSpectrum).MultiSampling := Max(1, FController.FSpecMSAA);
|
||||
TOpenGLControl(PbSpectrum).OnPaint := FSpecView.PaintSpectrum;
|
||||
TOpenGLControl(PbSpectrum).OnMouseDown := PbSpectrumMouseDown;
|
||||
TOpenGLControl(PbSpectrum).OnDblClick := PbSpectrumDblClick;
|
||||
@@ -6400,16 +6398,12 @@ end;
|
||||
|
||||
procedure TMainForm.OnWaterfallReady(const Pixels: array of Single;
|
||||
Count: Integer);
|
||||
// Подписчик на FController.OnWaterfallData — рендер с децимацией скорости
|
||||
// прокрутки (FWaterfallFrameInterval). Web получает каждый кадр (в контроллере).
|
||||
// Подписчик на FController.OnWaterfallData. Каждый кадр уходит во view —
|
||||
// замедление/накопление (max-hold) делает сам TWaterfallView по
|
||||
// WfFrameInterval; рендер дёргаем только когда view собрал строку.
|
||||
begin
|
||||
Inc(FWaterfallFrameCounter);
|
||||
if FWaterfallFrameCounter >= Max(1, FWaterfallFrameInterval) then
|
||||
begin
|
||||
FWaterfallFrameCounter := 0;
|
||||
FSpecView.SetWaterfallData(Pixels, Count);
|
||||
FWaterfallDirty := True;
|
||||
end;
|
||||
FSpecView.SetWaterfallData(Pixels, Count);
|
||||
if FSpecView.WaterfallDirty then FWaterfallDirty := True;
|
||||
end;
|
||||
|
||||
// ===========================================================================
|
||||
@@ -6442,19 +6436,37 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyWfRenderParams(Palette: Integer; Gamma: Double;
|
||||
ResLimit: Integer);
|
||||
ResLimit, SpeedDiv: Integer);
|
||||
begin
|
||||
FController.FWfPalette := Palette;
|
||||
FController.FWfGamma := Gamma;
|
||||
FController.FDisplayPixels := ResLimit;
|
||||
FController.FWfSpeedDiv := SpeedDiv;
|
||||
FSpecView.WfPalette := Palette;
|
||||
FSpecView.WfGamma := Gamma;
|
||||
FSpecView.WfFrameInterval := EffectiveWfInterval;
|
||||
if FController.FWDSPReady then
|
||||
FController.FDSPEngine.SetDisplayResLimit(ResLimit);
|
||||
FWaterfallDirty := True;
|
||||
FSpectrumDirty := True;
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplySpecMSAA(Samples: Integer);
|
||||
begin
|
||||
Samples := EnsureRange(Samples, 1, 8);
|
||||
FController.FSpecMSAA := Samples;
|
||||
if FUseOpenGLSpectrum and (PbSpectrum is TOpenGLControl) and
|
||||
(TOpenGLControl(PbSpectrum).MultiSampling <> Cardinal(Samples)) then
|
||||
begin
|
||||
// Смена MSAA пересоздаёт хэндл → старый GL-контекст (и все текстуры)
|
||||
// умирает; кэши view нужно обнулить БЕЗ glDelete.
|
||||
TOpenGLControl(PbSpectrum).MultiSampling := Samples;
|
||||
if FSpecView is TSpectrumViewOpenGL then
|
||||
TSpectrumViewOpenGL(FSpecView).ResetGLCache;
|
||||
FSpectrumDirty := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyGridParams(RefLevel, Range, GridStep: Double);
|
||||
begin
|
||||
FController.FSpecRefLevel := RefLevel;
|
||||
@@ -6565,19 +6577,21 @@ begin
|
||||
FDisplayFPS := FPS;
|
||||
FController.FLoadedGlobal.DisplayFPS := FPS; // зеркало в persist-буфер контроллера
|
||||
FSpectrumTimer.Interval := 1000 div FPS;
|
||||
// CPU path keeps the historical every-other-frame waterfall update.
|
||||
// OpenGL uploads only one texture row per frame, so it can match display FPS.
|
||||
if FUseOpenGLSpectrum then
|
||||
FWaterfallFrameInterval := 1
|
||||
else
|
||||
FWaterfallFrameInterval := 2;
|
||||
FWaterfallFrameCounter := 0;
|
||||
FWaterfallDirty := True;
|
||||
FSpecView.WfFrameInterval := FWaterfallFrameInterval;
|
||||
FSpecView.WfFrameInterval := EffectiveWfInterval;
|
||||
if FController.FWDSPReady then
|
||||
FController.FDSPEngine.SetDisplayFPS(FPS);
|
||||
end;
|
||||
|
||||
function TMainForm.EffectiveWfInterval: Integer;
|
||||
// Делитель скорости водопада: пользовательский Speed (max-hold накопление
|
||||
// в TWaterfallView); CPU-путь дополнительно не быстрее полукадровой частоты
|
||||
// (исторически — экономия на полной перерисовке bitmap).
|
||||
begin
|
||||
Result := Max(1, FController.FWfSpeedDiv);
|
||||
if not FUseOpenGLSpectrum then Result := Max(Result, 2);
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyFreqMhzDigits(Digits: Integer);
|
||||
begin
|
||||
Digits := EnsureRange(Digits, 3, 5);
|
||||
@@ -6623,6 +6637,7 @@ begin
|
||||
SF.OnDisplayChange := ApplyDisplayParams;
|
||||
SF.OnWaterfallChange := ApplyWaterfallParams;
|
||||
SF.OnWfRenderChange := ApplyWfRenderParams;
|
||||
SF.OnSpecMSAAChange := ApplySpecMSAA;
|
||||
SF.OnGridChange := ApplyGridParams;
|
||||
SF.OnAudioDevChange := ApplyAudioDevice;
|
||||
SF.OnAudioInDevChange := ApplyAudioInputDevice;
|
||||
@@ -6668,7 +6683,8 @@ begin
|
||||
FController.FSpectrumFill);
|
||||
SF.LoadWfAGCNF(FController.FWfAGCEnabled, FController.FWfNFEnabled);
|
||||
SF.LoadWfRender(FController.FWfPalette, FController.FWfGamma,
|
||||
FController.FDisplayPixels);
|
||||
FController.FDisplayPixels, FController.FWfSpeedDiv);
|
||||
SF.LoadSpecMSAA(FController.FSpecMSAA);
|
||||
SF.LoadADCSettings(FController.FDitherEnabled, FController.FRandomEnabled);
|
||||
SF.LoadWebSettings(FWebEnabled, FWebPort, FWebBindAddr, FWebUser, FWebPass);
|
||||
SF.LoadFPS(FDisplayFPS);
|
||||
|
||||
Reference in New Issue
Block a user