mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
feat(dmr): decode independent receiver slices
This commit is contained in:
+49
-9
@@ -337,6 +337,7 @@ type
|
||||
FSliceOutL: array of Single; // деинтерливленный L для callback
|
||||
FSliceOutR: array of Single; // R
|
||||
FOnSliceAudio: TOnSliceAudio;
|
||||
FOnSliceDemodAudio: TOnSliceAudio; // pre-volume/mute tap for digital slices
|
||||
|
||||
// --- Панадаптеры на аппаратных DDC (этап 3.2) ---
|
||||
FPans: array[1..MAX_PANS-1] of TPanChan;
|
||||
@@ -452,6 +453,7 @@ type
|
||||
function EffectiveTXNC: Integer;
|
||||
procedure ApplyDSPRate(Mode: Integer);
|
||||
procedure ApplyRXWFMToChan(Chan: Integer);
|
||||
procedure ApplyRXDMRToChan(Chan: Integer);
|
||||
procedure ApplyWFMSettings;
|
||||
// --- Мультислайсы ---
|
||||
function FindSliceIdx(Id: Integer): Integer; // -1 если нет
|
||||
@@ -687,6 +689,8 @@ type
|
||||
property OnAudio: TOnAudioReady read FOnAudio write FOnAudio;
|
||||
property OnDemodAudio: TOnAudioReady read FOnDemodAudio write FOnDemodAudio;
|
||||
property OnSliceAudio: TOnSliceAudio read FOnSliceAudio write FOnSliceAudio;
|
||||
property OnSliceDemodAudio: TOnSliceAudio
|
||||
read FOnSliceDemodAudio write FOnSliceDemodAudio;
|
||||
property OnSpectrum: TOnSpectrumReady read FOnSpectrum write FOnSpectrum;
|
||||
property OnWaterfall: TOnWaterfallReady read FOnWaterfall write FOnWaterfall;
|
||||
// Пиксели доп. панов (display-поток). UI вешает при появлении панов (3.3).
|
||||
@@ -1061,6 +1065,14 @@ begin
|
||||
SetRXAWFMDeemphTau (Chan, WFM_TAU_DE_US);
|
||||
end;
|
||||
|
||||
procedure TWDSPEngine.ApplyRXDMRToChan(Chan: Integer);
|
||||
begin
|
||||
// DMR needs the flat 4FSK discriminator, not broadcast-FM deemphasis.
|
||||
SetRXAWFMDeviation (Chan, DMR_DEVIATION);
|
||||
SetRXAWFMAFFilter (Chan, 20.0, 7000.0);
|
||||
SetRXAWFMDeemphRun (Chan, 0);
|
||||
end;
|
||||
|
||||
procedure TWDSPEngine.ApplyWFMSettings;
|
||||
begin
|
||||
ApplyRXWFMToChan(RXA_CHAN);
|
||||
@@ -1177,6 +1189,7 @@ begin
|
||||
FSliceLock := TCriticalSection.Create;
|
||||
FillChar(FSlices, SizeOf(FSlices), 0);
|
||||
FOnSliceAudio := nil;
|
||||
FOnSliceDemodAudio := nil;
|
||||
AllocSliceBuffers;
|
||||
|
||||
// TX инициализация
|
||||
@@ -1945,7 +1958,7 @@ begin
|
||||
if Pan^.AccPos >= Pan^.BufSize then
|
||||
begin
|
||||
Pan^.AccPos := 0;
|
||||
if Assigned(FOnSliceAudio) then
|
||||
if Assigned(FOnSliceAudio) or Assigned(FOnSliceDemodAudio) then
|
||||
try
|
||||
ProcessSlicesFor(PanId, Pan^.AccI, Pan^.AccQ, Pan^.BufSize);
|
||||
except
|
||||
@@ -2232,6 +2245,7 @@ begin
|
||||
SetRXABandpassWindow(Chan, 1);
|
||||
SetRXAMode(Chan, ModeToWDSP(FSlices[Idx].Mode));
|
||||
if FSlices[Idx].Mode = MODE_WFM then ApplyRXWFMToChan(Chan);
|
||||
if FSlices[Idx].Mode = MODE_DMR then ApplyRXDMRToChan(Chan);
|
||||
SetRXAShiftRun(Chan, 1);
|
||||
SetRXAShiftFreq(Chan, FSlices[Idx].ShiftHz);
|
||||
RXASetPassband(Chan, ClampToNyquist(FSlices[Idx].FilterLo, DSPRate),
|
||||
@@ -2243,7 +2257,11 @@ begin
|
||||
ApplySNBToChan(Chan, FSlices[Idx].SNBOn);
|
||||
ApplyANFToChan(Chan, FSlices[Idx].ANFOn);
|
||||
ApplyFMSQToChan(Chan, FSlices[Idx].FMSQOn, FSlices[Idx].FMSQLevel);
|
||||
SetRXAPanelGain1(Chan, FSlices[Idx].Volume);
|
||||
// Decoder input must not disappear or change scale with speaker volume.
|
||||
if FSlices[Idx].Mode = MODE_DMR then
|
||||
SetRXAPanelGain1(Chan, 1.0)
|
||||
else
|
||||
SetRXAPanelGain1(Chan, FSlices[Idx].Volume);
|
||||
SetRXAPanelSelect(Chan, 3);
|
||||
SetRXAPanelRun(Chan, 1);
|
||||
SetChannelState(Chan, 1, 0);
|
||||
@@ -2268,7 +2286,7 @@ end;
|
||||
// после основного канала.
|
||||
procedure TWDSPEngine.ProcessSlices;
|
||||
begin
|
||||
if not Assigned(FOnSliceAudio) then Exit;
|
||||
if not Assigned(FOnSliceAudio) and not Assigned(FOnSliceDemodAudio) then Exit;
|
||||
FSliceLock.Enter;
|
||||
try
|
||||
ProcessSlicesFor(0, FRXAccI, FRXAccQ, FBufSize);
|
||||
@@ -2289,7 +2307,8 @@ begin
|
||||
begin
|
||||
if not (FSlices[s].Active and FSlices[s].Opened) then Continue;
|
||||
if FSlices[s].PanId <> PanId then Continue;
|
||||
if FSlices[s].Muted then Continue;
|
||||
// Muting a DMR speaker must not make its decoder lose synchronization.
|
||||
if FSlices[s].Muted and (FSlices[s].Mode <> MODE_DMR) then Continue;
|
||||
// Свежая копия входного IQ — fexchange0 портит вход in-place.
|
||||
for i := 0 to N - 1 do
|
||||
begin
|
||||
@@ -2300,13 +2319,28 @@ begin
|
||||
fexchange0(FSlices[s].Chan, @FSliceIn[0], @FSliceOut[0], @Err);
|
||||
// S-метр канала читаем здесь (DSP-поток) — GetRXAMeter сбрасывает аккумулятор.
|
||||
FSlices[s].SMeter := GetRXAMeter(FSlices[s].Chan, RXA_S_AV);
|
||||
V := FSlices[s].Volume;
|
||||
for k := 0 to FAudioBufSize - 1 do
|
||||
begin
|
||||
FSliceOutL[k] := FSliceOut[k * 2] * V;
|
||||
FSliceOutR[k] := FSliceOut[k * 2 + 1] * V;
|
||||
FSliceOutL[k] := FSliceOut[k * 2];
|
||||
FSliceOutR[k] := FSliceOut[k * 2 + 1];
|
||||
end;
|
||||
if FSlices[s].Mode = MODE_DMR then
|
||||
begin
|
||||
if Assigned(FOnSliceDemodAudio) then
|
||||
FOnSliceDemodAudio(FSlices[s].Id, FSliceOutL, FSliceOutR,
|
||||
FAudioBufSize);
|
||||
Continue; // never route the raw 4FSK discriminator to the speaker
|
||||
end;
|
||||
if Assigned(FOnSliceAudio) then
|
||||
begin
|
||||
V := FSlices[s].Volume;
|
||||
for k := 0 to FAudioBufSize - 1 do
|
||||
begin
|
||||
FSliceOutL[k] := FSliceOutL[k] * V;
|
||||
FSliceOutR[k] := FSliceOutR[k] * V;
|
||||
end;
|
||||
FOnSliceAudio(FSlices[s].Id, FSliceOutL, FSliceOutR, FAudioBufSize);
|
||||
end;
|
||||
FOnSliceAudio(FSlices[s].Id, FSliceOutL, FSliceOutR, FAudioBufSize);
|
||||
end;
|
||||
end;
|
||||
|
||||
@@ -2515,6 +2549,11 @@ begin
|
||||
begin
|
||||
SetRXAMode(FSlices[idx].Chan, ModeToWDSP(Mode));
|
||||
if Mode = MODE_WFM then ApplyRXWFMToChan(FSlices[idx].Chan);
|
||||
if Mode = MODE_DMR then ApplyRXDMRToChan(FSlices[idx].Chan);
|
||||
if Mode = MODE_DMR then
|
||||
SetRXAPanelGain1(FSlices[idx].Chan, 1.0)
|
||||
else
|
||||
SetRXAPanelGain1(FSlices[idx].Chan, FSlices[idx].Volume);
|
||||
end;
|
||||
finally
|
||||
FSliceLock.Leave;
|
||||
@@ -2560,7 +2599,8 @@ begin
|
||||
try
|
||||
idx := FindSliceIdx(Id); if idx < 0 then Exit;
|
||||
FSlices[idx].Volume := Vol;
|
||||
if FSlices[idx].Opened then SetRXAPanelGain1(FSlices[idx].Chan, Vol);
|
||||
if FSlices[idx].Opened and (FSlices[idx].Mode <> MODE_DMR) then
|
||||
SetRXAPanelGain1(FSlices[idx].Chan, Vol);
|
||||
finally
|
||||
FSliceLock.Leave;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user