From cb9f7207aeb930aebf43b5dee5a4a83e1845c797 Mon Sep 17 00:00:00 2001 From: David Kleingeld Date: Mon, 15 Sep 2025 11:33:20 +0200 Subject: [PATCH] gets denoising to 'work' --- crates/audio/src/audio.rs | 5 ++- crates/audio/src/rodio_ext.rs | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/crates/audio/src/audio.rs b/crates/audio/src/audio.rs index c6566306b83766a3a76b652b6455166356a79790..d3f9f72cbba3444a86b68ec819b3fdee340b4f88 100644 --- a/crates/audio/src/audio.rs +++ b/crates/audio/src/audio.rs @@ -161,12 +161,13 @@ impl Audio { .default_device()? .default_config()? .prefer_sample_rates([SAMPLE_RATE, SAMPLE_RATE.saturating_mul(nz!(2))]) - .prefer_channel_counts([nz!(1), nz!(2)]) + .prefer_channel_counts([nz!(2)]) .prefer_buffer_sizes(512..) .open_stream()?; info!("Opened microphone: {:?}", stream.config()); let (replay, stream) = stream + // .suspicious_stereo_to_mono() .constant_params(CHANNEL_COUNT, SAMPLE_RATE) .limit(LimitSettings::live_performance()) .process_buffer::(move |buffer| { @@ -216,7 +217,7 @@ impl Audio { let (replay_source, source) = source .automatic_gain_control(1.0, 4.0, 0.0, 5.0) .periodic_access(Duration::from_millis(100), move |agc_source| { - agc_source.set_enabled(LIVE_SETTINGS.control_input_volume.load(Ordering::Relaxed)); + agc_source.set_enabled(LIVE_SETTINGS.control_output_volume.load(Ordering::Relaxed)); }) .replayable(REPLAY_DURATION) .expect("REPLAY_DURATION is longer then 100ms"); diff --git a/crates/audio/src/rodio_ext.rs b/crates/audio/src/rodio_ext.rs index edcb49fea8ad2c10b63301803c9fa46bbd86d66f..c4a7ef1982c4ea5d49cbbdd4b9700f9bdfad9bcb 100644 --- a/crates/audio/src/rodio_ext.rs +++ b/crates/audio/src/rodio_ext.rs @@ -1,4 +1,5 @@ use std::{ + f32, sync::{ Arc, Mutex, atomic::{AtomicBool, Ordering}, @@ -32,6 +33,7 @@ pub trait RodioExt: Source + Sized { channel_count: ChannelCount, sample_rate: SampleRate, ) -> UniformSourceIterator; + fn suspicious_stereo_to_mono(self) -> ToMono; } impl RodioExt for S { @@ -120,8 +122,76 @@ impl RodioExt for S { ) -> UniformSourceIterator { UniformSourceIterator::new(self, channel_count, sample_rate) } + fn suspicious_stereo_to_mono(self) -> ToMono { + ToMono { + input_channel_count: self.channels(), + inner: self, + mean: f32::EPSILON * 3.0, + } + } +} + +/// constant source, only works on a single span +pub struct ToMono { + inner: S, + input_channel_count: ChannelCount, + /// running mean of second channel 'volume' + mean: f32, +} +impl ToMono { + fn real_stereo(&self) -> bool { + dbg!(self.mean); + dbg!(self.mean >= f32::EPSILON * 3.0) + } + + fn update_mean(&mut self, second_channel: Sample) { + const HISTORY: f32 = 500.0; + self.mean *= (HISTORY - 1.0) / HISTORY; + self.mean += second_channel.abs() / HISTORY; + } +} + +impl Source for ToMono { + fn current_span_len(&self) -> Option { + None + } + + fn channels(&self) -> ChannelCount { + rodio::nz!(1) + } + + fn sample_rate(&self) -> SampleRate { + self.inner.sample_rate() + } + + fn total_duration(&self) -> Option { + self.inner.total_duration() + } +} + +impl Iterator for ToMono { + type Item = Sample; + + fn next(&mut self) -> Option { + match self.input_channel_count.get() { + 1 => self.next(), + 2 => { + let first_channel = self.next()?; + let second_channel = self.next()?; + self.update_mean(second_channel); + + if self.real_stereo() { + Some((first_channel + second_channel) / 2.0) + } else { + Some(first_channel) + } + } + _ => todo!("unsupported channel count"), + } + } } +/// constant source, only works on a single span pub struct TakeSamples { inner: S, left_to_take: usize, @@ -166,6 +236,7 @@ impl Source for TakeSamples { } } +/// constant source, only works on a single span #[derive(Debug)] struct ReplayQueue { inner: ArrayQueue>, @@ -212,6 +283,7 @@ impl ReplayQueue { } } +/// constant source, only works on a single span pub struct ProcessBuffer where S: Source + Sized, @@ -279,6 +351,7 @@ where } } +/// constant source, only works on a single span pub struct InspectBuffer where S: Source + Sized, @@ -343,6 +416,7 @@ where } } +/// constant source, only works on a single span #[derive(Debug)] pub struct Replayable { inner: S, @@ -394,6 +468,7 @@ impl Source for Replayable { } } +/// constant source, only works on a single span #[derive(Debug)] pub struct Replay { rx: Arc,