@@ -40,13 +40,11 @@ impl Samplerate {
4040 let mut error_int = 0i32 ;
4141 let ptr: * mut SRC_STATE = unsafe { src_new ( converter_type as i32 , channels as i32 , & mut error_int as * mut i32 ) } ;
4242 match ErrorCode :: from_int ( error_int) {
43- ErrorCode :: NoError => {
44- Ok ( Samplerate {
45- ptr,
46- from_rate,
47- to_rate,
48- } )
49- } ,
43+ ErrorCode :: NoError => Ok ( Samplerate {
44+ ptr,
45+ from_rate,
46+ to_rate,
47+ } ) ,
5048 _ => Err ( Error :: from_int ( error_int) ) ,
5149 }
5250 }
@@ -91,13 +89,13 @@ impl Samplerate {
9189 if channels >= 0 {
9290 Ok ( channels as usize )
9391 } else {
94- Err ( Error :: from_int ( channels) )
92+ Err ( Error :: from_int ( - channels) )
9593 }
9694 }
9795
9896 fn _process ( & self , input : & [ f32 ] , output_len : usize , end_of_input : bool ) -> Result < Vec < f32 > , Error > {
9997 let channels = self . channels ( ) ?;
100- let mut output = vec ! [ 0f32 ; output_len] ;
98+ let mut output = vec ! [ 0f32 ; output_len] ;
10199 let mut src = SRC_DATA {
102100 data_in : input. as_ptr ( ) ,
103101 data_out : output. as_mut_ptr ( ) ,
@@ -111,22 +109,58 @@ impl Samplerate {
111109 } ;
112110 let error_int = unsafe { src_process ( self . ptr , & mut src as * mut SRC_DATA ) } ;
113111 match ErrorCode :: from_int ( error_int) {
114- ErrorCode :: NoError => Ok ( output[ ..src. output_frames_gen as usize * channels] . into ( ) ) ,
115- _ => Err ( Error :: from_int ( error_int) ) ,
112+ ErrorCode :: NoError => Ok ( output[ ..src. output_frames_gen as usize * channels] . into ( ) ) ,
113+ code => Err ( Error :: from_code ( code) ) ,
114+ }
115+ }
116+
117+ fn _process_into ( & self , input : & [ f32 ] , output : & mut [ f32 ] , end_of_input : bool ) -> Result < ( usize , usize ) , Error > {
118+ let channels = self . channels ( ) ?;
119+ let mut src = SRC_DATA {
120+ data_in : input. as_ptr ( ) ,
121+ data_out : output. as_mut_ptr ( ) ,
122+ input_frames : ( input. len ( ) as i32 / channels as i32 ) . into ( ) ,
123+ output_frames : ( output. len ( ) as i32 / channels as i32 ) . into ( ) ,
124+ src_ratio : self . ratio ( ) ,
125+ end_of_input : if end_of_input { 1 } else { 0 } ,
126+ input_frames_used : 0 ,
127+ output_frames_gen : 0 ,
128+ ..Default :: default ( )
129+ } ;
130+ let error_int = unsafe { src_process ( self . ptr , & mut src as * mut SRC_DATA ) } ;
131+ match ErrorCode :: from_int ( error_int) {
132+ ErrorCode :: NoError => Ok ( ( src. input_frames_used as usize , src. output_frames_gen as usize ) ) ,
133+ code => Err ( Error :: from_code ( code) ) ,
116134 }
117135 }
118136
119137 /// Perform a samplerate conversion on a block of data (use `process_last` if it is the last one)
120138 /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
121139 /// interleaved.
140+ ///
141+ /// Will allocate a new [Vec] to store the result of the conversion (use `process_into` to use
142+ /// an existing buffer).
122143 pub fn process ( & self , input : & [ f32 ] ) -> Result < Vec < f32 > , Error > {
123144 let channels = self . channels ( ) ?;
124145 self . _process ( input, ( self . ratio ( ) * input. len ( ) as f64 ) as usize + channels, false )
125146 }
126-
147+
148+ /// Perform a samplerate conversion on a block of data (use `process_last_into` if it is the last one)
149+ /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
150+ /// interleaved.
151+ ///
152+ /// Will write its output to the specified buffer (use `process` to let a [Vec] be constructed
153+ /// to store the result of the conversion.
154+ pub fn process_into ( & self , input : & [ f32 ] , output : & mut [ f32 ] ) -> Result < ( usize , usize ) , Error > {
155+ self . _process_into ( input, output, false )
156+ }
157+
127158 /// Perform a samplerate conversion on last block of given input data.
128159 /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
129160 /// interleaved.
161+ ///
162+ /// Will allocate a new [Vec] to store the result of the final conversion (use `process_into_last`
163+ /// to use an existing buffer).
130164 pub fn process_last ( & self , input : & [ f32 ] ) -> Result < Vec < f32 > , Error > {
131165 let channels = self . channels ( ) ?;
132166 let output_len = ( self . ratio ( ) * input. len ( ) as f64 ) as usize + channels;
@@ -140,15 +174,28 @@ impl Samplerate {
140174 } else {
141175 output. extend ( output_last) ;
142176 }
143- } ,
177+ }
144178 Err ( err) => return Err ( err)
145179 }
146180 }
147181 Ok ( output)
148- } ,
182+ }
149183 Err ( err) => Err ( err)
150184 }
151185 }
186+
187+ /// Perform a samplerate conversion on a last block of given input data.
188+ /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
189+ /// interleaved.
190+ ///
191+ /// Will write its output to the specified buffer (use `process_last` to let a [Vec] be constructed
192+ /// to store the result of the conversion.
193+ ///
194+ /// Note: you may need to call this function multiple times with an empty `input` to drain the
195+ /// internal buffer.
196+ pub fn process_into_last ( & self , input : & [ f32 ] , output : & mut [ f32 ] ) -> Result < ( usize , usize ) , Error > {
197+ self . _process_into ( input, output, true )
198+ }
152199}
153200
154201impl Drop for Samplerate {
@@ -210,13 +257,13 @@ mod tests {
210257 let mut converter = Samplerate :: new ( ConverterType :: SincBestQuality , 44100 , 48000 , 1 ) . unwrap ( ) ;
211258
212259 // Resample the audio in chunks.
213- let mut resampled = vec ! [ 0f32 ; 0 ] ;
260+ let mut resampled = vec ! [ 0f32 ; 0 ] ;
214261 let chunk_size = 4410 ; // 100ms
215262 for i in 0 ..input. len ( ) / chunk_size {
216263 resampled. extend ( if i < ( input. len ( ) / chunk_size - 1 ) {
217- converter. process ( & input[ i * chunk_size .. ( i + 1 ) * chunk_size] ) . unwrap ( )
264+ converter. process ( & input[ i * chunk_size.. ( i + 1 ) * chunk_size] ) . unwrap ( )
218265 } else {
219- converter. process_last ( & input[ i * chunk_size .. ( i + 1 ) * chunk_size] ) . unwrap ( )
266+ converter. process_last ( & input[ i * chunk_size.. ( i + 1 ) * chunk_size] ) . unwrap ( )
220267 } ) ;
221268 }
222269 assert_eq ! ( resampled. len( ) , 48000 ) ;
@@ -225,13 +272,13 @@ mod tests {
225272 converter. reset ( ) . unwrap ( ) ;
226273 converter. set_to_rate ( 44100 ) ;
227274 converter. set_from_rate ( 48000 ) ;
228- let mut output = vec ! [ 0f32 ; 0 ] ;
275+ let mut output = vec ! [ 0f32 ; 0 ] ;
229276 let chunk_size = 4800 ; // 100ms
230277 for i in 0 ..resampled. len ( ) / chunk_size {
231278 output. extend ( if i < ( resampled. len ( ) / chunk_size - 1 ) {
232- converter. process ( & resampled[ i * chunk_size .. ( i + 1 ) * chunk_size] ) . unwrap ( )
279+ converter. process ( & resampled[ i * chunk_size.. ( i + 1 ) * chunk_size] ) . unwrap ( )
233280 } else {
234- converter. process_last ( & resampled[ i * chunk_size .. ( i + 1 ) * chunk_size] ) . unwrap ( )
281+ converter. process_last ( & resampled[ i * chunk_size.. ( i + 1 ) * chunk_size] ) . unwrap ( )
235282 } ) ;
236283 }
237284 assert_eq ! ( output. len( ) , 44100 ) ;
@@ -241,4 +288,72 @@ mod tests {
241288 let error = input. iter ( ) . zip ( output) . fold ( 0f32 , |max, ( input, output) | max. max ( ( input - output) . abs ( ) ) ) ;
242289 assert ! ( error < 0.002 ) ;
243290 }
291+
292+ #[ test]
293+ fn samplerate_conversion_into ( ) {
294+ // Generate a 880Hz sine wave for 1 second in 44100Hz with one channel.
295+ let freq = std:: f32:: consts:: PI * 880f32 / 44100f32 ;
296+ let input: Vec < f32 > = ( 0 ..44100 ) . map ( |i| ( freq * i as f32 ) . sin ( ) ) . collect ( ) ;
297+
298+ // Create a new converter.
299+ let mut converter = Samplerate :: new ( ConverterType :: SincBestQuality , 44100 , 48000 , 1 ) . unwrap ( ) ;
300+
301+ // Resample the audio in chunks.
302+ let mut resampled = vec ! [ 0f32 ; 0 ] ;
303+ let chunk_size = 4410 ; // 100ms
304+ let mut resampled_buff: Vec < f32 > = vec ! [ 0. ; chunk_size * 480 / 441 + 1 ] ;
305+ let mut frame_ptr = 0 ;
306+ while frame_ptr < input. len ( ) {
307+ let ( input_used, output_generated) = if input. len ( ) - frame_ptr > chunk_size {
308+ converter. process_into ( & input[ frame_ptr..frame_ptr + chunk_size. min ( input. len ( ) - frame_ptr) ] , & mut resampled_buff) . unwrap ( )
309+ } else {
310+ converter. process_into_last ( & input[ frame_ptr..] , & mut resampled_buff) . unwrap ( )
311+ } ;
312+ frame_ptr += input_used;
313+ resampled. extend ( & resampled_buff[ ..output_generated] )
314+ }
315+ // Drain the remaining resample buffer
316+ loop {
317+ let ( input_used, output_generated) = converter. process_into_last ( & [ 0. ; 0 ] , & mut resampled_buff) . unwrap ( ) ;
318+ if output_generated == 0 {
319+ break ;
320+ }
321+ resampled. extend ( & resampled_buff[ ..output_generated] )
322+ }
323+ assert_eq ! ( resampled. len( ) , 48000 ) ;
324+
325+ // Resample the audio back.
326+ converter. reset ( ) . unwrap ( ) ;
327+ converter. set_to_rate ( 44100 ) ;
328+ converter. set_from_rate ( 48000 ) ;
329+ let mut output = vec ! [ 0f32 ; 0 ] ;
330+ let chunk_size = 4800 ; // 100ms
331+ let mut resampled_buff = vec ! [ 0f32 ; chunk_size * 441 / 480 + 1 ] ;
332+ let mut frame_ptr = 0 ;
333+ while frame_ptr < resampled. len ( ) {
334+ let ( input_used, output_generated) = if resampled. len ( ) - frame_ptr > chunk_size {
335+ converter. process_into ( & resampled[ frame_ptr..frame_ptr + chunk_size. min ( resampled. len ( ) - frame_ptr) ] , & mut resampled_buff) . unwrap ( )
336+ } else {
337+ converter. process_into_last ( & resampled[ frame_ptr..] , & mut resampled_buff) . unwrap ( )
338+ } ;
339+ frame_ptr += input_used;
340+ output. extend ( & resampled_buff[ ..output_generated] )
341+ }
342+ // Drain the remaining resample buffer
343+ loop {
344+ let ( input_used, output_generated) = converter. process_into_last ( & [ 0. ; 0 ] , & mut resampled_buff) . unwrap ( ) ;
345+ if output_generated == 0 {
346+ break ;
347+ }
348+ output. extend ( & resampled_buff[ ..output_generated] )
349+ }
350+ assert_eq ! ( output. len( ) , 44100 ) ;
351+
352+ let mut invalid = 0 ;
353+
354+ // Expect the difference between all input frames and all output frames to be less than
355+ // an epsilon.
356+ let error = input. iter ( ) . zip ( output) . fold ( 0f32 , |max, ( input, output) | max. max ( ( input - output) . abs ( ) ) ) ;
357+ assert ! ( error < 0.002 ) ;
358+ }
244359}
0 commit comments