@@ -18,6 +18,107 @@ pub trait ResampleExtDynamicNew: AsyncSource + Sized + Unpin {
1818
1919impl < T > ResampleExtDynamicNew for T where T : AsyncSource + Sized + Unpin { }
2020
21+ enum Backend {
22+ Passthrough ( Vec < f32 > ) ,
23+ Resampler ( RubatoChunkResampler < FastFixedIn < f32 > , 1 > ) ,
24+ }
25+
26+ impl Backend {
27+ fn passthrough ( capacity : usize ) -> Self {
28+ Self :: Passthrough ( Vec :: with_capacity ( capacity) )
29+ }
30+
31+ fn ensure_passthrough ( & mut self , capacity : usize ) {
32+ match self {
33+ Self :: Passthrough ( buffer) => buffer. clear ( ) ,
34+ Self :: Resampler ( _) => * self = Self :: passthrough ( capacity) ,
35+ }
36+ }
37+
38+ fn ensure_resampler (
39+ & mut self ,
40+ resampler : FastFixedIn < f32 > ,
41+ output_chunk_size : usize ,
42+ input_block_size : usize ,
43+ ) {
44+ match self {
45+ Self :: Passthrough ( _) => {
46+ * self = Self :: Resampler ( RubatoChunkResampler :: new (
47+ resampler,
48+ output_chunk_size,
49+ input_block_size,
50+ ) ) ;
51+ }
52+ Self :: Resampler ( driver) => {
53+ driver. rebind_resampler ( resampler, output_chunk_size, input_block_size)
54+ }
55+ }
56+ }
57+
58+ fn push_sample ( & mut self , sample : f32 ) {
59+ match self {
60+ Self :: Passthrough ( buffer) => buffer. push ( sample) ,
61+ Self :: Resampler ( driver) => driver. push_sample ( sample) ,
62+ }
63+ }
64+
65+ fn try_yield_chunk ( & mut self , chunk_size : usize , allow_partial : bool ) -> Option < Vec < f32 > > {
66+ match self {
67+ Self :: Passthrough ( buffer) => {
68+ if buffer. len ( ) >= chunk_size {
69+ Some ( buffer. drain ( ..chunk_size) . collect ( ) )
70+ } else if allow_partial && !buffer. is_empty ( ) {
71+ Some ( buffer. drain ( ..) . collect ( ) )
72+ } else {
73+ None
74+ }
75+ }
76+ Self :: Resampler ( driver) => {
77+ if driver. has_full_chunk ( ) {
78+ driver. take_full_chunk ( )
79+ } else if allow_partial && !driver. output_is_empty ( ) {
80+ driver. take_all_output ( )
81+ } else {
82+ None
83+ }
84+ }
85+ }
86+ }
87+
88+ fn process_all_ready_blocks ( & mut self ) -> Result < bool , crate :: Error > {
89+ match self {
90+ Self :: Passthrough ( _) => Ok ( false ) ,
91+ Self :: Resampler ( driver) => driver. process_all_ready_blocks ( ) ,
92+ }
93+ }
94+
95+ fn drain_for_rate_change ( & mut self ) -> Result < bool , crate :: Error > {
96+ match self {
97+ Self :: Passthrough ( buffer) => Ok ( buffer. is_empty ( ) ) ,
98+ Self :: Resampler ( driver) => {
99+ driver. process_all_ready_blocks ( ) ?;
100+ if driver. has_input ( ) {
101+ driver. process_partial_block ( true ) ?;
102+ }
103+ Ok ( driver. output_is_empty ( ) )
104+ }
105+ }
106+ }
107+
108+ fn drain_at_eos ( & mut self ) -> Result < ( ) , crate :: Error > {
109+ match self {
110+ Self :: Passthrough ( _) => Ok ( ( ) ) ,
111+ Self :: Resampler ( driver) => {
112+ driver. process_all_ready_blocks ( ) ?;
113+ if driver. has_input ( ) {
114+ driver. process_partial_block ( true ) ?;
115+ }
116+ Ok ( ( ) )
117+ }
118+ }
119+ }
120+ }
121+
21122pub struct ResamplerDynamicNew < S >
22123where
23124 S : AsyncSource + Unpin ,
26127 target_rate : u32 ,
27128 output_chunk_size : usize ,
28129 input_block_size : usize ,
29- driver : RubatoChunkResampler < FastFixedIn < f32 > , 1 > ,
130+ backend : Backend ,
30131 last_source_rate : u32 ,
31132 draining : bool ,
32133}
@@ -42,53 +143,51 @@ where
42143 ) -> Result < Self , crate :: Error > {
43144 let source_rate = source. sample_rate ( ) ;
44145 let input_block_size = output_chunk_size;
45- let ratio = target_rate as f64 / source_rate as f64 ;
46- let resampler = Self :: create_resampler ( ratio, input_block_size) ?;
47- let driver = RubatoChunkResampler :: new ( resampler, output_chunk_size, input_block_size) ;
146+ let backend = if source_rate == target_rate {
147+ Backend :: passthrough ( output_chunk_size)
148+ } else {
149+ let ratio = target_rate as f64 / source_rate as f64 ;
150+ Backend :: Resampler ( RubatoChunkResampler :: new (
151+ Self :: create_resampler ( ratio, input_block_size) ?,
152+ output_chunk_size,
153+ input_block_size,
154+ ) )
155+ } ;
48156 Ok ( Self {
49157 source,
50158 target_rate,
51159 output_chunk_size,
52160 input_block_size,
53- driver ,
161+ backend ,
54162 last_source_rate : source_rate,
55163 draining : false ,
56164 } )
57165 }
58166
59- fn rebuild_resampler ( & mut self , new_rate : u32 ) -> Result < ( ) , crate :: Error > {
60- let ratio = self . target_rate as f64 / new_rate as f64 ;
61- let resampler = Self :: create_resampler ( ratio, self . input_block_size ) ?;
62- self . driver
63- . rebind_resampler ( resampler, self . output_chunk_size , self . input_block_size ) ;
167+ fn rebuild_backend ( & mut self , new_rate : u32 ) -> Result < ( ) , crate :: Error > {
168+ if new_rate == self . target_rate {
169+ self . backend . ensure_passthrough ( self . output_chunk_size ) ;
170+ } else {
171+ let ratio = self . target_rate as f64 / new_rate as f64 ;
172+ let resampler = Self :: create_resampler ( ratio, self . input_block_size ) ?;
173+ self . backend
174+ . ensure_resampler ( resampler, self . output_chunk_size , self . input_block_size ) ;
175+ }
64176 self . last_source_rate = new_rate;
65177 Ok ( ( ) )
66178 }
67179
68- fn try_yield_chunk ( & mut self ) -> Option < Vec < f32 > > {
69- if self . driver . has_full_chunk ( ) {
70- self . driver . take_full_chunk ( )
71- } else if self . draining && !self . driver . output_is_empty ( ) {
72- self . driver . take_all_output ( )
73- } else {
74- None
75- }
180+ fn try_yield_chunk ( & mut self , allow_partial : bool ) -> Option < Vec < f32 > > {
181+ self . backend
182+ . try_yield_chunk ( self . output_chunk_size , allow_partial)
76183 }
77184
78185 fn drain_for_rate_change ( & mut self ) -> Result < bool , crate :: Error > {
79- self . driver . process_all_ready_blocks ( ) ?;
80- if self . driver . has_input ( ) {
81- self . driver . process_partial_block ( true ) ?;
82- }
83- Ok ( self . driver . output_is_empty ( ) )
186+ self . backend . drain_for_rate_change ( )
84187 }
85188
86189 fn drain_at_eos ( & mut self ) -> Result < ( ) , crate :: Error > {
87- self . driver . process_all_ready_blocks ( ) ?;
88- if self . driver . has_input ( ) {
89- self . driver . process_partial_block ( true ) ?;
90- }
91- Ok ( ( ) )
190+ self . backend . drain_at_eos ( )
92191 }
93192
94193 fn create_resampler (
@@ -116,7 +215,7 @@ where
116215 let me = Pin :: into_inner ( self ) ;
117216
118217 loop {
119- if let Some ( chunk) = me. try_yield_chunk ( ) {
218+ if let Some ( chunk) = me. try_yield_chunk ( me . draining ) {
120219 return Poll :: Ready ( Some ( Ok ( chunk) ) ) ;
121220 }
122221
@@ -128,29 +227,22 @@ where
128227 if current_rate != me. last_source_rate {
129228 match me. drain_for_rate_change ( ) {
130229 Ok ( true ) => {
131- if let Err ( err) = me. rebuild_resampler ( current_rate) {
230+ if let Err ( err) = me. rebuild_backend ( current_rate) {
132231 return Poll :: Ready ( Some ( Err ( err) ) ) ;
133232 }
134233 continue ;
135234 }
136235 Ok ( false ) => {
137- if me. driver . has_full_chunk ( ) {
138- if let Some ( chunk) = me. driver . take_full_chunk ( ) {
139- return Poll :: Ready ( Some ( Ok ( chunk) ) ) ;
140- }
141- }
142- if !me. driver . output_is_empty ( ) {
143- if let Some ( chunk) = me. driver . take_all_output ( ) {
144- return Poll :: Ready ( Some ( Ok ( chunk) ) ) ;
145- }
236+ if let Some ( chunk) = me. try_yield_chunk ( true ) {
237+ return Poll :: Ready ( Some ( Ok ( chunk) ) ) ;
146238 }
147239 continue ;
148240 }
149241 Err ( err) => return Poll :: Ready ( Some ( Err ( err) ) ) ,
150242 }
151243 }
152244
153- match me. driver . process_all_ready_blocks ( ) {
245+ match me. backend . process_all_ready_blocks ( ) {
154246 Ok ( true ) => continue ,
155247 Ok ( false ) => { }
156248 Err ( err) => return Poll :: Ready ( Some ( Err ( err) ) ) ,
@@ -164,7 +256,7 @@ where
164256
165257 match sample_poll {
166258 Poll :: Ready ( Some ( sample) ) => {
167- me. driver . push_sample ( sample) ;
259+ me. backend . push_sample ( sample) ;
168260 }
169261 Poll :: Ready ( None ) => {
170262 if let Err ( err) = me. drain_at_eos ( ) {
0 commit comments