11use std:: { mem, str:: FromStr , time:: Duration } ;
22
33pub use crate :: dither:: { mk_ditherer, DithererBuilder , TriangularDitherer } ;
4- use crate :: { convert:: i24, RESAMPLER_INPUT_SIZE , SAMPLE_RATE } ;
4+
5+ use crate :: {
6+ convert:: i24,
7+ filter_coefficients:: {
8+ HZ48000_HIGH , HZ48000_LOW , HZ88200_HIGH , HZ88200_LOW , HZ96000_HIGH , HZ96000_LOW ,
9+ } ,
10+ RESAMPLER_INPUT_SIZE , SAMPLE_RATE ,
11+ } ;
512
613// Reciprocals allow us to multiply instead of divide during interpolation.
714const HZ48000_RESAMPLE_FACTOR_RECIPROCAL : f64 = SAMPLE_RATE as f64 / 48_000.0 ;
@@ -26,21 +33,9 @@ const HZ88200_INTERPOLATION_OUTPUT_SIZE: usize =
2633const HZ96000_INTERPOLATION_OUTPUT_SIZE : usize =
2734 ( RESAMPLER_INPUT_SIZE as f64 * ( 1.0 / HZ96000_RESAMPLE_FACTOR_RECIPROCAL ) ) as usize ;
2835
29- pub const NUM_FIR_FILTER_TAPS : usize = 5 ;
30-
31- // Blackman Window coefficients
32- const BLACKMAN_A0 : f64 = 0.42 ;
33- const BLACKMAN_A1 : f64 = 0.5 ;
34- const BLACKMAN_A2 : f64 = 0.08 ;
35-
36- // Constants for calculations
37- const TWO_TIMES_PI : f64 = 2.0 * std:: f64:: consts:: PI ;
38- const FOUR_TIMES_PI : f64 = 4.0 * std:: f64:: consts:: PI ;
39-
4036#[ derive( Clone , Copy , Debug , Default ) ]
4137pub enum InterpolationQuality {
4238 Low ,
43- Medium ,
4439 #[ default]
4540 High ,
4641}
@@ -53,7 +48,6 @@ impl FromStr for InterpolationQuality {
5348
5449 match s. to_lowercase ( ) . as_ref ( ) {
5550 "low" => Ok ( Low ) ,
56- "medium" => Ok ( Medium ) ,
5751 "high" => Ok ( High ) ,
5852 _ => Err ( ( ) ) ,
5953 }
@@ -66,107 +60,32 @@ impl std::fmt::Display for InterpolationQuality {
6660
6761 match self {
6862 Low => write ! ( f, "Low" ) ,
69- Medium => write ! ( f, "Medium" ) ,
7063 High => write ! ( f, "High" ) ,
7164 }
7265 }
7366}
7467
7568impl InterpolationQuality {
76- pub fn get_interpolation_coefficients ( & self , resample_factor_reciprocal : f64 ) -> Vec < f64 > {
77- let interpolation_coefficients_length = self . get_interpolation_coefficients_length ( ) ;
78-
79- let mut coefficients = Vec :: with_capacity ( interpolation_coefficients_length) ;
80-
81- if interpolation_coefficients_length == 0 {
82- warn ! ( "InterpolationQuality::Low::get_interpolation_coefficients always returns an empty Vec<f64>" ) ;
83- warn ! ( "Linear Interpolation does not use coefficients" ) ;
84-
85- return coefficients;
86- }
87-
88- let last_index = interpolation_coefficients_length as f64 - 1.0 ;
89-
90- let sinc_center = last_index * 0.5 ;
91-
69+ pub fn get_interpolation_coefficients (
70+ & self ,
71+ mut coefficients : Vec < f64 > ,
72+ resample_factor_reciprocal : f64 ,
73+ ) -> Vec < f64 > {
9274 let mut coefficient_sum = 0.0 ;
9375
94- coefficients. extend ( ( 0 ..interpolation_coefficients_length) . map (
95- |interpolation_coefficient_index| {
96- let index_float = interpolation_coefficient_index as f64 ;
97- let sample_index_fractional = ( index_float * resample_factor_reciprocal) . fract ( ) ;
98-
99- let sample_index_fractional_sinc_weight = Self :: sinc ( sample_index_fractional) ;
100-
101- let fir_filter = Self :: fir_filter (
102- index_float,
103- last_index,
104- sinc_center,
105- resample_factor_reciprocal,
106- ) ;
107-
108- let coefficient = sample_index_fractional_sinc_weight * fir_filter;
109-
110- coefficient_sum += coefficient;
111-
112- coefficient
113- } ,
114- ) ) ;
115-
116- coefficients
117- . iter_mut ( )
118- . for_each ( |coefficient| * coefficient /= coefficient_sum) ;
119-
120- coefficients
121- }
122-
123- pub fn get_fir_filter_coefficients ( & self , resample_factor_reciprocal : f64 ) -> Vec < f64 > {
124- let mut coefficients = Vec :: with_capacity ( NUM_FIR_FILTER_TAPS ) ;
125-
126- if self . get_interpolation_coefficients_length ( ) != 0 {
127- warn ! ( "InterpolationQuality::Medium/High::get_fir_filter_coefficients always returns an empty Vec<f64>" ) ;
128- warn ! ( "The FIR Filter coefficients are a part of the Windowed Sinc Interpolation coefficients" ) ;
76+ for ( index, coefficient) in coefficients. iter_mut ( ) . enumerate ( ) {
77+ * coefficient *= Self :: sinc ( ( index as f64 * resample_factor_reciprocal) . fract ( ) ) ;
12978
130- return coefficients ;
79+ coefficient_sum += * coefficient ;
13180 }
13281
133- let last_index = NUM_FIR_FILTER_TAPS as f64 - 1.0 ;
134-
135- let sinc_center = last_index * 0.5 ;
136-
137- let mut coefficient_sum = 0.0 ;
138-
139- coefficients. extend (
140- ( 0 ..NUM_FIR_FILTER_TAPS ) . map ( |fir_filter_coefficient_index| {
141- let coefficient = Self :: fir_filter (
142- fir_filter_coefficient_index as f64 ,
143- last_index,
144- sinc_center,
145- resample_factor_reciprocal,
146- ) ;
147-
148- coefficient_sum += coefficient;
149-
150- coefficient
151- } ) ,
152- ) ;
153-
15482 coefficients
15583 . iter_mut ( )
15684 . for_each ( |coefficient| * coefficient /= coefficient_sum) ;
15785
15886 coefficients
15987 }
16088
161- pub fn get_interpolation_coefficients_length ( & self ) -> usize {
162- use InterpolationQuality :: * ;
163- match self {
164- Low => 0 ,
165- Medium => 129 ,
166- High => 257 ,
167- }
168- }
169-
17089 fn sinc ( x : f64 ) -> f64 {
17190 if x. abs ( ) < f64:: EPSILON {
17291 1.0
@@ -175,35 +94,6 @@ impl InterpolationQuality {
17594 pi_x. sin ( ) / pi_x
17695 }
17796 }
178-
179- fn blackman ( index : f64 , last_index : f64 ) -> f64 {
180- // Calculate the Blackman window function for the given center offset
181- // w(n) = A0 - A1*cos(2πn / (N-1)) + A2*cos(4πn / (N-1)),
182- // where n is the center offset, N is the window size,
183- // and A0, A1, A2 are precalculated coefficients
184- let two_pi_n = TWO_TIMES_PI * index;
185- let four_pi_n = FOUR_TIMES_PI * index;
186-
187- BLACKMAN_A0 - BLACKMAN_A1 * ( two_pi_n / last_index) . cos ( )
188- + BLACKMAN_A2 * ( four_pi_n / last_index) . cos ( )
189- }
190-
191- fn fir_filter (
192- index : f64 ,
193- last_index : f64 ,
194- sinc_center : f64 ,
195- resample_factor_reciprocal : f64 ,
196- ) -> f64 {
197- // The resample_factor_reciprocal also happens to be our
198- // anti-alias cutoff. In this case it represents the minimum
199- // output bandwidth needed to fully represent the input.
200- let adjusted_sinc_center_offset = ( index - sinc_center) * resample_factor_reciprocal;
201-
202- let sinc_value = Self :: sinc ( adjusted_sinc_center_offset) ;
203- let blackman_window_value = Self :: blackman ( index, last_index) ;
204-
205- sinc_value * blackman_window_value
206- }
20797}
20898
20999#[ derive( Clone , Copy , Debug , Default ) ]
@@ -262,10 +152,12 @@ impl std::fmt::Display for SampleRate {
262152 }
263153}
264154
265- #[ derive( Clone , Copy , Debug , Default ) ]
155+ #[ derive( Debug , Default ) ]
266156pub struct ResampleSpec {
267157 pub resample_factor_reciprocal : f64 ,
268158 pub interpolation_output_size : usize ,
159+ pub high_coefficients : Vec < f64 > ,
160+ pub low_coefficients : Vec < f64 > ,
269161}
270162
271163impl SampleRate {
@@ -328,19 +220,27 @@ impl SampleRate {
328220 ResampleSpec {
329221 resample_factor_reciprocal : 1.0 ,
330222 interpolation_output_size : RESAMPLER_INPUT_SIZE ,
223+ high_coefficients : vec ! [ ] ,
224+ low_coefficients : vec ! [ ] ,
331225 }
332226 }
333227 Hz48000 => ResampleSpec {
334228 resample_factor_reciprocal : HZ48000_RESAMPLE_FACTOR_RECIPROCAL ,
335229 interpolation_output_size : HZ48000_INTERPOLATION_OUTPUT_SIZE ,
230+ high_coefficients : HZ48000_HIGH . to_vec ( ) ,
231+ low_coefficients : HZ48000_LOW . to_vec ( ) ,
336232 } ,
337233 Hz88200 => ResampleSpec {
338234 resample_factor_reciprocal : HZ88200_RESAMPLE_FACTOR_RECIPROCAL ,
339235 interpolation_output_size : HZ88200_INTERPOLATION_OUTPUT_SIZE ,
236+ high_coefficients : HZ88200_HIGH . to_vec ( ) ,
237+ low_coefficients : HZ88200_LOW . to_vec ( ) ,
340238 } ,
341239 Hz96000 => ResampleSpec {
342240 resample_factor_reciprocal : HZ96000_RESAMPLE_FACTOR_RECIPROCAL ,
343241 interpolation_output_size : HZ96000_INTERPOLATION_OUTPUT_SIZE ,
242+ high_coefficients : HZ96000_HIGH . to_vec ( ) ,
243+ low_coefficients : HZ96000_LOW . to_vec ( ) ,
344244 } ,
345245 }
346246 }
0 commit comments