diff --git a/crates/audio/src/audio.rs b/crates/audio/src/audio.rs index f60ddb87b9615d2da9c2be248ab397c19a463616..35d8b318e52568bada029c645146e128f9895965 100644 --- a/crates/audio/src/audio.rs +++ b/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::(move |buffer| { let mut int_buffer: [i16; _] = buffer.map(|s| s.to_sample()); diff --git a/crates/audio/src/rodio_ext.rs b/crates/audio/src/rodio_ext.rs index e80b00e15a8fdbd3fc438b78a9ca45d0902dcef1..533fca1ffce2267c163aabe692e4dfb4af38eca4 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}, @@ -25,6 +26,13 @@ pub trait RodioExt: Source + Sized { duration: Duration, ) -> Result<(Replay, Replayable), ReplayDurationTooShort>; fn take_samples(self, n: usize) -> TakeSamples; + fn denoise(self) -> Result, DenoiserError>; + fn constant_params( + self, + channel_count: ChannelCount, + sample_rate: SampleRate, + ) -> UniformSourceIterator; + fn suspicious_stereo_to_mono(self) -> ToMono; } impl RodioExt for S { @@ -101,8 +109,88 @@ impl RodioExt for S { left_to_take: n, } } + fn denoise(self) -> Result, 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 { + 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, @@ -147,6 +235,7 @@ impl Source for TakeSamples { } } +/// constant source, only works on a single span #[derive(Debug)] struct ReplayQueue { inner: ArrayQueue>, @@ -193,6 +282,7 @@ impl ReplayQueue { } } +/// constant source, only works on a single span pub struct ProcessBuffer where S: Source + Sized, @@ -260,6 +350,7 @@ where } } +/// constant source, only works on a single span pub struct InspectBuffer where S: Source + Sized, @@ -324,6 +415,7 @@ where } } +/// constant source, only works on a single span #[derive(Debug)] pub struct Replayable { inner: S, @@ -375,6 +467,7 @@ impl Source for Replayable { } } +/// constant source, only works on a single span #[derive(Debug)] pub struct Replay { rx: Arc,