@@ -6,6 +6,9 @@ use cpal::{Sample, Stream};
66use opus:: Decoder ;
77use ringbuf:: { LocalRb , Rb } ;
88
9+ use spectrum_analyzer;
10+ use spectrum_analyzer:: scaling:: { divide_by_N_sqrt, scale_to_zero_to_one, scale_20_times_log10} ;
11+
912type Ringbuf < T > = LocalRb < T , Vec < MaybeUninit < T > > > ;
1013
1114const PLAYER_BUFFER_SIZE : usize = 48000 * 10 ; // 10s of samples?
@@ -14,7 +17,8 @@ pub struct Player {
1417 decoder : Decoder ,
1518 buffer : Arc < Mutex < Ringbuf < f32 > > > ,
1619 stream : Option < Stream > ,
17- frames_received : usize ,
20+ pub frames_received : usize ,
21+ visualizer_buffer : Arc < Mutex < Vec < [ f32 ; 480 * 5 ] > > > , // :3
1822}
1923impl Player {
2024 pub fn new ( ) -> Self {
@@ -23,13 +27,14 @@ impl Player {
2327 buffer : Arc :: new ( Mutex :: new ( Ringbuf :: < f32 > :: new ( PLAYER_BUFFER_SIZE ) ) ) ,
2428 stream : None ,
2529 frames_received : 0 ,
30+ visualizer_buffer : Arc :: new ( Mutex :: new ( vec ! [ ] ) ) ,
2631 }
2732 }
2833
2934 // decode opus data when received and buffer the samples
3035 pub fn receive ( & mut self , frame : Vec < u8 > ) {
3136 // allocate and decode into here
32- let mut pcm = vec ! [ 0.0 ; 960 ] ;
37+ let mut pcm = [ 0.0 ; 960 ] ;
3338 self . decoder . decode_float ( & frame, & mut pcm, false ) . unwrap ( ) ;
3439 self . frames_received += 1 ;
3540
@@ -41,6 +46,21 @@ impl Player {
4146 // otherwise just discard i guess
4247 println ! ( "player buffer full... discarding :/" )
4348 }
49+
50+ let chunk = self . frames_received % 5 ;
51+ let mut buf = self . visualizer_buffer . lock ( ) . unwrap ( ) ;
52+ let bl = buf. len ( ) ;
53+
54+ if chunk == 0 || bl == 0 {
55+ buf. push ( [ 0.0 ; 480 * 5 ] ) ;
56+ }
57+
58+ let bl = buf. len ( ) ;
59+
60+ for ( i, s) in pcm. iter ( ) . step_by ( 2 ) . enumerate ( ) {
61+ let summed = s + pcm[ i + 1 ] / 2.0 ;
62+ buf[ bl-1 ] [ chunk + i] = summed;
63+ }
4464 }
4565
4666 pub fn start ( & mut self ) {
@@ -127,6 +147,10 @@ impl Player {
127147 pub fn fake_frames_received ( & mut self , frames : usize ) {
128148 self . frames_received = frames;
129149 }
150+ pub fn get_visualizer_buffer ( & mut self ) -> Arc < Mutex < Vec < [ f32 ; 480 * 5 ] > > > {
151+ assert ! ( self . frames_received % 5 == 0 ) ;
152+ self . visualizer_buffer . clone ( )
153+ }
130154}
131155
132156// callback when the audio output needs more data
@@ -150,3 +174,46 @@ fn write_audio<T: Sample>(
150174 println ! ( "write_audio: buffer has {} left" , buffer. len( ) ) ;
151175 }
152176}
177+
178+ pub fn calculate_visualizer ( samples : & [ f32 ; 2400 ] ) -> [ u8 ; 14 ] {
179+ let samples_truncated = & samples[ ..2048 ] ;
180+ let hamming_window = spectrum_analyzer:: windows:: hann_window ( samples_truncated) ;
181+ let spectrum = spectrum_analyzer:: samples_fft_to_spectrum (
182+ & hamming_window,
183+ 48000 ,
184+ spectrum_analyzer:: FrequencyLimit :: All ,
185+ Some ( & scale_to_zero_to_one) ,
186+ )
187+ . unwrap ( ) ;
188+
189+ let mut bars_float = [ 0.0 ; 14 ] ;
190+ let min_freq = 20.0 ;
191+ let max_freq = 20000.0 ;
192+
193+ for ( fr, fr_val) in spectrum. data ( ) . iter ( ) {
194+ let fr = fr. val ( ) ;
195+ if fr < 25.0 {
196+ continue ;
197+ }
198+
199+ let index = ( -5.25062 * fr. log ( 0.06 ) - 7.56997 ) . round ( ) . min ( 13.0 ) as usize ;
200+ //println!("{}, {}, {}", index, fr);
201+ let lmao = if fr < 200.0 {
202+ 3.0
203+ } else if fr < 500.0 {
204+ 2.0
205+ } else {
206+ 1.0
207+ } ;
208+ bars_float[ index] += fr_val. val ( ) * lmao;
209+ }
210+ //println!("{:?}", bars_float);
211+ let bars: [ u8 ; 14 ] = bars_float
212+ . iter ( )
213+ . map ( |& num| ( num as f32 / 2.0 ) . round ( ) . min ( 8.0 ) as u8 )
214+ . collect :: < Vec < u8 > > ( )
215+ . try_into ( )
216+ . unwrap ( ) ;
217+ //println!("{:?}", bars);
218+ bars
219+ }
0 commit comments