add browser mic TX: Opus-encoded mic audio from web client to WDSP TX chain

- Browser: AudioWorklet accumulates 960-sample frames, AudioEncoder encodes
  to Opus, sends binary WS frame 'M' + raw Opus packet
- Server: opcode $02 handler decodes Opus via libopus, calls OnWebMic callback
- MainForm: WebOnMic converts PSingle→Double, pushes to PushTXMicSamplesD;
  ApplyMOX switches mic source to txmsWeb when web client active, restores on TX-off
- WDSPEngine: added txmsWeb to TTXMicSource enum

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 21:49:51 +03:00
co-authored by Claude Sonnet 4.6
parent 3d25f837af
commit 2ab90e8855
4 changed files with 117 additions and 2 deletions
+32
View File
@@ -255,6 +255,8 @@ type
// --- Settings ---
FSettings: TSettingsManager;
FWebServer: TWebServer; // веб-интерфейс (порт 8080)
FSavedMicSource: TTXMicSource; // сохраняется при переключении на txmsWeb
FWebMicActive: Boolean; // True если текущий TX идёт через txmsWeb
// --- CAT ---
FCATEngine: TCATEngine;
FCATSerial: TCATSerialManager;
@@ -493,6 +495,7 @@ type
procedure WebOnFreqA(Hz: Double);
procedure WebOnAttn(Idx: Integer);
procedure WebOnTun(On_: Boolean);
procedure WebOnMic(Samples: PSingle; Count: Integer);
// Synchronize-обёртки (выполняются в UI-потоке)
procedure SyncWebFreq;
procedure SyncWebMode;
@@ -1101,6 +1104,7 @@ begin
FWebServer.OnFreqA := WebOnFreqA;
FWebServer.OnAttn := WebOnAttn;
FWebServer.OnTun := WebOnTun;
FWebServer.OnWebMic := WebOnMic;
FWebServer.Start;
FillChar(FCATLastGlobal, SizeOf(FCATLastGlobal), 0);
FCATLastGlobal.CATTcpPort := 19090;
@@ -4488,6 +4492,19 @@ begin
end;
if FWDSPReady then
begin
// Переключаем источник микрофона: при TX из браузера — txmsWeb,
// при TX с кнопки без веб-клиента — штатный источник из настроек.
if FTransmitting and Assigned(FWebServer) and FWebServer.WebClientActive then
begin
FSavedMicSource := TTXMicSource(FTXSettings.MicSource);
FWebMicActive := True;
FDSPEngine.SetTXMicSource(txmsWeb);
end
else if not FTransmitting and FWebMicActive then
begin
FWebMicActive := False;
FDSPEngine.SetTXMicSource(FSavedMicSource);
end;
// В non-DUP RX-IQ пакеты дропаются на входе DSP-потока во время TX,
// чтобы TX leakage не накапливался в RXA pipeline и FFT-истории
// RX-анализатора. В DUP RX-тракт работает как обычно.
@@ -5252,6 +5269,21 @@ begin
ApplyTUN(FWebSyncBool);
end;
procedure TMainForm.WebOnMic(Samples: PSingle; Count: Integer);
var
Singles: array[0..5759] of Single;
Buf: array[0..5759] of Double;
i, n: Integer;
begin
if not FWDSPReady then Exit;
n := Count;
if n > Length(Buf) then n := Length(Buf);
Move(Samples^, Singles[0], n * SizeOf(Single));
for i := 0 to n - 1 do
Buf[i] := Singles[i];
FDSPEngine.PushTXMicSamplesD(Buf, n);
end;
procedure TMainForm.TrkDriveChange(Sender: TObject);
begin
FDriveLevel := CalcDriveByte;