@@ -7,6 +7,7 @@ use cpal::Stream;
77use opus:: Decoder ;
88use ringbuf:: ring_buffer:: RbBase ;
99use ringbuf:: { LocalRb , Rb } ;
10+ use rubato:: { InterpolationParameters , Resampler , SincFixedIn } ;
1011use tokio:: sync:: mpsc;
1112use tokio:: time:: { Instant , Interval } ;
1213
@@ -21,6 +22,7 @@ type Ringbuf<T> = LocalRb<T, Vec<MaybeUninit<T>>>;
2122
2223pub struct Player {
2324 decoder : Decoder ,
25+ resampler : Option < SincFixedIn < f32 > > ,
2426 buffer : Arc < Mutex < Ringbuf < f32 > > > ,
2527 stream : Option < Stream > ,
2628 volume : Arc < Mutex < f32 > > ,
@@ -30,6 +32,7 @@ impl Player {
3032 pub fn new ( ) -> Self {
3133 Self {
3234 decoder : Decoder :: new ( 48000 , opus:: Channels :: Stereo ) . unwrap ( ) ,
35+ resampler : None ,
3336 buffer : Arc :: new ( Mutex :: new ( Ringbuf :: < f32 > :: new ( PLAYER_BUFFER_SIZE ) ) ) ,
3437 stream : None ,
3538 last_frame : None ,
@@ -49,8 +52,24 @@ impl Player {
4952
5053 let mut buffer = self . buffer . lock ( ) . unwrap ( ) ;
5154 if buffer. len ( ) < buffer. free_len ( ) {
52- // copy to ringbuffer
53- buffer. push_slice ( & pcm) ;
55+ if let Some ( resampler) = & mut self . resampler {
56+ // resample first
57+ let mut chunk_samples: Vec < Vec < f32 > > = vec ! [ Vec :: with_capacity( 480 ) ; 2 ] ;
58+ for ( sample_idx, sample) in pcm. into_iter ( ) . enumerate ( ) {
59+ chunk_samples[ sample_idx % 2 ] . push ( sample) ;
60+ }
61+ let resampled = resampler. process ( & chunk_samples, None ) . unwrap ( ) ;
62+ let flat = resampled[ 0 ]
63+ . iter ( )
64+ . copied ( )
65+ . zip ( resampled[ 1 ] . iter ( ) . copied ( ) )
66+ . flat_map ( |( a, b) | [ a, b] )
67+ . collect :: < Vec < _ > > ( ) ;
68+ buffer. push_slice ( & flat) ;
69+ } else {
70+ // copy decoded packet directly to ringbuffer
71+ buffer. push_slice ( & pcm) ;
72+ }
5473 } else {
5574 // otherwise just discard i guess
5675 println ! ( "player buffer full... discarding :/" )
@@ -66,19 +85,41 @@ impl Player {
6685 . default_output_device ( )
6786 . expect ( "no output device available" ) ;
6887
69- let mut supported_configs_range = device
70- . supported_output_configs ( )
71- . expect ( "error while querying configs" ) ;
72- let supported_config = supported_configs_range
73- . next ( )
74- . expect ( "no supported config?!" )
75- . with_sample_rate ( cpal:: SampleRate ( 48000 ) ) ;
76- // .with_max_sample_rate(); //???
88+ let stream_config = {
89+ let mut configs = device
90+ . supported_output_configs ( )
91+ . expect ( "error while querying configs" ) ;
92+
93+ let range = configs. next ( ) . expect ( "no supported config?!" ) ;
94+
95+ if range. min_sample_rate ( ) . 0 <= 48000 && range. max_sample_rate ( ) . 0 >= 48000 {
96+ range. with_sample_rate ( cpal:: SampleRate ( 48000 ) )
97+ } else {
98+ range. with_max_sample_rate ( )
99+ }
100+ } ;
101+
102+ let sample_rate = stream_config. sample_rate ( ) . 0 ;
103+
104+ if stream_config. sample_rate ( ) . 0 != 48000 {
105+ let params = InterpolationParameters {
106+ sinc_len : 256 ,
107+ f_cutoff : 0.95 ,
108+ interpolation : rubato:: InterpolationType :: Linear ,
109+ oversampling_factor : 256 ,
110+ window : rubato:: WindowFunction :: BlackmanHarris2 ,
111+ } ;
112+ self . resampler = Some (
113+ SincFixedIn :: new ( sample_rate as f64 / 48000_f64 , 1.0 , params, 480 , 2 ) . unwrap ( ) ,
114+ ) ;
115+ } else {
116+ self . resampler = None ;
117+ }
77118
78119 let err_fn = |err| eprintln ! ( "an error occurred on the output audio stream: {}" , err) ;
79- let sample_format = supported_config . sample_format ( ) ;
120+ let sample_format = stream_config . sample_format ( ) ;
80121 println ! ( "sample format is {:?}" , sample_format) ; //?? do we care about other sample formats
81- let config = supported_config . into ( ) ;
122+ let config = stream_config . into ( ) ;
82123
83124 let buffer_handle = self . buffer . clone ( ) ;
84125 let volume_handle = self . volume . clone ( ) ;
0 commit comments