mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
wip(audio): выбор устройства ВВОДА на каждом слайсе + вкладки OUT/IN в AUD
Паритет с уже существующим выбором вывода: на каждом слайсе своё устройство входа (микрофон/виртуальный кабель). - RadioController: TCtrlSlice += InDeviceIndex/InDevName/AudioIn (ссылка, не владение); mic-пул FMicPool с refcount (Acquire/ReleaseMicInput) — один открытый TAudioInput на уникальное PA-устройство, смена TX-слайса не переоткрывает поток; ActiveMicInput/ActiveMicInDevName для PullSoundCardMic, Flush и DefaultMicSource; SetMainMicDevice перепривязывает ссылки слайсов. - VfoOverlay: во fly-out AUD ряд вкладок OUT | IN, событие OnAudioInDevice. - PanafallPanel: проброс списка входных устройств во флаги слайсов и главный. - Settings: персист in_dev_name. НЕ ГОТОВО: зависание GUI при выборе на слайсе того же входа, что в настройках (пул открывает поток вместо шортката на общий FAudioIn). В коде оставлена временная диагностика [MIC] в stderr. Также подозрение на замедление потока данных от радио — проверяем сравнением с main. Со мной в коммите временные тестовые программы PortAudio (other/pa*.lpr). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+28
-13
@@ -599,6 +599,7 @@ type
|
||||
procedure OnVfoOverlayVolume(Vol: Integer);
|
||||
procedure OnVfoOverlayMute(Sender: TObject);
|
||||
procedure OnVfoOverlayAudioDevice(DevIndex: Integer; const DevName: string);
|
||||
procedure OnVfoOverlayAudioInDevice(DevIndex: Integer; const DevName: string);
|
||||
procedure OnVfoOverlaySplit(Sender: TObject);
|
||||
procedure OnVfoOverlayTxSelect(Sender: TObject);
|
||||
procedure OnVfoOverlayRxMuteTx(Sender: TObject); // RXM — приём слайса на TX
|
||||
@@ -3838,8 +3839,10 @@ function TMainForm.DefaultMicSource: TTXMicSource;
|
||||
// иначе используем HW mic-стрим от трансивера.
|
||||
// HW PTT всегда переключает на txmsRadio непосредственно в ApplyMOX.
|
||||
begin
|
||||
if FController.FAudioInDevName <> '' then Result := txmsSoundCard
|
||||
else Result := txmsRadio;
|
||||
// Учитываем вход TX-слайса: у него может быть свой (виртуальный кабель),
|
||||
// даже когда общего входа нет — иначе взяли бы микрофон радио.
|
||||
if FController.ActiveMicInDevName <> '' then Result := txmsSoundCard
|
||||
else Result := txmsRadio;
|
||||
end;
|
||||
|
||||
// ApplyTXSettingsToDSP переехал в TRadioController (вся TX-цепь над FTXSettings).
|
||||
@@ -5739,6 +5742,20 @@ begin
|
||||
FPan.PushMainFlagAudioDevices; // обновить подсветку текущего устройства
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnVfoOverlayAudioInDevice(DevIndex: Integer; const DevName: string);
|
||||
// Вкладка IN во флаге: откуда слайс берёт модуляцию на передаче. У флага
|
||||
// главного VFO это общий вход приложения (то же поле, что в настройках).
|
||||
begin
|
||||
if CurSliceId <> 0 then
|
||||
begin
|
||||
FController.SetSliceInDevice(CurSliceId, DevIndex, DevName);
|
||||
PushFlagStateAllPans(CurSliceId);
|
||||
Exit;
|
||||
end;
|
||||
ApplyAudioInputDevice(DevIndex, DevName);
|
||||
FPan.PushMainFlagAudioDevices;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OnVfoOverlayInvalidate(Sender: TObject);
|
||||
var P: TPanafallPanel;
|
||||
begin
|
||||
@@ -5797,6 +5814,7 @@ begin
|
||||
O.OnVolume := OnVfoOverlayVolume;
|
||||
O.OnMute := OnVfoOverlayMute;
|
||||
O.OnAudioDevice := OnVfoOverlayAudioDevice;
|
||||
O.OnAudioInDevice := OnVfoOverlayAudioInDevice;
|
||||
O.OnSplit := OnVfoOverlaySplit;
|
||||
O.OnTxSelect := OnVfoOverlayTxSelect;
|
||||
O.OnRxMuteTx := OnVfoOverlayRxMuteTx;
|
||||
@@ -6742,6 +6760,7 @@ begin
|
||||
Cfg.Pans[i].Slices[n].FMSQOn := FController.FSlices[s].FMSQOn;
|
||||
Cfg.Pans[i].Slices[n].FMSQLevel := FController.FSlices[s].FMSQLevel;
|
||||
Cfg.Pans[i].Slices[n].DevName := FController.FSlices[s].DevName;
|
||||
Cfg.Pans[i].Slices[n].InDevName := FController.FSlices[s].InDevName;
|
||||
Inc(n);
|
||||
end;
|
||||
end;
|
||||
@@ -6762,6 +6781,10 @@ begin
|
||||
TWDSPAGCMode(EnsureRange(SC.AGC, 0, Ord(High(TWDSPAGCMode)))),
|
||||
EnsureRange(SC.Volume, 0.0, 1.0), DevIdx, SC.DevName, PanId);
|
||||
if Id < 0 then Exit;
|
||||
// Свой вход слайса (имя устройства → PA-индекс текущей сессии).
|
||||
if SC.InDevName <> '' then
|
||||
FController.SetSliceInDevice(Id,
|
||||
FController.FAudioIn.FindDeviceByName(SC.InDevName), SC.InDevName);
|
||||
if SC.Muted then FController.SetSliceMute(Id, True);
|
||||
FController.SetSliceRxMuteOnTx(Id, SC.RxMuteOnTx);
|
||||
if SC.FMSQOn then FController.SetSliceFMSquelch(Id, True, SC.FMSQLevel);
|
||||
@@ -8176,18 +8199,10 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyAudioInputDevice(DevIndex: Integer; const DevName: string);
|
||||
// Общий вход: контроллер сам переоткрывает поток и перепривязывает к нему
|
||||
// слайсы, которые ссылались на общее устройство (mic-пул).
|
||||
begin
|
||||
if FController.FAudioIn.IsOpen then
|
||||
FController.FAudioIn.Close;
|
||||
FController.FAudioIn.DeviceIndex := DevIndex;
|
||||
FController.FAudioInDevName := DevName;
|
||||
if DevIndex >= 0 then
|
||||
begin
|
||||
try
|
||||
FController.FAudioIn.Open;
|
||||
except
|
||||
end;
|
||||
end;
|
||||
FController.SetMainMicDevice(DevIndex, DevName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.ApplyAudioBufferSize(BufferSize: Integer);
|
||||
|
||||
Reference in New Issue
Block a user