diff --git a/lib/src/processor/memory/mmio/apu/downsampler.rs b/lib/src/processor/memory/mmio/apu/downsampler.rs index 7365c5f..79e8b1f 100644 --- a/lib/src/processor/memory/mmio/apu/downsampler.rs +++ b/lib/src/processor/memory/mmio/apu/downsampler.rs @@ -2,9 +2,47 @@ use crate::constants::CLOCK_SPEED; const TIME_PER_CYCLE: f32 = 1. / CLOCK_SPEED as f32; +struct Averager { + accum: [f32; 2], + num: usize, +} + +impl Default for Averager { + fn default() -> Self { + Self { + accum: [0.; 2], + num: 0, + } + } +} + +impl Averager { + fn push(&mut self, next: &[f32; 2]) { + self.accum[0] += next[0]; + self.accum[1] += next[1]; + self.num += 1; + } + + fn get(&self) -> [f32; 2] { + let div = self.num as f32; + [self.accum[0] / div, self.accum[1] / div] + } + + fn reset(&mut self) { + *self = Self::default(); + } + + fn finish(&mut self) -> [f32; 2] { + let result = self.get(); + self.reset(); + result + } +} + pub(super) struct Downsampler { ratio: f32, time_accum: f32, + average: Averager, } impl Downsampler { @@ -12,16 +50,18 @@ impl Downsampler { Self { ratio: 1. / sample_rate, time_accum: 0., + average: Averager::default(), } } pub fn process(&mut self, signal: Vec<[f32; 2]>) -> Vec<[f32; 2]> { let mut output = vec![]; - for val in signal { + for ref val in signal { self.time_accum += TIME_PER_CYCLE; + self.average.push(val); if self.time_accum >= self.ratio { self.time_accum = 0.; - output.push(val); + output.push(self.average.finish()); } } output