Skip to content

Commit 9caccb0

Browse files
committed
let user choose scaling & fmt
1 parent dacd53c commit 9caccb0

File tree

12 files changed

+81
-32
lines changed

12 files changed

+81
-32
lines changed

build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ fn main() {
33
if target.contains("windows") {
44
embed_resource::compile("assets/icon.rc", embed_resource::NONE);
55
}
6-
}
6+
}

src/components/microphone.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use egui::{Color32, Pos2, Rect};
44
use serde::{Deserialize, Serialize};
55

66
use super::gizmo::GizmoComponent;
7-
use crate::simulation::plugin::ComponentIDs;
87
use crate::math::transformations::grid_to_image;
8+
use crate::simulation::plugin::ComponentIDs;
99
use crate::ui::state::ToolType;
1010

1111
/// A microphone on the grid that records the pressure at its position

src/components/source.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use rand::{thread_rng, Rng};
88
use serde::{Deserialize, Serialize};
99

1010
use super::gizmo::GizmoComponent;
11-
use crate::simulation::plugin::ComponentIDs;
1211
use crate::math::constants::*;
1312
use crate::math::transformations::grid_to_image;
13+
use crate::simulation::plugin::ComponentIDs;
1414
use crate::ui::state::ToolType;
1515

1616
/// A sound source on the grid

src/events.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use bevy_file_dialog::FileDialogExt;
44
use crate::components::microphone::Microphone;
55
use crate::components::source::Source;
66
use crate::components::wall::{CircWall, RectWall};
7-
use crate::simulation::grid::Grid;
87
use crate::render::gradient::Gradient;
8+
use crate::simulation::grid::Grid;
99
use crate::ui::loading::SaveFileContents;
1010
use crate::ui::state::{SimTime, UiState};
1111

src/input/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
pub mod systems;
21
pub mod plugin;
2+
pub mod systems;

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
pub mod components;
44
pub mod events;
5-
pub mod simulation;
65
pub mod input;
76
pub mod math;
87
pub mod render;
8+
pub mod simulation;
99
pub mod ui;
1010
pub mod undo;

src/math/fft.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
use spectrum_analyzer::scaling::scale_to_zero_to_one;
1+
use spectrum_analyzer::scaling::{scale_20_times_log10, scale_to_zero_to_one};
22
use spectrum_analyzer::windows::hann_window;
33
use spectrum_analyzer::{samples_fft_to_spectrum, FrequencyLimit};
44

55
use crate::components::microphone::Microphone;
66
use crate::math::constants::*;
7+
use crate::ui::state::FftScaling;
78

