Phase 3 (batch 10): route sample-rate/span change through controller

Span ≡ sample rate in this app; OnSampleRateSelect (overlay dropdown) is a
fairly self-contained heavy-class item.

- TRadioController.SetSampleRate(Hz): sets FSampleRate/FSpanHz + band cache,
  recreates the WDSP channel (ChangeSampleRate = Close+FlushQueue+Open),
  pushes the new DDC rate to the radio, and restores full DSP state
  (mode/volume/filter/NR/NB/SNB/ANF/AGC-top/AGC/shift).
- Fixes the same latent AGC cast bug as earlier batches: the inline restore
  used SetAGC(TWDSPAGCMode(FAGCMode)) (index cast); now goes through the
  shared ApplyAGCToEngine mapping.

MainForm: OnSampleRateSelect is a thin wrapper (global-settings SaveGlobal
stays in UI). OnControllerState(rfSampleRate) renders the rate overlay and
recomputes AGC display lines (UpdateAGCLines needs UI spectrum width).
Dropped the cosmetic ProcessMessages pre-paint. Startup paths that set
FSampleRate directly + RecreateDSPEngine left as-is. Builds clean, links.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-04 20:03:59 +03:00
co-authored by Claude Opus 4.8
parent 967e7cb7b1
commit 6edcf8bdf4
2 changed files with 56 additions and 45 deletions
+42 -1
View File
@@ -589,7 +589,48 @@ procedure TRadioController.SetSpan(Hz: Integer);
begin FSpanHz := Hz; Changed(rfSpan); { TODO wiring } end;
procedure TRadioController.SetSampleRate(Hz: Integer);
begin FSampleRate := Hz; Changed(rfSampleRate); { TODO wiring: RecreateDSPEngine } end;
// Смена частоты дискретизации DDC. В этом приложении span ≡ sample rate.
// Несёт: пересоздание WDSP-канала (Close+FlushQueue+Open), новый rate в
// трансивер и полное восстановление DSP-состояния. Сохранение в global
// settings + рендер overlay/AGC-линий остаются в UI (OnControllerState).
begin
if (Hz <= 0) or (Hz = FSampleRate) then Exit;
FSampleRate := Hz;
FSpanHz := Hz;
FBandCache[FCurrentBand].SpanHz := FSpanHz; // для обратной совместимости
// 1. Останавливаем WDSP и меняем rate (Close + FlushQueue + Open).
if FWDSPReady and Assigned(FDSPEngine) then
begin
FWDSPReady := False;
FDSPEngine.ChangeSampleRate(Hz);
end;
// 2. Новый rate трансиверу (после остановки DSP — пакеты сразу с верным rate).
if Assigned(FNetwork) and FNetwork.Connected then
FNetwork.ConfigureDDCs(1, Hz div 1000, 0, FDitherEnabled, FRandomEnabled);
// 3. Восстанавливаем DSP-состояние (ChangeSampleRate пересоздал канал).
if Assigned(FDSPEngine) then
begin
FWDSPReady := FDSPEngine.Initialized;
if FWDSPReady then
begin
FDSPEngine.SetMode(FMode);
FDSPEngine.SetVolume(FVolume / 100.0);
ApplyModeFilter;
FDSPEngine.SetNRMode(FNRMode);
FDSPEngine.SetNBMode(FNBMode);
FDSPEngine.SetSNB(FSNB);
FDSPEngine.SetANF(FANF);
FDSPEngine.SetAGCTop(FAGCTop);
ApplyAGCToEngine; // единый маппинг (раньше здесь был ошибочный каст индекса)
if Assigned(FNetwork) and FNetwork.Connected then
FDSPEngine.SetShift(FVfoA - FCenterFreq);
end;
end;
Changed(rfSampleRate);
end;
procedure TRadioController.SetCTun(On_: Boolean);
begin