mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Revert "fix TX clicks в TUN: 1 ProcessTXBlock на тик вместо 2-3"
This reverts commit e813ada6b2.
This commit is contained in:
+34
-29
@@ -527,52 +527,56 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTXDSPThread.Execute;
|
procedure TTXDSPThread.Execute;
|
||||||
// Тикает по таймеру с периодом одного mic-буфера (FAudioBufSize/FAudioRate).
|
// Аналог tx_thread в piHPSDR/transmitter.c:
|
||||||
// Семафор НЕ используется как сигнал «есть mic-данные» — он бы давал
|
// Тикает с периодом одного mic-буфера (FAudioBufSize/FAudioRate).
|
||||||
// немедленные возвраты из WaitFor (auto-reset event) и приводил к
|
// Если mic-данные накопились — обрабатывает их; если нет — обрабатывает тишину.
|
||||||
// over-production IQ-потока: за один реальный период радио мы шлём
|
// Это обеспечивает непрерывный поток DUC IQ к железу и TX-сигнал на спектре/водопаде.
|
||||||
// 2–3 блока вместо одного. Это и было слышно в TUN как щелчки.
|
|
||||||
// Семафор оставлен только для будилки на shutdown (Terminate → Set).
|
|
||||||
//
|
|
||||||
// За один тик:
|
|
||||||
// - Pull mic из PortAudio (sound-card path).
|
|
||||||
// - Inner loop: процессим все накопившиеся полные блоки (обычно 1).
|
|
||||||
// - Если ничего реального не процессили — гоним один блок тишины,
|
|
||||||
// чтобы DUC IQ поток не прерывался и FIFO радио не голодал.
|
|
||||||
var
|
var
|
||||||
Avail: Integer;
|
Avail: Integer;
|
||||||
PeriodMs: Integer;
|
PeriodMs: Integer;
|
||||||
ProcessedAny: Boolean;
|
|
||||||
begin
|
begin
|
||||||
|
// 512 сэмплов / 48000 Гц = ~10.67 мс → округляем вниз до 10 мс
|
||||||
PeriodMs := Max(1, FEngine.FAudioBufSize * 1000 div FEngine.FAudioRate);
|
PeriodMs := Max(1, FEngine.FAudioBufSize * 1000 div FEngine.FAudioRate);
|
||||||
|
|
||||||
while not Terminated do
|
while not Terminated do
|
||||||
begin
|
begin
|
||||||
// Ждём ровно PeriodMs. Сем сигналится только при Terminate → быстрый shutdown.
|
// Ждём сигнала от mic-данных ИЛИ истечения периода —
|
||||||
|
// в piHPSDR timing идёт от receive thread; здесь — от таймаута
|
||||||
RTLEventWaitFor(FEngine.FTXMicSem, PeriodMs);
|
RTLEventWaitFor(FEngine.FTXMicSem, PeriodMs);
|
||||||
if Terminated then Break;
|
if Terminated then Break;
|
||||||
if not FEngine.FTXActive then Continue;
|
if not FEngine.FTXActive then Continue;
|
||||||
|
|
||||||
|
// Если выбран sound-card mic — тянем сэмплы из внешнего источника
|
||||||
|
// (PortAudio через FOnPullMic в MainForm) ПЕРЕД проверкой ring buffer.
|
||||||
|
// Callback сам пушит сэмплы в FTXMicRing через PushTXMicSampleD.
|
||||||
if (FEngine.FTXMicSource = txmsSoundCard) and
|
if (FEngine.FTXMicSource = txmsSoundCard) and
|
||||||
Assigned(FEngine.FOnPullMic) then
|
Assigned(FEngine.FOnPullMic) then
|
||||||
FEngine.FOnPullMic(FEngine.FAudioBufSize * 2);
|
FEngine.FOnPullMic(FEngine.FAudioBufSize * 2);
|
||||||
|
|
||||||
ProcessedAny := False;
|
// Обрабатываем накопившиеся блоки с реальными mic-данными
|
||||||
repeat
|
repeat
|
||||||
Avail := (FEngine.FTXMicHead - FEngine.FTXMicTail + TX_MIC_RING)
|
Avail := (FEngine.FTXMicHead - FEngine.FTXMicTail + TX_MIC_RING)
|
||||||
and (TX_MIC_RING - 1);
|
and (TX_MIC_RING - 1);
|
||||||
if (Avail >= FEngine.FAudioBufSize) and not Terminated then
|
if (Avail >= FEngine.FAudioBufSize) and not Terminated then
|
||||||
begin
|
FEngine.ProcessTXBlock
|
||||||
FEngine.ProcessTXBlock;
|
else
|
||||||
ProcessedAny := True;
|
|
||||||
end else
|
|
||||||
Break;
|
Break;
|
||||||
until False;
|
until False;
|
||||||
|
|
||||||
if Terminated then Break;
|
if Terminated then Break;
|
||||||
|
|
||||||
if not ProcessedAny then
|
// Если mic-данных не было — обрабатываем один блок тишины, чтобы
|
||||||
FEngine.ProcessTXBlock;
|
// DUC IQ поток не прерывался и спектр/водопад обновлялись.
|
||||||
|
// НО для sound-card mic неполный блок (0 < Avail < AudioBufSize) нельзя
|
||||||
|
// подменять тишиной: PortAudio часто отдаёт 128-сэмпловые callback'и,
|
||||||
|
// и если в кольце уже есть голосовой хвост — он застрянет, а в эфир
|
||||||
|
// уйдёт тишина. Слышно как чередование «голос/тишина» = треск ≈50–100 Гц.
|
||||||
|
// В этом случае ждём следующий тик, хвост накопится до полного блока.
|
||||||
|
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;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1610,10 +1614,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
// если буфер полон — сэмпл отбрасывается (overrun)
|
// если буфер полон — сэмпл отбрасывается (overrun)
|
||||||
end;
|
end;
|
||||||
// Семафор намеренно не сигналим — TX-поток тикает по таймеру
|
|
||||||
// (PeriodMs = AudioBufSize/AudioRate). Сигнал давал бы немедленный
|
RTLEventSetEvent(FTXMicSem); // будим TX поток
|
||||||
// возврат из WaitFor → лишний ProcessTXBlock → over-production
|
|
||||||
// IQ-потока относительно темпа радио → щелчки/FIFO-overrun.
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.PushTXMicSampleD(const S: Double);
|
procedure TWDSPEngine.PushTXMicSampleD(const S: Double);
|
||||||
@@ -1625,7 +1627,8 @@ begin
|
|||||||
FTXMicRing[FTXMicHead] := S;
|
FTXMicRing[FTXMicHead] := S;
|
||||||
FTXMicHead := newHead;
|
FTXMicHead := newHead;
|
||||||
end;
|
end;
|
||||||
// overrun → дроп, как в HW path. Сем не сигналим — см. PushTXMicSamples16.
|
// overrun → дроп, как в HW path
|
||||||
|
RTLEventSetEvent(FTXMicSem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TWDSPEngine.PushTXMicSamplesD(const Src: array of Double; N: Integer);
|
procedure TWDSPEngine.PushTXMicSamplesD(const Src: array of Double; N: Integer);
|
||||||
@@ -1646,7 +1649,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
// overrun → дроп
|
// overrun → дроп
|
||||||
end;
|
end;
|
||||||
// Сем не сигналим — см. PushTXMicSamples16.
|
|
||||||
|
if cnt > 0 then
|
||||||
|
RTLEventSetEvent(FTXMicSem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user