@@ -252,6 +252,40 @@ impl Manager {
252252 } )
253253 }
254254
255+ fn new_internal ( ratio : Rational64 , atten : f64 , quan : u32 , trans_width : f64 ) -> Result < Self > {
256+ if !supported_ratio ( ratio) {
257+ return Err ( Error :: UnsupportedRatio ) ;
258+ }
259+ if !( MIN_ATTEN ..=MAX_ATTEN ) . contains ( & atten)
260+ || !( MIN_QUAN ..=MAX_QUAN ) . contains ( & quan)
261+ || !( 0.01 ..=1.0 ) . contains ( & trans_width)
262+ {
263+ return Err ( Error :: InvalidParam ) ;
264+ }
265+ let kaiser_beta = calc_kaiser_beta ( atten) ;
266+ let fratio = * ratio. numer ( ) as f64 / * ratio. denom ( ) as f64 ;
267+ let order = calc_order ( fratio, atten, trans_width) ;
268+ let cutoff = fratio. min ( 1.0 ) * ( 1.0 - 0.5 * trans_width) ;
269+ Self :: with_raw_internal ( ratio, quan, order, kaiser_beta, cutoff)
270+ }
271+
272+ fn with_order_internal ( ratio : Rational64 , atten : f64 , quan : u32 , order : u32 ) -> Result < Self > {
273+ if !supported_ratio ( ratio) {
274+ return Err ( Error :: UnsupportedRatio ) ;
275+ }
276+ if !( MIN_ATTEN ..=MAX_ATTEN ) . contains ( & atten)
277+ || !( MIN_QUAN ..=MAX_QUAN ) . contains ( & quan)
278+ || !( MIN_ORDER ..=MAX_ORDER ) . contains ( & order)
279+ {
280+ return Err ( Error :: InvalidParam ) ;
281+ }
282+ let fratio = * ratio. numer ( ) as f64 / * ratio. denom ( ) as f64 ;
283+ let kaiser_beta = calc_kaiser_beta ( atten) ;
284+ let trans_width = calc_trans_width ( fratio, atten, order) ;
285+ let cutoff = fratio. min ( 1.0 ) * ( 1.0 - 0.5 * trans_width) ;
286+ Self :: with_raw_internal ( ratio, quan, order, kaiser_beta, cutoff)
287+ }
288+
255289 /// Create a `Manager` with raw parameters, that means all of these should
256290 /// be calculated in advance.
257291 ///
@@ -281,20 +315,8 @@ impl Manager {
281315 /// - trans_width: the transition band width in `[0.01, 1.0]`
282316 #[ inline]
283317 pub fn new ( ratio : f64 , atten : f64 , quan : u32 , trans_width : f64 ) -> Result < Self > {
284- let ratio_i64 = Rational64 :: approximate_float ( ratio) . unwrap_or_default ( ) ;
285- if !supported_ratio ( ratio_i64) {
286- return Err ( Error :: UnsupportedRatio ) ;
287- }
288- if !( MIN_ATTEN ..=MAX_ATTEN ) . contains ( & atten)
289- || !( MIN_QUAN ..=MAX_QUAN ) . contains ( & quan)
290- || !( 0.01 ..=1.0 ) . contains ( & trans_width)
291- {
292- return Err ( Error :: InvalidParam ) ;
293- }
294- let kaiser_beta = calc_kaiser_beta ( atten) ;
295- let order = calc_order ( ratio, atten, trans_width) ;
296- let cutoff = ratio. min ( 1.0 ) * ( 1.0 - 0.5 * trans_width) ;
297- Self :: with_raw_internal ( ratio_i64, quan, order, kaiser_beta, cutoff)
318+ let ratio = Rational64 :: approximate_float ( ratio) . unwrap_or_default ( ) ;
319+ Self :: new_internal ( ratio, atten, quan, trans_width)
298320 }
299321
300322 /// Create a `Manager` with attenuation, quantify and order
@@ -307,20 +329,28 @@ impl Manager {
307329 /// - order: `[1, 2048]`
308330 #[ inline]
309331 pub fn with_order ( ratio : f64 , atten : f64 , quan : u32 , order : u32 ) -> Result < Self > {
310- let ratio_i64 = Rational64 :: approximate_float ( ratio) . unwrap_or_default ( ) ;
311- if !supported_ratio ( ratio_i64) {
312- return Err ( Error :: UnsupportedRatio ) ;
313- }
314- if !( MIN_ATTEN ..=MAX_ATTEN ) . contains ( & atten)
315- || !( MIN_QUAN ..=MAX_QUAN ) . contains ( & quan)
316- || !( MIN_ORDER ..=MAX_ORDER ) . contains ( & order)
317- {
332+ let ratio = Rational64 :: approximate_float ( ratio) . unwrap_or_default ( ) ;
333+ Self :: with_order_internal ( ratio, atten, quan, order)
334+ }
335+
336+ #[ inline]
337+ pub fn with_sample_rate (
338+ old_sr : u32 ,
339+ new_sr : u32 ,
340+ atten : f64 ,
341+ quan : u32 ,
342+ pass_freq : u32 ,
343+ ) -> Result < Self > {
344+ if old_sr == 0 || new_sr == 0 {
318345 return Err ( Error :: InvalidParam ) ;
319346 }
320- let kaiser_beta = calc_kaiser_beta ( atten) ;
321- let trans_width = calc_trans_width ( ratio, atten, order) ;
322- let cutoff = ratio. min ( 1.0 ) * ( 1.0 - 0.5 * trans_width) ;
323- Self :: with_raw_internal ( ratio_i64, quan, order, kaiser_beta, cutoff)
347+ let ratio = Rational64 :: new ( new_sr. into ( ) , old_sr. into ( ) ) ;
348+ if !supported_ratio ( ratio) {
349+ return Err ( Error :: UnsupportedRatio ) ;
350+ }
351+ let min_sr = new_sr. min ( old_sr) ;
352+ let trans_width = min_sr. saturating_sub ( pass_freq. saturating_mul ( 2 ) ) as f64 / min_sr as f64 ;
353+ Self :: new_internal ( ratio, atten, quan, trans_width)
324354 }
325355
326356 /// Create a `Converter` which actually implement the interpolation.
@@ -345,6 +375,118 @@ impl Manager {
345375 pub fn order ( & self ) -> u32 {
346376 self . order
347377 }
378+
379+ #[ inline]
380+ pub fn builder ( ) -> Builder {
381+ Builder :: default ( )
382+ }
383+ }
384+
385+ #[ derive( Default ) ]
386+ pub struct Builder {
387+ ratio : Option < Rational64 > ,
388+ order : Option < u32 > ,
389+ quan : Option < u32 > ,
390+ kaiser_beta : Option < f64 > ,
391+ cutoff : Option < f64 > ,
392+ atten : Option < f64 > ,
393+ trans_width : Option < f64 > ,
394+ old_sr : Option < u32 > ,
395+ new_sr : Option < u32 > ,
396+ pass_freq : Option < u32 > ,
397+ }
398+
399+ impl Builder {
400+ pub fn ratio ( mut self , ratio : f64 ) -> Self {
401+ self . ratio = Some ( Rational64 :: approximate_float ( ratio) . unwrap_or_default ( ) ) ;
402+ self
403+ }
404+
405+ pub fn sample_rate ( mut self , old_sr : u32 , new_sr : u32 ) -> Self {
406+ self . old_sr = Some ( old_sr) ;
407+ self . new_sr = Some ( new_sr) ;
408+ self
409+ }
410+
411+ pub fn quantify ( mut self , quan : u32 ) -> Self {
412+ self . quan = Some ( quan) ;
413+ self
414+ }
415+
416+ pub fn order ( mut self , order : u32 ) -> Self {
417+ self . order = Some ( order) ;
418+ self
419+ }
420+
421+ pub fn kaiser_beta < B : Into < f64 > > ( mut self , beta : B ) -> Self {
422+ self . kaiser_beta = Some ( beta. into ( ) ) ;
423+ self
424+ }
425+
426+ pub fn cutoff ( mut self , cutoff : f64 ) -> Self {
427+ self . cutoff = Some ( cutoff) ;
428+ self
429+ }
430+
431+ pub fn attenuation < A : Into < f64 > > ( mut self , atten : A ) -> Self {
432+ self . atten = Some ( atten. into ( ) ) ;
433+ self
434+ }
435+
436+ pub fn trans_width ( mut self , width : f64 ) -> Self {
437+ self . trans_width = Some ( width) ;
438+ self
439+ }
440+
441+ pub fn pass_width ( mut self , width : f64 ) -> Self {
442+ self . trans_width = Some ( 1.0 - width) ;
443+ self
444+ }
445+
446+ pub fn pass_freq ( mut self , freq : u32 ) -> Self {
447+ self . pass_freq = Some ( freq) ;
448+ self
449+ }
450+
451+ pub fn build ( self ) -> Result < Manager > {
452+ let ( ratio, quan) = match ( self . ratio , self . quan , self . old_sr , self . new_sr ) {
453+ ( Some ( ratio) , Some ( quan) , _, _) => ( ratio, quan) ,
454+ ( _, Some ( quan) , Some ( old_sr) , Some ( new_sr) ) => {
455+ if old_sr == 0 || new_sr == 0 {
456+ return Err ( Error :: InvalidParam ) ;
457+ }
458+ ( Rational64 :: new ( new_sr. into ( ) , old_sr. into ( ) ) , quan)
459+ }
460+ _ => return Err ( Error :: NotEnoughParam ) ,
461+ } ;
462+ if !supported_ratio ( ratio) {
463+ return Err ( Error :: UnsupportedRatio ) ;
464+ }
465+ match (
466+ self . order ,
467+ self . kaiser_beta ,
468+ self . cutoff ,
469+ self . atten ,
470+ self . trans_width ,
471+ self . old_sr ,
472+ self . new_sr ,
473+ self . pass_freq ,
474+ ) {
475+ ( Some ( order) , Some ( kaiser_beta) , Some ( cutoff) , _, _, _, _, _) => {
476+ Manager :: with_raw_internal ( ratio, quan, order, kaiser_beta, cutoff)
477+ }
478+ ( _, _, _, Some ( atten) , Some ( trans_width) , _, _, _) => {
479+ Manager :: new_internal ( ratio, atten, quan, trans_width)
480+ }
481+ ( Some ( order) , _, _, Some ( atten) , _, _, _, _) => {
482+ Manager :: with_order_internal ( ratio, atten, quan, order)
483+ }
484+ ( _, _, _, Some ( atten) , _, Some ( old_sr) , Some ( new_sr) , Some ( pass_freq) ) => {
485+ Manager :: with_sample_rate ( old_sr, new_sr, atten, quan, pass_freq)
486+ }
487+ _ => Err ( Error :: NotEnoughParam ) ,
488+ }
489+ }
348490}
349491
350492#[ cfg( test) ]
@@ -380,4 +522,16 @@ mod tests {
380522 assert ! ( Manager :: with_order( 2.0 , 12.0 , 32 , 32 ) . is_ok( ) ) ;
381523 assert ! ( Manager :: with_order( 2.0 , 11.9 , 32 , 32 ) . is_err( ) ) ;
382524 }
525+
526+ #[ test]
527+ fn test_builder ( ) {
528+ assert ! ( Manager :: builder( ) . build( ) . is_err( ) ) ;
529+ let manager = Manager :: builder ( )
530+ . sample_rate ( 44100 , 48000 )
531+ . quantify ( 32 )
532+ . attenuation ( 72 )
533+ . pass_freq ( 20000 )
534+ . build ( ) ;
535+ assert ! ( manager. is_ok( ) ) ;
536+ }
383537}
0 commit comments