choose profile from supported
This commit is contained in:
+3
-3
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user