Skip to content

Commit

Permalink
Merge pull request #7 from gursi26/freq_rescaling
Browse files Browse the repository at this point in the history
finished freq_rescaling
  • Loading branch information
gursi26 committed Mar 10, 2024
2 parents d481e9a + 9f1e8de commit 661c977
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 27 deletions.
23 changes: 5 additions & 18 deletions src/args.rs
Expand Up @@ -15,8 +15,8 @@ pub struct CLIArgs {
fft_fps: u32,

/// Smoothing factor for spatial interpolation between bars
#[clap(long = "bar-smoothness", default_value_t = 1)]
bar_smoothness: u32,
#[clap(long = "smoothness", default_value_t = 1)]
smoothness: u32,

/// Number of individual frequencies detected by the FFT
#[arg(long = "freq-resolution", default_value_t = 90)]
Expand All @@ -30,10 +30,6 @@ pub struct CLIArgs {
#[arg(long = "max-freq", default_value_t = 5000.0)]
max_freq: f32,

/// Size of averaging window (larger = less movement)
#[arg(long = "averaging-window", default_value_t = 1)]
averaging_window: u32,

/// Window width
#[arg(long = "width", default_value_t = 1000.0)]
window_width: f32,
Expand Down Expand Up @@ -81,10 +77,9 @@ pub fn cli_args_to_fft_args(cli_args: CLIArgs) -> FFTArgs {
std::process::exit(1);
}

bar_smoothness_constraint(cli_args.bar_smoothness);
bar_smoothness_constraint(cli_args.smoothness);
fft_fps_constraint(cli_args.fft_fps);
freq_resolution_constraint(cli_args.freq_resolution);
averaging_window_constraint(cli_args.averaging_window);

FFTArgs {
file_path: Path::new(&cli_args.file_path).to_path_buf(),
Expand All @@ -95,12 +90,11 @@ pub fn cli_args_to_fft_args(cli_args: CLIArgs) -> FFTArgs {
text_color: Color::hex(cli_args.text_color).unwrap(),
font_size: cli_args.font_size as i32,
background_color: Color::hex(cli_args.background_color).unwrap(),
bar_smoothness: cli_args.bar_smoothness,
smoothness: cli_args.smoothness,
fft_fps: cli_args.fft_fps,
freq_resolution: cli_args.freq_resolution,
window_height: cli_args.window_height,
window_width: cli_args.window_width,
averaging_window: cli_args.averaging_window,
min_freq: cli_args.min_freq,
max_freq: cli_args.max_freq,
display_gui: cli_args.display_gui
Expand All @@ -113,7 +107,7 @@ pub fn parse_cli_args() -> FFTArgs {
// Value constraints
pub fn bar_smoothness_constraint(v: u32) {
if v > 3 {
println!("bar-smoothness must be between 0 and 3 inclusive.");
println!("smoothness must be between 0 and 3 inclusive.");
std::process::exit(1);
}
}
Expand All @@ -131,10 +125,3 @@ fn freq_resolution_constraint(v: u32) {
std::process::exit(1);
}
}

fn averaging_window_constraint(v: u32) {
if v < 1 || v > 5 {
println!("averaging-window must be between 1 and 5 inclusive.");
std::process::exit(1);
}
}
17 changes: 15 additions & 2 deletions src/fft.rs
Expand Up @@ -40,7 +40,6 @@ pub fn space_interpolate(v: &mut Vec<f32>, num_new_frames: u32) {
}
}

#[allow(dead_code)]
pub fn smooth_fft(mut fft: FFT, alpha: u32) -> FFT {
let mut new_fft = Vec::new();
for i in (alpha as usize)..(fft.num_frames - alpha as usize) {
Expand All @@ -58,7 +57,7 @@ pub fn smooth_fft(mut fft: FFT, alpha: u32) -> FFT {
fft
}

pub fn normalize_fft(mut fft: FFT, bounds: &[f32], scaling_factor: &[f32]) -> FFT {
pub fn intensity_normalize_fft(mut fft: FFT, bounds: &[f32], scaling_factor: &[f32]) -> FFT {
let min_max_scale = fft.max - fft.min;
let rescale = |mut x: Vec<f32>| -> Vec<f32> {
for i in x.iter_mut() {
Expand All @@ -76,6 +75,20 @@ pub fn normalize_fft(mut fft: FFT, bounds: &[f32], scaling_factor: &[f32]) -> FF
fft
}

pub fn frequency_normalize_fft(mut fft: FFT, scaling_factor: &[f32]) -> FFT {
let n_freq_buckets = scaling_factor.len();
let n_bars = fft.fft[0].len();
let bars_per_bucket = n_bars / n_freq_buckets;
let rescale = |mut x: Vec<f32>| -> Vec<f32> {
for (i, v) in x.iter_mut().enumerate() {
*v *= scaling_factor[(i / bars_per_bucket).min(n_freq_buckets - 1)];
}
x
};
fft.fft = fft.fft.into_par_iter().map(|x| rescale(x)).collect();
fft
}

#[allow(dead_code)]
pub fn write_fft_to_binary_file(filepath: &PathBuf, fft: &FFT) -> io::Result<()> {
let mut file = File::create(filepath)?;
Expand Down
17 changes: 10 additions & 7 deletions src/main.rs
Expand Up @@ -30,15 +30,17 @@ use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;

// TODO : Add to brew, and whatever linux/windows uses
// TODO : Add to other package managers
// TODO : Add yaml config file for changing default settings
// TODO : Add a button to gui to write current state to config file
// TODO : Add a button to gui to reset to default

// Constants
const RENDERING_FPS: u32 = 60;
const RESCALING_THRESHOLDS: &[f32] = &[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
const RESCALING_FACTOR: &[f32] = &[0.4, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6, 0.5];
const INTENSITY_RESCALING: &[f32] = &[0.4, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6, 0.5];
const FREQ_RESCALING: &[f32] = &[0.9, 1.2, 1.2, 1.2, 1.0];
const AVERAGING_WINDOW: u32 = 1;

const MIN_BAR_HEIGHT: f32 = 0.001;
const MAX_BAR_HEIGHT: f32 = 0.45;
Expand All @@ -54,11 +56,10 @@ struct FFTArgs {
font_size: i32,
background_color: Color,
fft_fps: u32,
bar_smoothness: u32,
smoothness: u32,
freq_resolution: u32,
window_width: f32,
window_height: f32,
averaging_window: u32,
min_freq: f32,
max_freq: f32,
display_gui: bool,
Expand All @@ -84,11 +85,13 @@ fn compute_and_preprocess_fft(fp: &PathBuf, args: &FFTArgs) -> Vec<Vec<f32>> {
args.max_freq,
);

fft = smooth_fft(fft, args.averaging_window);
fft = normalize_fft(fft, RESCALING_THRESHOLDS, RESCALING_FACTOR);
fft = smooth_fft(fft, AVERAGING_WINDOW);
fft = intensity_normalize_fft(fft, RESCALING_THRESHOLDS, INTENSITY_RESCALING);
fft = frequency_normalize_fft(fft, FREQ_RESCALING);

let mut fft_vec = fft.fft;

// Reverses bar order and prepends
for c in fft_vec.iter_mut() {
let mut reversed = c.clone();
reversed.reverse();
Expand All @@ -98,7 +101,7 @@ fn compute_and_preprocess_fft(fp: &PathBuf, args: &FFTArgs) -> Vec<Vec<f32>> {

fft_vec
.par_iter_mut()
.for_each(|x| space_interpolate(x, args.bar_smoothness));
.for_each(|x| space_interpolate(x, args.smoothness));

fft_vec
}
Expand Down

0 comments on commit 661c977

Please sign in to comment.