Phase 5 (D1): move RX audio routing into the controller

OnAudioReady moves from MainForm into TRadioController (radio-speaker push +
local AudioOut). The web steal becomes a route hook: controller fires
OnAudioConsume; TWebAdapter.AudioConsume mixes to mono and pushes to the web
client, returning True to skip local AudioOut. Behavior-preserving; removes the
last audio-path coupling to MainForm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-09 14:43:04 +03:00
co-authored by Claude Opus 4.8
parent 682025e99b
commit 7c8fd298ae
3 changed files with 48 additions and 22 deletions
+22
View File
@@ -102,6 +102,12 @@ type
// подача в движок thread-safe (как OnMicPacket/OnDDCIQ контроллера).
procedure OnMic(Samples: PSingle; Count: Integer);
// RX-аудио-перехват: навешивается на FController.OnAudioConsume. Если есть
// активный web-клиент — сводим в моно и шлём ему, возвращаем True (локальный
// AudioOut пропускается контроллером). Вызывается из DSP-потока.
function AudioConsume(const Left, Right: array of Single;
Count: Integer): Boolean;
// Исходящее зеркало: периодический снимок состояния + спектр/водопад в web.
// Зовётся хозяином из GUI-таймера (буферы пикселей — у хозяина, остальное из
// FController). Сервер сам гейтит по FRunning и шлёт активным клиентам.
@@ -360,6 +366,22 @@ begin
FController.FDSPEngine.PushTXMicSamplesD(Buf, n);
end;
function TWebAdapter.AudioConsume(const Left, Right: array of Single;
Count: Integer): Boolean;
var
MonoBuf: array[0..1023] of Single;
i, n: Integer;
begin
Result := False;
if not (Assigned(FServer) and FServer.WebClientActive) then Exit;
n := Count;
if n > Length(MonoBuf) then n := Length(MonoBuf);
for i := 0 to n - 1 do
MonoBuf[i] := (Left[i] + Right[i]) * 0.5;
FServer.PushAudio(@MonoBuf[0], n);
Result := True;
end;
// ── Исходящее зеркало состояния ──────────────────────────────────────────────
procedure TWebAdapter.PushState(const ASpec, AWf: array of Single);