diff --git a/WDSPEngine.pas b/WDSPEngine.pas index 46c3a2b..6607bc1 100644 --- a/WDSPEngine.pas +++ b/WDSPEngine.pas @@ -78,6 +78,10 @@ const WFM_AF_HIGH = 15000.0; WFM_TAU_DE_US = 50.0e-6; // Европа/Россия (Америка — 75 мкс) DMR_DEVIATION = 2500.0; + // FM RAW: плоский baseband для внешних декодеров — одна величина на RX-AF, + // TX-AF и bp0 (раньше 20/7000 стояли числами в трёх местах). + RAW_AF_LOW = 20.0; + RAW_AF_HIGH = 7000.0; // Потолок dsp_rate для WFM. Вещательному каналу (200 кГц) хватает 192 кГц, // а гнать цепь на полном IQ-rate нельзя: при 576 кГц dsp_size стал бы 12288, // и fircore спланировал бы FFT на 2*12288 = 24576 точек. Это не степень @@ -1167,7 +1171,7 @@ procedure TWDSPEngine.ApplyRXRawToChan(Chan: Integer); begin // Decoder-grade discriminator: no broadcast de-emphasis or limiter. SetRXAWFMDeviation (Chan, FRawFMDeviation); - SetRXAWFMAFFilter (Chan, 20.0, 7000.0); + SetRXAWFMAFFilter (Chan, RAW_AF_LOW, RAW_AF_HIGH); SetRXAWFMDeemphRun (Chan, 0); SetRXAWFMLimRun (Chan, 0); end; @@ -1221,7 +1225,7 @@ begin // Плоский baseband для внешних декодеров (совпадает с RX AF в ApplyRXRawToChan // и с явным SetTXABandpassFreqs в ApplyTXModeSettings). РЧ-ширина FILT_RAW_BW // (6..25 кГц) — селективность RX, к аудио-полосовику отношения не имеет. - begin Lo := 20.0; Hi := 7000.0; end; + begin Lo := RAW_AF_LOW; Hi := RAW_AF_HIGH; end; else begin Lo := L; Hi := H; end; // прочее — как есть end; @@ -1236,9 +1240,9 @@ begin // selected peak deviation. Keep only a broad linear-phase AF bandpass; // APRS and other external modems must not see voice EQ, dynamics or emphasis. SetTXAWFMDeviation (TXA_CHAN, FRawFMDeviation); - SetTXAWFMAFFreqs (TXA_CHAN, 20.0, 7000.0); + SetTXAWFMAFFreqs (TXA_CHAN, RAW_AF_LOW, RAW_AF_HIGH); SetTXAWFMPreEmphRun (TXA_CHAN, 0); - SetTXABandpassFreqs (TXA_CHAN, 20.0, 7000.0); + SetTXABandpassFreqs (TXA_CHAN, RAW_AF_LOW, RAW_AF_HIGH); SetTXAPanelGain1 (TXA_CHAN, 1.0); SetTXACompressorRun (TXA_CHAN, 0); SetTXALevelerSt (TXA_CHAN, 0); @@ -3715,8 +3719,27 @@ begin end; procedure TWDSPEngine.TXFilterEdgesHz(out Lo, Hi: Integer); -var L, H: Double; +// ЭКРАННЫЕ кромки — занимаемая полоса вокруг несущей, а НЕ bp0. У SSB/CW/DIGI/ +// AM/DSB это одно и то же, поэтому здесь и стояла обёртка над TXSignedEdges. +// Но у ЧМ bp0 — АУДИО-полосовик ПЕРЕД модулятором: у FM RAW он (20..7000), у +// WFM (20..15000), и полоса на спектре уезжала вверх от несущей — визуально +// «переключалась на USB». Для ЧМ считаем по Карсону: ±(девиация + верхний срез +// аудио), симметрично несущей. У MODE_FM TXSignedEdges отдаёт ровно эту +// величину и без нас (порт Thetis), но пусть формула будет в одном месте. +var L, H, Half: Double; begin + Half := 0.0; + case FTXMode of + MODE_FM: Half := FTXFMDeviation + FTXFMHighCut; + MODE_WFM: Half := WFM_DEVIATION + WFM_AF_HIGH; + MODE_FMRAW: Half := FRawFMDeviation + RAW_AF_HIGH; + end; + if Half > 0.0 then + begin + Lo := -Round(Half); + Hi := Round(Half); + Exit; + end; TXSignedEdges(FTXMode, L, H); Lo := Round(L); Hi := Round(H);