Add audio buffer setting and optimize overlays

This commit is contained in:
2026-05-22 18:07:05 +03:00
parent 26aa55ddde
commit c5f225332b
6 changed files with 327 additions and 38 deletions
+83 -22
View File
@@ -660,6 +660,7 @@ type
procedure OnModeFilterSelect(Mode: Integer; FilterBW: Integer);
procedure OnVfoOverlayDSPChange(NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
procedure OnVfoOverlayAGCChange(AGCMode: Integer);
procedure OnVfoOverlayInvalidate(Sender: TObject);
procedure PbSpectrumDblClick(Sender: TObject);
procedure TrkDriveChange(Sender: TObject);
procedure TrkVolumeChange(Sender: TObject);
@@ -702,6 +703,7 @@ type
procedure ApplySpecViewGridFromState;
procedure ApplyAudioDevice(DevIndex: Integer; const DevName: string);
procedure ApplyAudioInputDevice(DevIndex: Integer; const DevName: string);
procedure ApplyAudioBufferSize(BufferSize: Integer);
// TX settings: применить FTXSettings к WDSP и переслать DUC Specific
// (mic-биты Boost/Bias/LineIn/PTT попадают в byte 50 DUCSpecific).
procedure ApplyTXSettingsToDSP;
@@ -1321,6 +1323,7 @@ begin
FVfoOverlay.OnSelect := OnModeFilterSelect;
FVfoOverlay.OnDSPChange := OnVfoOverlayDSPChange;
FVfoOverlay.OnAGCChange := OnVfoOverlayAGCChange;
FVfoOverlay.OnInvalidate := OnVfoOverlayInvalidate;
FVfoOverlay.Visible := False;
FPanelHidden := False;
FShowSpectrum := True;
@@ -1331,6 +1334,7 @@ begin
FSplitterDrag := False;
FSpecView := TSpectrumView.Create;
FSpecView.VfoOverlay := FVfoOverlay;
FSpecView.VfoA := FVfoA;
FSpecView.VfoB := FVfoB;
FSpecView.ActiveVfo := FActiveVfo;
@@ -1387,6 +1391,7 @@ begin
// Audio output/input — создаём объекты сейчас, открываем после показа формы
// (Pa_Initialize на Linux пишет в stderr до перехвата сигналов FPC)
FAudioOut := TAudioOutput.Create(48000);
FAudioOut.OutputBufferSize := FSettings.LoadAudioBufferSize;
FAudioIn := TAudioInput.Create(48000);
FMeterTimer := TTimer.Create(Self);
@@ -4417,20 +4422,15 @@ begin
FNetwork.SendFullHP;
end;
// Перерисовываем спектр всегда (маркер и полоса двигаются)
// Если идёт drag — не вызываем Draw напрямую, таймер подхватит
// Не рисуем синхронно из wheel/drag path: частые события мыши иначе
// забивают UI-поток и мешают аудио. Таймер подхватит ближайший кадр.
SyncSpecViewFreq;
if FSpecDrag then
FSpectrumDirty := True
else
FSpectrumDirty := True;
PbSpectrum.Invalidate;
if Scrolled then
begin
FSpecView.DrawSpectrum;
PbSpectrum.Invalidate;
if Scrolled then
begin
FSpecView.DrawWaterfall;
PbWaterfall.Invalidate;
end;
FWaterfallDirty := True;
PbWaterfall.Invalidate;
end;
end;
@@ -4648,6 +4648,8 @@ end;
procedure TMainForm.PbSpectrumMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FVfoOverlay) and
FVfoOverlay.HandleMouseDown(Button, X, Y) then Exit;
if Assigned(FSampleRateOverlay) and
FSampleRateOverlay.HandleMouseDown(Button, X, Y) then Exit;
@@ -4694,9 +4696,15 @@ begin
if Assigned(FSampleRateOverlay) then
begin
FSampleRateOverlay.HandleMouseMove(X, Y);
if (FSampleRateOverlay.HotIdx >= 0) and (not FSpecDrag) then
end;
if Assigned(FVfoOverlay) then
FVfoOverlay.HandleMouseMove(X, Y);
if not FSpecDrag then
begin
if (Assigned(FVfoOverlay) and (FVfoOverlay.HotIdx >= 0)) or
(Assigned(FSampleRateOverlay) and (FSampleRateOverlay.HotIdx >= 0)) then
PbSpectrum.Cursor := crHandPoint
else if not FSpecDrag then
else
PbSpectrum.Cursor := crDefault;
end;
@@ -4726,6 +4734,8 @@ procedure TMainForm.PbSpectrumMouseLeave(Sender: TObject);
begin
if Assigned(FSampleRateOverlay) then
FSampleRateOverlay.HandleMouseLeave;
if Assigned(FVfoOverlay) then
FVfoOverlay.HandleMouseLeave;
if not FSpecDrag then PbSpectrum.Cursor := crDefault;
end;
@@ -5304,18 +5314,17 @@ begin
if FPanelHidden then
begin
PanelLeft.Width := 0;
FVfoOverlay.Parent := PanelRight;
FVfoOverlay.Width := 260;
FVfoOverlay.Height := 136; // OVL_H_NORM — расширяется сам при открытии AGC-пикера
FVfoOverlay.SetState(FMode, FFilterBW, FVfoA, FLastSMeter);
FVfoOverlay.SetDSPState(BtnNR.Tag, BtnNB.Tag, BtnSNB.Tag <> 0, BtnANF.Tag <> 0, FAGCMode);
FVfoOverlay.Visible := True;
FVfoOverlay.BringToFront;
PositionVfoOverlay;
end
else
begin
PanelLeft.Width := 232;
FVfoOverlay.HandleMouseLeave;
FVfoOverlay.Visible := False;
end;
if Assigned(FSampleRateOverlay) then
@@ -5326,20 +5335,40 @@ end;
procedure TMainForm.PositionVfoOverlay;
var
VfoX, OW, SpTop: Integer;
VfoX, FilterEndX, OW, NewLeft, NewTop: Integer;
HiHz: Double;
begin
if not Assigned(FVfoOverlay) or not FVfoOverlay.Visible then Exit;
OW := FVfoOverlay.Width;
SpTop := PbSpectrum.Top; // смещение PbSpectrum внутри PanelRight
if PbSpectrum.Width > 0 then
if (PbSpectrum.Width > 0) and (FSpanHz > 0) then
begin
VfoX := Round((FVfoA - FCenterFreq + FSpanHz / 2) / FSpanHz * PbSpectrum.Width)
end
else
VfoX := PbSpectrum.Width div 2;
// Всегда справа от VFO-линии
FVfoOverlay.Left := Min(PanelRight.Width - OW - 4, VfoX + 6);
FVfoOverlay.Top := SpTop + 6;
case FMode of
MODE_LSB: HiHz := -100;
MODE_USB: HiHz := FFilterBW;
else
HiHz := FFilterBW / 2;
end;
if (PbSpectrum.Width > 0) and (FSpanHz > 0) then
FilterEndX := VfoX + Round(HiHz / FSpanHz * PbSpectrum.Width)
else
FilterEndX := VfoX;
FilterEndX := Max(0, Min(PbSpectrum.Width - 1, FilterEndX));
// Всегда справа от правого края полосы фильтра.
NewLeft := Max(4, Min(PbSpectrum.Width - OW - 4, FilterEndX + 6));
NewTop := 16;
if (FVfoOverlay.Left <> NewLeft) or (FVfoOverlay.Top <> NewTop) then
begin
FVfoOverlay.Left := NewLeft;
FVfoOverlay.Top := NewTop;
OnVfoOverlayInvalidate(FVfoOverlay);
end;
end;
procedure TMainForm.PbSpectrumDblClick(Sender: TObject);
@@ -5400,6 +5429,13 @@ begin
FBandCache[FCurrentBand].AGCMode := FAGCMode;
end;
procedure TMainForm.OnVfoOverlayInvalidate(Sender: TObject);
begin
FSpectrumDirty := True;
if Assigned(FSpecView) then FSpecView.SpectrumDirty := True;
if Assigned(PbSpectrum) then PbSpectrum.Invalidate;
end;
procedure TMainForm.OnSampleRateSelect(SampleRate: Integer);
var
NewRate: Integer;
@@ -6731,6 +6767,29 @@ begin
end;
end;
procedure TMainForm.ApplyAudioBufferSize(BufferSize: Integer);
var
WasOpen: Boolean;
begin
if BufferSize <= 128 then BufferSize := 128
else if BufferSize <= 256 then BufferSize := 256
else BufferSize := 512;
if FAudioOut.OutputBufferSize = BufferSize then Exit;
WasOpen := FAudioOut.IsOpen;
if WasOpen then FAudioOut.Close;
FAudioOut.OutputBufferSize := BufferSize;
if WasOpen then
begin
try
FAudioOut.Open;
except
end;
end;
FSettings.SaveAudioBufferSize(BufferSize);
FSettings.Save;
end;
procedure TMainForm.ApplyVisibility(ShowSpectrum, ShowWaterfall: Boolean);
begin
FShowSpectrum := ShowSpectrum;
@@ -6781,6 +6840,7 @@ begin
SF.OnGridChange := ApplyGridParams;
SF.OnAudioDevChange := ApplyAudioDevice;
SF.OnAudioInDevChange := ApplyAudioInputDevice;
SF.OnAudioBufferChange := ApplyAudioBufferSize;
SF.OnVisibilityChange := ApplyVisibility;
SF.OnFPSChange := ApplyFPS;
SF.OnPAChange := OnPASettingsChange;
@@ -6821,6 +6881,7 @@ begin
SF.LoadFPS(FDisplayFPS);
SF.LoadLightTheme(FLightTheme);
SF.LoadFreqMhzDigits(FFreqMhzDigits);
SF.LoadAudioBufferSize(FAudioOut.OutputBufferSize);
// Загружаем текущие значения
if FWDSPReady then
SF.LoadValues(