Skip to content

Commit

Permalink
restructured AppState resource, replace fft_stopwatch with Instant
Browse files Browse the repository at this point in the history
  • Loading branch information
gursi26 committed Mar 15, 2024
1 parent d12ae9d commit 3ef57a0
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 69 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Expand Up @@ -23,7 +23,6 @@ serde = { version = "1.0.197", features = ["derive"] }
dirs = "5.0.1"
serde_yaml = "0.9.32"
spectrum-analyzer = "1.5.0"
stopwatch = "0.0.7"

[profile.release]
strip = true
Expand Down
10 changes: 4 additions & 6 deletions src/args.rs
@@ -1,7 +1,7 @@
use std::path::Path;
use bevy::prelude::*;
use crate::*;
use bevy::prelude::*;
use clap::{ArgAction, Parser};
use std::path::Path;

#[derive(Debug, Parser)]
#[clap(author, version, about)]
Expand Down Expand Up @@ -101,23 +101,21 @@ pub fn cli_args_to_fft_args(mut cli_args: CLIArgs, use_default: bool) -> FFTArgs
max_freq: cli_args.max_freq.unwrap(),
display_gui: cli_args.display_gui.unwrap(),
volume: cli_args.volume.unwrap(),
paused: false,
fft_fps: FFT_FPS
}
}

