Skip to content

Commit 648a8cb

Browse files
committed
feat(ui): separate settings panels and refine radio navigation
1 parent ca7affe commit 648a8cb

2 files changed

Lines changed: 362 additions & 152 deletions

File tree

src/audio_player.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use std::{
1414
time::{Duration, Instant},
1515
};
1616

17+
const RADIO_VISUALIZER_HISTORY_SECONDS: usize = 180;
18+
const RADIO_VISUALIZER_BUCKETS_PER_SECOND: usize = 5;
19+
const RADIO_VISUALIZER_MAX_BUCKETS: usize = RADIO_VISUALIZER_HISTORY_SECONDS * RADIO_VISUALIZER_BUCKETS_PER_SECOND;
20+
1721
#[derive(Clone, Debug)]
1822
pub struct PlaybackInfo {
1923
pub path: PathBuf,
@@ -135,7 +139,7 @@ impl<S: Source<Item = f32>> LiveRadioSource<S> {
135139
}
136140

137141
fn process_frame(&mut self, stereo: [f32; 2], mono: f32) -> [f32; 2] {
138-
record_radio_peak(&self.visualizer, stereo[0].abs().max(stereo[1].abs()).max(mono.abs()));
142+
record_radio_peak(&self.visualizer, self.sample_rate, stereo[0].abs().max(stereo[1].abs()).max(mono.abs()));
139143
let output_level = self.settings.output_level_percent.clamp(1, 100) as f32 / 100.0;
140144
if !self.settings.orbit_enabled {
141145
return [
@@ -203,16 +207,18 @@ impl<S: Source<Item = f32>> Source for LiveRadioSource<S> {
203207
}
204208
}
205209

206-
fn record_radio_peak(visualizer: &RadioVisualizerHandle, peak: f32) {
210+
fn record_radio_peak(visualizer: &RadioVisualizerHandle, sample_rate: u32, peak: f32) {
207211
let Ok(mut state) = visualizer.lock() else {
208212
return;
209213
};
210214
state.current_peak = state.current_peak.max(peak.min(1.0));
211215
state.sample_counter += 1;
212-
if state.sample_counter >= 768 {
216+
217+
let samples_per_bucket = (sample_rate.max(1) as usize / RADIO_VISUALIZER_BUCKETS_PER_SECOND).max(1);
218+
if state.sample_counter >= samples_per_bucket {
213219
let peak = state.current_peak;
214220
state.peaks.push_back(peak);
215-
while state.peaks.len() > 4096 {
221+
while state.peaks.len() > RADIO_VISUALIZER_MAX_BUCKETS {
216222
state.peaks.pop_front();
217223
}
218224
state.current_peak = 0.0;
@@ -321,8 +327,26 @@ impl AudioPlayer {
321327
if requested_points == 0 || state.peaks.is_empty() {
322328
return Vec::new();
323329
}
324-
let take = requested_points.min(state.peaks.len());
325-
state.peaks.iter().skip(state.peaks.len() - take).copied().collect()
330+
331+
let peaks: Vec<f32> = state.peaks.iter().copied().collect();
332+
if peaks.len() <= requested_points {
333+
return peaks;
334+
}
335+
336+
let mut rendered = Vec::with_capacity(requested_points);
337+
let bucket_width = peaks.len() as f32 / requested_points as f32;
338+
for index in 0..requested_points {
339+
let start = ((index as f32 * bucket_width).floor() as usize).min(peaks.len() - 1);
340+
let end = (((index + 1) as f32 * bucket_width).ceil() as usize)
341+
.max(start + 1)
342+
.min(peaks.len());
343+
let peak = peaks[start..end]
344+
.iter()
345+
.copied()
346+
.fold(0.0_f32, f32::max);
347+
rendered.push(peak);
348+
}
349+
rendered
326350
}
327351

328352
pub fn play_file_with_orbit_from(

0 commit comments

Comments
 (0)