use alloc::vec::Vec;
pub fn apply_lpf_i16(data: &mut [i16], sample_rate_hz: u16, cutoff_frequency_hz: u16) {
let rc = 1_f64 / (cutoff_frequency_hz as f64 * 2_f64 * core::f64::consts::PI);
let dt = 1_f64 / sample_rate_hz as f64;
let alpha = dt / (rc + dt);
let mut cpy_orig_data = Vec::with_capacity(data.len());
cpy_orig_data.extend_from_slice(data);
data[0] = (alpha * cpy_orig_data[0] as f64) as i16;
for i in 1..data.len() {
data[i] = (data[i - 1] as f64
+ alpha *
(cpy_orig_data[i] as f64 - data[i-1] as f64)) as i16;
}
}
pub fn apply_lpf_i32(data: &mut [i32], sample_rate_hz: u16, cutoff_frequency_hz: u16) {
let rc = 1_f64 / (cutoff_frequency_hz as f64 * 2_f64 * core::f64::consts::PI);
let dt = 1_f64 / sample_rate_hz as f64;
let alpha = dt / (rc + dt);
let mut cpy_orig_data = Vec::with_capacity(data.len());
cpy_orig_data.extend_from_slice(data);
data[0] = (alpha * cpy_orig_data[0] as f64) as i32;
for i in 1..data.len() {
data[i] = (data[i - 1] as f64
+ alpha *
(cpy_orig_data[i] as f64 - data[i-1] as f64)) as i32;
}
}
#[cfg(test)]
mod tests {
use super::*;
use minimp3::{Decoder as Mp3Decoder, Frame as Mp3Frame, Error as Mp3Error};
use crate::test::{TEST_SAMPLES_DIR, TEST_OUT_DIR};
use std::path::PathBuf;
use std::fs::File;
use audio_visualizer::{Channels, ChannelInterleavement};
use audio_visualizer::waveform::staticc::png_file::visualize;
use std::time::Instant;
#[test]
fn test_visualize_lowpassed_data() {
let mut path = PathBuf::new();
path.push(TEST_SAMPLES_DIR);
path.push("sample_1.mp3");
let mut decoder = Mp3Decoder::new(File::open(path).unwrap());
let mut lrlr_mp3_samples = vec![];
loop {
match decoder.next_frame() {
Ok(Mp3Frame { data: samples_of_frame, .. }) => {
for sample in samples_of_frame {
lrlr_mp3_samples.push(sample);
}
}
Err(Mp3Error::Eof) => break,
Err(e) => panic!("{:?}", e),
}
}
visualize(
&lrlr_mp3_samples,
Channels::Stereo(ChannelInterleavement::LRLR),
TEST_OUT_DIR,
"sample_1_waveform.png"
);
let (mut left, mut right) = Channels::Stereo(ChannelInterleavement::LRLR)
.stereo_interleavement()
.to_channel_data(&lrlr_mp3_samples);
let now = Instant::now();
apply_lpf_i16(&mut left, 44100, 120);
let then = now.elapsed();
println!("took {}us to apply low pass filter for left channel ({}) samples", then.as_micros(), left.len());
apply_lpf_i16(&mut right, 44100, 120);
visualize(
&left,
Channels::Mono,
TEST_OUT_DIR,
"sample_1_waveform_lowpassed_left.png"
);
visualize(
&right,
Channels::Mono,
TEST_OUT_DIR,
"sample_1_waveform_lowpassed_right.png"
);
}
}