fix: isolate continuous-mode mic capture and clarify voice settings

- Use a separate Microphone instance for continuous-mode VAD monitoring
  so it no longer races with the transmit capture path.
- Respect selected input device in continuous-mode monitor subscription.
- Make talk-mode and Sonora processing labels clearer in settings UI.
This commit is contained in:
ReTeamSpeak
2026-05-13 19:14:50 +09:00
parent 272d3a1cb7
commit 83346c337f
2 changed files with 55 additions and 21 deletions
+9 -3
View File
@@ -991,15 +991,21 @@ impl App {
// Continuous talk: monitor mic input when in continuous mode
if self.talk_mode == audio::TalkMode::Continuous {
let mic = self.mic.clone();
let selected_input_device = self.selected_input_device.clone();
let session_id = self.session_id;
subs.push(Subscription::run_with_id(
(session_id, "continuous"),
(session_id, "continuous", selected_input_device.clone()),
iced::stream::channel(100, move |mut sender| async move {
let mic = Arc::new(Mutex::new(audio::Microphone::new()));
let (sample_tx, sample_rx) = std::sync::mpsc::channel();
{
let mut mic_guard = mic.lock().await;
if mic_guard.start(None, sample_tx).is_err() {
let device = if selected_input_device.is_empty() {
None
} else {
Some(selected_input_device.as_str())
};
if mic_guard.start(device, sample_tx).is_err() {
return;
}
}
+46 -18
View File
@@ -643,36 +643,59 @@ impl App {
.width(560),
);
let talk_mode_text = match self.talk_mode {
audio::TalkMode::PushToTalk => "Push-to-Talk (hold V)",
audio::TalkMode::Continuous => "Continuous (voice activation)",
};
let nc_label = self.nc_method.label();
let sonora_noise_label = self.sonora_settings.noise_suppression_level.label();
let voice_col = column![
text("Voice Activation Mode").size(13),
text(talk_mode_text).size(12).style(text::secondary),
text("Talk Mode").size(13),
text("Choose how your microphone starts transmitting.").size(12).style(text::secondary),
vertical_space().height(8),
text("Push-to-Talk Key").size(13),
text("V (hold to talk)").size(12).style(text::secondary),
vertical_space().height(8),
text("Noise Cancellation").size(13),
text("Microphone Processing Backend").size(13),
text(nc_label).size(12).style(text::secondary),
]
.spacing(4)
.padding(16);
let voice_col = voice_col.push(
button(text("Toggle Voice Mode").size(11))
let voice_col = voice_col.push(row![
button(text("Push-to-Talk").size(11))
.padding([4, 12])
.style(theme::secondary_button)
.on_press(Message::ToggleTalkMode),
.style(if self.talk_mode == audio::TalkMode::PushToTalk {
theme::primary_button
} else {
theme::secondary_button
})
.on_press(if self.talk_mode == audio::TalkMode::PushToTalk {
Message::Noop
} else {
Message::ToggleTalkMode
}),
button(text("Voice Activation").size(11))
.padding([4, 12])
.style(if self.talk_mode == audio::TalkMode::Continuous {
theme::primary_button
} else {
theme::secondary_button
})
.on_press(if self.talk_mode == audio::TalkMode::Continuous {
Message::Noop
} else {
Message::ToggleTalkMode
}),
]
.spacing(8)
.align_y(iced::Alignment::Center));
let voice_col = voice_col.push(
text("Advanced options below only affect microphone cleanup, not playback.")
.size(11)
.style(text::secondary),
);
let voice_col = noise_cancel::NoiseCancelMethod::all().iter().copied().fold(
voice_col.push(text("Noise Cancel Backend").size(11).style(text::secondary)),
voice_col.push(text("Processing backend").size(11).style(text::secondary)),
|column, method| {
let label = method.label().to_string();
column.push(
@@ -691,7 +714,10 @@ impl App {
let voice_col = if self.nc_method == noise_cancel::NoiseCancelMethod::Sonora {
let voice_col = voice_col
.push(vertical_space().height(8))
.push(text("Sonora Noise Suppression").size(11).style(text::secondary))
.push(text("Advanced Sonora Processing").size(13))
.push(text("Tune noise cleanup, auto gain, and low-frequency filtering.").size(11).style(text::secondary))
.push(vertical_space().height(4))
.push(text("Noise Suppression Strength").size(11).style(text::secondary))
.push(text(sonora_noise_label).size(12).style(text::secondary));
let voice_col = noise_cancel::NoiseSuppressionLevelSetting::all()
@@ -712,11 +738,12 @@ impl App {
voice_col
.push(vertical_space().height(8))
.push(text("Automatic Gain Control").size(11).style(text::secondary))
.push(
button(text(if self.sonora_settings.agc_enabled {
"AGC2: On"
"AGC2 On"
} else {
"AGC2: Off"
"AGC2 Off"
})
.size(11))
.padding([4, 12])
@@ -727,11 +754,12 @@ impl App {
})
.on_press(Message::ToggleSonoraAgc),
)
.push(text("High-Pass Filter").size(11).style(text::secondary))
.push(
button(text(if self.sonora_settings.high_pass_enabled {
"High-Pass: On"
"High-Pass On"
} else {
"High-Pass: Off"
"High-Pass Off"
})
.size(11))
.padding([4, 12])