Mercurial > hg > sv-dependency-builds
comparison src/libsamplerate-0.1.8/tests/multi_channel_test.c @ 0:c7265573341e
Import initial set of sources
author | Chris Cannam |
---|---|
date | Mon, 18 Mar 2013 14:12:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c7265573341e |
---|---|
1 /* | |
2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com> | |
3 ** | |
4 ** This program is free software; you can redistribute it and/or modify | |
5 ** it under the terms of the GNU General Public License as published by | |
6 ** the Free Software Foundation; either version 2 of the License, or | |
7 ** (at your option) any later version. | |
8 ** | |
9 ** This program is distributed in the hope that it will be useful, | |
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 ** GNU General Public License for more details. | |
13 ** | |
14 ** You should have received a copy of the GNU General Public License | |
15 ** along with this program; if not, write to the Free Software | |
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | |
17 */ | |
18 | |
19 #include "config.h" | |
20 | |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <math.h> | |
25 #include <assert.h> | |
26 | |
27 #include <samplerate.h> | |
28 | |
29 #include "util.h" | |
30 #define BUFFER_LEN 50000 | |
31 #define BLOCK_LEN (12) | |
32 | |
33 #define MAX_CHANNELS 10 | |
34 | |
35 static void simple_test (int converter, int channel_count, double target_snr) ; | |
36 static void process_test (int converter, int channel_count, double target_snr) ; | |
37 static void callback_test (int converter, int channel_count, double target_snr) ; | |
38 | |
39 int | |
40 main (void) | |
41 { double target ; | |
42 int k ; | |
43 | |
44 puts ("\n Zero Order Hold interpolator :") ; | |
45 target = 38.0 ; | |
46 for (k = 1 ; k <= 3 ; k++) | |
47 { simple_test (SRC_ZERO_ORDER_HOLD, k, target) ; | |
48 process_test (SRC_ZERO_ORDER_HOLD, k, target) ; | |
49 callback_test (SRC_ZERO_ORDER_HOLD, k, target) ; | |
50 } ; | |
51 | |
52 puts ("\n Linear interpolator :") ; | |
53 target = 79.0 ; | |
54 for (k = 1 ; k <= 3 ; k++) | |
55 { simple_test (SRC_LINEAR, k, target) ; | |
56 process_test (SRC_LINEAR, k, target) ; | |
57 callback_test (SRC_LINEAR, k, target) ; | |
58 } ; | |
59 | |
60 puts ("\n Sinc interpolator :") ; | |
61 target = 100.0 ; | |
62 for (k = 1 ; k <= MAX_CHANNELS ; k++) | |
63 { simple_test (SRC_SINC_FASTEST, k, target) ; | |
64 process_test (SRC_SINC_FASTEST, k, target) ; | |
65 callback_test (SRC_SINC_FASTEST, k, target) ; | |
66 } ; | |
67 | |
68 puts ("") ; | |
69 | |
70 return 0 ; | |
71 } /* main */ | |
72 | |
73 /*============================================================================== | |
74 */ | |
75 | |
76 static float input_serial [BUFFER_LEN * MAX_CHANNELS] ; | |
77 static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ; | |
78 static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ; | |
79 static float output_serial [BUFFER_LEN * MAX_CHANNELS] ; | |
80 | |
81 static void | |
82 simple_test (int converter, int channel_count, double target_snr) | |
83 { SRC_DATA src_data ; | |
84 | |
85 double freq, snr ; | |
86 int ch, error, frames ; | |
87 | |
88 printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ; | |
89 fflush (stdout) ; | |
90 | |
91 assert (channel_count <= MAX_CHANNELS) ; | |
92 | |
93 memset (input_serial, 0, sizeof (input_serial)) ; | |
94 memset (input_interleaved, 0, sizeof (input_interleaved)) ; | |
95 memset (output_interleaved, 0, sizeof (output_interleaved)) ; | |
96 memset (output_serial, 0, sizeof (output_serial)) ; | |
97 | |
98 frames = BUFFER_LEN ; | |
99 | |
100 /* Calculate channel_count separate windowed sine waves. */ | |
101 for (ch = 0 ; ch < channel_count ; ch++) | |
102 { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; | |
103 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; | |
104 } ; | |
105 | |
106 /* Interleave the data in preparation for SRC. */ | |
107 interleave_data (input_serial, input_interleaved, frames, channel_count) ; | |
108 | |
109 /* Choose a converstion ratio <= 1.0. */ | |
110 src_data.src_ratio = 0.95 ; | |
111 | |
112 src_data.data_in = input_interleaved ; | |
113 src_data.input_frames = frames ; | |
114 | |
115 src_data.data_out = output_interleaved ; | |
116 src_data.output_frames = frames ; | |
117 | |
118 if ((error = src_simple (&src_data, converter, channel_count))) | |
119 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
120 exit (1) ; | |
121 } ; | |
122 | |
123 if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2) | |
124 { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, | |
125 src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ; | |
126 printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; | |
127 printf ("\tinput_len : %ld\n", src_data.input_frames) ; | |
128 printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ; | |
129 exit (1) ; | |
130 } ; | |
131 | |
132 /* De-interleave data so SNR can be calculated for each channel. */ | |
133 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; | |
134 | |
135 for (ch = 0 ; ch < channel_count ; ch++) | |
136 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; | |
137 if (snr < target_snr) | |
138 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; | |
139 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; | |
140 exit (1) ; | |
141 } ; | |
142 } ; | |
143 | |
144 puts ("ok") ; | |
145 | |
146 return ; | |
147 } /* simple_test */ | |
148 | |
149 /*============================================================================== | |
150 */ | |
151 | |
152 static void | |
153 process_test (int converter, int channel_count, double target_snr) | |
154 { SRC_STATE *src_state ; | |
155 SRC_DATA src_data ; | |
156 | |
157 double freq, snr ; | |
158 int ch, error, frames, current_in, current_out ; | |
159 | |
160 printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ; | |
161 fflush (stdout) ; | |
162 | |
163 assert (channel_count <= MAX_CHANNELS) ; | |
164 | |
165 memset (input_serial, 0, sizeof (input_serial)) ; | |
166 memset (input_interleaved, 0, sizeof (input_interleaved)) ; | |
167 memset (output_interleaved, 0, sizeof (output_interleaved)) ; | |
168 memset (output_serial, 0, sizeof (output_serial)) ; | |
169 | |
170 frames = BUFFER_LEN ; | |
171 | |
172 /* Calculate channel_count separate windowed sine waves. */ | |
173 for (ch = 0 ; ch < channel_count ; ch++) | |
174 { freq = (400.0 + 11.333333333 * ch) / 44100.0 ; | |
175 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; | |
176 } ; | |
177 | |
178 /* Interleave the data in preparation for SRC. */ | |
179 interleave_data (input_serial, input_interleaved, frames, channel_count) ; | |
180 | |
181 /* Perform sample rate conversion. */ | |
182 if ((src_state = src_new (converter, channel_count, &error)) == NULL) | |
183 { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; | |
184 exit (1) ; | |
185 } ; | |
186 | |
187 src_data.end_of_input = 0 ; /* Set this later. */ | |
188 | |
189 /* Choose a converstion ratio < 1.0. */ | |
190 src_data.src_ratio = 0.95 ; | |
191 | |
192 src_data.data_in = input_interleaved ; | |
193 src_data.data_out = output_interleaved ; | |
194 | |
195 current_in = current_out = 0 ; | |
196 | |
197 while (1) | |
198 { src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ; | |
199 src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ; | |
200 | |
201 if ((error = src_process (src_state, &src_data))) | |
202 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
203 exit (1) ; | |
204 } ; | |
205 | |
206 if (src_data.end_of_input && src_data.output_frames_gen == 0) | |
207 break ; | |
208 | |
209 current_in += src_data.input_frames_used ; | |
210 current_out += src_data.output_frames_gen ; | |
211 | |
212 src_data.data_in += src_data.input_frames_used * channel_count ; | |
213 src_data.data_out += src_data.output_frames_gen * channel_count ; | |
214 | |
215 src_data.end_of_input = (current_in >= frames) ? 1 : 0 ; | |
216 } ; | |
217 | |
218 src_state = src_delete (src_state) ; | |
219 | |
220 if (fabs (current_out - src_data.src_ratio * current_in) > 2) | |
221 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, | |
222 current_out, (int) floor (src_data.src_ratio * current_in)) ; | |
223 printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; | |
224 printf ("\tinput_len : %d\n", frames) ; | |
225 printf ("\toutput_len : %d\n\n", current_out) ; | |
226 exit (1) ; | |
227 } ; | |
228 | |
229 /* De-interleave data so SNR can be calculated for each channel. */ | |
230 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; | |
231 | |
232 for (ch = 0 ; ch < channel_count ; ch++) | |
233 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; | |
234 if (snr < target_snr) | |
235 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; | |
236 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; | |
237 exit (1) ; | |
238 } ; | |
239 } ; | |
240 | |
241 puts ("ok") ; | |
242 | |
243 return ; | |
244 } /* process_test */ | |
245 | |
246 /*============================================================================== | |
247 */ | |
248 | |
249 typedef struct | |
250 { int channels ; | |
251 long total_frames ; | |
252 long current_frame ; | |
253 float *data ; | |
254 } TEST_CB_DATA ; | |
255 | |
256 static long | |
257 test_callback_func (void *cb_data, float **data) | |
258 { TEST_CB_DATA *pcb_data ; | |
259 | |
260 long frames ; | |
261 | |
262 if ((pcb_data = cb_data) == NULL) | |
263 return 0 ; | |
264 | |
265 if (data == NULL) | |
266 return 0 ; | |
267 | |
268 *data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ; | |
269 | |
270 if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN) | |
271 frames = pcb_data->total_frames - pcb_data->current_frame ; | |
272 else | |
273 frames = BLOCK_LEN ; | |
274 | |
275 pcb_data->current_frame += frames ; | |
276 | |
277 return frames ; | |
278 } /* test_callback_func */ | |
279 | |
280 static void | |
281 callback_test (int converter, int channel_count, double target_snr) | |
282 { TEST_CB_DATA test_callback_data ; | |
283 SRC_STATE *src_state = NULL ; | |
284 | |
285 double freq, snr, src_ratio ; | |
286 int ch, error, frames, read_total, read_count ; | |
287 | |
288 printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ; | |
289 fflush (stdout) ; | |
290 | |
291 assert (channel_count <= MAX_CHANNELS) ; | |
292 | |
293 memset (input_serial, 0, sizeof (input_serial)) ; | |
294 memset (input_interleaved, 0, sizeof (input_interleaved)) ; | |
295 memset (output_interleaved, 0, sizeof (output_interleaved)) ; | |
296 memset (output_serial, 0, sizeof (output_serial)) ; | |
297 memset (&test_callback_data, 0, sizeof (test_callback_data)) ; | |
298 | |
299 frames = BUFFER_LEN ; | |
300 | |
301 /* Calculate channel_count separate windowed sine waves. */ | |
302 for (ch = 0 ; ch < channel_count ; ch++) | |
303 { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; | |
304 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; | |
305 } ; | |
306 | |
307 /* Interleave the data in preparation for SRC. */ | |
308 interleave_data (input_serial, input_interleaved, frames, channel_count) ; | |
309 | |
310 /* Perform sample rate conversion. */ | |
311 src_ratio = 0.95 ; | |
312 test_callback_data.channels = channel_count ; | |
313 test_callback_data.total_frames = frames ; | |
314 test_callback_data.current_frame = 0 ; | |
315 test_callback_data.data = input_interleaved ; | |
316 | |
317 if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL) | |
318 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
319 exit (1) ; | |
320 } ; | |
321 | |
322 read_total = 0 ; | |
323 while (read_total < frames) | |
324 { read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ; | |
325 | |
326 if (read_count <= 0) | |
327 break ; | |
328 | |
329 read_total += read_count ; | |
330 } ; | |
331 | |
332 if ((error = src_error (src_state)) != 0) | |
333 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
334 exit (1) ; | |
335 } ; | |
336 | |
337 src_state = src_delete (src_state) ; | |
338 | |
339 if (fabs (read_total - src_ratio * frames) > 2) | |
340 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, | |
341 read_total, (int) floor (src_ratio * frames)) ; | |
342 printf ("\tsrc_ratio : %.4f\n", src_ratio) ; | |
343 printf ("\tinput_len : %d\n", frames) ; | |
344 printf ("\toutput_len : %d\n\n", read_total) ; | |
345 exit (1) ; | |
346 } ; | |
347 | |
348 /* De-interleave data so SNR can be calculated for each channel. */ | |
349 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; | |
350 | |
351 for (ch = 0 ; ch < channel_count ; ch++) | |
352 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; | |
353 if (snr < target_snr) | |
354 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; | |
355 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; | |
356 exit (1) ; | |
357 } ; | |
358 } ; | |
359 | |
360 puts ("ok") ; | |
361 | |
362 return ; | |
363 } /* callback_test */ | |
364 |