choose profile from supported
Build Mumble Web 2 / linux_build (push) Successful in 1m39s
Build Mumble Web 2 / windows_build (push) Successful in 2m30s

This commit is contained in:
2025-12-04 22:08:15 -07:00
parent f3ffcf6d89
commit fa6f336305
4 changed files with 41 additions and 23 deletions
+3 -3
View File
@@ -97,13 +97,13 @@ impl AudioProcessor {
}
impl AudioProcessor {
pub fn process(&mut self, audio: &[f32], output: &mut Vec<f32>) {
pub fn process(&mut self, audio: &[f32], channels: usize, output: &mut Vec<f32>) {
let mut include_raw = true;
if self.denoise {
with_denoising_model(&self.spawn, |df| {
include_raw = false;
self.buffer.extend_from_slice(audio);
self.buffer.extend(audio.iter().step_by(channels).copied());
output.reserve(audio.len());
let hop = df.hop_size;
@@ -130,7 +130,7 @@ impl AudioProcessor {
}
if include_raw {
output.extend_from_slice(audio);
output.extend(audio.iter().step_by(channels).copied());
}
}
}
+36 -18
View File
@@ -1,7 +1,7 @@
use crate::app::Command;
use crate::effects::{AudioProcessor, AudioProcessorSender};
use color_eyre::eyre::{eyre, Context, Error};
use cpal::traits::{DeviceTrait, HostTrait};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait as _};
use dioxus::hooks::UnboundedReceiver;
use futures::io::{AsyncRead, AsyncWrite};
use mumble_protocol::control::ClientControlCodec;
@@ -64,11 +64,34 @@ impl AudioSystem {
self.processors.store(Some(processor))
}
fn choose_config(&self, configs: impl Iterator<Item=cpal::SupportedStreamConfigRange>) -> Result<cpal::StreamConfig, Error> {
let mut supported_configs: Vec<_> = configs
.filter_map(|cfg| cfg.try_with_sample_rate(cpal::SampleRate(SAMPLE_RATE)))
.filter(|cfg| cfg.sample_format() == cpal::SampleFormat::I16)
.map(|cfg| {
cpal::StreamConfig {
buffer_size: cpal::BufferSize::Fixed(match *cfg.buffer_size() {
cpal::SupportedBufferSize::Range { min, max } => 480.clamp(min, max),
cpal::SupportedBufferSize::Unknown => 480,
}),
..cfg.config()
}
})
.collect();
supported_configs.sort_by(|a, b| {
let cpal::BufferSize::Fixed(a_buf) = a.buffer_size else { unreachable!() };
let cpal::BufferSize::Fixed(b_buf) = b.buffer_size else { unreachable!() };
Ord::cmp(&a.channels, &b.channels).then(Ord::cmp(&a_buf, &b_buf))
});
supported_configs.get(0).cloned().ok_or(eyre!("no supported stream configs"))
}
pub fn start_recording(
&mut self,
mut each: impl FnMut(Vec<u8>) + Send + 'static,
) -> Result<(), Error> {
info!("creating recording on {:?} with {:#?}", self.input.name()?, self.input.supported_input_configs()?.collect::<Vec<_>>());
let config = self.choose_config(self.input.supported_input_configs()?)?;
info!("creating recording on {:?} with {:#?}", self.input.name()?, config);
let mut encoder =
opus::Encoder::new(SAMPLE_RATE, opus::Channels::Mono, opus::Application::Voip)?;
let mut current_processor = AudioProcessor::new_plain();
@@ -79,7 +102,7 @@ impl AudioSystem {
if let Some(new_processor) = processors.take() {
current_processor = new_processor;
}
current_processor.process(frame, &mut output_buffer);
current_processor.process(frame, config.channels as usize, &mut output_buffer);
if output_buffer.len() < PACKET_SAMPLES as usize {
return;
}
@@ -96,16 +119,13 @@ impl AudioSystem {
};
match self.input.build_input_stream(
&cpal::StreamConfig {
channels: 1,
sample_rate: cpal::SampleRate(SAMPLE_RATE),
buffer_size: cpal::BufferSize::Fixed(PACKET_SAMPLES),
},
&config,
data_callback,
error_callback,
None,
) {
Ok(stream) => {
stream.play()?;
self.recording_stream = Some(stream);
Ok(())
}
@@ -117,7 +137,8 @@ impl AudioSystem {
}
pub fn create_player(&mut self) -> Result<AudioPlayer, Error> {
info!("creating player on {:?} with {:#?}", self.output.name()?, self.output.supported_output_configs()?.collect::<Vec<_>>());
let config = self.choose_config(self.input.supported_input_configs()?)?;
info!("creating player on {:?} with {:#?}", self.output.name().ok(), &config);
let buffer = Arc::new(Mutex::new(dasp_ring_buffer::Bounded::from_raw_parts(
0,
0,
@@ -130,20 +151,16 @@ impl AudioSystem {
let stream = {
let buffer = buffer.clone();
self.output.build_output_stream(
&cpal::StreamConfig {
channels: 1,
sample_rate: cpal::SampleRate(SAMPLE_RATE),
buffer_size: cpal::BufferSize::Fixed(480), // 10ms playback delay
},
move |frame, info| {
&config,
move |frame, _info| {
let mut buffer = buffer.lock().unwrap();
for x in frame.iter_mut() {
for x in frame.chunks_mut(config.channels as usize) {
match buffer.pop() {
Some(y) => {
*x = y;
x.fill(y);
}
None => {
*x = 0;
x.fill(0);
}
}
}
@@ -152,6 +169,7 @@ impl AudioSystem {
None,
)?
};
stream.play()?;
Ok(AudioPlayer {
decoder,
stream,
+1 -1
View File
@@ -209,7 +209,7 @@ fn process_audio(frame: &JsValue, processor: &mut AudioProcessor) {
};
let input = samples.to_vec();
let mut output = Vec::with_capacity(input.len());
processor.process(&input, &mut output);
processor.process(&input, 1, &mut output);
samples.copy_from(&output);
}