89
/// Calculate the spectrum of a [`Microphone`] based on the record field.
910
/// The spectrum is calculated using the FFT algorithm and a Hann window. The corresponding window size is specified in [`FFT_WINDOW_SIZE`].
10-
/// The spectrum is then mapped to a logarithmic scale and returned.
11+
/// The spectrum is then mapped to a logarithmic scale on the frequency axis and returned.
1112
/// * `microphone` - The microphone to calculate the spectrum for.
1213
/// * `ui_state` - The current state of the UI.
13-
pub fn calc_mic_spectrum(microphone: &Microphone) -> Vec<[f64; 2]> {
14+
/// * `scaling` - The scaling to apply to the spectrum on the amplitude axis.
15+
pub fn calc_mic_spectrum(microphone: &Microphone, scaling: FftScaling) -> Vec<[f64; 2]> {
1416
let samples = if microphone.record.len() < FFT_WINDOW_SIZE {
1517
let mut s = microphone.record.clone();
1618
s.resize(FFT_WINDOW_SIZE, [0.0, 0.0]);
@@ -28,7 +30,10 @@ pub fn calc_mic_spectrum(microphone: &Microphone) -> Vec<[f64; 2]> {
2830
// we can just use the constant value. Calculated as 1/(0.001 / 343) = 343200
2931
343200,
3032
FrequencyLimit::All,
31-
Some(&scale_to_zero_to_one),
33+
match scaling {
34+
FftScaling::ZeroToOne => Some(&scale_to_zero_to_one),
35+
FftScaling::Decibels => Some(&scale_20_times_log10),
36+
},
3237
)
3338
.unwrap();
3439

src/render/draw.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use super::gradient::Gradient;
99
use crate::components::microphone::Microphone;
1010
use crate::components::states::Drag;
1111
use crate::components::wall::{CircWall, RectWall, WResize, Wall};
12-
use crate::simulation::grid::Grid;
1312
use crate::math::constants::{SIMULATION_HEIGHT, SIMULATION_WIDTH};
1413
use crate::math::transformations::{coords_to_index, map_range};
15-
use crate::ui::state::{FftMicrophone, UiState};
14+
use crate::simulation::grid::Grid;
15+
use crate::ui::state::{FftMicrophone, FftScaling, UiState};
1616

1717
pub fn draw_pixels(
1818
pixel_buffers: QueryPixelBuffer,
@@ -85,7 +85,7 @@ pub fn draw_pixels(
8585

8686
// TODO: maybe reset the frame each time the mic changes
8787

88-
let new_spectrum = crate::math::fft::calc_mic_spectrum(mic);
88+
let new_spectrum = crate::math::fft::calc_mic_spectrum(mic, FftScaling::ZeroToOne);
8989
let frame_size = frame.size();
9090

9191
// shift the old values to the left

src/ui/draw.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ pub fn draw_egui(
11731173
fft_microphone: &mut fft_mic,
11741174
commands: &mut commands.reborrow(),
11751175
enabled_spectrogram: ui_state.enable_spectrogram,
1176+
scaling: &mut ui_state.fft_scaling,
11761177
},
11771178
);
11781179
});

src/ui/loading.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use crate::components::microphone::Microphone;
77
use crate::components::source::Source;
88
use crate::components::wall::{CircWall, RectWall};
99
use crate::events::UpdateWalls;
10+
use crate::render::gradient::Gradient;
1011
use crate::simulation::grid::Grid;
1112
use crate::simulation::plugin::ComponentIDs;
12-
use crate::render::gradient::Gradient;
1313

1414
/// Marker component for the file dialog and the corresponding event.
1515
pub struct SaveFileContents;

src/ui/state.rs

+17
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ pub struct FftMicrophone {
4343
pub mic_id: Option<usize>,
4444
}
4545

46+
#[derive(Debug, PartialEq, Clone, Copy)]
47+
pub enum FftScaling {
48+
ZeroToOne,
49+
Decibels,
50+
}
51+
52+
impl fmt::Display for FftScaling {
53+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54+
match self {
55+
FftScaling::ZeroToOne => write!(f, "0-1"),
56+
FftScaling::Decibels => write!(f, "dB"),
57+
}
58+
}
59+
}
60+
4661
#[derive(Resource, PartialEq, Clone, Copy)]
4762
pub struct UiState {
4863
pub is_running: bool,
@@ -63,6 +78,7 @@ pub struct UiState {
6378
pub show_about: bool,
6479
pub show_help: bool,
6580
pub enable_spectrogram: bool,
81+
pub fft_scaling: FftScaling,
6682
}
6783

6884
impl Default for UiState {
@@ -89,6 +105,7 @@ impl Default for UiState {
89105
show_about: false,
90106
show_help: false,
91107
enable_spectrogram: false,
108+
fft_scaling: FftScaling::ZeroToOne,
92109
}
93110
}
94111
}

src/ui/tabs.rs

+44-18
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use egui_plot::{GridMark, Line, Plot, PlotPoints};
77
use plotters::prelude::*;
88

99
use super::loading::SaveFileContents;
10-
use super::state::FftMicrophone;
10+
use super::state::{FftMicrophone, FftScaling};
1111
use crate::components::microphone::Microphone;
1212
use crate::math::fft::calc_mic_spectrum;
1313

@@ -33,6 +33,7 @@ pub struct PlotTabs<'a> {
3333
pub mics: &'a [&'a Microphone],
3434
pub pixel_buffer: &'a mut PixelBuffersItem<'a>,
3535
pub fft_microphone: &'a mut FftMicrophone,
36+
pub scaling: &'a mut FftScaling,
3637
pub commands: &'a mut Commands<'a, 'a>,
3738
pub enabled_spectrogram: bool,
3839
}
@@ -190,30 +191,54 @@ impl<'a> egui_dock::TabViewer for PlotTabs<'a> {
190191
});
191192
}
192193
Tab::Frequency => {
193-
egui::ComboBox::from_label("FFT Microphone")
194-
.selected_text(if let Some(index) = self.fft_microphone.mic_id {
195-
format!("Microphone {index}")
196-
} else {
197-
"No Microphone Selected".to_string()
198-
})
199-
.show_ui(ui, |ui| {
200-
for mic in self.mics {
194+
ui.horizontal(|ui| {
195+
egui::ComboBox::from_label("FFT Microphone")
196+
.selected_text(if let Some(index) = self.fft_microphone.mic_id {
197+
format!("Microphone {index}")
198+
} else {
199+
"No Microphone Selected".to_string()
200+
})
201+
.show_ui(ui, |ui| {
202+
for mic in self.mics {
203+
ui.selectable_value(
204+
&mut self.fft_microphone.mic_id,
205+
Some(mic.id),
206+
format!("Microphone {}", mic.id),
207+
);
208+
}
209+
});
210+
211+
ui.add(egui::Separator::default().vertical());
212+
213+
egui::ComboBox::from_label("Scaling")
214+
.selected_text(self.scaling.to_string())
215+
.show_ui(ui, |ui| {
201216
ui.selectable_value(
202-
&mut self.fft_microphone.mic_id,
203-
Some(mic.id),
204-
format!("Microphone {}", mic.id),
217+
self.scaling,
218+
FftScaling::ZeroToOne,
219+
format!("{}", FftScaling::ZeroToOne),
205220
);
206-
}
207-
});
221+
ui.selectable_value(
222+
self.scaling,
223+
FftScaling::Decibels,
224+
format!("{}", FftScaling::Decibels),
225+
);
226+
});
227+
});
208228

209229
ui.separator();
230+
231+
let unit = match self.scaling {
232+
FftScaling::ZeroToOne => "(0-1)",
233+
FftScaling::Decibels => "(dB)",
234+
};
210235
Plot::new("fft_plot")
211236
.allow_zoom([false, false])
212237
.allow_scroll(false)
213238
.allow_drag(false)
214239
.allow_boxed_zoom(false)
215240
.x_axis_label("Frequency (Hz)")
216-
.y_axis_label("Intensity (dB)")
241+
.y_axis_label(format!("Intensity {}", unit))
217242
.x_grid_spacer(|input| {
218243
let mut marks = Vec::with_capacity(
219244
input.bounds.1 as usize - input.bounds.0 as usize + 1,
@@ -228,10 +253,11 @@ impl<'a> egui_dock::TabViewer for PlotTabs<'a> {
228253
marks
229254
})
230255
.x_axis_formatter(|mark, _, _| format!("{:.0}", 10_f64.powf(mark.value)))
231-
.label_formatter(|_, value| {
256+
.label_formatter(move |_, value| {
232257
format!(
233-
"Intensity: {:.2} dB\nFrequency: {:.2} Hz",
258+
"Intensity: {:.2} {}\nFrequency: {:.2} (Hz)",
234259
value.y,
260+
unit,
235261
10_f64.powf(value.x)
236262
)
237263
})
@@ -245,7 +271,7 @@ impl<'a> egui_dock::TabViewer for PlotTabs<'a> {
245271
.iter()
246272
.find(|m| m.id == self.fft_microphone.mic_id.expect("no mic selected"))
247273
{
248-
let mapped_spectrum = calc_mic_spectrum(mic);
274+
let mapped_spectrum = calc_mic_spectrum(mic, *self.scaling);
249275
// remove the first element, because of log it is at x=-inf
250276
let mapped_spectrum = &mapped_spectrum[1..];
251277

0 commit comments

Comments
 (0)