mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
Fix DUC IQ pacing for TX tune
This commit is contained in:
+29
-13
@@ -534,12 +534,22 @@ procedure TTXDSPThread.Execute;
|
||||
var
|
||||
Avail: Integer;
|
||||
PeriodMs: Integer;
|
||||
PeriodUs: Integer;
|
||||
AccUs: Integer;
|
||||
DidBlock: Boolean;
|
||||
begin
|
||||
// 512 сэмплов / 48000 Гц = ~10.67 мс → округляем вниз до 10 мс
|
||||
PeriodMs := Max(1, FEngine.FAudioBufSize * 1000 div FEngine.FAudioRate);
|
||||
// 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;
|
||||
|
||||
while not Terminated do
|
||||
begin
|
||||
Inc(AccUs, PeriodUs);
|
||||
PeriodMs := Max(1, AccUs div 1000);
|
||||
Dec(AccUs, PeriodMs * 1000);
|
||||
|
||||
// Ждём сигнала от mic-данных ИЛИ истечения периода —
|
||||
// в piHPSDR timing идёт от receive thread; здесь — от таймаута
|
||||
RTLEventWaitFor(FEngine.FTXMicSem, PeriodMs);
|
||||
@@ -554,29 +564,35 @@ begin
|
||||
FEngine.FOnPullMic(FEngine.FAudioBufSize * 2);
|
||||
|
||||
// Обрабатываем накопившиеся блоки с реальными mic-данными
|
||||
DidBlock := False;
|
||||
repeat
|
||||
Avail := (FEngine.FTXMicHead - FEngine.FTXMicTail + TX_MIC_RING)
|
||||
and (TX_MIC_RING - 1);
|
||||
if (Avail >= FEngine.FAudioBufSize) and not Terminated then
|
||||
FEngine.ProcessTXBlock
|
||||
begin
|
||||
FEngine.ProcessTXBlock;
|
||||
DidBlock := True;
|
||||
end
|
||||
else
|
||||
Break;
|
||||
until False;
|
||||
|
||||
if Terminated then Break;
|
||||
|
||||
// Если mic-данных не было — обрабатываем один блок тишины, чтобы
|
||||
// DUC IQ поток не прерывался и спектр/водопад обновлялись.
|
||||
// НО для sound-card mic неполный блок (0 < Avail < AudioBufSize) нельзя
|
||||
// подменять тишиной: PortAudio часто отдаёт 128-сэмпловые callback'и,
|
||||
// и если в кольце уже есть голосовой хвост — он застрянет, а в эфир
|
||||
// уйдёт тишина. Слышно как чередование «голос/тишина» = треск ≈50–100 Гц.
|
||||
// В этом случае ждём следующий тик, хвост накопится до полного блока.
|
||||
// Если на этом тике не было ни одного полного 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);
|
||||
if (Avail = 0) or (FEngine.FTXMicSource <> txmsSoundCard) then
|
||||
if Avail < FEngine.FAudioBufSize then
|
||||
FEngine.ProcessTXBlock;
|
||||
if (not DidBlock) and (Avail = 0) then
|
||||
FEngine.ProcessTXBlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user