refactoring SettingsForm

This commit is contained in:
2026-04-25 14:50:52 +03:00
parent 4c48f22447
commit 537d288e1e
6 changed files with 710 additions and 512 deletions
+42 -6
View File
@@ -15,6 +15,7 @@ unit AudioInput;
{$IFDEF FPC}
{$MODE Delphi}
{$PACKRECORDS C}
{$ENDIF}
interface
@@ -156,9 +157,13 @@ const
'libportaudio.so.0'
);
{$ELSE}
PA_IN_LIBS: array[0..1] of AnsiString = (
PA_IN_LIBS: array[0..5] of AnsiString = (
'portaudio_x64.dll',
'portaudio.dll'
'portaudio_x86.dll',
'portaudio.dll',
'libportaudio-2.dll',
'libportaudio.dll',
'libportaudio64.dll'
);
{$ENDIF}
PA_NO_ERROR = 0;
@@ -265,7 +270,11 @@ begin
if FLibHandle = NilHandle then
begin
{$IFDEF WINDOWS}
FLastError := 'PortAudio DLL not found. Put portaudio_x64.dll, portaudio.dll, or libportaudio-2.dll next to ewsdr.exe';
{$ELSE}
FLastError := 'libportaudio not found';
{$ENDIF}
Exit;
end;
@@ -279,7 +288,15 @@ begin
FPa_CloseStream := TPaMic_CloseStream (GetProcAddress(FLibHandle, 'Pa_CloseStream'));
FPa_GetErrorText := TPaMic_GetErrorText(GetProcAddress(FLibHandle, 'Pa_GetErrorText'));
if not Assigned(FPa_Initialize) or not Assigned(FPa_OpenStream) then
if not Assigned(FPa_Initialize) or
not Assigned(FPa_Terminate) or
not Assigned(FPa_GetDeviceCount) or
not Assigned(FPa_GetDeviceInfo) or
not Assigned(FPa_OpenStream) or
not Assigned(FPa_StartStream) or
not Assigned(FPa_StopStream) or
not Assigned(FPa_CloseStream) or
not Assigned(FPa_GetErrorText) then
begin
FLastError := 'libportaudio: symbols not found';
FreeLibrary(FLibHandle);
@@ -329,10 +346,27 @@ begin
Count := 0;
Result := False;
if not Initialize then Exit;
if not Assigned(FPa_GetDeviceCount) or not Assigned(FPa_GetDeviceInfo) then Exit;
if not Assigned(FPa_GetDeviceCount) or not Assigned(FPa_GetDeviceInfo) then
begin
FLastError := 'PortAudio device enumeration is not available';
Exit;
end;
N := FPa_GetDeviceCount();
if N <= 0 then Exit;
if N < 0 then
begin
FLastError := 'Pa_GetDeviceCount: ';
if Assigned(FPa_GetErrorText) then
FLastError := FLastError + string(FPa_GetErrorText(N))
else
FLastError := FLastError + IntToStr(N);
Exit;
end;
if N = 0 then
begin
FLastError := 'No PortAudio devices found';
Exit;
end;
for I := 0 to N - 1 do
begin
@@ -410,8 +444,10 @@ begin
InParam.device := FDeviceIndex;
InParam.sampleFormat := PA_FLOAT32;
// suggestedLatency = defaultLowInputLatency устройства (как в piHPSDR)
Info := FPa_GetDeviceInfo(FDeviceIndex);
{$IFDEF WINDOWS}
// На Windows latency=0 часто ломает WASAPI/MME; берём значение от устройства.
{$ENDIF}
if Info <> nil then
InParam.suggestedLatency := Info^.defaultLowInputLatency
else
+47 -7
View File
@@ -15,6 +15,7 @@ unit AudioOutput;
{$IFDEF FPC}
{$MODE Delphi}
{$PACKRECORDS C}
{$ENDIF}
interface
@@ -166,9 +167,13 @@ const
'libportaudio.so.0'
);
{$ELSE}
PA_LIBS: array[0..1] of AnsiString = (
PA_LIBS: array[0..5] of AnsiString = (
'portaudio_x64.dll',
'portaudio.dll'
'portaudio_x86.dll',
'portaudio.dll',
'libportaudio-2.dll',
'libportaudio.dll',
'libportaudio64.dll'
);
{$ENDIF}
PA_NO_ERROR = 0;
@@ -282,7 +287,11 @@ begin
if FLibHandle = NilHandle then
begin
{$IFDEF WINDOWS}
FLastError := 'PortAudio DLL not found. Put portaudio_x64.dll, portaudio.dll, or libportaudio-2.dll next to ewsdr.exe';
{$ELSE}
FLastError := 'libportaudio not found. sudo apt install libportaudio2';
{$ENDIF}
Exit;
end;
@@ -297,7 +306,16 @@ begin
FPa_CloseStream := TPa_CloseStream(GetProcAddress(FLibHandle, 'Pa_CloseStream'));
FPa_GetErrorText := TPa_GetErrorText(GetProcAddress(FLibHandle, 'Pa_GetErrorText'));
if not Assigned(FPa_Initialize) or not Assigned(FPa_OpenStream) then
if not Assigned(FPa_Initialize) or
not Assigned(FPa_Terminate) or
not Assigned(FPa_GetDefaultOutputDevice) or
not Assigned(FPa_GetDeviceCount) or
not Assigned(FPa_GetDeviceInfo) or
not Assigned(FPa_OpenStream) or
not Assigned(FPa_StartStream) or
not Assigned(FPa_StopStream) or
not Assigned(FPa_CloseStream) or
not Assigned(FPa_GetErrorText) then
begin
FLastError := 'libportaudio: symbols not found';
FreeLibrary(FLibHandle);
@@ -350,10 +368,27 @@ begin
Count := 0;
Result := False;
if not Initialize then Exit;
if not Assigned(FPa_GetDeviceCount) or not Assigned(FPa_GetDeviceInfo) then Exit;
if not Assigned(FPa_GetDeviceCount) or not Assigned(FPa_GetDeviceInfo) then
begin
FLastError := 'PortAudio device enumeration is not available';
Exit;
end;
N := FPa_GetDeviceCount();
if N <= 0 then Exit;
if N < 0 then
begin
FLastError := 'Pa_GetDeviceCount: ';
if Assigned(FPa_GetErrorText) then
FLastError := FLastError + string(FPa_GetErrorText(N))
else
FLastError := FLastError + IntToStr(N);
Exit;
end;
if N = 0 then
begin
FLastError := 'No PortAudio devices found';
Exit;
end;
for I := 0 to N - 1 do
begin
@@ -416,6 +451,7 @@ var
OutParam: TPaStreamParameters;
Err: TPaError;
Dev: TPaDeviceIndex;
Info: PPaDeviceInfo;
begin
Result := False;
if FOpen then begin Result := True; Exit; end;
@@ -441,8 +477,12 @@ begin
OutParam.hostApiSpecificStreamInfo := nil;
OutParam.sampleFormat := PA_FLOAT32;
{$IFDEF WINDOWS}
// На Windows latency=0 вызывает фризы — используем разумный минимум
OutParam.suggestedLatency := 0.050; // 50ms — стабильно на Windows WASAPI/MME
// На Windows latency=0 часто ломает WASAPI/MME; берём значение от устройства.
Info := FPa_GetDeviceInfo(Dev);
if (Info <> nil) and (Info^.defaultLowOutputLatency > 0.0) then
OutParam.suggestedLatency := Info^.defaultLowOutputLatency
else
OutParam.suggestedLatency := 0.050;
{$ELSE}
OutParam.suggestedLatency := 0.0; // на Linux ALSA справляется с минимумом
{$ENDIF}
+3 -3
View File
@@ -952,7 +952,7 @@ begin
end
else
begin
Result.FFTSize := 4096;
Result.FFTSize := 131072;
Result.WindowType := 2;
Result.SpecDetector := 0;
Result.SpecAvgMode := 3;
@@ -1177,7 +1177,7 @@ begin
FPanelHidden := False;
FShowSpectrum := True;
FShowWaterfall := True;
FDisplayFPS := 20;
FDisplayFPS := 60;
FWaterfallDirty := True;
FSplitterRatio := 0.40; // 40% спектр, 60% водопад по умолчанию
FSplitterDrag := False;
@@ -5815,7 +5815,7 @@ begin
FAudioOutDevName, FAudioInDevName)
else
SF.LoadValues(
4096, 2, 0, 3, 30.0,
131072, 2, 0, 3, 30.0,
0, 3, 120.0, FWfManualHigh, FWfManualLow, FWfAGCOffset,
FSpecRefLevel, FSpecRange, FSpecGridStep,
FAudioOutDevName, FAudioInDevName);
+25 -15
View File
@@ -49,7 +49,7 @@ type
WindowWidth: Integer;
WindowHeight: Integer;
// --- Display settings ---
FFTSize: Integer; // 1024,2048,4096,8192,16384
FFTSize: Integer; // 4096..262144
WindowType: Integer; // 0=Rect,1=BH4,2=Hann,3=FlatTop,4=Hamming,5=Kaiser,6=BH7
SpecDetector: Integer; // 0=Peak,1=Rosenfell,2=Average,3=Sample,4=RMS
SpecAvgMode: Integer; // 0=None,1=Recursive,2=TimeWindow,3=LogRecursive
@@ -171,7 +171,7 @@ begin
G.PAMaxPower := 100.0;
for i := 0 to CFG_BAND_COUNT-1 do G.PABandCal[i] := 100.0;
// Display defaults
G.FFTSize := 4096;
G.FFTSize := 131072;
G.WindowType := 2; // Hann
G.SpecDetector := 0; // Peak
G.SpecAvgMode := 3; // Log Recursive
@@ -190,7 +190,7 @@ begin
G.AudioInDevice := '';
G.ShowSpectrum := True;
G.ShowWaterfall := True;
G.DisplayFPS := 20;
G.DisplayFPS := 60;
end;
constructor TSettingsManager.Create(const FilePath: string);
@@ -336,30 +336,40 @@ begin
G.LastBand := JI(GObj,'last_band',5);
G.SampleRate := JI(GObj,'sample_rate',192000);
// Display settings
G.FFTSize := JI(GObj,'fft_size',4096);
G.WindowType := JI(GObj,'win_type',5);
G.FFTSize := JI(GObj,'fft_size',131072);
G.WindowType := JI(GObj,'win_type',2);
G.SpecDetector := JI(GObj,'spec_detector',0);
G.SpecAvgMode := JI(GObj,'spec_avg_mode',0);
G.SpecAvgMode := JI(GObj,'spec_avg_mode',3);
if GObj.Find('spec_avg_time_ms') <> nil then
G.SpecAvgTimeMS := JD(GObj,'spec_avg_time_ms',120.0)
else
G.SpecAvgTimeMS := JD(GObj,'spec_avg_time_ms',30.0)
else if (GObj.Find('spec_avg_count') <> nil) or
(GObj.Find('spec_backmult') <> nil) then
begin
G.SpecAvgTimeMS := LegacyAverageTimeMS(
JI(GObj,'display_fps',20),
JI(GObj,'display_fps',60),
G.SpecAvgMode,
JI(GObj,'spec_avg_count',1),
JD(GObj,'spec_backmult',0.0),
120.0);
G.WfDetector := JI(GObj,'wf_detector',2);
G.WfAvgMode := JI(GObj,'wf_avg_mode',1);
30.0);
end
else
G.SpecAvgTimeMS := 30.0;
G.WfDetector := JI(GObj,'wf_detector',0);
G.WfAvgMode := JI(GObj,'wf_avg_mode',3);
if GObj.Find('wf_avg_time_ms') <> nil then
G.WfAvgTimeMS := JD(GObj,'wf_avg_time_ms',120.0)
else
else if (GObj.Find('wf_avg_count') <> nil) or
(GObj.Find('wf_backmult') <> nil) then
begin
G.WfAvgTimeMS := LegacyAverageTimeMS(
JI(GObj,'display_fps',20),
JI(GObj,'display_fps',60),
G.WfAvgMode,
JI(GObj,'wf_avg_count',2),
JD(GObj,'wf_backmult',0.25),
120.0);
end
else
G.WfAvgTimeMS := 120.0;
G.WfManualHigh := JD(GObj,'wf_manual_high',-80.0);
G.WfManualLow := JD(GObj,'wf_manual_low',-130.0);
G.WfAGCOffset := JD(GObj,'wf_agc_offset',0.0);
@@ -373,7 +383,7 @@ begin
// Visibility settings
G.ShowSpectrum := JB(GObj,'show_spectrum',True);
G.ShowWaterfall := JB(GObj,'show_waterfall',True);
G.DisplayFPS := JI(GObj,'display_fps',20);
G.DisplayFPS := JI(GObj,'display_fps',60);
// PA settings
G.PAMaxPower := JD(GObj,'pa_max_power',100.0);
for i := 0 to CFG_BAND_COUNT-1 do
+589 -477
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -551,10 +551,10 @@ begin
FANFEnabled := False;
FRXAccPos := 0;
// Analyzer defaults
FFFTSize := 4096;
FFFTSize := 131072;
FWindowType := 2; // Hann
FDisplayFPS := 20;
FEffectiveDisplayFPS := 20.0;
FDisplayFPS := 60;
FEffectiveDisplayFPS := 60.0;
FDisplayPixelCount := SPECTRUM_PIXELS;
FSpecDetector := 0; // Peak
FSpecAvgMode := 3; // Log Recursive