mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
fix(tx): убраны инъекции данных в DUC IQ-поток — всплески на водопаде при TX
Два источника фабрикации данных в TX IQ-поток рисовали всплески на водопаде при передаче (openHPSDR, особенно TUN/DUP): 1. HPSDRNetwork (sender): анти-старв zero-fill при пустой очереди впрыскивал нулевые пакеты = 1.25мс тишины прямо в поток = разрыв данных = всплеск. Теперь пустая очередь → просто ждём следующий блок (модель dl1ycf pihpsdr txiq_thread: данные не инжектируются никогда; короткий разрыв покрывает pre-roll в FPGA-FIFO радио). Убраны DUC_FIFO_LOW/REANCHOR/ZeroPkt. 2. WDSPEngine (продюсер TTXDSPThread): silence-инъекция при стойле mic впрыскивала лишний блок сверх mic-темпа (для TUN он нёс PostGen-тон → боковые/разрыв темпа). Продюсер теперь строго mic-гейтед. Замерено на эфире: всплески при TUN 5-6/сессию → ~1. Остаточный редкий клик по прямому замеру НЕ из TX-пейсинга (sender ровно на радиоклоке 800 пак/с через supply-limiting, дропов/underrun нет) — источник отдельный (дисплей/RX), разбор позже. Windows-ветка sender'а не тронута. Pluto — свой TX-тракт (TPlutoTXThread + libiio DMA), задета только общая silence-removal (push-поток сам добивает нулями). Обе не перепроверены на железе. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+12
-38
@@ -669,15 +669,12 @@ var
|
||||
PeriodMs: Integer;
|
||||
PeriodUs: Integer;
|
||||
AccUs: Integer;
|
||||
DidBlock: Boolean;
|
||||
StallCount: Integer;
|
||||
begin
|
||||
// 512 samples / 48000 Hz = 10.666 ms. Do not floor this to 10 ms:
|
||||
// that over-produces TX IQ by ~6.7%, eventually forcing DUC queue
|
||||
// corrections/drops and producing periodic sidebands on a pure TUN tone.
|
||||
PeriodUs := Max(1000, FEngine.FAudioBufSize * 1000000 div FEngine.FAudioRate);
|
||||
AccUs := 0;
|
||||
StallCount := 0;
|
||||
|
||||
while not Terminated do
|
||||
begin
|
||||
@@ -698,51 +695,28 @@ begin
|
||||
Assigned(FEngine.FOnPullMic) then
|
||||
FEngine.FOnPullMic(FEngine.FAudioBufSize * 2);
|
||||
|
||||
// Обрабатываем накопившиеся блоки с реальными mic-данными
|
||||
DidBlock := False;
|
||||
// Обрабатываем накопившиеся блоки с реальными mic-данными (строго
|
||||
// mic-гейтед: сколько полных mic-блоков в ring — столько TX-блоков).
|
||||
repeat
|
||||
Avail := (FEngine.FTXMicHead - FEngine.FTXMicTail + TX_MIC_RING)
|
||||
and (TX_MIC_RING - 1);
|
||||
if (Avail >= FEngine.FAudioBufSize) and not Terminated then
|
||||
begin
|
||||
FEngine.ProcessTXBlock;
|
||||
DidBlock := True;
|
||||
end
|
||||
FEngine.ProcessTXBlock
|
||||
else
|
||||
Break;
|
||||
until False;
|
||||
|
||||
if Terminated then Break;
|
||||
|
||||
// Если на этом тике не было ни одного полного mic-блока и mic-данных
|
||||
// вообще нет — обрабатываем один блок тишины, чтобы DUC IQ поток не
|
||||
// прерывался и спектр/водопад обновлялись.
|
||||
// Важно: не добавлять silence-block сразу после реального блока. Для TUN
|
||||
// этот "silence" тоже содержит PostGen tone, поэтому лишний блок ломает
|
||||
// темп DUC IQ и даёт периодические боковые/тр-р-р.
|
||||
// Если же в ring уже есть неполный блок, нельзя подменять его тишиной:
|
||||
// radio mic приходит пакетами по 64 сэмпла, sound-card часто по 128.
|
||||
// Иначе каждый mic packet будит поток раньше срока, а мы генерируем
|
||||
// лишний TX-блок тишины вместо ожидания полного 512-sample блока.
|
||||
Avail := (FEngine.FTXMicHead - FEngine.FTXMicTail + TX_MIC_RING)
|
||||
and (TX_MIC_RING - 1);
|
||||
// Тишину генерируем только после 6 подряд пустых тиков (~64 ms).
|
||||
// Порог 64 ms даёт 44 ms запаса относительно периода Opus-фрейма (20 ms),
|
||||
// что покрывает WiFi-джиттер до ~40 ms без ложного инжекта тишины.
|
||||
// При реальной потере пакета тишина всё равно инжектируется.
|
||||
if not DidBlock then
|
||||
begin
|
||||
if Avail = 0 then
|
||||
begin
|
||||
Inc(StallCount);
|
||||
if StallCount >= 6 then
|
||||
FEngine.ProcessTXBlock;
|
||||
end
|
||||
else
|
||||
StallCount := 0;
|
||||
end
|
||||
else
|
||||
StallCount := 0;
|
||||
// Silence-инъекция УБРАНА (модель dl1ycf pihpsdr). Раньше при пустом ring
|
||||
// (>6 тиков) сюда впрыскивался блок тишины «чтобы DUC IQ не прерывался».
|
||||
// Но это фабрикация данных не на радиоклоке: для TUN такой «silence» несёт
|
||||
// PostGen-тон, и лишний блок ломает темп DUC IQ (боковые/тр-р-р); плюс он
|
||||
// над-производит блоки сверх mic-темпа. Продюсер теперь строго mic-гейтед:
|
||||
// блок создаётся ТОЛЬКО когда в ring накопился полный mic-блок (радиокварц
|
||||
// шлёт mic-пакеты непрерывно и на TX/TUN → очередь пополняется радиоклоком).
|
||||
// Реальный обрыв mic (сеть) = короткий разрыв, покрываемый подушкой
|
||||
// FPGA-FIFO радио, без фабрикации тишины в поток.
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user