Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- fn main() {
- let samples : Vec<f32> = Oscillator::sine().take(20).collect();
- println!("sine: {:?}", samples);
- let lp_samples : Vec<f32> = butterworth_lowpass(Oscillator::sine(), 5000.0).take(20).collect();
- println!("filtered: {:?}", lp_samples);
- }
- struct Oscillator<'a> {
- func: Box<dyn Fn(f32) -> f32 + 'a>,
- phase: f32,
- inc: f32,
- }
- impl<'a> Iterator for Oscillator<'a> {
- type Item = f32;
- fn next(&mut self) -> Option<Self::Item> {
- let wave = (*self.func)(self.phase);
- self.phase += self.inc;
- if self.phase >= 1.0 { self.phase -= 1.0; }
- Some(wave)
- }
- }
- impl<'a> Oscillator<'a> {
- pub fn new< F>(func : F) -> Self where F: Fn(f32)->f32 + 'a {
- Self {
- phase : 0.0,
- inc : 0.05,
- func : Box::new(func),
- }
- }
- pub fn sine() -> Self {
- use std::f32::consts::PI;
- Self::new ( |phase| (2.0 * PI * phase).sin() )
- }
- }
- struct ButterWorthState {
- b0: f32,
- b1: f32,
- b2: f32,
- a1: f32,
- a2: f32,
- x : [f32; 2],
- y : [f32; 2],
- }
- /// pass the given iterator through a 2nd-order butterworth lowpass filter with the given cutoff frequency
- fn butterworth_lowpass<I: Iterator<Item = f32>>(i: I, cutoff: f32) -> impl Iterator<Item = f32> {
- let ita = 1.0 / (std::f32::consts::PI * cutoff / 48000.0).tan();
- let q = 2.0f32.sqrt();
- let b0 = 1.0 / (1.0 + q * ita + ita * ita);
- let b1 = 2.0 * b0;
- let b2 = b0;
- let a1 = 2.0 * (ita * ita - 1.0) * b0;
- let a2 = -(1.0 - q * ita + ita * ita) * b0;
- i.scan(ButterWorthState { b0, b1, b2, a1, a2, x: [0.0, 0.0], y: [0.0, 0.0]}, |s, new_sample| {
- let output = s.b0 * new_sample + s.b1 * s.x[0] + s.b2 * s.x[1] + s.a1 * s.y[0] + s.a2 * s.y[1];
- s.x[1] = s.x[0];
- s.x[0] = new_sample;
- s.y[1] = s.y[0];
- s.y[0] = output;
- Some(output)
- })
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement