@@ -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 ) ]
1822pub 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