1
1
use std:: { mem, str:: FromStr , time:: Duration } ;
2
2
3
3
pub 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
+ } ;
5
12
6
13
// Reciprocals allow us to multiply instead of divide during interpolation.
7
14
const HZ48000_RESAMPLE_FACTOR_RECIPROCAL : f64 = SAMPLE_RATE as f64 / 48_000.0 ;
@@ -26,21 +33,9 @@ const HZ88200_INTERPOLATION_OUTPUT_SIZE: usize =
26
33
const HZ96000_INTERPOLATION_OUTPUT_SIZE : usize =
27
34
( RESAMPLER_INPUT_SIZE as f64 * ( 1.0 / HZ96000_RESAMPLE_FACTOR_RECIPROCAL ) ) as usize ;
28
35
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
-
40
36
#[ derive( Clone , Copy , Debug , Default ) ]
41
37
pub enum InterpolationQuality {
42
38
Low ,
43
- Medium ,
44
39
#[ default]
45
40
High ,
46
41
}
@@ -53,7 +48,6 @@ impl FromStr for InterpolationQuality {
53
48
54
49
match s. to_lowercase ( ) . as_ref ( ) {
55
50
"low" => Ok ( Low ) ,
56
- "medium" => Ok ( Medium ) ,
57
51
"high" => Ok ( High ) ,
58
52
_ => Err ( ( ) ) ,
59
53
}
@@ -66,107 +60,32 @@ impl std::fmt::Display for InterpolationQuality {
66
60
67
61
match self {
68
62
Low => write ! ( f, "Low" ) ,
69
- Medium => write ! ( f, "Medium" ) ,
70
63
High => write ! ( f, "High" ) ,
71
64
}
72
65
}
73
66
}
74
67
75
68
impl 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 > {
92
74
let mut coefficient_sum = 0.0 ;
93
75
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 ( ) ) ;
129
78
130
- return coefficients ;
79
+ coefficient_sum += * coefficient ;
131
80
}
132
81
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
-
154
82
coefficients
155
83
. iter_mut ( )
156
84
. for_each ( |coefficient| * coefficient /= coefficient_sum) ;
157
85
158
86
coefficients
159
87
}
160
88
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
-
170
89
fn sinc ( x : f64 ) -> f64 {
171
90
if x. abs ( ) < f64:: EPSILON {
172
91
1.0
@@ -175,35 +94,6 @@ impl InterpolationQuality {
175
94
pi_x. sin ( ) / pi_x
176
95
}
177
96
}
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
- }
207
97
}
208
98
209
99
#[ derive( Clone , Copy , Debug , Default ) ]
@@ -262,10 +152,12 @@ impl std::fmt::Display for SampleRate {
262
152
}
263
153
}
264
154
265
- #[ derive( Clone , Copy , Debug , Default ) ]
155
+ #[ derive( Debug , Default ) ]
266
156
pub struct ResampleSpec {
267
157
pub resample_factor_reciprocal : f64 ,
268
158
pub interpolation_output_size : usize ,
159
+ pub high_coefficients : Vec < f64 > ,
160
+ pub low_coefficients : Vec < f64 > ,
269
161
}
270
162
271
163
impl SampleRate {
@@ -328,19 +220,27 @@ impl SampleRate {
328
220
ResampleSpec {
329
221
resample_factor_reciprocal : 1.0 ,
330
222
interpolation_output_size : RESAMPLER_INPUT_SIZE ,
223
+ high_coefficients : vec ! [ ] ,
224
+ low_coefficients : vec ! [ ] ,
331
225
}
332
226
}
333
227
Hz48000 => ResampleSpec {
334
228
resample_factor_reciprocal : HZ48000_RESAMPLE_FACTOR_RECIPROCAL ,
335
229
interpolation_output_size : HZ48000_INTERPOLATION_OUTPUT_SIZE ,
230
+ high_coefficients : HZ48000_HIGH . to_vec ( ) ,
231
+ low_coefficients : HZ48000_LOW . to_vec ( ) ,
336
232
} ,
337
233
Hz88200 => ResampleSpec {
338
234
resample_factor_reciprocal : HZ88200_RESAMPLE_FACTOR_RECIPROCAL ,
339
235
interpolation_output_size : HZ88200_INTERPOLATION_OUTPUT_SIZE ,
236
+ high_coefficients : HZ88200_HIGH . to_vec ( ) ,
237
+ low_coefficients : HZ88200_LOW . to_vec ( ) ,
340
238
} ,
341
239
Hz96000 => ResampleSpec {
342
240
resample_factor_reciprocal : HZ96000_RESAMPLE_FACTOR_RECIPROCAL ,
343
241
interpolation_output_size : HZ96000_INTERPOLATION_OUTPUT_SIZE ,
242
+ high_coefficients : HZ96000_HIGH . to_vec ( ) ,
243
+ low_coefficients : HZ96000_LOW . to_vec ( ) ,
344
244
} ,
345
245
}
346
246
}
0 commit comments