]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | |
3 | ** All rights reserved. | |
4 | ** | |
5 | ** This code is released under 2-clause BSD license. Please see the | |
6 | ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING | |
7 | */ | |
8 | ||
9 | #include <stdio.h> | |
10 | #include <stdlib.h> | |
11 | #include <math.h> | |
12 | ||
13 | #include <samplerate.h> | |
14 | ||
15 | #include "util.h" | |
16 | ||
17 | #define SHORT_BUFFER_LEN 2048 | |
18 | #define LONG_BUFFER_LEN ((1 << 16) - 20) | |
19 | ||
20 | static void simple_test (int converter) ; | |
21 | static void stream_test (int converter, double ratio) ; | |
22 | static void init_term_test (int converter, double ratio) ; | |
23 | ||
24 | static int next_block_length (int reset) ; | |
25 | ||
26 | int | |
27 | main (void) | |
28 | { static double src_ratios [] = | |
29 | { 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000, | |
30 | 0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000 | |
31 | } ; | |
32 | ||
33 | int k ; | |
34 | ||
35 | puts ("\n Zero Order Hold interpolator:") ; | |
36 | ||
37 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
38 | init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; | |
39 | puts ("") ; | |
40 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
41 | stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; | |
42 | ||
43 | ||
44 | puts ("\n Linear interpolator:") ; | |
45 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
46 | init_term_test (SRC_LINEAR, src_ratios [k]) ; | |
47 | puts ("") ; | |
48 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
49 | stream_test (SRC_LINEAR, src_ratios [k]) ; | |
50 | ||
51 | ||
52 | puts ("\n Sinc interpolator:") ; | |
53 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
54 | init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ; | |
55 | puts ("") ; | |
56 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
57 | stream_test (SRC_SINC_FASTEST, src_ratios [k]) ; | |
58 | ||
59 | puts ("") ; | |
60 | ||
61 | simple_test (SRC_SINC_FASTEST) ; | |
62 | ||
63 | return 0 ; | |
64 | } /* main */ | |
65 | ||
66 | static void | |
67 | simple_test (int converter) | |
68 | { | |
69 | int ilen = 199030, olen = 1000, error ; | |
70 | ||
71 | { | |
72 | float in [ilen] ; | |
73 | float out [olen] ; | |
74 | double ratio = (1.0 * olen) / ilen ; | |
75 | SRC_DATA src_data = | |
76 | { in, out, | |
77 | ilen, olen, | |
78 | 0, 0, 0, | |
79 | ratio | |
80 | } ; | |
81 | ||
82 | error = src_simple (&src_data, converter, 1) ; | |
83 | if (error) | |
84 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
85 | exit (1) ; | |
86 | } ; | |
87 | } ; | |
88 | ||
89 | return ; | |
90 | } /* simple_test */ | |
91 | ||
92 | static void | |
93 | init_term_test (int converter, double src_ratio) | |
94 | { static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ; | |
95 | ||
96 | SRC_DATA src_data ; | |
97 | ||
98 | int k, input_len, output_len, error, terminate ; | |
99 | ||
100 | printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ; | |
101 | fflush (stdout) ; | |
102 | ||
103 | /* Calculate maximun input and output lengths. */ | |
104 | if (src_ratio >= 1.0) | |
105 | { output_len = SHORT_BUFFER_LEN ; | |
106 | input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ; | |
107 | } | |
108 | else | |
109 | { input_len = SHORT_BUFFER_LEN ; | |
110 | output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ; | |
111 | } ; | |
112 | ||
113 | /* Reduce input_len by 10 so output is longer than necessary. */ | |
114 | input_len -= 10 ; | |
115 | ||
116 | for (k = 0 ; k < ARRAY_LEN (input) ; k++) | |
117 | input [k] = 1.0 ; | |
118 | ||
119 | if (output_len > SHORT_BUFFER_LEN) | |
120 | { printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ; | |
121 | exit (1) ; | |
122 | } ; | |
123 | ||
124 | src_data.data_in = input ; | |
125 | src_data.input_frames = input_len ; | |
126 | ||
127 | src_data.src_ratio = src_ratio ; | |
128 | ||
129 | src_data.data_out = output ; | |
130 | src_data.output_frames = SHORT_BUFFER_LEN ; | |
131 | ||
132 | if ((error = src_simple (&src_data, converter, 1))) | |
133 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
134 | exit (1) ; | |
135 | } ; | |
136 | ||
137 | terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ; | |
138 | ||
139 | if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate) | |
140 | { printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ; | |
141 | printf ("\tterminate : %d\n", terminate) ; | |
142 | printf ("\tsrc_ratio : %.4f\n", src_ratio) ; | |
143 | printf ("\tinput_len : %d\n" | |
144 | "\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ; | |
145 | printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ; | |
146 | exit (1) ; | |
147 | } ; | |
148 | ||
149 | if (labs (src_data.input_frames_used - input_len) > 1) | |
150 | { printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n", | |
151 | __LINE__, input_len, src_data.input_frames_used) ; | |
152 | printf ("\tsrc_ratio : %.4f\n", src_ratio) ; | |
153 | printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ; | |
154 | exit (1) ; | |
155 | } ; | |
156 | ||
157 | if (fabs (output [0]) < 0.1) | |
158 | { printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ; | |
159 | printf ("\toutput [0] == %f\n\n", output [0]) ; | |
160 | exit (1) ; | |
161 | } | |
162 | ||
163 | puts ("ok") ; | |
164 | ||
165 | return ; | |
166 | } /* init_term_test */ | |
167 | ||
168 | static void | |
169 | stream_test (int converter, double src_ratio) | |
170 | { static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ; | |
171 | ||
172 | SRC_STATE *src_state ; | |
173 | SRC_DATA src_data ; | |
174 | ||
175 | int input_len, output_len, current_in, current_out ; | |
176 | int k, error, terminate ; | |
177 | ||
178 | printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ; | |
179 | fflush (stdout) ; | |
180 | ||
181 | /* Erik */ | |
182 | for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0 ; | |
183 | ||
184 | /* Calculate maximun input and output lengths. */ | |
185 | if (src_ratio >= 1.0) | |
186 | { output_len = LONG_BUFFER_LEN ; | |
187 | input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ; | |
188 | } | |
189 | else | |
190 | { input_len = LONG_BUFFER_LEN ; | |
191 | output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ; | |
192 | } ; | |
193 | ||
194 | /* Reduce input_len by 10 so output is longer than necessary. */ | |
195 | input_len -= 20 ; | |
196 | ||
197 | if (output_len > LONG_BUFFER_LEN) | |
198 | { printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ; | |
199 | exit (1) ; | |
200 | } ; | |
201 | ||
202 | current_in = current_out = 0 ; | |
203 | ||
204 | /* Perform sample rate conversion. */ | |
205 | if ((src_state = src_new (converter, 1, &error)) == NULL) | |
206 | { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; | |
207 | exit (1) ; | |
208 | } ; | |
209 | ||
210 | src_data.end_of_input = 0 ; /* Set this later. */ | |
211 | ||
212 | src_data.data_in = input ; | |
213 | ||
214 | src_data.src_ratio = src_ratio ; | |
215 | ||
216 | src_data.data_out = output ; | |
217 | src_data.output_frames = ARRAY_LEN (output) / 10 ; | |
218 | ||
219 | terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; | |
220 | ||
221 | while (1) | |
222 | { | |
223 | src_data.input_frames = next_block_length (0) ; | |
224 | src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ; | |
225 | ||
226 | src_data.output_frames = ARRAY_LEN (output) - current_out ; | |
227 | /*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/ | |
228 | ||
229 | src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ; | |
230 | ||
231 | if ((error = src_process (src_state, &src_data))) | |
232 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
233 | printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; | |
234 | printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; | |
235 | exit (1) ; | |
236 | } ; | |
237 | ||
238 | if (src_data.end_of_input && src_data.output_frames_gen == 0) | |
239 | break ; | |
240 | ||
241 | if (src_data.input_frames_used > src_data.input_frames) | |
242 | { printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ; | |
243 | printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; | |
244 | printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ; | |
245 | printf (" src_data.output_frames : %ld\n", src_data.output_frames) ; | |
246 | printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ; | |
247 | exit (1) ; | |
248 | } ; | |
249 | ||
250 | if (src_data.input_frames_used < 0) | |
251 | { printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ; | |
252 | exit (1) ; | |
253 | } ; | |
254 | ||
255 | if (src_data.output_frames_gen < 0) | |
256 | { printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ; | |
257 | exit (1) ; | |
258 | } ; | |
259 | ||
260 | current_in += src_data.input_frames_used ; | |
261 | current_out += src_data.output_frames_gen ; | |
262 | ||
263 | if (current_in > input_len + terminate) | |
264 | { printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ; | |
265 | exit (1) ; | |
266 | } ; | |
267 | ||
268 | if (current_out > output_len) | |
269 | { printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ; | |
270 | exit (1) ; | |
271 | } ; | |
272 | ||
273 | if (src_data.input_frames_used > input_len) | |
274 | { printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ; | |
275 | exit (1) ; | |
276 | } ; | |
277 | ||
278 | if (src_data.output_frames_gen > output_len) | |
279 | { printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ; | |
280 | exit (1) ; | |
281 | } ; | |
282 | ||
283 | if (src_data.data_in == NULL && src_data.output_frames_gen == 0) | |
284 | break ; | |
285 | ||
286 | ||
287 | src_data.data_in += src_data.input_frames_used ; | |
288 | src_data.data_out += src_data.output_frames_gen ; | |
289 | } ; | |
290 | ||
291 | src_state = src_delete (src_state) ; | |
292 | ||
293 | if (fabs (current_out - src_ratio * input_len) > terminate) | |
294 | { printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__, | |
295 | current_out, src_ratio * input_len, terminate) ; | |
296 | printf ("\tsrc_ratio : %.4f\n", src_ratio) ; | |
297 | printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ; | |
298 | printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ; | |
299 | exit (1) ; | |
300 | } ; | |
301 | ||
302 | if (current_in != input_len) | |
303 | { printf ("\n\nLine %d : unused input.\n", __LINE__) ; | |
304 | printf ("\tinput_len : %d\n", input_len) ; | |
305 | printf ("\tinput_frames_used : %d\n\n", current_in) ; | |
306 | exit (1) ; | |
307 | } ; | |
308 | ||
309 | puts ("ok") ; | |
310 | ||
311 | return ; | |
312 | } /* stream_test */ | |
313 | ||
314 | static int | |
315 | next_block_length (int reset) | |
316 | { static int block_lengths [] = /* Should be an odd length. */ | |
317 | { /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/ | |
318 | 5, 400, 10, 300, 20, 200, 50, 100, 70 | |
319 | } ; | |
320 | static int block_len_index = 0 ; | |
321 | ||
322 | if (reset) | |
323 | block_len_index = 0 ; | |
324 | else | |
325 | block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ; | |
326 | ||
327 | return block_lengths [block_len_index] ; | |
328 | } /* next_block_length */ | |
329 |