Mercurial > hg > sv-dependency-builds
comparison src/libsndfile-1.0.27/tests/utils.tpl @ 40:1df64224f5ac
Current libsndfile source
author | Chris Cannam |
---|---|
date | Tue, 18 Oct 2016 13:22:47 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
39:7ddb4fc30dac | 40:1df64224f5ac |
---|---|
1 [+ AutoGen5 template h c +] | |
2 /* | |
3 ** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com> | |
4 ** | |
5 ** This program is free software; you can redistribute it and/or modify | |
6 ** it under the terms of the GNU General Public License as published by | |
7 ** the Free Software Foundation; either version 2 of the License, or | |
8 ** (at your option) any later version. | |
9 ** | |
10 ** This program is distributed in the hope that it will be useful, | |
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 ** GNU General Public License for more details. | |
14 ** | |
15 ** You should have received a copy of the GNU General Public License | |
16 ** along with this program; if not, write to the Free Software | |
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 */ | |
19 | |
20 /* | |
21 ** Utility functions to make writing the test suite easier. | |
22 ** | |
23 ** The .c and .h files were generated automagically with Autogen from | |
24 ** the files utils.def and utils.tpl. | |
25 */ | |
26 | |
27 [+ CASE (suffix) +] | |
28 [+ == h +] | |
29 | |
30 #ifdef __cplusplus | |
31 extern "C" { | |
32 #endif /* __cplusplus */ | |
33 | |
34 #include <stdint.h> | |
35 #include <stdarg.h> | |
36 | |
37 #define ARRAY_LEN(x) ((int) (sizeof (x)) / (sizeof ((x) [0]))) | |
38 #define SIGNED_SIZEOF(x) ((int64_t) (sizeof (x))) | |
39 #define NOT(x) (! (x)) | |
40 #define ABS(x) ((x) >= 0 ? (x) : -(x)) | |
41 | |
42 #define PIPE_INDEX(x) ((x) + 500) | |
43 #define PIPE_TEST_LEN 12345 | |
44 | |
45 | |
46 [+ FOR float_type | |
47 +]void gen_windowed_sine_[+ (get "name") +] ([+ (get "name") +] *data, int len, double maximum) ; | |
48 [+ ENDFOR float_type | |
49 +] | |
50 | |
51 void create_short_sndfile (const char *filename, int format, int channels) ; | |
52 | |
53 void check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num) ; | |
54 | |
55 void print_test_name (const char *test, const char *filename) ; | |
56 | |
57 void dump_data_to_file (const char *filename, const void *data, unsigned int datalen) ; | |
58 | |
59 void write_mono_file (const char * filename, int format, int srate, float * output, int len) ; | |
60 | |
61 #ifdef __GNUC__ | |
62 static inline void | |
63 exit_if_true (int test, const char *format, ...) | |
64 #if (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO) | |
65 __attribute__ ((format (gnu_printf, 2, 3))) ; | |
66 #else | |
67 __attribute__ ((format (printf, 2, 3))) ; | |
68 #endif | |
69 #endif | |
70 | |
71 static inline void | |
72 exit_if_true (int test, const char *format, ...) | |
73 { if (test) | |
74 { va_list argptr ; | |
75 va_start (argptr, format) ; | |
76 vprintf (format, argptr) ; | |
77 va_end (argptr) ; | |
78 exit (1) ; | |
79 } ; | |
80 } /* exit_if_true */ | |
81 | |
82 static inline int32_t | |
83 arith_shift_left (int32_t x, int shift) | |
84 { return (int32_t) (((uint32_t) x) << shift) ; | |
85 } /* arith_shift_left */ | |
86 | |
87 /* | |
88 ** Functions for saving two vectors of data in an ascii text file which | |
89 ** can then be loaded into GNU octave for comparison. | |
90 */ | |
91 | |
92 [+ FOR io_type | |
93 +]int oct_save_[+ (get "io_element") +] (const [+ (get "io_element") +] *a, const [+ (get "io_element") +] *b, int len) ; | |
94 [+ ENDFOR io_type | |
95 +] | |
96 | |
97 void delete_file (int format, const char *filename) ; | |
98 | |
99 void count_open_files (void) ; | |
100 void increment_open_file_count (void) ; | |
101 void check_open_file_count_or_die (int lineno) ; | |
102 | |
103 #ifdef SNDFILE_H | |
104 | |
105 static inline void | |
106 sf_info_clear (SF_INFO * info) | |
107 { memset (info, 0, sizeof (SF_INFO)) ; | |
108 } /* sf_info_clear */ | |
109 | |
110 static inline void | |
111 sf_info_setup (SF_INFO * info, int format, int samplerate, int channels) | |
112 { sf_info_clear (info) ; | |
113 | |
114 info->format = format ; | |
115 info->samplerate = samplerate ; | |
116 info->channels = channels ; | |
117 } /* sf_info_setup */ | |
118 | |
119 | |
120 void dump_log_buffer (SNDFILE *file) ; | |
121 void check_log_buffer_or_die (SNDFILE *file, int line_num) ; | |
122 int string_in_log_buffer (SNDFILE *file, const char *s) ; | |
123 void hexdump_file (const char * filename, sf_count_t offset, sf_count_t length) ; | |
124 | |
125 void test_sf_format_or_die (const SF_INFO *info, int line_num) ; | |
126 | |
127 SNDFILE *test_open_file_or_die | |
128 (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) ; | |
129 | |
130 void test_read_write_position_or_die | |
131 (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos) ; | |
132 | |
133 void test_seek_or_die | |
134 (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num) ; | |
135 | |
136 [+ FOR read_op +] | |
137 [+ FOR io_type | |
138 +]void test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die | |
139 (SNDFILE *file, int pass, [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) ; | |
140 [+ ENDFOR io_type +][+ ENDFOR read_op +] | |
141 | |
142 void | |
143 test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num) ; | |
144 | |
145 [+ FOR write_op +] | |
146 [+ FOR io_type | |
147 +]void test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die | |
148 (SNDFILE *file, int pass, const [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) ; | |
149 [+ ENDFOR io_type +][+ ENDFOR write_op +] | |
150 | |
151 void | |
152 test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num) ; | |
153 | |
154 [+ FOR io_type | |
155 +]void compare_[+ (get "io_element") +]_or_die (const [+ (get "io_element") +] *expected, const [+ (get "io_element") +] *actual, unsigned count, int line_num) ; | |
156 [+ ENDFOR io_type +] | |
157 | |
158 | |
159 void gen_lowpass_signal_float (float *data, int len) ; | |
160 | |
161 sf_count_t file_length (const char * fname) ; | |
162 sf_count_t file_length_fd (int fd) ; | |
163 | |
164 #endif | |
165 | |
166 #ifdef __cplusplus | |
167 } /* extern "C" */ | |
168 #endif /* __cplusplus */ | |
169 | |
170 [+ == c +] | |
171 | |
172 #include "sfconfig.h" | |
173 | |
174 #include <stdio.h> | |
175 #include <stdlib.h> | |
176 #include <inttypes.h> | |
177 | |
178 #if HAVE_UNISTD_H | |
179 #include <unistd.h> | |
180 #endif | |
181 | |
182 #if (HAVE_DECL_S_IRGRP == 0) | |
183 #include <sf_unistd.h> | |
184 #endif | |
185 | |
186 #include <errno.h> | |
187 #include <string.h> | |
188 #include <ctype.h> | |
189 #include <math.h> | |
190 #include <fcntl.h> | |
191 #include <sys/stat.h> | |
192 | |
193 #include <sndfile.h> | |
194 | |
195 #include "utils.h" | |
196 | |
197 #ifndef M_PI | |
198 #define M_PI 3.14159265358979323846264338 | |
199 #endif | |
200 | |
201 #define LOG_BUFFER_SIZE 2048 | |
202 | |
203 /* | |
204 ** Neat solution to the Win32/OS2 binary file flage requirement. | |
205 ** If O_BINARY isn't already defined by the inclusion of the system | |
206 ** headers, set it to zero. | |
207 */ | |
208 #ifndef O_BINARY | |
209 #define O_BINARY 0 | |
210 #endif | |
211 | |
212 [+ FOR float_type +] | |
213 void | |
214 gen_windowed_sine_[+ (get "name") +] ([+ (get "name") +] *data, int len, double maximum) | |
215 { int k ; | |
216 | |
217 memset (data, 0, len * sizeof ([+ (get "name") +])) ; | |
218 | |
219 len = (5 * len) / 6 ; | |
220 | |
221 for (k = 0 ; k < len ; k++) | |
222 { data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ; | |
223 | |
224 /* Apply Hanning Window. */ | |
225 data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ; | |
226 } | |
227 | |
228 return ; | |
229 } /* gen_windowed_sine_[+ (get "name") +] */ | |
230 [+ ENDFOR float_type +] | |
231 | |
232 void | |
233 create_short_sndfile (const char *filename, int format, int channels) | |
234 { short data [2 * 3 * 4 * 5 * 6 * 7] = { 0, } ; | |
235 SNDFILE *file ; | |
236 SF_INFO sfinfo ; | |
237 | |
238 sfinfo.samplerate = 44100 ; | |
239 sfinfo.channels = channels ; | |
240 sfinfo.format = format ; | |
241 | |
242 if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) | |
243 { printf ("Error (%s, %d) : sf_open failed : %s\n", __FILE__, __LINE__, sf_strerror (file)) ; | |
244 exit (1) ; | |
245 } ; | |
246 | |
247 sf_write_short (file, data, ARRAY_LEN (data)) ; | |
248 | |
249 sf_close (file) ; | |
250 } /* create_short_sndfile */ | |
251 | |
252 void | |
253 check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num) | |
254 { static unsigned char buf [4096] ; | |
255 uint64_t cksum ; | |
256 FILE *file ; | |
257 int k, read_count ; | |
258 | |
259 memset (buf, 0, sizeof (buf)) ; | |
260 | |
261 /* The 'b' in the mode string means binary for Win32. */ | |
262 if ((file = fopen (filename, "rb")) == NULL) | |
263 { printf ("\n\nLine %d: could not open file '%s'\n\n", line_num, filename) ; | |
264 exit (1) ; | |
265 } ; | |
266 | |
267 cksum = 0 ; | |
268 | |
269 while ((read_count = fread (buf, 1, sizeof (buf), file))) | |
270 for (k = 0 ; k < read_count ; k++) | |
271 cksum = (cksum * 511 + buf [k]) & 0xfffffffffffff ; | |
272 | |
273 fclose (file) ; | |
274 | |
275 if (target_hash == 0) | |
276 { printf (" 0x%" PRIx64 "\n", cksum) ; | |
277 return ; | |
278 } ; | |
279 | |
280 if (cksum != target_hash) | |
281 { printf ("\n\nLine %d: incorrect hash value 0x%" PRIx64 " should be 0x%" PRIx64 ".\n\n", line_num, cksum, target_hash) ; | |
282 exit (1) ; | |
283 } ; | |
284 | |
285 return ; | |
286 } /* check_file_hash_or_die */ | |
287 | |
288 void | |
289 print_test_name (const char *test, const char *filename) | |
290 { int count ; | |
291 | |
292 if (test == NULL) | |
293 { printf (__FILE__ ": bad test of filename parameter.\n") ; | |
294 exit (1) ; | |
295 } ; | |
296 | |
297 if (filename == NULL || strlen (filename) == 0) | |
298 { printf (" %-30s : ", test) ; | |
299 count = 25 ; | |
300 } | |
301 else | |
302 { printf (" %-30s : %s ", test, filename) ; | |
303 count = 24 - strlen (filename) ; | |
304 } ; | |
305 | |
306 while (count -- > 0) | |
307 putchar ('.') ; | |
308 putchar (' ') ; | |
309 | |
310 fflush (stdout) ; | |
311 } /* print_test_name */ | |
312 | |
313 void | |
314 dump_data_to_file (const char *filename, const void *data, unsigned int datalen) | |
315 { FILE *file ; | |
316 | |
317 if ((file = fopen (filename, "wb")) == NULL) | |
318 { printf ("\n\nLine %d : could not open file : %s\n\n", __LINE__, filename) ; | |
319 exit (1) ; | |
320 } ; | |
321 | |
322 if (fwrite (data, 1, datalen, file) != datalen) | |
323 { printf ("\n\nLine %d : fwrite failed.\n\n", __LINE__) ; | |
324 exit (1) ; | |
325 } ; | |
326 | |
327 fclose (file) ; | |
328 | |
329 } /* dump_data_to_file */ | |
330 | |
331 /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- | |
332 */ | |
333 | |
334 static char octfilename [] = "error.dat" ; | |
335 | |
336 [+ FOR io_type | |
337 +]int | |
338 oct_save_[+ (get "io_element") +] (const [+ (get "io_element") +] *a, const [+ (get "io_element") +] *b, int len) | |
339 { FILE *file ; | |
340 int k ; | |
341 | |
342 if (! (file = fopen (octfilename, "w"))) | |
343 return 1 ; | |
344 | |
345 fprintf (file, "# Not created by Octave\n") ; | |
346 | |
347 fprintf (file, "# name: a\n") ; | |
348 fprintf (file, "# type: matrix\n") ; | |
349 fprintf (file, "# rows: %d\n", len) ; | |
350 fprintf (file, "# columns: 1\n") ; | |
351 | |
352 for (k = 0 ; k < len ; k++) | |
353 fprintf (file, [+ (get "format_str") +] "\n", a [k]) ; | |
354 | |
355 fprintf (file, "# name: b\n") ; | |
356 fprintf (file, "# type: matrix\n") ; | |
357 fprintf (file, "# rows: %d\n", len) ; | |
358 fprintf (file, "# columns: 1\n") ; | |
359 | |
360 for (k = 0 ; k < len ; k++) | |
361 fprintf (file, [+ (get "format_str") +] "\n", b [k]) ; | |
362 | |
363 fclose (file) ; | |
364 return 0 ; | |
365 } /* oct_save_[+ (get "io_element") +] */ | |
366 [+ ENDFOR io_type | |
367 +] | |
368 | |
369 void | |
370 check_log_buffer_or_die (SNDFILE *file, int line_num) | |
371 { static char buffer [LOG_BUFFER_SIZE] ; | |
372 int count ; | |
373 | |
374 memset (buffer, 0, sizeof (buffer)) ; | |
375 | |
376 /* Get the log buffer data. */ | |
377 count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ; | |
378 | |
379 if (LOG_BUFFER_SIZE - count < 2) | |
380 { printf ("\n\nLine %d : Possible long log buffer.\n", line_num) ; | |
381 exit (1) ; | |
382 } | |
383 | |
384 /* Look for "Should" */ | |
385 if (strstr (buffer, "ould")) | |
386 { printf ("\n\nLine %d : Log buffer contains `ould'. Dumping.\n", line_num) ; | |
387 puts (buffer) ; | |
388 exit (1) ; | |
389 } ; | |
390 | |
391 /* Look for "**" */ | |
392 if (strstr (buffer, "*")) | |
393 { printf ("\n\nLine %d : Log buffer contains `*'. Dumping.\n", line_num) ; | |
394 puts (buffer) ; | |
395 exit (1) ; | |
396 } ; | |
397 | |
398 /* Look for "Should" */ | |
399 if (strstr (buffer, "nknown marker")) | |
400 { printf ("\n\nLine %d : Log buffer contains `nknown marker'. Dumping.\n", line_num) ; | |
401 puts (buffer) ; | |
402 exit (1) ; | |
403 } ; | |
404 | |
405 return ; | |
406 } /* check_log_buffer_or_die */ | |
407 | |
408 int | |
409 string_in_log_buffer (SNDFILE *file, const char *s) | |
410 { static char buffer [LOG_BUFFER_SIZE] ; | |
411 int count ; | |
412 | |
413 memset (buffer, 0, sizeof (buffer)) ; | |
414 | |
415 /* Get the log buffer data. */ | |
416 count = sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ; | |
417 | |
418 if (LOG_BUFFER_SIZE - count < 2) | |
419 { printf ("Possible long log buffer.\n") ; | |
420 exit (1) ; | |
421 } | |
422 | |
423 /* Look for string */ | |
424 return strstr (buffer, s) ? SF_TRUE : SF_FALSE ; | |
425 } /* string_in_log_buffer */ | |
426 | |
427 void | |
428 hexdump_file (const char * filename, sf_count_t offset, sf_count_t length) | |
429 { | |
430 FILE * file ; | |
431 char buffer [16] ; | |
432 int k, m, ch, readcount ; | |
433 | |
434 if (length > 1000000) | |
435 { printf ("\n\nError : length (%" PRId64 ") too long.\n\n", offset) ; | |
436 exit (1) ; | |
437 } ; | |
438 | |
439 if ((file = fopen (filename, "r")) == NULL) | |
440 { printf ("\n\nError : hexdump_file (%s) could not open file for read.\n\n", filename) ; | |
441 exit (1) ; | |
442 } ; | |
443 | |
444 if (fseek (file, offset, SEEK_SET) != 0) | |
445 { printf ("\n\nError : fseek(file, %" PRId64 ", SEEK_SET) failed : %s\n\n", offset, strerror (errno)) ; | |
446 exit (1) ; | |
447 } ; | |
448 | |
449 puts ("\n\n") ; | |
450 | |
451 for (k = 0 ; k < length ; k+= sizeof (buffer)) | |
452 { readcount = fread (buffer, 1, sizeof (buffer), file) ; | |
453 | |
454 printf ("%08" PRIx64 " : ", offset + k) ; | |
455 | |
456 for (m = 0 ; m < readcount ; m++) | |
457 printf ("%02x ", buffer [m] & 0xFF) ; | |
458 | |
459 for (m = readcount ; m < SIGNED_SIZEOF (buffer) ; m++) | |
460 printf (" ") ; | |
461 | |
462 printf (" ") ; | |
463 for (m = 0 ; m < readcount ; m++) | |
464 { ch = isprint (buffer [m]) ? buffer [m] : '.' ; | |
465 putchar (ch) ; | |
466 } ; | |
467 | |
468 if (readcount < SIGNED_SIZEOF (buffer)) | |
469 break ; | |
470 | |
471 putchar ('\n') ; | |
472 } ; | |
473 | |
474 puts ("\n") ; | |
475 | |
476 fclose (file) ; | |
477 } /* hexdump_file */ | |
478 | |
479 void | |
480 dump_log_buffer (SNDFILE *file) | |
481 { static char buffer [LOG_BUFFER_SIZE] ; | |
482 | |
483 memset (buffer, 0, sizeof (buffer)) ; | |
484 | |
485 /* Get the log buffer data. */ | |
486 sf_command (file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ; | |
487 | |
488 if (strlen (buffer) < 1) | |
489 puts ("Log buffer empty.\n") ; | |
490 else | |
491 puts (buffer) ; | |
492 | |
493 return ; | |
494 } /* dump_log_buffer */ | |
495 | |
496 void | |
497 test_sf_format_or_die (const SF_INFO *info, int line_num) | |
498 { int res ; | |
499 | |
500 if ((res = sf_format_check (info)) != 1) | |
501 { printf ("\n\nLine %d : sf_format_check returned error (%d)\n\n", line_num,res) ; | |
502 exit (1) ; | |
503 } ; | |
504 | |
505 return ; | |
506 } /* test_sf_format_or_die */ | |
507 | |
508 SNDFILE * | |
509 test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num) | |
510 { static int count = 0 ; | |
511 | |
512 SNDFILE *file ; | |
513 const char *modestr, *func_name ; | |
514 int oflags = 0, omode = 0, err ; | |
515 | |
516 /* | |
517 ** Need to test both sf_open() and sf_open_fd(). | |
518 ** Do so alternately. | |
519 */ | |
520 switch (mode) | |
521 { case SFM_READ : | |
522 modestr = "SFM_READ" ; | |
523 oflags = O_RDONLY | O_BINARY ; | |
524 omode = 0 ; | |
525 break ; | |
526 | |
527 case SFM_WRITE : | |
528 modestr = "SFM_WRITE" ; | |
529 oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; | |
530 omode = S_IRUSR | S_IWUSR | S_IRGRP ; | |
531 break ; | |
532 | |
533 case SFM_RDWR : | |
534 modestr = "SFM_RDWR" ; | |
535 oflags = O_RDWR | O_CREAT | O_BINARY ; | |
536 omode = S_IRUSR | S_IWUSR | S_IRGRP ; | |
537 break ; | |
538 default : | |
539 printf ("\n\nLine %d: Bad mode.\n", line_num) ; | |
540 fflush (stdout) ; | |
541 exit (1) ; | |
542 } ; | |
543 | |
544 if (OS_IS_WIN32) | |
545 { /* Windows does not understand and ignores the S_IRGRP flag, but Wine | |
546 ** gives a run time warning message, so just clear it. | |
547 */ | |
548 omode &= ~S_IRGRP ; | |
549 } ; | |
550 | |
551 if (allow_fd && ((++count) & 1) == 1) | |
552 { int fd ; | |
553 | |
554 /* Only use the three argument open() function if omode != 0. */ | |
555 fd = (omode == 0) ? open (filename, oflags) : open (filename, oflags, omode) ; | |
556 | |
557 if (fd < 0) | |
558 { printf ("\n\n%s : open failed : %s\n", __func__, strerror (errno)) ; | |
559 exit (1) ; | |
560 } ; | |
561 | |
562 func_name = "sf_open_fd" ; | |
563 file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ; | |
564 } | |
565 else | |
566 { func_name = "sf_open" ; | |
567 file = sf_open (filename, mode, sfinfo) ; | |
568 } ; | |
569 | |
570 if (file == NULL) | |
571 { printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ; | |
572 dump_log_buffer (file) ; | |
573 exit (1) ; | |
574 } ; | |
575 | |
576 err = sf_error (file) ; | |
577 if (err != SF_ERR_NO_ERROR) | |
578 { printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ; | |
579 dump_log_buffer (file) ; | |
580 exit (1) ; | |
581 } ; | |
582 | |
583 return file ; | |
584 } /* test_open_file_or_die */ | |
585 | |
586 void | |
587 test_read_write_position_or_die (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos) | |
588 { sf_count_t pos ; | |
589 | |
590 /* Check the current read position. */ | |
591 if (read_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_READ)) != read_pos) | |
592 { printf ("\n\nLine %d ", line_num) ; | |
593 if (pass > 0) | |
594 printf ("(pass %d): ", pass) ; | |
595 printf ("Read position (%" PRId64 ") should be %" PRId64 ".\n", pos, read_pos) ; | |
596 exit (1) ; | |
597 } ; | |
598 | |
599 /* Check the current write position. */ | |
600 if (write_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_WRITE)) != write_pos) | |
601 { printf ("\n\nLine %d", line_num) ; | |
602 if (pass > 0) | |
603 printf (" (pass %d)", pass) ; | |
604 printf (" : Write position (%" PRId64 ") should be %" PRId64 ".\n", pos, write_pos) ; | |
605 exit (1) ; | |
606 } ; | |
607 | |
608 return ; | |
609 } /* test_read_write_position */ | |
610 | |
611 void | |
612 test_seek_or_die (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num) | |
613 { sf_count_t position ; | |
614 const char *channel_name, *whence_name ; | |
615 | |
616 switch (whence) | |
617 { case SEEK_SET : | |
618 whence_name = "SEEK_SET" ; | |
619 break ; | |
620 case SEEK_CUR : | |
621 whence_name = "SEEK_CUR" ; | |
622 break ; | |
623 case SEEK_END : | |
624 whence_name = "SEEK_END" ; | |
625 break ; | |
626 | |
627 /* SFM_READ */ | |
628 case SEEK_SET | SFM_READ : | |
629 whence_name = "SFM_READ | SEEK_SET" ; | |
630 break ; | |
631 case SEEK_CUR | SFM_READ : | |
632 whence_name = "SFM_READ | SEEK_CUR" ; | |
633 break ; | |
634 case SEEK_END | SFM_READ : | |
635 whence_name = "SFM_READ | SEEK_END" ; | |
636 break ; | |
637 | |
638 /* SFM_WRITE */ | |
639 case SEEK_SET | SFM_WRITE : | |
640 whence_name = "SFM_WRITE | SEEK_SET" ; | |
641 break ; | |
642 case SEEK_CUR | SFM_WRITE : | |
643 whence_name = "SFM_WRITE | SEEK_CUR" ; | |
644 break ; | |
645 case SEEK_END | SFM_WRITE : | |
646 whence_name = "SFM_WRITE | SEEK_END" ; | |
647 break ; | |
648 | |
649 default : | |
650 printf ("\n\nLine %d: bad whence parameter.\n", line_num) ; | |
651 exit (1) ; | |
652 } ; | |
653 | |
654 channel_name = (channels == 1) ? "Mono" : "Stereo" ; | |
655 | |
656 if ((position = sf_seek (file, offset, whence)) != new_pos) | |
657 { printf ("\n\nLine %d : %s : sf_seek (file, %" PRId64 ", %s) returned %" PRId64 " (should be %" PRId64 ").\n\n", | |
658 line_num, channel_name, offset, whence_name, position, new_pos) ; | |
659 exit (1) ; | |
660 } ; | |
661 | |
662 } /* test_seek_or_die */ | |
663 | |
664 [+ FOR read_op +] | |
665 [+ FOR io_type +] | |
666 void | |
667 test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die (SNDFILE *file, int pass, [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) | |
668 { sf_count_t count ; | |
669 | |
670 if ((count = sf_[+ (get "op_element") +]_[+ (get "io_element") +] (file, test, [+ (get "count_name") +])) != [+ (get "count_name") +]) | |
671 { printf ("\n\nLine %d", line_num) ; | |
672 if (pass > 0) | |
673 printf (" (pass %d)", pass) ; | |
674 printf (" : sf_[+ (get "op_element") +]_[+ (get "io_element") +] failed with short [+ (get "op_element") +] (%" PRId64 " => %" PRId64 ").\n", | |
675 [+ (get "count_name") +], count) ; | |
676 fflush (stdout) ; | |
677 puts (sf_strerror (file)) ; | |
678 exit (1) ; | |
679 } ; | |
680 | |
681 return ; | |
682 } /* test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die */ | |
683 [+ ENDFOR io_type +][+ ENDFOR read_op +] | |
684 | |
685 void | |
686 test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num) | |
687 { sf_count_t count ; | |
688 | |
689 if ((count = sf_read_raw (file, test, items)) != items) | |
690 { printf ("\n\nLine %d", line_num) ; | |
691 if (pass > 0) | |
692 printf (" (pass %d)", pass) ; | |
693 printf (" : sf_read_raw failed with short read (%" PRId64 " => %" PRId64 ").\n", items, count) ; | |
694 fflush (stdout) ; | |
695 puts (sf_strerror (file)) ; | |
696 exit (1) ; | |
697 } ; | |
698 | |
699 return ; | |
700 } /* test_read_raw_or_die */ | |
701 | |
702 [+ FOR write_op +] | |
703 [+ FOR io_type +] | |
704 void | |
705 test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die (SNDFILE *file, int pass, const [+ (get "io_element") +] *test, sf_count_t [+ (get "count_name") +], int line_num) | |
706 { sf_count_t count ; | |
707 | |
708 if ((count = sf_[+ (get "op_element") +]_[+ (get "io_element") +] (file, test, [+ (get "count_name") +])) != [+ (get "count_name") +]) | |
709 { printf ("\n\nLine %d", line_num) ; | |
710 if (pass > 0) | |
711 printf (" (pass %d)", pass) ; | |
712 printf (" : sf_[+ (get "op_element") +]_[+ (get "io_element") +] failed with short [+ (get "op_element") +] (%" PRId64 " => %" PRId64 ").\n", | |
713 [+ (get "count_name") +], count) ; | |
714 fflush (stdout) ; | |
715 puts (sf_strerror (file)) ; | |
716 exit (1) ; | |
717 } ; | |
718 | |
719 return ; | |
720 } /* test_[+ (get "op_element") +]_[+ (get "io_element") +]_or_die */ | |
721 [+ ENDFOR io_type +][+ ENDFOR write_op +] | |
722 | |
723 void | |
724 test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num) | |
725 { sf_count_t count ; | |
726 | |
727 if ((count = sf_write_raw (file, test, items)) != items) | |
728 { printf ("\n\nLine %d", line_num) ; | |
729 if (pass > 0) | |
730 printf (" (pass %d)", pass) ; | |
731 printf (" : sf_write_raw failed with short write (%" PRId64 " => %" PRId64 ").\n", items, count) ; | |
732 fflush (stdout) ; | |
733 puts (sf_strerror (file)) ; | |
734 exit (1) ; | |
735 } ; | |
736 | |
737 return ; | |
738 } /* test_write_raw_or_die */ | |
739 | |
740 | |
741 [+ FOR io_type | |
742 +]void | |
743 compare_[+ (get "io_element") +]_or_die (const [+ (get "io_element") +] *expected, const [+ (get "io_element") +] *actual, unsigned count, int line_num) | |
744 { | |
745 unsigned k ; | |
746 | |
747 for (k = 0 ; k < count ; k++) | |
748 if (expected [k] != actual [k]) | |
749 { printf ("\n\nLine %d : Error at index %d, got " [+ (get "format_str") +] ", should be " [+ (get "format_str") +] ".\n\n", line_num, k, actual [k], expected [k]) ; | |
750 exit (1) ; | |
751 } ; | |
752 | |
753 return ; | |
754 } /* compare_[+ (get "io_element") +]_or_die */ | |
755 [+ ENDFOR io_type +] | |
756 | |
757 | |
758 void | |
759 delete_file (int format, const char *filename) | |
760 { char rsrc_name [512], *fname ; | |
761 | |
762 unlink (filename) ; | |
763 | |
764 if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2) | |
765 return ; | |
766 | |
767 /* | |
768 ** Now try for a resource fork stored as a separate file. | |
769 ** Grab the un-adulterated filename again. | |
770 */ | |
771 snprintf (rsrc_name, sizeof (rsrc_name), "%s", filename) ; | |
772 | |
773 if ((fname = strrchr (rsrc_name, '/')) != NULL) | |
774 fname ++ ; | |
775 else if ((fname = strrchr (rsrc_name, '\\')) != NULL) | |
776 fname ++ ; | |
777 else | |
778 fname = rsrc_name ; | |
779 | |
780 memmove (fname + 2, fname, strlen (fname) + 1) ; | |
781 fname [0] = '.' ; | |
782 fname [1] = '_' ; | |
783 | |
784 unlink (rsrc_name) ; | |
785 } /* delete_file */ | |
786 | |
787 static int allowed_open_files = -1 ; | |
788 | |
789 void | |
790 count_open_files (void) | |
791 { | |
792 #if OS_IS_WIN32 | |
793 return ; | |
794 #else | |
795 int k, count = 0 ; | |
796 struct stat statbuf ; | |
797 | |
798 if (allowed_open_files > 0) | |
799 return ; | |
800 | |
801 for (k = 0 ; k < 1024 ; k++) | |
802 if (fstat (k, &statbuf) == 0) | |
803 count ++ ; | |
804 | |
805 allowed_open_files = count ; | |
806 #endif | |
807 } /* count_open_files */ | |
808 | |
809 void | |
810 increment_open_file_count (void) | |
811 { allowed_open_files ++ ; | |
812 } /* increment_open_file_count */ | |
813 | |
814 void | |
815 check_open_file_count_or_die (int lineno) | |
816 { | |
817 #if OS_IS_WIN32 | |
818 (void) lineno ; | |
819 return ; | |
820 #else | |
821 int k, count = 0 ; | |
822 struct stat statbuf ; | |
823 | |
824 if (allowed_open_files < 0) | |
825 count_open_files () ; | |
826 | |
827 for (k = 0 ; k < 1024 ; k++) | |
828 if (fstat (k, &statbuf) == 0) | |
829 count ++ ; | |
830 | |
831 if (count > allowed_open_files) | |
832 { printf ("\nLine %d : number of open files (%d) > allowed (%d).\n\n", lineno, count, allowed_open_files) ; | |
833 exit (1) ; | |
834 } ; | |
835 #endif | |
836 } /* check_open_file_count_or_die */ | |
837 | |
838 void | |
839 write_mono_file (const char * filename, int format, int srate, float * output, int len) | |
840 { SNDFILE * file ; | |
841 SF_INFO sfinfo ; | |
842 | |
843 memset (&sfinfo, 0, sizeof (sfinfo)) ; | |
844 | |
845 sfinfo.samplerate = srate ; | |
846 sfinfo.channels = 1 ; | |
847 sfinfo.format = format ; | |
848 | |
849 if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) | |
850 { printf ("sf_open (%s) : %s\n", filename, sf_strerror (NULL)) ; | |
851 exit (1) ; | |
852 } ; | |
853 | |
854 sf_write_float (file, output, len) ; | |
855 | |
856 sf_close (file) ; | |
857 } /* write_mono_file */ | |
858 | |
859 void | |
860 gen_lowpass_signal_float (float *data, int len) | |
861 { int64_t value = 0x1243456 ; | |
862 double sample, last_val = 0.0 ; | |
863 int k ; | |
864 | |
865 for (k = 0 ; k < len ; k++) | |
866 { /* Not a crypto quality RNG. */ | |
867 value = (11117 * value + 211231) & 0xffffffff ; | |
868 value = (11117 * value + 211231) & 0xffffffff ; | |
869 value = (11117 * value + 211231) & 0xffffffff ; | |
870 | |
871 sample = value / (0x7fffffff * 1.000001) ; | |
872 sample = 0.2 * sample - 0.9 * last_val ; | |
873 | |
874 last_val = sample ; | |
875 | |
876 data [k] = 0.5 * (sample + sin (2.0 * k * M_PI * 1.0 / 32.0)) ; | |
877 } ; | |
878 | |
879 } /* gen_lowpass_signal_float */ | |
880 | |
881 | |
882 /* | |
883 ** Windows is fucked. | |
884 ** If a file is opened R/W and data is written to it, then fstat will return | |
885 ** the correct file length, but stat will return zero. | |
886 */ | |
887 | |
888 sf_count_t | |
889 file_length (const char * fname) | |
890 { struct stat data ; | |
891 | |
892 if (stat (fname, &data) != 0) | |
893 return 0 ; | |
894 | |
895 return (sf_count_t) data.st_size ; | |
896 } /* file_length */ | |
897 | |
898 sf_count_t | |
899 file_length_fd (int fd) | |
900 { struct stat data ; | |
901 | |
902 memset (&data, 0, sizeof (data)) ; | |
903 if (fstat (fd, &data) != 0) | |
904 return 0 ; | |
905 | |
906 return (sf_count_t) data.st_size ; | |
907 } /* file_length_fd */ | |
908 | |
909 | |
910 [+ ESAC +] | |
911 |