From fc9419e580c78dec63c668613bb1c56359468567 Mon Sep 17 00:00:00 2001 From: Matt McPherrin <git@mcpherrin.ca> Date: Wed, 15 Jul 2015 15:27:15 -0700 Subject: [PATCH] A basic implementation, mostly untested! --- src/lib.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a93251b..bfe3258 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,67 @@ +// This (implicitly/naively) uses a rectangular window. Some way to set up a window function +// will be needed probably -- if mutating your samples before calling this isn't sufficient. + +/// Set up parameters (and some precomputed values for those). +#[derive(Clone, Copy)] +pub struct Parameters { + // Parameters we're working with + window_size: u32, + // Precomputed value: + sine: f32, + cosine: f32, + term_coefficient: f32, +} + +pub struct Partial { + params: Parameters, + //count: u32, + prev: f32, + prevprev: f32, +} + +impl Parameters { + pub fn new(target_freq: f32, sample_rate: f32, window_size: u32) -> Self { + use std::f32; + let k = target_freq * (window_size as f32) / sample_rate; + let omega = (f32::consts::PI * 2. * k) / (window_size as f32); + let cosine = omega.cos(); + Parameters { + window_size: window_size, + sine: omega.sin(), + cosine: cosine, + term_coefficient: 2. * cosine, + } + } + + pub fn start(self) -> Partial { + Partial{ params: self, prev: 0., prevprev: 0. } + } +} + +impl Partial { + pub fn add(mut self, samples: &[u16]) -> Self { + for &sample in samples { + let this = self.params.term_coefficient * self.prev - self.prevprev + (sample as f32); + self.prevprev = self.prev; + self.prev = this; + } + self + } + pub fn finish(self) -> (f32, f32) { + let real = self.prev - self.prevprev * self.params.cosine; + let imag = self.prevprev * self.params.sine; + (real, imag) + } + + pub fn finish_mag(self) -> f32 { + let (real, imag) = self.finish(); + (real*real + imag*imag).sqrt() + } +} + #[test] -fn it_works() { +fn zero_data() { + let p = Parameters::new(1800., 44100., 256); + assert!(p.start().add(&[0; 256]).finish_mag() == 0.); + assert!(p.start().add(&[0; 128]).add(&[0;128]).finish_mag() == 0.); } -- GitLab