feat(vfo): кнопка SQL + ползунок FM-squelch в DSP-меню флага (main + слайсы)

В fly-out DSP появляется ряд SQL (тумблер + порог 0..100) только в режиме FM.
Squelch работает per-slice: у слайсов свои WDSP-каналы, поэтому добавлены
поля/сеттеры FMSQ в TSliceChan/TCtrlSlice, ApplyFMSQToChan и восстановление
при переоткрытии канала. Роутинг события по SliceId (0=RXA, иначе слайс).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 12:51:02 +03:00
co-authored by Claude Opus 4.8
parent ce9cfd730f
commit b2b3339a2a
4 changed files with 158 additions and 2 deletions
+16
View File
@@ -135,6 +135,8 @@ type
AGC: TWDSPAGCMode;
Volume: Double; // 0..1
Muted: Boolean;
FMSQOn: Boolean; // FM-squelch включён (слайс в режиме FM)
FMSQLevel: Integer; // порог squelch 0..100
DeviceIndex: Integer; // PortAudio-индекс (-1 = default)
DevName: string;
Audio: TAudioOutput; // владеет; свой поток вывода
@@ -529,6 +531,7 @@ type
procedure SetSliceVolume(Id: Integer; Vol: Double); // 0..1
procedure SetSliceMute(Id: Integer; Mute: Boolean);
procedure SetSliceDSP(Id, NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
procedure SetSliceFMSquelch(Id: Integer; On_: Boolean; Level: Integer);
function SliceSMeter(Id: Integer): Double; // dBm, из DSP-потока
procedure SetSliceDevice(Id, DevIndex: Integer; const DevName: string);
function SliceCount: Integer;
@@ -1153,6 +1156,8 @@ begin
FSlices[slot].AGC := AGC;
FSlices[slot].Volume := Vol;
FSlices[slot].Muted := False;
FSlices[slot].FMSQOn := False; // squelch по умолчанию выключен
FSlices[slot].FMSQLevel := 40;
FSlices[slot].DeviceIndex := DevIndex;
FSlices[slot].DevName := DevName;
FSlices[slot].Audio := AO;
@@ -1247,6 +1252,17 @@ begin
end;
end;
procedure TRadioController.SetSliceFMSquelch(Id: Integer; On_: Boolean; Level: Integer);
var idx: Integer;
begin
idx := FindSliceIndex(Id);
if idx < 0 then Exit;
FSlices[idx].FMSQOn := On_;
FSlices[idx].FMSQLevel := Level;
if Assigned(FDSPEngine) then
FDSPEngine.SetSliceFMSquelch(Id, On_, Level);
end;
function TRadioController.SliceSMeter(Id: Integer): Double;
begin
if Assigned(FDSPEngine) then Result := FDSPEngine.GetSliceSMeter(Id)