gets denoising to 'work'

David Kleingeld created

Change summary

crates/audio/src/audio.rs     |  6 +
crates/audio/src/rodio_ext.rs | 93 +++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 2 deletions(-)

Detailed changes

crates/audio/src/audio.rs 🔗

@@ -161,12 +161,14 @@ 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!(1), nz!(2)])
             .prefer_buffer_sizes(512..)
             .open_stream()?;
         info!("Opened microphone: {:?}", stream.config());
 
-        let (replay, stream) = UniformSourceIterator::new(stream, CHANNEL_COUNT, SAMPLE_RATE)
+        let (replay, stream) = stream
+            // .suspicious_stereo_to_mono()
+            .constant_params(CHANNEL_COUNT, SAMPLE_RATE)
             .limit(LimitSettings::live_performance())
             .process_buffer::<BUFFER_SIZE, _>(move |buffer| {
                 let mut int_buffer: [i16; _] = buffer.map(|s| s.to_sample());

crates/audio/src/rodio_ext.rs 🔗

@@ -1,4 +1,5 @@
 use std::{
+    f32,
     sync::{
         Arc, Mutex,
         atomic::{AtomicBool, Ordering},
@@ -25,6 +26,13 @@ pub trait RodioExt: Source + Sized {
         duration: Duration,
     ) -> Result<(Replay, Replayable<Self>), ReplayDurationTooShort>;
     fn take_samples(self, n: usize) -> TakeSamples<Self>;
+    fn denoise(self) -> Result<Denoiser<Self>, DenoiserError>;
+    fn constant_params(
+        self,
+        channel_count: ChannelCount,
+        sample_rate: SampleRate,
+    ) -> UniformSourceIterator<Self>;
+    fn suspicious_stereo_to_mono(self) -> ToMono<Self>;
 }
 
 impl<S: Source> RodioExt for S {
@@ -101,8 +109,88 @@ impl<S: Source> RodioExt for S {
             left_to_take: n,
         }
     }
+    fn denoise(self) -> Result<Denoiser<Self>, DenoiserError> {
+        let res = Denoiser::try_new(self);
+        log::info!("result of new: {res:?}");
+        res
+    }
+    fn constant_params(
+        self,
+        channel_count: ChannelCount,
+        sample_rate: SampleRate,
+    ) -> UniformSourceIterator<Self> {
+        UniformSourceIterator::new(self, channel_count, sample_rate)
+    }
+    fn suspicious_stereo_to_mono(self) -> ToMono<Self> {
+        ToMono {
+            input_channel_count: self.channels(),
+            inner: self,
+            mean: f32::EPSILON * 3.0,
+        }
+    }
+}
+
+/// constant source, only works on a single span
+pub struct ToMono<S> {
+    inner: S,
+    input_channel_count: ChannelCount,
+    /// running mean of second channel 'volume'
+    mean: f32,
+}
+impl<S> ToMono<S> {
+    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<S: Source> Source for ToMono<S> {
+    fn current_span_len(&self) -> Option<usize> {
+        None
+    }
+
+    fn channels(&self) -> ChannelCount {
+        rodio::nz!(1)
+    }
+
+    fn sample_rate(&self) -> SampleRate {
+        self.inner.sample_rate()
+    }
+
+    fn total_duration(&self) -> Option<Duration> {
+        self.inner.total_duration()
+    }
+}
+
+impl<S: Source> Iterator for ToMono<S> {
+    type Item = Sample;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        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<S> {
     inner: S,
     left_to_take: usize,
@@ -147,6 +235,7 @@ impl<S: Source> Source for TakeSamples<S> {
     }
 }
 
+/// constant source, only works on a single span
 #[derive(Debug)]
 struct ReplayQueue {
     inner: ArrayQueue<Vec<Sample>>,
@@ -193,6 +282,7 @@ impl ReplayQueue {
     }
 }
 
+/// constant source, only works on a single span
 pub struct ProcessBuffer<const N: usize, S, F>
 where
     S: Source + Sized,
@@ -260,6 +350,7 @@ where
     }
 }
 
+/// constant source, only works on a single span
 pub struct InspectBuffer<const N: usize, S, F>
 where
     S: Source + Sized,
@@ -324,6 +415,7 @@ where
     }
 }
 
+/// constant source, only works on a single span
 #[derive(Debug)]
 pub struct Replayable<S: Source> {
     inner: S,
@@ -375,6 +467,7 @@ impl<S: Source> Source for Replayable<S> {
     }
 }
 
+/// constant source, only works on a single span
 #[derive(Debug)]
 pub struct Replay {
     rx: Arc<ReplayQueue>,