pub fn parse_cli_args() -> FFTArgs {
cli_args_to_fft_args(args::CLIArgs::parse(), false)
}
// Value constraints
pub fn bar_smoothness_constraint(v: u32) {
pub fn bar_smoothness_constraint(v: u32) {
if v > 3 {
println!("smoothness must be between 0 and 3 inclusive.");
std::process::exit(1);
}
}

fn freq_resolution_constraint(v: u32) {
fn freq_resolution_constraint(v: u32) {
if v < 10 || v > 300 {
println!("freq-resolution must be between 10 and 300 inclusive.");
std::process::exit(1);
Expand Down
36 changes: 23 additions & 13 deletions src/main.rs
Expand Up @@ -8,7 +8,6 @@ mod systems;
use args::*;
use config::*;
use fft::*;
use stopwatch::Stopwatch;
use systems::egui::*;
use systems::get_keyboard_input::*;
use systems::startup::*;
Expand All @@ -34,6 +33,7 @@ use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;
use std::time::Instant;

// TODO: Add to other package managers
// TODO: Remove fft_fps and other deprecated configs from readme
Expand Down Expand Up @@ -70,29 +70,33 @@ struct FFTArgs {
max_freq: f32,
display_gui: bool,
volume: u32,
paused: bool,
fft_fps: u32,
}

#[derive(Resource)]
struct AppState {
sink: rodio::Sink,
display_str: String,
display_start_time: f64,
paused: bool,
fft_fps: u32,
rendering_fps: u32,
}

#[derive(Resource)]
struct FFTState {
fft: Vec<Vec<f32>>,
curr_bars: Vec<(Handle<Mesh>, Handle<ColorMaterial>)>,
despawn_handles: Vec<Entity>,
total_frame_counter: usize,
fft_frame_counter: usize,
song_stopwatch: Stopwatch,
update_fft_counter: bool,
display_str_stopwatch: Stopwatch,
display_str: String,
fft_timer: Instant,
}

fn compute_and_preprocess_fft(fp: &PathBuf, args: &FFTArgs) -> Vec<Vec<f32>> {
println!("Computing FFT...");
let mut fft = compute_fft(
fp,
args.fft_fps,
FFT_FPS,
args.freq_resolution,
args.min_freq,
args.max_freq,
Expand Down Expand Up @@ -175,19 +179,25 @@ fn main() {
let sink = rodio::Sink::try_new(&stream_handle).unwrap();
sink.set_volume(volume as f32 / 100.0);
sink.append(source);
let song_stopwatch = Stopwatch::start_new();

// Start stopwatch that keeps fft in sync
let fft_timer = Instant::now();

app.insert_resource(AppState {
sink,
display_str: String::new(),
display_start_time: 0.0,
paused: false,
fft_fps: FFT_FPS,
rendering_fps: RENDERING_FPS,
})
.insert_resource(FFTState {
fft: fft_vec,
curr_bars: Vec::new(),
despawn_handles: Vec::new(),
fft_frame_counter: 0,
total_frame_counter: 0,
song_stopwatch,
display_str_stopwatch: Stopwatch::new(),
display_str: String::new(),
update_fft_counter: false,
fft_timer,
});

app.run();
Expand Down
25 changes: 12 additions & 13 deletions src/systems/egui.rs
@@ -1,12 +1,15 @@
use crate::{cli_args_to_fft_args, config_path, parse_cli_args, reset_config_file, write_fftargs_to_config, AppState, FFTArgs};
use crate::{
cli_args_to_fft_args, config_path, parse_cli_args, reset_config_file, write_fftargs_to_config,
AppState, FFTArgs, FFTState,
};
use bevy::render::mesh::VertexAttributeValues;
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy::sprite::Anchor;
use bevy::{
app::AppExit,
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use clap::{ArgAction, Parser};
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
Expand All @@ -17,10 +20,10 @@ use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;


pub fn ui_example_system(
mut contexts: EguiContexts,
keyboard_input: Res<ButtonInput<KeyCode>>,
mut fft_state: ResMut<FFTState>,
mut app_state: ResMut<AppState>,
mut args: ResMut<FFTArgs>,
) {
Expand Down Expand Up @@ -68,28 +71,25 @@ pub fn ui_example_system(
if ui.button("Save").clicked() {
write_fftargs_to_config(&args);
app_state.display_str = format!("Saved to {:?}", config_path());
app_state.display_str_stopwatch.start();
app_state.display_start_time = fft_state.fft_timer.elapsed().as_secs_f64();
}
if ui.button("Reset").clicked() {
*args = parse_cli_args();
app_state.display_str = String::from("Reset to saved settings.");
app_state.display_str_stopwatch.start();
app_state.display_start_time = fft_state.fft_timer.elapsed().as_secs_f64();
args.display_gui = true;
}
if ui.button("Reset to default").clicked() {
*args = cli_args_to_fft_args(crate::args::CLIArgs::parse(), true);
app_state.display_str = String::from("Reset to default settings.");
app_state.display_str_stopwatch.start();
app_state.display_start_time = fft_state.fft_timer.elapsed().as_secs_f64();
args.display_gui = true;
}
});

if app_state.display_str_stopwatch.is_running() {
ui.label(&app_state.display_str);
}
if app_state.display_str_stopwatch.elapsed().as_secs() > 3 {
app_state.display_str_stopwatch.stop();
app_state.display_str_stopwatch.reset();
ui.label(&app_state.display_str);
if fft_state.fft_timer.elapsed().as_secs_f64() - app_state.display_start_time > 5.0 {
app_state.display_str = String::new();
}
});
}
Expand Down Expand Up @@ -117,4 +117,3 @@ fn color_picker_widget(ui: &mut egui::Ui, color: &mut Color) -> egui::Response {
);
res
}

8 changes: 4 additions & 4 deletions src/systems/get_keyboard_input.rs
@@ -1,12 +1,12 @@
use crate::{AppState, FFTArgs};
use crate::{AppState, FFTArgs, FFTState};
use bevy::render::mesh::VertexAttributeValues;
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy::sprite::Anchor;
use bevy::{
app::AppExit,
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use clap::{ArgAction, Parser};
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
Expand All @@ -17,10 +17,10 @@ use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;


pub fn get_keyboard_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut exit: EventWriter<AppExit>,
mut fft_state: ResMut<FFTState>,
mut app_state: ResMut<AppState>,
mut args: ResMut<FFTArgs>,
) {
Expand All @@ -31,7 +31,7 @@ pub fn get_keyboard_input(
args.display_gui = !args.display_gui;
}
if keyboard_input.just_pressed(KeyCode::Space) {
args.paused = !args.paused;
app_state.paused = !app_state.paused;
if app_state.sink.is_paused() {
app_state.sink.play();
} else {
Expand Down
7 changes: 3 additions & 4 deletions src/systems/startup.rs
@@ -1,12 +1,12 @@
use crate::{AppState, FFTArgs};
use crate::{FFTArgs, FFTState};
use bevy::render::mesh::VertexAttributeValues;
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy::sprite::Anchor;
use bevy::{
app::AppExit,
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};
use bevy_egui::egui::{Align2, Color32, Stroke};
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use clap::{ArgAction, Parser};
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
Expand All @@ -17,7 +17,6 @@ use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;


fn spawn_bars(
num_bars: u32,
w: f32,
Expand Down Expand Up @@ -75,7 +74,7 @@ pub fn startup(
mut window: Query<&mut Window>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
mut fft_queue: ResMut<AppState>,
mut fft_queue: ResMut<FFTState>,
clear_color: Res<ClearColor>,
args: Res<FFTArgs>,
) {
Expand Down
16 changes: 8 additions & 8 deletions src/systems/update_fft.rs
Expand Up @@ -23,32 +23,32 @@ pub fn update_fft(
mut window: Query<&mut Window>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
mut fft_state: ResMut<FFTState>,
mut app_state: ResMut<AppState>,
mut args: ResMut<FFTArgs>,
mut clear_color: ResMut<ClearColor>,
mut text_query: Query<&mut Text>,
) {
let h = window.single_mut().height();
app_state.update_fft_counter = false;
let interval = RENDERING_FPS / args.fft_fps;
let interval = app_state.rendering_fps / app_state.fft_fps;

// Get the current frame (either from fft or interpolation)
let curr_fft = match app_state.total_frame_counter as u32 % interval {
let curr_fft = match fft_state.total_frame_counter as u32 % interval {
0 => {
if app_state.fft_frame_counter >= app_state.fft.len() - 1 {
if fft_state.fft_frame_counter >= fft_state.fft.len() - 1 {
std::process::exit(0);
}
app_state.fft[app_state.fft_frame_counter].clone()
fft_state.fft[fft_state.fft_frame_counter].clone()
}
rem => time_interpolate(
&(app_state.fft[app_state.fft_frame_counter]),
&(app_state.fft[app_state.fft_frame_counter + 1]),
&(fft_state.fft[fft_state.fft_frame_counter]),
&(fft_state.fft[fft_state.fft_frame_counter + 1]),
rem as f32 / interval as f32,
),
};

// Iterate through all currently displayed bars to change values
for (handle, new_value) in app_state.curr_bars.chunks(2).zip(curr_fft.iter()) {
for (handle, new_value) in fft_state.curr_bars.chunks(2).zip(curr_fft.iter()) {
let (handle1, handle2) = (handle[0].0.clone_weak(), handle[1].0.clone_weak());

let dims = meshes
Expand Down
12 changes: 4 additions & 8 deletions src/systems/update_frame_counters.rs
Expand Up @@ -18,12 +18,8 @@ use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;


pub fn update_frame_counters(
mut app_state: ResMut<AppState>,
mut args: ResMut<FFTArgs>,
) {
let elapsed_time = app_state.song_stopwatch.elapsed().as_secs_f64();
app_state.fft_frame_counter = (elapsed_time / TIME_BETWEEN_FFT_FRAMES) as usize;
app_state.total_frame_counter = (elapsed_time / TIME_BETWEEN_FRAMES) as usize;
pub fn update_frame_counters(mut fft_state: ResMut<FFTState>, mut args: ResMut<FFTArgs>) {
let elapsed_time = fft_state.fft_timer.elapsed().as_secs_f64();
fft_state.fft_frame_counter = (elapsed_time / TIME_BETWEEN_FFT_FRAMES) as usize;
fft_state.total_frame_counter = (elapsed_time / TIME_BETWEEN_FRAMES) as usize;
}

0 comments on commit 3ef57a0

Please sign in to comment.